From eaed4009873e6dc28e0aa0794209be2857552163 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Wed, 3 Sep 2025 05:52:27 +0200 Subject: [PATCH 01/76] Fixed a bug in plotting cross sections with S(a,b) data (#3558) --- openmc/plotter.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/plotter.py b/openmc/plotter.py index 85c4963a76..693cdaca4e 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -413,7 +413,8 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, # Prep S(a,b) data if needed if sab_name: - sab = openmc.data.ThermalScattering.from_hdf5(sab_name) + sab = openmc.data.ThermalScattering.from_hdf5( + library.get_by_material(sab_name, data_type='thermal')['path']) # Obtain the nearest temperature if strT in sab.temperatures: sabT = strT @@ -640,14 +641,13 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., sab = openmc.data.ThermalScattering.from_hdf5( library.get_by_material(sab_name, data_type='thermal')['path']) for nuc in sab.nuclides: - sabs[nuc] = library.get_by_material(sab_name, - data_type='thermal')['path'] + sabs[nuc] = sab_name else: if sab_name: - sab = openmc.data.ThermalScattering.from_hdf5(sab_name) + sab = openmc.data.ThermalScattering.from_hdf5( + library.get_by_material(sab_name, data_type='thermal')['path']) for nuc in sab.nuclides: - sabs[nuc] = library.get_by_material(sab_name, - data_type='thermal')['path'] + sabs[nuc] = sab_name # Now we can create the data sets to be plotted xs = {} @@ -655,8 +655,8 @@ def _calculate_cexs_elem_mat(this, types, temperature=294., for nuclide in nuclides.items(): name = nuclide[0] nuc = nuclide[1] - sab_tab = sabs[name] - temp_E, temp_xs = calculate_cexs(nuc, types, T, sab_tab, cross_sections, + sab_name = sabs[name] + temp_E, temp_xs = calculate_cexs(nuc, types, T, sab_name, cross_sections, ncrystal_cfg=ncrystal_cfg ) E.append(temp_E) From 5918564727a34ac7bb071ceafe1a7bf4d50542d7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 3 Sep 2025 11:35:11 -0500 Subject: [PATCH 02/76] Bump up tolerance for flaky activation test (#3560) --- tests/unit_tests/test_deplete_activation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index 6afea8c9f9..cbe00d680c 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -45,7 +45,7 @@ ENERGIES = np.logspace(log10(1e-5), log10(2e7), 100) @pytest.mark.parametrize("reaction_rate_mode,reaction_rate_opts,tolerance", [ ("direct", {}, 1e-5), - ("flux", {'energies': ENERGIES}, 0.01), + ("flux", {'energies': ENERGIES}, 0.1), ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)']}, 1e-5), ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186', 'H3']}, 1e-2), ]) @@ -61,11 +61,10 @@ def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts w186 = openmc.deplete.Nuclide('W186') w186.add_reaction('(n,gamma)', None, 0.0, 1.0) chain.add_nuclide(w186) - chain.export_to_xml('test_chain.xml') # Create transport operator op = openmc.deplete.CoupledOperator( - model, 'test_chain.xml', + model, chain, normalization_mode="source-rate", reaction_rate_mode=reaction_rate_mode, reaction_rate_opts=reaction_rate_opts, From 366509051381db89a3a6a7b3346e3b339e8af0af Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 5 Sep 2025 06:34:49 -0500 Subject: [PATCH 03/76] Do not apply boundary conditions when initialized in volume calculation mode (#3562) --- src/particle.cpp | 3 ++- tests/unit_tests/test_mesh.py | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/particle.cpp b/src/particle.cpp index fb41d82e95..fd4df14c3f 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -544,7 +544,8 @@ void Particle::cross_surface(const Surface& surf) #endif // Handle any applicable boundary conditions. - if (surf.bc_ && settings::run_mode != RunMode::PLOTTING) { + if (surf.bc_ && settings::run_mode != RunMode::PLOTTING && + settings::run_mode != RunMode::VOLUME) { surf.bc_->handle_particle(*this, surf); return; } diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index 67ca4028e0..1930e3264e 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -620,6 +620,33 @@ def test_mesh_material_volumes_serialize(): assert new_volumes.by_element(3) == [(2, 1.0)] +def test_mesh_material_volumes_boundary_conditions(sphere_model): + """Test the material volumes method using a regular mesh + that overlaps with a vacuum boundary condition.""" + + mesh = openmc.SphericalMesh.from_domain(sphere_model.geometry, dimension=(1, 1, 1)) + # extend mesh beyond the outer sphere surface to test rays crossing the boundary condition + mesh.r_grid[-1] += 5.0 + + # add a new cell to the modelthat occupies the outside of the sphere + sphere_surfaces = list(filter(lambda s: isinstance(s, openmc.Sphere), + sphere_model.geometry.get_all_surfaces().values())) + outer_cell = openmc.Cell(region=+sphere_surfaces[0]) + sphere_model.geometry.root_universe.add_cell(outer_cell) + + volumes = mesh.material_volumes(sphere_model, (0, 100, 100)) + sphere_volume = 4/3*np.pi*25**3 + mats = sphere_model.materials + expected_volumes = [(mats[0].id, 0.25*sphere_volume), + (mats[1].id, 0.25*sphere_volume), + (mats[2].id, 0.5*sphere_volume), + (None, 4/3*np.pi*mesh.r_grid[-1]**3 - sphere_volume)] + + for evaluated, expected in zip(volumes.by_element(0), expected_volumes): + assert evaluated[0] == expected[0] + assert evaluated[1] == pytest.approx(expected[1], rel=1e-2) + + def test_raytrace_mesh_infinite_loop(run_in_tmpdir): # Create a model with one large spherical cell sphere = openmc.Sphere(r=100, boundary_type='vacuum') From ca4295748d1b547ea3e5d9c8fb1ec55b64809289 Mon Sep 17 00:00:00 2001 From: Robert Carlsen Date: Wed, 10 Sep 2025 20:13:28 -0600 Subject: [PATCH 04/76] depletion: fix performance of chain matrix construction (#3567) Co-authored-by: GuySten <62616591+GuySten@users.noreply.github.com> --- openmc/deplete/chain.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index f1a23317fb..ac5c02aa50 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -627,9 +627,15 @@ class Chain: """ reactions = set() - # Use DOK matrix as intermediate representation for matrix n = len(self) - matrix = sp.dok_matrix((n, n)) + + # we accumulate indices and value entries for everything and create the matrix + # in one step at the end to avoid expensive index checks scipy otherwise does. + rows, cols, vals = [], [], [] + def setval(i, j, val): + rows.append(i) + cols.append(j) + vals.append(val) if fission_yields is None: fission_yields = self.get_default_fission_yields() @@ -639,7 +645,7 @@ class Chain: if nuc.half_life is not None: decay_constant = math.log(2) / nuc.half_life if decay_constant != 0.0: - matrix[i, i] -= decay_constant + setval(i, i, -decay_constant) # Gain from radioactive decay if nuc.n_decay_modes != 0: @@ -650,19 +656,19 @@ class Chain: if branch_val != 0.0: if target is not None: k = self.nuclide_dict[target] - matrix[k, i] += branch_val + setval(k, i, branch_val) # Produce alphas and protons from decay if 'alpha' in decay_type: k = self.nuclide_dict.get('He4') if k is not None: count = decay_type.count('alpha') - matrix[k, i] += count * branch_val + setval(k, i, count * branch_val) elif 'p' in decay_type: k = self.nuclide_dict.get('H1') if k is not None: count = decay_type.count('p') - matrix[k, i] += count * branch_val + setval(k, i, count * branch_val) if nuc.name in rates.index_nuc: # Extract all reactions for this nuclide in this cell @@ -679,13 +685,13 @@ class Chain: if r_type not in reactions: reactions.add(r_type) if path_rate != 0.0: - matrix[i, i] -= path_rate + setval(i, i, -path_rate) # Gain term; allow for total annihilation for debug purposes if r_type != 'fission': if target is not None and path_rate != 0.0: k = self.nuclide_dict[target] - matrix[k, i] += path_rate * br + setval(k, i, path_rate * br) # Determine light nuclide production, e.g., (n,d) should # produce H2 @@ -693,20 +699,20 @@ class Chain: for light_nuc in light_nucs: k = self.nuclide_dict.get(light_nuc) if k is not None: - matrix[k, i] += path_rate * br + setval(k, i, path_rate * br) else: for product, y in fission_yields[nuc.name].items(): yield_val = y * path_rate if yield_val != 0.0: k = self.nuclide_dict[product] - matrix[k, i] += yield_val + setval(k, i, yield_val) # Clear set of reactions reactions.clear() # Return CSC representation instead of DOK - return matrix.tocsc() + return sp.csc_matrix((vals, (rows, cols)), shape=(n, n)) def form_rr_term(self, tr_rates, current_timestep, mats): """Function to form the transfer rate term matrices. From c7175289eb0f801b38b7b684a5ddd4803261f66a Mon Sep 17 00:00:00 2001 From: Jack Fletcher <115663563+j-fletcher@users.noreply.github.com> Date: Thu, 11 Sep 2025 08:57:02 -0400 Subject: [PATCH 05/76] PowerLaw raises an error if sampling interval contains negative values (#3542) --- openmc/stats/univariate.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index 28d5e87ef9..d6cf19f2b8 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -480,6 +480,9 @@ class PowerLaw(Univariate): """ def __init__(self, a: float = 0.0, b: float = 1.0, n: float = 0.): + if a >= b: + raise ValueError( + "Lower bound of sampling interval must be less than upper bound.") self.a = a self.b = b self.n = n @@ -494,6 +497,9 @@ class PowerLaw(Univariate): @a.setter def a(self, a): cv.check_type('interval lower bound', a, Real) + if a < 0: + raise ValueError( + "PowerLaw sampling is restricted to positive-valued intervals.") self._a = a @property @@ -503,6 +509,9 @@ class PowerLaw(Univariate): @b.setter def b(self, b): cv.check_type('interval upper bound', b, Real) + if b < 0: + raise ValueError( + "PowerLaw sampling is restricted to positive-valued intervals.") self._b = b @property From afd9d0607445f00c6de97b1ff866521c319722b0 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Fri, 12 Sep 2025 22:23:17 +0200 Subject: [PATCH 06/76] Fixed a bug when combining TimeFilter, MeshFilter, and tracklength estimator (#3525) Co-authored-by: Paul Romano --- include/openmc/tallies/tally.h | 10 ++++ include/openmc/tallies/tally_scoring.h | 10 ++++ src/particle.cpp | 5 ++ src/tallies/tally.cpp | 80 ++++++++++++++++++++----- src/tallies/tally_scoring.cpp | 59 ++++++++++++++++-- tests/unit_tests/test_mesh.py | 83 +++++++++++++++++++++++++- 6 files changed, 227 insertions(+), 20 deletions(-) diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 8c088c4608..3beeb9d5ac 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -203,11 +203,14 @@ extern vector> tallies; extern vector active_tallies; extern vector active_analog_tallies; extern vector active_tracklength_tallies; +extern vector active_timed_tracklength_tallies; extern vector active_collision_tallies; extern vector active_meshsurf_tallies; extern vector active_surface_tallies; extern vector active_pulse_height_tallies; extern vector pulse_height_cells; +extern vector time_grid; + } // namespace model namespace simulation { @@ -239,6 +242,13 @@ void read_tallies_xml(pugi::xml_node root); //! batch to a new random variable void accumulate_tallies(); +//! Determine distance to next time boundary +// +//! \param time Current time of particle +//! \param speed Speed of particle +//! \return Distance to next time boundary (or INFTY if none) +double distance_to_time_boundary(double time, double speed); + //! Determine which tallies should be active void setup_active_tallies(); diff --git a/include/openmc/tallies/tally_scoring.h b/include/openmc/tallies/tally_scoring.h index 28f1f16223..c3ab779e6a 100644 --- a/include/openmc/tallies/tally_scoring.h +++ b/include/openmc/tallies/tally_scoring.h @@ -91,6 +91,16 @@ void score_analog_tally_mg(Particle& p); //! \param distance The distance in [cm] traveled by the particle void score_tracklength_tally(Particle& p, double distance); +//! Score time filtered tallies using a tracklength estimate of the flux. +// +//! This is triggered at every event (surface crossing, lattice crossing, or +//! collision) and thus cannot be done for tallies that require post-collision +//! information. +// +//! \param p The particle being tracked +//! \param total_distance The distance in [cm] traveled by the particle +void score_timed_tracklength_tally(Particle& p, double total_distance); + //! Score surface or mesh-surface tallies for particle currents. // //! \param p The particle being tracked diff --git a/src/particle.cpp b/src/particle.cpp index fd4df14c3f..f25ada02c8 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -252,6 +252,11 @@ void Particle::event_advance() this->time() += dt; this->lifetime() += dt; + // Score timed track-length tallies + if (!model::active_timed_tracklength_tallies.empty()) { + score_timed_tracklength_tally(*this, distance); + } + // Score track-length tallies if (!model::active_tracklength_tallies.empty()) { score_tracklength_tally(*this, distance); diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index ba18386026..ae0bffe6eb 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -27,10 +27,12 @@ #include "openmc/tallies/filter_legendre.h" #include "openmc/tallies/filter_mesh.h" #include "openmc/tallies/filter_meshborn.h" +#include "openmc/tallies/filter_meshmaterial.h" #include "openmc/tallies/filter_meshsurface.h" #include "openmc/tallies/filter_particle.h" #include "openmc/tallies/filter_sph_harm.h" #include "openmc/tallies/filter_surface.h" +#include "openmc/tallies/filter_time.h" #include "openmc/xml_interface.h" #include "xtensor/xadapt.hpp" @@ -38,9 +40,10 @@ #include "xtensor/xview.hpp" #include -#include // for max +#include // for max, set_union #include -#include // for size_t +#include // for size_t +#include // for back_inserter #include namespace openmc { @@ -56,11 +59,13 @@ vector> tallies; vector active_tallies; vector active_analog_tallies; vector active_tracklength_tallies; +vector active_timed_tracklength_tallies; vector active_collision_tallies; vector active_meshsurf_tallies; vector active_surface_tallies; vector active_pulse_height_tallies; vector pulse_height_cells; +vector time_grid; } // namespace model namespace simulation { @@ -243,8 +248,8 @@ Tally::Tally(pugi::xml_node node) for (int score : scores_) { switch (score) { case SCORE_PULSE_HEIGHT: - fatal_error( - "For pulse-height tallies, photon transport needs to be activated."); + fatal_error("For pulse-height tallies, photon transport needs to be " + "activated."); break; } } @@ -318,7 +323,8 @@ Tally::Tally(pugi::xml_node node) if (has_energyout && i_nuc == -1) { fatal_error(fmt::format( "Error on tally {}: Cannot use a " - "'nuclide_density' or 'temperature' derivative on a tally with an " + "'nuclide_density' or 'temperature' derivative on a tally with " + "an " "outgoing energy filter and 'total' nuclide rate. Instead, tally " "each nuclide in the material individually.", id_)); @@ -493,9 +499,9 @@ void Tally::add_filter(Filter* filter) void Tally::set_strides() { - // Set the strides. Filters are traversed in reverse so that the last filter - // has the shortest stride in memory and the first filter has the longest - // stride. + // Set the strides. Filters are traversed in reverse so that the last + // filter has the shortest stride in memory and the first filter has the + // longest stride. auto n = filters_.size(); strides_.resize(n, 0); int stride = 1; @@ -551,7 +557,8 @@ void Tally::set_scores(const vector& scores) // Iterate over the given scores. for (auto score_str : scores) { - // Make sure a delayed group filter wasn't used with an incompatible score. + // Make sure a delayed group filter wasn't used with an incompatible + // score. if (delayedgroup_filter_ != C_NONE) { if (score_str != "delayed-nu-fission" && score_str != "decay-rate") fatal_error("Cannot tally " + score_str + "with a delayedgroup filter"); @@ -984,8 +991,8 @@ void reduce_tally_results() } } - // Note that global tallies are *always* reduced even when no_reduce option is - // on. + // Note that global tallies are *always* reduced even when no_reduce option + // is on. // Get view of global tally values auto& gt = simulation::global_tallies; @@ -1064,21 +1071,59 @@ void accumulate_tallies() } } +double distance_to_time_boundary(double time, double speed) +{ + if (model::time_grid.empty()) { + return INFTY; + } else if (time >= model::time_grid.back()) { + return INFTY; + } else { + double next_time = + *std::upper_bound(model::time_grid.begin(), model::time_grid.end(), time); + return (next_time - time) * speed; + } +} + +//! Add new points to the global time grid +// +//! \param grid Vector of new time points to add +void add_to_time_grid(vector grid) +{ + if (grid.empty()) + return; + + // Create new vector with enough space to hold old and new grid points + vector merged; + merged.reserve(model::time_grid.size() + grid.size()); + + // Merge and remove duplicates + std::set_union(model::time_grid.begin(), model::time_grid.end(), grid.begin(), + grid.end(), std::back_inserter(merged)); + + // Swap in the new grid + model::time_grid.swap(merged); +} + void setup_active_tallies() { model::active_tallies.clear(); model::active_analog_tallies.clear(); model::active_tracklength_tallies.clear(); + model::active_timed_tracklength_tallies.clear(); model::active_collision_tallies.clear(); model::active_meshsurf_tallies.clear(); model::active_surface_tallies.clear(); model::active_pulse_height_tallies.clear(); + model::time_grid.clear(); for (auto i = 0; i < model::tallies.size(); ++i) { const auto& tally {*model::tallies[i]}; if (tally.active_) { model::active_tallies.push_back(i); + bool mesh_present = (tally.get_filter() || + tally.get_filter()); + auto time_filter = tally.get_filter(); switch (tally.type_) { case TallyType::VOLUME: @@ -1087,7 +1132,12 @@ void setup_active_tallies() model::active_analog_tallies.push_back(i); break; case TallyEstimator::TRACKLENGTH: - model::active_tracklength_tallies.push_back(i); + if (time_filter && mesh_present) { + model::active_timed_tracklength_tallies.push_back(i); + add_to_time_grid(time_filter->bins()); + } else { + model::active_tracklength_tallies.push_back(i); + } break; case TallyEstimator::COLLISION: model::active_collision_tallies.push_back(i); @@ -1123,10 +1173,12 @@ void free_memory_tally() model::active_tallies.clear(); model::active_analog_tallies.clear(); model::active_tracklength_tallies.clear(); + model::active_timed_tracklength_tallies.clear(); model::active_collision_tallies.clear(); model::active_meshsurf_tallies.clear(); model::active_surface_tallies.clear(); model::active_pulse_height_tallies.clear(); + model::time_grid.clear(); model::tally_map.clear(); } @@ -1465,8 +1517,8 @@ extern "C" int openmc_tally_get_n_realizations(int32_t index, int32_t* n) return 0; } -//! \brief Returns a pointer to a tally results array along with its shape. This -//! allows a user to obtain in-memory tally results from Python directly. +//! \brief Returns a pointer to a tally results array along with its shape. +//! This allows a user to obtain in-memory tally results from Python directly. extern "C" int openmc_tally_results( int32_t index, double** results, size_t* shape) { diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index e73fb90f31..04b047b649 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -2404,15 +2404,13 @@ void score_analog_tally_mg(Particle& p) match.bins_present_ = false; } -void score_tracklength_tally(Particle& p, double distance) +void score_tracklength_tally_general( + Particle& p, double flux, const vector& tallies) { - // Determine the tracklength estimate of the flux - double flux = p.wgt() * distance; - // Set 'none' value for log union grid index int i_log_union = C_NONE; - for (auto i_tally : model::active_tracklength_tallies) { + for (auto i_tally : tallies) { const Tally& tally {*model::tallies[i_tally]}; // Initialize an iterator over valid filter bin combinations. If there are @@ -2481,6 +2479,57 @@ void score_tracklength_tally(Particle& p, double distance) match.bins_present_ = false; } +void score_timed_tracklength_tally(Particle& p, double total_distance) +{ + double speed = p.speed(); + double total_dt = total_distance / speed; + + // save particle last state + auto time_last = p.time_last(); + auto r_last = p.r_last(); + + // move particle back + p.move_distance(-total_distance); + p.time() -= total_dt; + p.lifetime() -= total_dt; + + double distance_traveled = 0.0; + while (distance_traveled < total_distance) { + + double distance = std::min(distance_to_time_boundary(p.time(), speed), + total_distance - distance_traveled); + double dt = distance / speed; + + // Save particle last state for tracklength tallies + p.time_last() = p.time(); + p.r_last() = p.r(); + + // Advance particle in space and time + p.move_distance(distance); + p.time() += dt; + p.lifetime() += dt; + + // Determine the tracklength estimate of the flux + double flux = p.wgt() * distance; + + score_tracklength_tally_general( + p, flux, model::active_timed_tracklength_tallies); + distance_traveled += distance; + } + + p.time_last() = time_last; + p.r_last() = r_last; +} + +void score_tracklength_tally(Particle& p, double distance) +{ + + // Determine the tracklength estimate of the flux + double flux = p.wgt() * distance; + + score_tracklength_tally_general(p, flux, model::active_tracklength_tallies); +} + void score_collision_tally(Particle& p) { // Determine the collision estimate of the flux diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index 1930e3264e..f0f289408a 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -3,10 +3,12 @@ from tempfile import TemporaryDirectory from pathlib import Path import numpy as np +from scipy.stats import chi2 import pytest import openmc import openmc.lib from openmc.utility_funcs import change_directory +from uncertainties.unumpy import uarray, nominal_values, std_devs @pytest.mark.parametrize("val_left,val_right", [(0, 0), (-1., -1.), (2.0, 2)]) @@ -481,7 +483,7 @@ def test_umesh(run_in_tmpdir, simple_umesh, export_type): np.testing.assert_almost_equal(mean, ref_data) # attempt to apply a dataset with an improper size to a VTK write - with pytest.raises(ValueError, match='Cannot apply dataset "mean"') as e: + with pytest.raises(ValueError, match='Cannot apply dataset "mean"'): simple_umesh.write_data_to_vtk(datasets={'mean': ref_data[:-2]}, filename=filename) def test_mesh_get_homogenized_materials(): @@ -678,3 +680,82 @@ def test_raytrace_mesh_infinite_loop(run_in_tmpdir): # Run the model; this should not cause an infinite loop model.run() + + +def test_filter_time_mesh(run_in_tmpdir): + """Test combination of TimeFilter and MeshFilter""" + + # Define material + mat = openmc.Material() + mat.add_nuclide('Fe56', 1.0) + mat.set_density('g/cm3', 7.8) + + # Define geometry + surf_Z1 = openmc.XPlane(x0=-1e10, boundary_type="reflective") + surf_Z2 = openmc.XPlane(x0=1e10, boundary_type="reflective") + cell_F = openmc.Cell(fill=mat, region=+surf_Z1 & -surf_Z2) + model = openmc.Model() + model.geometry = openmc.Geometry([cell_F]) + + # Define settings + model.settings.run_mode = "fixed source" + model.settings.particles = 1000 + model.settings.batches = 20 + model.settings.output = {"tallies": False} + model.settings.cutoff = {"time_neutron": 1e-7} + + # Define tallies + + # Create a mesh filter that can be used in a tally + mesh = openmc.RegularMesh() + mesh.dimension = (21, 1, 1) + mesh.lower_left = (-20.5, -1e10, -1e10) + mesh.upper_right = (20.5, 1e10, 1e10) + time_grid = np.linspace(0.0, 1e-7, 21) + + mesh_filter = openmc.MeshFilter(mesh) + time_filter = openmc.TimeFilter(time_grid) + + # Now use the mesh filter in a tally and indicate what scores are desired + tally1 = openmc.Tally(name="collision") + tally1.estimator = "collision" + tally1.filters = [time_filter, mesh_filter] + tally1.scores = ["flux"] + tally2 = openmc.Tally(name="tracklength") + tally2.estimator = "tracklength" + tally2.filters = [time_filter, mesh_filter] + tally2.scores = ["flux"] + model.tallies = openmc.Tallies([tally1, tally2]) + + # Run and post-process + model.run(apply_tally_results=True) + + # Get radial flux distribution + flux_collision = tally1.mean.ravel() + flux_collision_unc = tally1.std_dev.ravel() + flux_tracklength = tally2.mean.ravel() + flux_tracklength_unc = tally2.std_dev.ravel() + + # Construct arrays with uncertainties + collision = uarray(flux_collision, flux_collision_unc) + tracklength = uarray(flux_tracklength, flux_tracklength_unc) + delta = collision - tracklength + + # Compute differences and standard deviations + diff = nominal_values(delta) + std_dev = std_devs(delta) + + # Exclude zero-uncertainty bins + mask = std_dev > 0.0 + dof = int(np.sum(mask)) + + # Global chi-square consistency test between collision and tracklength + # estimators. Target false positive rate ~1e-4 (1 in 10,000) + z = diff[mask] / std_dev[mask] + chi2_stat = np.sum(z * z) + alpha = 1.0e-4 + crit = chi2.ppf(1 - alpha, dof) + assert chi2_stat < crit, ( + f"Collision vs tracklength tallies disagree: chi2={chi2_stat:.2f} " + f">= {crit=:.2f} ({dof=}, {alpha=})" + ) From 607f6babe5c7fc1a441082fb355e7f30f182e72d Mon Sep 17 00:00:00 2001 From: Kevin Sawatzky <66632997+nuclearkevin@users.noreply.github.com> Date: Thu, 18 Sep 2025 23:11:06 -0500 Subject: [PATCH 07/76] Add distributed cell densities (#3546) Co-authored-by: Patrick Shriwise Co-authored-by: Paul Romano --- docs/source/capi/index.rst | 29 ++- docs/source/io_formats/properties.rst | 3 +- docs/source/io_formats/summary.rst | 3 +- include/openmc/capi.h | 4 + include/openmc/cell.h | 25 +++ include/openmc/constants.h | 4 +- include/openmc/geometry_aux.h | 6 + include/openmc/material.h | 7 + include/openmc/particle_data.h | 8 + openmc/cell.py | 43 ++++- openmc/lib/cell.py | 46 +++++ openmc/model/model.py | 16 +- src/cell.cpp | 178 +++++++++++++++++- src/geometry.cpp | 4 +- src/geometry_aux.cpp | 29 +++ src/initialize.cpp | 9 + src/material.cpp | 4 +- src/mgxs.cpp | 8 +- src/particle.cpp | 7 +- src/physics.cpp | 4 +- src/tallies/tally_scoring.cpp | 33 ++-- tests/regression_tests/cpp_driver/driver.cpp | 18 +- .../cpp_driver/results_true.dat | 22 +-- .../regression_tests/dagmc/external/main.cpp | 3 + .../lattice_distribrho/__init__.py | 0 .../lattice_distribrho/inputs_true.dat | 40 ++++ .../lattice_distribrho/results_true.dat | 2 + .../lattice_distribrho/test.py | 51 +++++ .../multipole/results_true.dat | 1 + tests/unit_tests/test_cell.py | 23 +++ tests/unit_tests/test_lib.py | 23 +++ tests/unit_tests/test_model.py | 6 +- 32 files changed, 607 insertions(+), 52 deletions(-) create mode 100644 tests/regression_tests/lattice_distribrho/__init__.py create mode 100644 tests/regression_tests/lattice_distribrho/inputs_true.dat create mode 100644 tests/regression_tests/lattice_distribrho/results_true.dat create mode 100644 tests/regression_tests/lattice_distribrho/test.py diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index d9ac0d1e01..2583d51dff 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -84,6 +84,17 @@ Functions :return: Return status (negative if an error occurred) :rtype: int +.. c:function:: int openmc_cell_get_density(int32_t index, const int32_t* instance, double* density) + + Get the density of a cell + + :param int32_t index: Index in the cells array + :param int32_t* instance: Which instance of the cell. If a null pointer is passed, the density + multiplier of the first instance is returned. + :param double* density: Density of the cell in [g/cm3] + :return: Return status (negative if an error occurred) + :rtype: int + .. c:function:: int openmc_cell_set_fill(int32_t index, int type, int32_t n, const int32_t* indices) Set the fill for a cell @@ -113,8 +124,22 @@ Functions :param double T: Temperature in Kelvin :param instance: Which instance of the cell. To set the temperature for all instances, pass a null pointer. - :param set_contained: If the cell is not filled by a material, whether to set the temperatures - of all filled cells + :param bool set_contained: If the cell is not filled by a material, whether + to set the temperatures of all filled cells + :type instance: const int32_t* + :return: Return status (negative if an error occurred) + :rtype: int + +.. c:function:: int openmc_cell_set_density(index index, double density, const int32_t* instance, bool set_contained) + + Set the density of a cell. + + :param int32_t index: Index in the cells array + :param double density: Density of the cell in [g/cm3] + :param instance: Which instance of the cell. To set the density multiplier for all + instances, pass a null pointer. + :param bool set_contained: If the cell is not filled by a material, whether + to set the density multiplier of all filled cells :type instance: const int32_t* :return: Return status (negative if an error occurred) :rtype: int diff --git a/docs/source/io_formats/properties.rst b/docs/source/io_formats/properties.rst index 5030e78f35..4cc5da379b 100644 --- a/docs/source/io_formats/properties.rst +++ b/docs/source/io_formats/properties.rst @@ -4,7 +4,7 @@ Properties File Format ====================== -The current version of the properties file format is 1.0. +The current version of the properties file format is 1.1. **/** @@ -25,6 +25,7 @@ The current version of the properties file format is 1.0. **/geometry/cells/cell /** :Datasets: - **temperature** (*double[]*) -- Temperature of the cell in [K]. + - **density** (*double[]*) -- Density of the cell in [g/cm3]. **/materials/** diff --git a/docs/source/io_formats/summary.rst b/docs/source/io_formats/summary.rst index 7d3ab94d9f..64ca68b9c3 100644 --- a/docs/source/io_formats/summary.rst +++ b/docs/source/io_formats/summary.rst @@ -4,7 +4,7 @@ Summary File Format =================== -The current version of the summary file format is 6.0. +The current version of the summary file format is 6.1. **/** @@ -38,6 +38,7 @@ The current version of the summary file format is 6.0. is an array if the cell uses distributed materials, otherwise it is a scalar. - **temperature** (*double[]*) -- Temperature of the cell in Kelvin. + - **density** (*double[]*) -- Density of the cell in [g/cm3]. - **translation** (*double[3]*) -- Translation applied to the fill universe. This dataset is present only if fill_type is set to 'universe'. diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 54257d0938..d8041ef414 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -17,6 +17,8 @@ int openmc_cell_get_fill( int openmc_cell_get_id(int32_t index, int32_t* id); int openmc_cell_get_temperature( int32_t index, const int32_t* instance, double* T); +int openmc_cell_get_density( + int32_t index, const int32_t* instance, double* rho); int openmc_cell_get_translation(int32_t index, double xyz[]); int openmc_cell_get_rotation(int32_t index, double rot[], size_t* n); int openmc_cell_get_name(int32_t index, const char** name); @@ -27,6 +29,8 @@ int openmc_cell_set_fill( int openmc_cell_set_id(int32_t index, int32_t id); int openmc_cell_set_temperature( int32_t index, double T, const int32_t* instance, bool set_contained = false); +int openmc_cell_set_density(int32_t index, double rho, const int32_t* instance, + bool set_contained = false); int openmc_cell_set_translation(int32_t index, const double xyz[]); int openmc_cell_set_rotation(int32_t index, const double rot[], size_t rot_len); int openmc_dagmc_universe_get_cell_ids( diff --git a/include/openmc/cell.h b/include/openmc/cell.h index e9fcfe3911..9dfe2339ab 100644 --- a/include/openmc/cell.h +++ b/include/openmc/cell.h @@ -216,6 +216,18 @@ public: //! \return Temperature in [K] double temperature(int32_t instance = -1) const; + //! Get the density multiplier of a cell instance + //! \param[in] instance Instance index. If -1 is given, the density multiplier + //! for the first instance is returned. + //! \return Density multiplier + double density_mult(int32_t instance = -1) const; + + //! Get the density of a cell instance in g/cm3 + //! \param[in] instance Instance index. If -1 is given, the density + //! for the first instance is returned. + //! \return Density in [g/cm3] + double density(int32_t instance = -1) const; + //! Set the temperature of a cell instance //! \param[in] T Temperature in [K] //! \param[in] instance Instance index. If -1 is given, the temperature for @@ -226,6 +238,16 @@ public: void set_temperature( double T, int32_t instance = -1, bool set_contained = false); + //! Set the density of a cell instance + //! \param[in] density Density [g/cm3] + //! \param[in] instance Instance index. If -1 is given, the density + //! for all instances is set. + //! \param[in] set_contained If this cell is not filled with a material, + //! collect all contained cells with material fills and set their + //! densities. + void set_density( + double density, int32_t instance = -1, bool set_contained = false); + int32_t n_instances() const; //! Set the rotation matrix of a cell instance @@ -334,6 +356,9 @@ public: //! T. The units are sqrt(eV). vector sqrtkT_; + //! \brief Unitless density multiplier(s) within this cell. + vector density_mult_; + //! \brief Neighboring cells in the same universe. NeighborList neighbors_; diff --git a/include/openmc/constants.h b/include/openmc/constants.h index ae70560795..df13da3707 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -28,11 +28,11 @@ constexpr int HDF5_VERSION[] {3, 0}; constexpr array VERSION_STATEPOINT {18, 1}; constexpr array VERSION_PARTICLE_RESTART {2, 0}; constexpr array VERSION_TRACK {3, 0}; -constexpr array VERSION_SUMMARY {6, 0}; +constexpr array VERSION_SUMMARY {6, 1}; constexpr array VERSION_VOLUME {1, 0}; constexpr array VERSION_VOXEL {2, 0}; constexpr array VERSION_MGXS_LIBRARY {1, 0}; -constexpr array VERSION_PROPERTIES {1, 0}; +constexpr array VERSION_PROPERTIES {1, 1}; constexpr array VERSION_WEIGHT_WINDOWS {1, 0}; // ============================================================================ diff --git a/include/openmc/geometry_aux.h b/include/openmc/geometry_aux.h index f60f2d649e..4dafdea5c2 100644 --- a/include/openmc/geometry_aux.h +++ b/include/openmc/geometry_aux.h @@ -37,6 +37,12 @@ void adjust_indices(); void assign_temperatures(); +//============================================================================== +//! Finalize densities (compute density multipliers). +//============================================================================== + +void finalize_cell_densities(); + //============================================================================== //! \brief Obtain a list of temperatures that each nuclide/thermal scattering //! table appears at in the model. Later, this list is used to determine the diff --git a/include/openmc/material.h b/include/openmc/material.h index fe587a86f9..e36946c71b 100644 --- a/include/openmc/material.h +++ b/include/openmc/material.h @@ -99,6 +99,13 @@ public: //---------------------------------------------------------------------------- // Accessors + //! Get the atom density in [atom/b-cm] + //! \return Density in [atom/b-cm] + double atom_density(int32_t i, double rho_multiplier = 1.0) const + { + return atom_density_(i) * rho_multiplier; + } + //! Get density in [atom/b-cm] //! \return Density in [atom/b-cm] double density() const { return density_; } diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index ec393845f8..1a22f58379 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -389,6 +389,11 @@ public: const double& sqrtkT() const { return sqrtkT_; } double& sqrtkT_last() { return sqrtkT_last_; } + // density multiplier of the current and last cell + double& density_mult() { return density_mult_; } + const double& density_mult() const { return density_mult_; } + double& density_mult_last() { return density_mult_last_; } + private: int64_t id_ {-1}; //!< Unique ID @@ -417,6 +422,9 @@ private: double sqrtkT_ {-1.0}; //!< sqrt(k_Boltzmann * temperature) in eV double sqrtkT_last_ {0.0}; //!< last temperature + double density_mult_ {1.0}; //!< density multiplier + double density_mult_last_ {1.0}; //!< last density multiplier + #ifdef OPENMC_DAGMC_ENABLED moab::DagMC::RayHistory history_; Direction last_dir_; diff --git a/openmc/cell.py b/openmc/cell.py index 88aaebc8f2..82a034b1c8 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -72,6 +72,10 @@ class Cell(IDManagerMixin): temperature : float or iterable of float Temperature of the cell in Kelvin. Multiple temperatures can be given to give each distributed cell instance a unique temperature. + density : float or iterable of float + Density of the cell in [g/cm3]. Multiple densities can be given to give + each distributed cell instance a unique density. Densities set here will + override the density set on materials used to fill the cell. translation : Iterable of float If the cell is filled with a universe, this array specifies a vector that is used to translate (shift) the universe. @@ -109,6 +113,7 @@ class Cell(IDManagerMixin): self._rotation = None self._rotation_matrix = None self._temperature = None + self._density = None self._translation = None self._paths = None self._num_instances = None @@ -141,6 +146,7 @@ class Cell(IDManagerMixin): if self.fill_type == 'material': string += '\t{0: <15}=\t{1}\n'.format('Temperature', self.temperature) + string += '\t{0: <15}=\t{1}\n'.format('Density', self.density) string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation) string += '{: <16}=\t{}\n'.format('\tVolume', self.volume) @@ -257,6 +263,30 @@ class Cell(IDManagerMixin): else: self._temperature = temperature + @property + def density(self): + return self._density + + @density.setter + def density(self, density): + # Make sure densities are greater than zero + cv.check_type('cell density', density, (Iterable, Real), none_ok=True) + if isinstance(density, Iterable): + cv.check_type('cell density', density, Iterable, Real) + for rho in density: + cv.check_greater_than('cell density', rho, 0.0, True) + elif isinstance(density, Real): + cv.check_greater_than('cell density', density, 0.0, True) + + # If this cell is filled with a universe or lattice, propagate + # densities to all cells contained. Otherwise, simply assign it. + if self.fill_type in ('universe', 'lattice'): + for c in self.get_all_cells().values(): + if c.fill_type == 'material': + c._density = density + else: + self._density = density + @property def translation(self): return self._translation @@ -525,6 +555,8 @@ class Cell(IDManagerMixin): clone.volume = self.volume if self.temperature is not None: clone.temperature = self.temperature + if self.density is not None: + clone.density = self.density if self.translation is not None: clone.translation = self.translation if self.rotation is not None: @@ -650,6 +682,12 @@ class Cell(IDManagerMixin): else: element.set("temperature", str(self.temperature)) + if self.density is not None: + if isinstance(self.density, Iterable): + element.set("density", ' '.join(str(t) for t in self.density)) + else: + element.set("density", str(self.density)) + if self.translation is not None: element.set("translation", ' '.join(map(str, self.translation))) @@ -711,10 +749,13 @@ class Cell(IDManagerMixin): c.temperature = temperature else: c.temperature = temperature[0] + density = get_elem_list(elem, 'density', float) + if density is not None: + c.density = density if len(density) > 1 else density[0] v = get_text(elem, 'volume') if v is not None: c.volume = float(v) - for key in ('temperature', 'rotation', 'translation'): + for key in ('temperature', 'density', 'rotation', 'translation'): values = get_elem_list(elem, key, float) if values is not None: if key == 'rotation' and len(values) == 9: diff --git a/openmc/lib/cell.py b/openmc/lib/cell.py index 971a24cba9..dfd09d2f9c 100644 --- a/openmc/lib/cell.py +++ b/openmc/lib/cell.py @@ -34,6 +34,10 @@ _dll.openmc_cell_get_temperature.argtypes = [ c_int32, POINTER(c_int32), POINTER(c_double)] _dll.openmc_cell_get_temperature.restype = c_int _dll.openmc_cell_get_temperature.errcheck = _error_handler +_dll.openmc_cell_get_density.argtypes = [ + c_int32, POINTER(c_int32), POINTER(c_double)] +_dll.openmc_cell_get_density.restype = c_int +_dll.openmc_cell_get_density.errcheck = _error_handler _dll.openmc_cell_get_name.argtypes = [c_int32, POINTER(c_char_p)] _dll.openmc_cell_get_name.restype = c_int _dll.openmc_cell_get_name.errcheck = _error_handler @@ -58,6 +62,10 @@ _dll.openmc_cell_set_temperature.argtypes = [ c_int32, c_double, POINTER(c_int32), c_bool] _dll.openmc_cell_set_temperature.restype = c_int _dll.openmc_cell_set_temperature.errcheck = _error_handler +_dll.openmc_cell_set_density.argtypes = [ + c_int32, c_double, POINTER(c_int32), c_bool] +_dll.openmc_cell_set_density.restype = c_int +_dll.openmc_cell_set_density.errcheck = _error_handler _dll.openmc_cell_set_translation.argtypes = [c_int32, POINTER(c_double)] _dll.openmc_cell_set_translation.restype = c_int _dll.openmc_cell_set_translation.errcheck = _error_handler @@ -236,6 +244,44 @@ class Cell(_FortranObjectWithID): _dll.openmc_cell_set_temperature(self._index, T, instance, set_contained) + def get_density(self, instance: int | None = None): + """Get the density of a cell in [g/cm3] + + Parameters + ---------- + instance : int or None + Which instance of the cell + + """ + + if instance is not None: + instance = c_int32(instance) + + rho = c_double() + _dll.openmc_cell_get_density(self._index, instance, rho) + return rho.value + + def set_density(self, rho: float, instance: int | None = None, + set_contained: bool = False): + """Set the density of a cell + + Parameters + ---------- + rho : float + Density of the cell in [g/cm3] + instance : int or None + Which instance of the cell + set_contained : bool + If cell is not filled by a material, whether to set the density + of all filled cells + + """ + + if instance is not None: + instance = c_int32(instance) + + _dll.openmc_cell_set_density(self._index, rho, instance, set_contained) + @property def translation(self): translation = np.zeros(3) diff --git a/openmc/model/model.py b/openmc/model/model.py index 03fdcda1fc..59e6fa511e 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -633,7 +633,7 @@ class Model: raise ValueError("Number of cells in properties file doesn't " "match current model.") - # Update temperatures for cells filled with materials + # Update temperatures and densities for cells filled with materials for name, group in cells_group.items(): cell_id = int(name.split()[1]) cell = cells[cell_id] @@ -648,6 +648,20 @@ class Model: else: lib_cell.set_temperature(temperature[0]) + if group['density']: + density = group['density'][()] + if density.size > 1: + cell.density = [rho for rho in density] + else: + cell.density = density + if self.is_initialized: + lib_cell = openmc.lib.cells[cell_id] + if density.size > 1: + for i, rho in enumerate(density): + lib_cell.set_density(rho, i) + else: + lib_cell.set_density(density[0]) + # Make sure number of materials matches mats_group = fh['materials'] n_cells = mats_group.attrs['n_materials'] diff --git a/src/cell.cpp b/src/cell.cpp index d838bfbb4d..e2479994a6 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -101,6 +101,25 @@ double Cell::temperature(int32_t instance) const } } +double Cell::density_mult(int32_t instance) const +{ + if (instance >= 0) { + return density_mult_.size() == 1 ? density_mult_.at(0) + : density_mult_.at(instance); + } else { + return density_mult_[0]; + } +} + +double Cell::density(int32_t instance) const +{ + const int32_t mat_index = material(instance); + if (mat_index == MATERIAL_VOID) + return 0.0; + + return density_mult(instance) * model::materials[mat_index]->density_gpcc(); +} + void Cell::set_temperature(double T, int32_t instance, bool set_contained) { if (settings::temperature_method == TemperatureMethod::INTERPOLATION) { @@ -151,6 +170,47 @@ void Cell::set_temperature(double T, int32_t instance, bool set_contained) } } +void Cell::set_density(double density, int32_t instance, bool set_contained) +{ + if (type_ != Fill::MATERIAL && !set_contained) { + fatal_error( + fmt::format("Attempted to set the density multiplier of cell {} " + "which is not filled by a material.", + id_)); + } + + if (type_ == Fill::MATERIAL) { + const int32_t mat_index = material(instance); + if (mat_index == MATERIAL_VOID) + return; + + if (instance >= 0) { + // If density multiplier vector is not big enough, resize it first + if (density_mult_.size() != n_instances()) + density_mult_.resize(n_instances(), density_mult_[0]); + + // Set density multiplier for the corresponding instance + density_mult_.at(instance) = + density / model::materials[mat_index]->density_gpcc(); + } else { + // Set density multiplier for all instances + for (auto& x : density_mult_) { + x = density / model::materials[mat_index]->density_gpcc(); + } + } + } else { + auto contained_cells = this->get_contained_cells(instance); + for (const auto& entry : contained_cells) { + auto& cell = model::cells[entry.first]; + assert(cell->type_ == Fill::MATERIAL); + auto& instances = entry.second; + for (auto instance : instances) { + cell->set_density(density, instance); + } + } + } +} + void Cell::export_properties_hdf5(hid_t group) const { // Create a group for this cell. @@ -162,6 +222,15 @@ void Cell::export_properties_hdf5(hid_t group) const temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN); write_dataset(cell_group, "temperature", temps); + // Write density for one or more cell instances + if (type_ == Fill::MATERIAL && material_.size() > 0) { + vector density; + for (int32_t i = 0; i < density_mult_.size(); ++i) + density.push_back(this->density(i)); + + write_dataset(cell_group, "density", density); + } + close_group(cell_group); } @@ -176,7 +245,7 @@ void Cell::import_properties_hdf5(hid_t group) // Ensure number of temperatures makes sense auto n_temps = temps.size(); if (n_temps > 1 && n_temps != n_instances()) { - throw std::runtime_error(fmt::format( + fatal_error(fmt::format( "Number of temperatures for cell {} doesn't match number of instances", id_)); } @@ -188,6 +257,25 @@ void Cell::import_properties_hdf5(hid_t group) this->set_temperature(temps[i], i); } + // Read densities + if (object_exists(cell_group, "density")) { + vector density; + read_dataset(cell_group, "density", density); + + // Ensure number of densities makes sense + auto n_density = density.size(); + if (n_density > 1 && n_density != n_instances()) { + fatal_error(fmt::format("Number of densities for cell {} " + "doesn't match number of instances", + id_)); + } + + // Set densities. + for (int32_t i = 0; i < n_density; ++i) { + this->set_density(density[i], i); + } + } + close_group(cell_group); } @@ -227,6 +315,8 @@ void Cell::to_hdf5(hid_t cell_group) const temps.push_back(sqrtkT_val * sqrtkT_val / K_BOLTZMANN); write_dataset(group, "temperature", temps); + write_dataset(group, "density_mult", density_mult_); + } else if (type_ == Fill::UNIVERSE) { write_dataset(group, "fill_type", "universe"); write_dataset(group, "fill", model::universes[fill_]->id_); @@ -344,6 +434,44 @@ CSGCell::CSGCell(pugi::xml_node cell_node) } } + // Read the density element which can be distributed similar to temperature. + // These get assigned to the density multiplier, requiring a division by + // the material density. + // Note: calculating the actual density multiplier is deferred until materials + // are finalized. density_mult_ contains the true density in the meantime. + if (check_for_node(cell_node, "density")) { + density_mult_ = get_node_array(cell_node, "density"); + density_mult_.shrink_to_fit(); + + // Make sure this is a material-filled cell. + if (material_.size() == 0) { + fatal_error(fmt::format( + "Cell {} was specified with a density but no material. Density" + "specification is only valid for cells filled with a material.", + id_)); + } + + // Make sure this is a non-void material. + for (auto mat_id : material_) { + if (mat_id == MATERIAL_VOID) { + fatal_error(fmt::format( + "Cell {} was specified with a density, but contains a void " + "material. Density specification is only valid for cells " + "filled with a non-void material.", + id_)); + } + } + + // Make sure all densities are non-negative and greater than zero. + for (auto rho : density_mult_) { + if (rho <= 0) { + fatal_error(fmt::format( + "Cell {} was specified with a density less than or equal to zero", + id_)); + } + } + } + // Read the region specification. std::string region_spec; if (check_for_node(cell_node, "region")) { @@ -1129,6 +1257,24 @@ extern "C" int openmc_cell_set_temperature( return 0; } +extern "C" int openmc_cell_set_density( + int32_t index, double density, const int32_t* instance, bool set_contained) +{ + if (index < 0 || index >= model::cells.size()) { + strcpy(openmc_err_msg, "Index in cells array is out of bounds."); + return OPENMC_E_OUT_OF_BOUNDS; + } + + int32_t instance_index = instance ? *instance : -1; + try { + model::cells[index]->set_density(density, instance_index, set_contained); + } catch (const std::exception& e) { + set_errmsg(e.what()); + return OPENMC_E_UNASSIGNED; + } + return 0; +} + extern "C" int openmc_cell_get_temperature( int32_t index, const int32_t* instance, double* T) { @@ -1147,6 +1293,36 @@ extern "C" int openmc_cell_get_temperature( return 0; } +extern "C" int openmc_cell_get_density( + int32_t index, const int32_t* instance, double* density) +{ + if (index < 0 || index >= model::cells.size()) { + strcpy(openmc_err_msg, "Index in cells array is out of bounds."); + return OPENMC_E_OUT_OF_BOUNDS; + } + + int32_t instance_index = instance ? *instance : -1; + try { + if (model::cells[index]->type_ != Fill::MATERIAL) { + fatal_error( + fmt::format("Cell {}, instance {} is not filled with a material.", + model::cells[index]->id_, instance_index)); + } + + int32_t mat_index = model::cells[index]->material(instance_index); + if (mat_index == MATERIAL_VOID) { + *density = 0.0; + } else { + *density = model::cells[index]->density_mult(instance_index) * + model::materials[mat_index]->density_gpcc(); + } + } catch (const std::exception& e) { + set_errmsg(e.what()); + return OPENMC_E_UNASSIGNED; + } + return 0; +} + //! Get the bounding box of a cell extern "C" int openmc_cell_bounding_box( const int32_t index, double* llc, double* urc) diff --git a/src/geometry.cpp b/src/geometry.cpp index df48508916..5ff15097b1 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -172,11 +172,13 @@ bool find_cell_inner( p.cell_instance() = cell_instance_at_level(p, p.n_coord() - 1); } - // Set the material and temperature. + // Set the material, temperature and density multiplier. p.material_last() = p.material(); p.material() = c.material(p.cell_instance()); p.sqrtkT_last() = p.sqrtkT(); p.sqrtkT() = c.sqrtkT(p.cell_instance()); + p.density_mult_last() = p.density_mult(); + p.density_mult() = c.density_mult(p.cell_instance()); return true; diff --git a/src/geometry_aux.cpp b/src/geometry_aux.cpp index 51732cf8b9..8a145fb1f1 100644 --- a/src/geometry_aux.cpp +++ b/src/geometry_aux.cpp @@ -195,6 +195,24 @@ void assign_temperatures() //============================================================================== +void finalize_cell_densities() +{ + for (auto& c : model::cells) { + // Convert to density multipliers. + if (!c->density_mult_.empty()) { + for (int32_t instance = 0; instance < c->density_mult_.size(); + ++instance) { + c->density_mult_[instance] /= + model::materials[c->material(instance)]->density_gpcc(); + } + } else { + c->density_mult_ = {1.0}; + } + } +} + +//============================================================================== + void get_temperatures( vector>& nuc_temps, vector>& thermal_temps) { @@ -362,6 +380,17 @@ void prepare_distribcell(const std::vector* user_distribcells) c.id_, c.sqrtkT_.size(), c.n_instances())); } } + + if (c.density_mult_.size() > 1) { + if (c.density_mult_.size() != c.n_instances()) { + fatal_error(fmt::format("Cell {} was specified with {} density " + "multipliers but has {} distributed " + "instances. The number of density multipliers " + "must equal one or the number " + "of instances.", + c.id_, c.density_mult_.size(), c.n_instances())); + } + } } // Search through universes for material cells and assign each one a diff --git a/src/initialize.cpp b/src/initialize.cpp index 2da78137d1..36f3261169 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -401,6 +401,10 @@ bool read_model_xml() // Finalize cross sections having assigned temperatures finalize_cross_sections(); + // Compute cell density multipliers now that material densities + // have been finalized (from geometry_aux.h) + finalize_cell_densities(); + if (check_for_node(root, "tallies")) read_tallies_xml(root.child("tallies")); @@ -441,6 +445,11 @@ void read_separate_xml_files() // Finalize cross sections having assigned temperatures finalize_cross_sections(); + + // Compute cell density multipliers now that material densities + // have been finalized (from geometry_aux.h) + finalize_cell_densities(); + read_tallies_xml(); // Initialize distribcell_filters diff --git a/src/material.cpp b/src/material.cpp index 32384ddf12..54caa38409 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -890,7 +890,7 @@ void Material::calculate_neutron_xs(Particle& p) const // ADD TO MACROSCOPIC CROSS SECTION // Copy atom density of nuclide in material - double atom_density = atom_density_(i); + double atom_density = this->atom_density(i, p.density_mult()); // Add contributions to cross sections p.macro_xs().total += atom_density * micro.total; @@ -925,7 +925,7 @@ void Material::calculate_photon_xs(Particle& p) const // ADD TO MACROSCOPIC CROSS SECTION // Copy atom density of nuclide in material - double atom_density = atom_density_(i); + double atom_density = this->atom_density(i, p.density_mult()); // Add contributions to material macroscopic cross sections p.macro_xs().total += atom_density * micro.total; diff --git a/src/mgxs.cpp b/src/mgxs.cpp index a88d2c196b..a2c479f215 100644 --- a/src/mgxs.cpp +++ b/src/mgxs.cpp @@ -617,10 +617,12 @@ void Mgxs::calculate_xs(Particle& p) } int temperature = p.mg_xs_cache().t; int angle = p.mg_xs_cache().a; - p.macro_xs().total = xs[temperature].total(angle, p.g()); - p.macro_xs().absorption = xs[temperature].absorption(angle, p.g()); + p.macro_xs().total = xs[temperature].total(angle, p.g()) * p.density_mult(); + p.macro_xs().absorption = + xs[temperature].absorption(angle, p.g()) * p.density_mult(); p.macro_xs().nu_fission = - fissionable ? xs[temperature].nu_fission(angle, p.g()) : 0.; + fissionable ? xs[temperature].nu_fission(angle, p.g()) * p.density_mult() + : 0.; } //============================================================================== diff --git a/src/particle.cpp b/src/particle.cpp index f25ada02c8..f5ad45d80f 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -200,7 +200,8 @@ void Particle::event_calculate_xs() // Calculate microscopic and macroscopic cross sections if (material() != MATERIAL_VOID) { if (settings::run_CE) { - if (material() != material_last() || sqrtkT() != sqrtkT_last()) { + if (material() != material_last() || sqrtkT() != sqrtkT_last() || + density_mult() != density_mult_last()) { // If the material is the same as the last material and the // temperature hasn't changed, we don't need to lookup cross // sections again. @@ -564,9 +565,10 @@ void Particle::cross_surface(const Surface& surf) int32_t i_cell = next_cell(surface_index(), cell_last(n_coord() - 1), lowest_coord().universe()) - 1; - // save material and temp + // save material, temperature, and density multiplier material_last() = material(); sqrtkT_last() = sqrtkT(); + density_mult_last() = density_mult(); // set new cell value lowest_coord().cell() = i_cell; auto& cell = model::cells[i_cell]; @@ -577,6 +579,7 @@ void Particle::cross_surface(const Surface& surf) material() = cell->material(cell_instance()); sqrtkT() = cell->sqrtkT(cell_instance()); + density_mult() = cell->density_mult(cell_instance()); return; } #endif diff --git a/src/physics.cpp b/src/physics.cpp index 3c06e543de..8ad1b99d75 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -496,7 +496,7 @@ int sample_nuclide(Particle& p) for (int i = 0; i < n; ++i) { // Get atom density int i_nuclide = mat->nuclide_[i]; - double atom_density = mat->atom_density_[i]; + double atom_density = mat->atom_density(i, p.density_mult()); // Increment probability to compare to cutoff prob += atom_density * p.neutron_xs(i_nuclide).total; @@ -521,7 +521,7 @@ int sample_element(Particle& p) for (int i = 0; i < mat->element_.size(); ++i) { // Find atom density int i_element = mat->element_[i]; - double atom_density = mat->atom_density_[i]; + double atom_density = mat->atom_density(i, p.density_mult()); // Determine microscopic cross section double sigma = atom_density * p.photon_xs(i_element).total; diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index 04b047b649..f078a5c6e5 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -233,7 +233,7 @@ double score_fission_q(const Particle& p, int score_bin, const Tally& tally, 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); + auto atom_density = material.atom_density(i, p.density_mult()); const Nuclide& nuc {*data::nuclides[j_nuclide]}; score += get_nuc_fission_q(nuc, p, score_bin) * atom_density * p.neutron_xs(j_nuclide).fission; @@ -696,7 +696,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); score += p.neutron_xs(j_nuclide).fission * data::nuclides[j_nuclide]->nu( E, ReactionProduct::EmissionMode::prompt) * @@ -743,7 +743,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); // Tally each delayed group bin individually for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { auto d = filt.groups()[d_bin]; @@ -763,7 +763,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); score += p.neutron_xs(j_nuclide).fission * data::nuclides[j_nuclide]->nu( E, ReactionProduct::EmissionMode::delayed) * @@ -824,7 +824,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); const auto& nuc {*data::nuclides[j_nuclide]}; if (nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; @@ -849,7 +849,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); const auto& nuc {*data::nuclides[j_nuclide]}; if (nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; @@ -893,7 +893,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); const auto& nuc {*data::nuclides[j_nuclide]}; if (nuc.fissionable_) { const auto& rxn {*nuc.fission_rx_[0]}; @@ -924,7 +924,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); if (p.neutron_xs(j_nuclide).elastic == CACHE_INVALID) data::nuclides[j_nuclide]->calculate_elastic_xs(p); score += p.neutron_xs(j_nuclide).elastic * atom_density * flux; @@ -1025,7 +1025,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); score += p.neutron_xs(j_nuclide).reaction[m] * atom_density * flux; } } @@ -1079,7 +1079,7 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, 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); + auto atom_density = material.atom_density(i, p.density_mult()); score += get_nuclide_xs(p, j_nuclide, score_bin) * atom_density * flux; } @@ -2383,7 +2383,8 @@ void score_analog_tally_mg(Particle& p) model::materials[p.material()]->mat_nuclide_index_[i_nuclide]; if (j == C_NONE) continue; - atom_density = model::materials[p.material()]->atom_density_(j); + atom_density = + model::materials[p.material()]->atom_density(j, p.density_mult()); } score_general_mg(p, i_tally, i * tally.scores_.size(), filter_index, @@ -2449,8 +2450,9 @@ void score_tracklength_tally_general( atom_density = 1.0; } } else { - atom_density = - tally.multiply_density() ? mat->atom_density_(j) : 1.0; + atom_density = tally.multiply_density() + ? mat->atom_density(j, p.density_mult()) + : 1.0; } } } @@ -2579,8 +2581,9 @@ void score_collision_tally(Particle& p) atom_density = 1.0; } } else { - atom_density = - tally.multiply_density() ? mat->atom_density_(j) : 1.0; + atom_density = tally.multiply_density() + ? mat->atom_density(j, p.density_mult()) + : 1.0; } } diff --git a/tests/regression_tests/cpp_driver/driver.cpp b/tests/regression_tests/cpp_driver/driver.cpp index 48ed7f3171..a99c97b64e 100644 --- a/tests/regression_tests/cpp_driver/driver.cpp +++ b/tests/regression_tests/cpp_driver/driver.cpp @@ -15,14 +15,16 @@ using namespace openmc; -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ #ifdef OPENMC_MPI MPI_Comm world {MPI_COMM_WORLD}; int err = openmc_init(argc, argv, &world); #else int err = openmc_init(argc, argv, nullptr); #endif - if (err) fatal_error(openmc_err_msg); + if (err) + fatal_error(openmc_err_msg); // create a new cell filter auto cell_filter = Filter::create(); @@ -30,7 +32,7 @@ int main(int argc, char** argv) { // add all cells to the cell filter std::vector cell_indices; for (auto& entry : openmc::model::cell_map) { - cell_indices.push_back(entry.second); + cell_indices.push_back(entry.second); } // enable distribcells offsets for all cells prepare_distribcell(&cell_indices); @@ -39,7 +41,6 @@ int main(int argc, char** argv) { std::sort(cell_indices.begin(), cell_indices.end()); cell_filter->set_cells(cell_indices); - // create a new tally auto tally = Tally::create(); std::vector filters = {cell_filter}; @@ -60,14 +61,19 @@ int main(int argc, char** argv) { } } - // set a higher temperature for only one of the lattice cells (ID is 4 in the model) + // set a higher temperature for only one of the lattice cells (ID is 4 in the + // model) model::cells[model::cell_map[4]]->set_temperature(400.0, 3, true); + // set the density of another lattice cell to 2 + model::cells[model::cell_map[4]]->set_density(2.0, 2, true); + // the summary file will be used to check that // temperatures were set correctly so clear // error output can be provided #ifdef OPENMC_MPI - if (openmc::mpi::master) openmc::write_summary(); + if (openmc::mpi::master) + openmc::write_summary(); #else openmc::write_summary(); #endif diff --git a/tests/regression_tests/cpp_driver/results_true.dat b/tests/regression_tests/cpp_driver/results_true.dat index c2b0b8d6f3..26f07842cd 100644 --- a/tests/regression_tests/cpp_driver/results_true.dat +++ b/tests/regression_tests/cpp_driver/results_true.dat @@ -1,13 +1,13 @@ k-combined: -1.933305E+00 1.300360E-02 +1.953962E+00 1.828426E-02 tally 1: -9.552846E+01 -1.019358E+03 -2.887973E+01 -9.308509E+01 -9.732441E+01 -1.059022E+03 -2.217326E+02 -5.486892E+03 -2.217326E+02 -5.486892E+03 +9.607953E+01 +1.031898E+03 +2.853683E+01 +9.085469E+01 +9.745011E+01 +1.058928E+03 +2.220665E+02 +5.496813E+03 +2.220665E+02 +5.496813E+03 diff --git a/tests/regression_tests/dagmc/external/main.cpp b/tests/regression_tests/dagmc/external/main.cpp index 3765cf79ae..e78ab03fa2 100644 --- a/tests/regression_tests/dagmc/external/main.cpp +++ b/tests/regression_tests/dagmc/external/main.cpp @@ -100,6 +100,9 @@ int main(int argc, char* argv[]) } } + // Finalize cell densities + openmc::finalize_cell_densities(); + // Run OpenMC openmc_err = openmc_run(); if (openmc_err) diff --git a/tests/regression_tests/lattice_distribrho/__init__.py b/tests/regression_tests/lattice_distribrho/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/lattice_distribrho/inputs_true.dat b/tests/regression_tests/lattice_distribrho/inputs_true.dat new file mode 100644 index 0000000000..5031bea6e2 --- /dev/null +++ b/tests/regression_tests/lattice_distribrho/inputs_true.dat @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + 1.0 1.0 + 2 2 + -1.0 -1.0 + +1 1 +1 1 + + + + + + + + + eigenvalue + 1000 + 10 + 5 + + diff --git a/tests/regression_tests/lattice_distribrho/results_true.dat b/tests/regression_tests/lattice_distribrho/results_true.dat new file mode 100644 index 0000000000..d7094f4e37 --- /dev/null +++ b/tests/regression_tests/lattice_distribrho/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.904471E+00 5.255549E-03 diff --git a/tests/regression_tests/lattice_distribrho/test.py b/tests/regression_tests/lattice_distribrho/test.py new file mode 100644 index 0000000000..ec94fe96b8 --- /dev/null +++ b/tests/regression_tests/lattice_distribrho/test.py @@ -0,0 +1,51 @@ +import openmc +import pytest + +from tests.testing_harness import PyAPITestHarness + + +@pytest.fixture +def model(): + model = openmc.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) + pin = openmc.model.pin([cyl], [uo2, water]) + d = 1.0 + + lattice = openmc.RectLattice() + lattice.lower_left = (-d, -d) + lattice.pitch = (d, d) + lattice.universes = [[pin, pin], + [pin, pin]] + box = openmc.model.RectangularPrism( + 2.0 * d, 2.0 * d, + origin=(0.0, 0.0), + boundary_type='reflective' + ) + + pin.cells[1].density = [10.0, 20.0, 10.0, 20.0] + + model.geometry = openmc.Geometry([openmc.Cell(fill=lattice, region=-box)]) + model.geometry.merge_surfaces = True + + model.settings.batches = 10 + model.settings.inactive = 5 + model.settings.particles = 1000 + + return model + + +def test_lattice_checkerboard(model): + harness = PyAPITestHarness('statepoint.10.h5', model) + harness.main() diff --git a/tests/regression_tests/multipole/results_true.dat b/tests/regression_tests/multipole/results_true.dat index 8e82655ce5..8eb75b894b 100644 --- a/tests/regression_tests/multipole/results_true.dat +++ b/tests/regression_tests/multipole/results_true.dat @@ -38,5 +38,6 @@ Cell Region = -1 Rotation = None Temperature = [500. 700. 0. 800.] + Density = None Translation = None Volume = None diff --git a/tests/unit_tests/test_cell.py b/tests/unit_tests/test_cell.py index 95c8249bb3..60b2058186 100644 --- a/tests/unit_tests/test_cell.py +++ b/tests/unit_tests/test_cell.py @@ -126,6 +126,29 @@ def test_temperature(cell_with_lattice): c.temperature = (300., 600., 900.) +def test_densities(cell_with_lattice): + # Make sure density propagates through universes + m = openmc.Material() + s = openmc.XPlane() + c1 = openmc.Cell(fill=m, region=+s) + c2 = openmc.Cell(fill=m, region=-s) + u1 = openmc.Universe(cells=[c1, c2]) + c = openmc.Cell(fill=u1) + + c.density = 1. + assert c1.density == 1. + assert c2.density == 1. + with pytest.raises(ValueError): + c.density = -1. + c.density = None + assert c1.density == None + assert c2.density == None + + # distributed density + cells, _, _, _ = cell_with_lattice + c = cells[0] + c.density = (1., 2., 3.) + def test_rotation(): u = openmc.Universe() c = openmc.Cell(fill=u) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 8ab35335fc..8080ce8948 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -159,6 +159,29 @@ def test_properties_temperature(lib_init): assert cell.get_temperature() == pytest.approx(200.0) +def test_cell_density(lib_init): + cell = openmc.lib.cells[1] + cell.set_density(1.5, 0) + assert cell.get_density(0) == pytest.approx(1.5) + cell.set_density(2.0) + assert cell.get_density() == pytest.approx(2.0) + + +def test_properties_cell_density(lib_init): + # Cell density should be 2.0 from above test + cell = openmc.lib.cells[1] + assert cell.get_density() == pytest.approx(2.0) + + # Export properties and change density + openmc.lib.export_properties('properties.h5') + cell.set_density(3.0) + assert cell.get_density() == pytest.approx(3.0) + + # Import properties and check that density is restored + openmc.lib.import_properties('properties.h5') + assert cell.get_density() == pytest.approx(2.0) + + def test_new_cell(lib_init): with pytest.raises(exc.AllocationError): openmc.lib.Cell(1) diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 6e4dec00ff..12f0df6c9e 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -251,10 +251,11 @@ def test_import_properties(run_in_tmpdir, mpi_intracomm): model = openmc.examples.pwr_pin_cell() model.init_lib(output=False, intracomm=mpi_intracomm) - # Change fuel temperature and density and export properties + # Change cell fuel temperature, density, material density and export properties cell = openmc.lib.cells[1] cell.set_temperature(600.0) cell.fill.set_density(5.0, 'g/cm3') + cell.set_density(10.0) openmc.lib.export_properties(output=False) # Import properties to existing model @@ -264,9 +265,11 @@ def test_import_properties(run_in_tmpdir, mpi_intracomm): # First python cell = model.geometry.get_all_cells()[1] assert cell.temperature == [600.0] + assert cell.density == [pytest.approx(10.0, 1e-5)] assert cell.fill.get_mass_density() == pytest.approx(5.0) # Now C assert openmc.lib.cells[1].get_temperature() == 600. + assert openmc.lib.cells[1].get_density() == pytest.approx(10.0, 1e-5) assert openmc.lib.materials[1].get_density('g/cm3') == pytest.approx(5.0) # Clear the C API @@ -283,6 +286,7 @@ def test_import_properties(run_in_tmpdir, mpi_intracomm): ) cell = model_with_properties.geometry.get_all_cells()[1] assert cell.temperature == [600.0] + assert cell.density == [pytest.approx(10.0, 1e-5)] assert cell.fill.get_mass_density() == pytest.approx(5.0) From 007ac8148bcda4911edb0191df762fa7ef3c5b8e Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 18 Sep 2025 23:27:41 -0500 Subject: [PATCH 08/76] Allow newer Sphinx version and fix docbuild warnings (#3571) --- docs/source/conf.py | 2 -- openmc/deplete/abc.py | 9 +++++---- openmc/deplete/integrators.py | 1 - openmc/mgxs/mgxs.py | 5 +++-- openmc/plots.py | 6 ++++-- pyproject.toml | 4 ++-- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8aeff5cdc7..826c20022a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -121,9 +121,7 @@ pygments_style = 'tango' # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages -import sphinx_rtd_theme html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] html_baseurl = "https://docs.openmc.org/en/stable/" html_logo = '_images/openmc_logo.png' diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index e6d4c15127..c5a6219c7b 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -12,6 +12,7 @@ from copy import deepcopy from inspect import signature from numbers import Real, Integral from pathlib import Path +from textwrap import dedent import time from typing import Optional, Union, Sequence from warnings import warn @@ -526,7 +527,7 @@ class Integrator(ABC): r"""Abstract class for solving the time-integration for depletion """ - _params = r""" + _params = dedent(r""" Parameters ---------- operator : openmc.deplete.abc.TransportOperator @@ -617,7 +618,7 @@ class Integrator(ABC): .. versionadded:: 0.15.3 - """ + """) def __init__( self, @@ -1020,7 +1021,7 @@ class SIIntegrator(Integrator): the number of particles used in initial transport calculation """ - _params = r""" + _params = dedent(r""" Parameters ---------- operator : openmc.deplete.abc.TransportOperator @@ -1108,7 +1109,7 @@ class SIIntegrator(Integrator): .. versionadded:: 0.12 - """ + """) def __init__( self, diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py index 000cb2c41c..7c543a6cb8 100644 --- a/openmc/deplete/integrators.py +++ b/openmc/deplete/integrators.py @@ -22,7 +22,6 @@ class PredictorIntegrator(Integrator): .. math:: \mathbf{n}_{i+1} = \exp\left(h\mathbf{A}(\mathbf{n}_i) \right) \mathbf{n}_i - """ _num_stages = 1 diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 1bc7f93878..b8f2b8d3fb 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -2,6 +2,7 @@ import copy from numbers import Integral import os import warnings +from textwrap import dedent import h5py import numpy as np @@ -164,7 +165,7 @@ class MGXS: """ - _params = """ + _params = dedent(""" Parameters ---------- domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh @@ -251,7 +252,7 @@ class MGXS: .. versionadded:: 0.13.1 - """ + """) # Store whether or not the number density should be removed for microscopic # values of this data diff --git a/openmc/plots.py b/openmc/plots.py index 072a9a319e..e9130f0bea 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -1,6 +1,7 @@ from collections.abc import Iterable, Mapping from numbers import Integral, Real from pathlib import Path +from textwrap import dedent import h5py import lxml.etree as ET @@ -167,7 +168,8 @@ _SVG_COLORS = { 'yellowgreen': (154, 205, 50) } -_PLOT_PARAMS = """ +_PLOT_PARAMS = dedent("""\ + Parameters ---------- origin : iterable of float @@ -249,7 +251,7 @@ _PLOT_PARAMS = """ ------- matplotlib.axes.Axes Axes containing resulting image -""" +""") # Decorator for consistently adding plot parameters to docstrings (Model.plot, diff --git a/pyproject.toml b/pyproject.toml index 6e8ed798e7..7705de8dae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,12 +41,12 @@ dependencies = [ [project.optional-dependencies] depletion-mpi = ["mpi4py"] docs = [ - "sphinx==5.0.2", + "sphinx", "sphinxcontrib-katex", "sphinx-numfig", "jupyter", "sphinxcontrib-svg2pdfconverter", - "sphinx-rtd-theme==1.0.0" + "sphinx-rtd-theme" ] test = ["packaging", "pytest", "pytest-cov", "colorama", "openpyxl"] ci = ["cpp-coveralls", "coveralls"] From ecb0a3361f600594984b72ce37e33cd7650497b6 Mon Sep 17 00:00:00 2001 From: Ilham Variansyah Date: Fri, 19 Sep 2025 15:10:08 +0700 Subject: [PATCH 09/76] Combing for fission site sampling, and delayed neutron emission time (#2992) Co-authored-by: Gavin Ridley Co-authored-by: Paul Romano --- docs/source/methods/neutron_physics.rst | 19 +- examples/pincell_pulsed/run_pulse.py | 101 + include/openmc/settings.h | 1 + openmc/settings.py | 27 + src/eigenvalue.cpp | 106 +- src/finalize.cpp | 1 + src/physics.cpp | 20 +- src/physics_mg.cpp | 20 +- src/settings.cpp | 6 + src/tallies/tally_scoring.cpp | 3 +- .../adj_cell_rotation/results_true.dat | 2 +- .../albedo_box/results_true.dat | 2 +- .../asymmetric_lattice/results_true.dat | 2 +- .../cmfd_feed/results_true.dat | 612 +-- .../cmfd_feed_2g/results_true.dat | 538 +-- .../results_true.dat | 562 +-- .../cmfd_feed_ng/results_true.dat | 680 ++-- .../cmfd_feed_rectlin/results_true.dat | 778 ++-- .../cmfd_feed_ref_d/results_true.dat | 562 +-- .../cmfd_feed_rolling_window/results_true.dat | 562 +-- .../cmfd_nofeed/results_true.dat | 610 +-- .../cmfd_restart/results_true.dat | 612 +-- .../complex_cell/results_true.dat | 16 +- .../confidence_intervals/results_true.dat | 6 +- .../cpp_driver/results_true.dat | 22 +- .../dagmc/external/results_true.dat | 6 +- .../dagmc/legacy/results_true.dat | 6 +- .../dagmc/refl/results_true.dat | 6 +- .../dagmc/universes/inputs_true.dat | 8 + .../dagmc/universes/results_true.dat | 18 +- .../regression_tests/dagmc/universes/test.py | 134 +- .../regression_tests/density/results_true.dat | 2 +- .../test_reference_coupled_days.h5 | Bin 36048 -> 36048 bytes .../test_reference_coupled_hours.h5 | Bin 36048 -> 36048 bytes .../test_reference_coupled_minutes.h5 | Bin 36048 -> 36048 bytes .../test_reference_coupled_months.h5 | Bin 36048 -> 36048 bytes .../test_reference_fission_q.h5 | Bin 36048 -> 36048 bytes .../test_reference_source_rate.h5 | Bin 36048 -> 36048 bytes .../ref_depletion_with_ext_source.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_feed.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_removal.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_transfer.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_only_feed.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_only_removal.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_with_ext_source.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_with_transfer.h5 | Bin 37328 -> 37328 bytes .../deplete_with_transfer_rates/test.py | 3 +- .../last_step_reference_materials.xml | 1280 +++---- .../deplete_with_transport/test_reference.h5 | Bin 163736 -> 163736 bytes .../diff_tally/results_true.dat | 220 +- .../distribmat/results_true.dat | 2 +- .../eigenvalue_genperbatch/results_true.dat | 6 +- .../eigenvalue_no_inactive/results_true.dat | 2 +- .../energy_grid/results_true.dat | 2 +- .../energy_laws/results_true.dat | 2 +- .../regression_tests/entropy/results_true.dat | 20 +- .../filter_cellfrom/results_true.dat | 62 +- .../filter_cellinstance/results_true.dat | 162 +- .../case-3/results_true.dat | 2 +- .../case-4/results_true.dat | 6 +- .../filter_energyfun/results_true.dat | 10 +- .../filter_mesh/results_true.dat | 2 +- .../filter_musurface/results_true.dat | 10 +- .../filter_translations/results_true.dat | 674 ++-- tests/regression_tests/ifp/results_true.dat | 14 +- .../infinite_cell/results_true.dat | 2 +- .../iso_in_lab/results_true.dat | 2 +- .../regression_tests/lattice/results_true.dat | 2 +- .../lattice_distribmat/False/results_true.dat | 2 +- .../lattice_distribmat/True/results_true.dat | 2 +- .../lattice_distribrho/results_true.dat | 2 +- .../lattice_hex/results_true.dat | 2 +- .../lattice_hex_coincident/results_true.dat | 2 +- .../lattice_hex_x/results_true.dat | 2 +- .../lattice_multiple/results_true.dat | 2 +- .../lattice_rotated/results_true.dat | 2 +- .../mg_basic/results_true.dat | 2 +- .../mg_basic_delayed/results_true.dat | 2 +- .../mg_convert/results_true.dat | 24 +- tests/regression_tests/mg_convert/test.py | 6 +- .../mg_legendre/results_true.dat | 2 +- .../mg_max_order/results_true.dat | 2 +- .../mg_survival_biasing/results_true.dat | 2 +- .../mg_tallies/results_true.dat | 2482 ++++++------ .../mg_temperature/results_true.dat | 20 +- .../mg_temperature_multi/results_true.dat | 10 +- .../mgxs_library_ce_to_mg/results_true.dat | 2 +- .../results_true.dat | 2 +- .../mgxs_library_condense/results_true.dat | 572 +-- .../mgxs_library_correction/results_true.dat | 72 +- .../mgxs_library_distribcell/results_true.dat | 142 +- .../mgxs_library_hdf5/results_true.dat | 266 +- .../mgxs_library_histogram/results_true.dat | 660 ++-- .../mgxs_library_mesh/results_true.dat | 548 +-- .../mgxs_library_no_nuclides/results_true.dat | 782 ++-- .../mgxs_library_nuclides/results_true.dat | 2 +- .../results_true.dat | 2 +- .../test_reference_materials_direct.csv | 8 +- .../microxs/test_reference_materials_flux.csv | 8 +- .../microxs/test_reference_mesh_direct.csv | 8 +- .../microxs/test_reference_mesh_flux.csv | 8 +- .../multipole/results_true.dat | 54 +- .../regression_tests/output/results_true.dat | 2 +- .../particle_restart_eigval/results_true.dat | 10 +- .../particle_restart_eigval/settings.xml | 2 +- .../particle_restart_eigval/test.py | 2 +- .../periodic/results_true.dat | 2 +- .../periodic_6fold/results_true.dat | 2 +- .../periodic_hex/results_true.dat | 2 +- .../results_true.dat | 58 +- .../ptables_off/results_true.dat | 2 +- .../quadric_surfaces/results_true.dat | 2 +- .../results_true.dat | 2 +- .../infinite_medium/results_true.dat | 2 +- .../material_wise/results_true.dat | 2 +- .../stochastic_slab/results_true.dat | 2 +- .../results_true.dat | 2 +- .../linear/results_true.dat | 4 +- .../flat/results_true.dat | 6 +- .../linear_xy/results_true.dat | 14 +- .../results_true.dat | 10 +- .../random_ray_k_eff/results_true.dat | 14 +- .../random_ray_k_eff_mesh/results_true.dat | 18 +- .../random_ray_linear/linear/results_true.dat | 6 +- .../hybrid/results_true.dat | 4 +- .../reflective_plane/results_true.dat | 2 +- .../resonance_scattering/results_true.dat | 2 +- .../rotation/results_true.dat | 2 +- .../salphabeta/results_true.dat | 2 +- .../score_current/results_true.dat | 3366 ++++++++--------- tests/regression_tests/seed/results_true.dat | 2 +- .../regression_tests/source/results_true.dat | 2 +- .../source_file/results_true.dat | 2 +- .../source_mcpl_file/results_true.dat | 2 +- .../sourcepoint_batch/results_true.dat | 4 +- .../sourcepoint_latest/results_true.dat | 2 +- .../sourcepoint_restart/results_true.dat | 1578 ++++---- .../statepoint_batch/__init__.py | 0 .../statepoint_batch/geometry.xml | 8 - .../statepoint_batch/materials.xml | 9 - .../statepoint_batch/results_true.dat | 2 - .../statepoint_batch/settings.xml | 17 - .../regression_tests/statepoint_batch/test.py | 18 - .../statepoint_restart/results_true.dat | 2306 +++++------ .../statepoint_sourcesep/results_true.dat | 2 +- .../regression_tests/stride/results_true.dat | 2 +- .../surface_source/surface_source_true.h5 | Bin 106144 -> 106144 bytes .../surface_source/surface_source_true.mcpl | Bin 36071 -> 36120 bytes .../case-01/results_true.dat | 2 +- .../case-01/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-02/results_true.dat | 2 +- .../case-02/surface_source_true.h5 | Bin 12752 -> 13896 bytes .../case-03/results_true.dat | 2 +- .../case-03/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-04/results_true.dat | 2 +- .../case-04/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-05/results_true.dat | 2 +- .../case-05/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-06/results_true.dat | 2 +- .../case-06/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-07/results_true.dat | 2 +- .../case-07/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-08/results_true.dat | 2 +- .../case-08/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-09/results_true.dat | 2 +- .../case-09/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-10/results_true.dat | 2 +- .../case-10/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-11/results_true.dat | 2 +- .../case-11/surface_source_true.h5 | Bin 6408 -> 5160 bytes .../case-12/results_true.dat | 2 +- .../case-12/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-13/results_true.dat | 2 +- .../case-13/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-14/results_true.dat | 2 +- .../case-14/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-15/results_true.dat | 2 +- .../case-15/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-16/results_true.dat | 2 +- .../case-16/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-17/results_true.dat | 2 +- .../case-17/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-18/results_true.dat | 2 +- .../case-18/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-19/results_true.dat | 2 +- .../case-19/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-20/results_true.dat | 2 +- .../case-20/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-21/results_true.dat | 2 +- .../case-21/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-a01/results_true.dat | 2 +- .../case-a01/surface_source_true.h5 | Bin 6616 -> 6720 bytes .../case-d01/results_true.dat | 2 +- .../case-d01/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-d02/results_true.dat | 2 +- .../case-d02/surface_source_true.h5 | Bin 31472 -> 33344 bytes .../case-d03/results_true.dat | 2 +- .../case-d03/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-d04/results_true.dat | 2 +- .../case-d04/surface_source_true.h5 | Bin 31472 -> 33344 bytes .../case-d05/results_true.dat | 2 +- .../case-d05/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-d06/results_true.dat | 2 +- .../case-d06/surface_source_true.h5 | Bin 29496 -> 30744 bytes .../case-d07/results_true.dat | 2 +- .../case-d07/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-d08/results_true.dat | 2 +- .../case-d08/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e01/results_true.dat | 2 +- .../case-e01/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e02/results_true.dat | 2 +- .../case-e02/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e03/results_true.dat | 2 +- .../case-e03/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../surface_tally/results_true.dat | 82 +- .../survival_biasing/results_true.dat | 34 +- .../regression_tests/tallies/results_true.dat | 2 +- .../tally_aggregation/results_true.dat | 194 +- .../tally_arithmetic/results_true.dat | 98 +- .../tally_assumesep/results_true.dat | 14 +- .../tally_nuclides/results_true.dat | 50 +- .../tally_slice_merge/results_true.dat | 104 +- tests/regression_tests/torus/results_true.dat | 2 +- tests/regression_tests/trace/results_true.dat | 2 +- .../track_output/results_true.dat | 144 +- .../translation/results_true.dat | 2 +- .../trigger_batch_interval/results_true.dat | 50 +- .../results_true.dat | 50 +- .../trigger_no_status/results_true.dat | 50 +- .../inputs_true.dat | 2 +- .../results_true.dat | 6 +- .../trigger_statepoint_restart/test.py | 10 +- .../trigger_tallies/results_true.dat | 50 +- tests/regression_tests/triso/results_true.dat | 2 +- .../uniform_fs/results_true.dat | 2 +- .../universe/results_true.dat | 2 +- .../white_plane/results_true.dat | 2 +- tests/unit_tests/test_deplete_resultslist.py | 20 +- tests/unit_tests/test_lib.py | 17 +- tests/unit_tests/test_settings.py | 2 + tests/unit_tests/test_statepoint_batches.py | 26 + 241 files changed, 11472 insertions(+), 11352 deletions(-) create mode 100644 examples/pincell_pulsed/run_pulse.py delete mode 100644 tests/regression_tests/statepoint_batch/__init__.py delete mode 100644 tests/regression_tests/statepoint_batch/geometry.xml delete mode 100644 tests/regression_tests/statepoint_batch/materials.xml delete mode 100644 tests/regression_tests/statepoint_batch/results_true.dat delete mode 100644 tests/regression_tests/statepoint_batch/settings.xml delete mode 100644 tests/regression_tests/statepoint_batch/test.py create mode 100644 tests/unit_tests/test_statepoint_batches.py diff --git a/docs/source/methods/neutron_physics.rst b/docs/source/methods/neutron_physics.rst index fe8b8ad850..2b797e3dbc 100644 --- a/docs/source/methods/neutron_physics.rst +++ b/docs/source/methods/neutron_physics.rst @@ -290,7 +290,10 @@ create and store fission sites for the following generation. First, the average number of prompt and delayed neutrons must be determined to decide whether the secondary neutrons will be prompt or delayed. This is important because delayed neutrons have a markedly different spectrum from prompt neutrons, one that has a -lower average energy of emission. The total number of neutrons emitted +lower average energy of emission. Furthermore, in simulations where tracking +time of neutrons is important, we need to consider the emission time delay of +the secondary neutrons, which is dependent on the decay constant of the +delayed neutron precursor. The total number of neutrons emitted :math:`\nu_t` is given as a function of incident energy in the ENDF format. Two representations exist for :math:`\nu_t`. The first is a polynomial of order :math:`N` with coefficients :math:`c_0,c_1,\dots,c_N`. If :math:`\nu_t` has this @@ -306,8 +309,8 @@ interpolation law. The number of prompt neutrons released per fission event :math:`\nu_p` is also given as a function of incident energy and can be specified in a polynomial or tabular format. The number of delayed neutrons released per fission event :math:`\nu_d` can only be specified in a tabular -format. In practice, we only need to determine :math:`nu_t` and -:math:`nu_d`. Once these have been determined, we can calculated the delayed +format. In practice, we only need to determine :math:`\nu_t` and +:math:`\nu_d`. Once these have been determined, we can calculate the delayed neutron fraction .. math:: @@ -335,8 +338,14 @@ neutrons. Otherwise, we produce :math:`\lfloor \nu \rfloor + 1` neutrons. Then, for each fission site produced, we sample the outgoing angle and energy according to the algorithms given in :ref:`sample-angle` and :ref:`sample-energy` respectively. If the neutron is to be born delayed, then -there is an extra step of sampling a delayed neutron precursor group since they -each have an associated secondary energy distribution. +there is an extra step of sampling a delayed neutron precursor group to get the +associated secondary energy distribution and the decay constant +:math:`\lambda`, which is needed to sample the emission delay time :math:`t_d`: + +.. math:: + :label: sample-delay-time + + t_d = -\frac{\ln \xi}{\lambda}. The sampled outgoing angle and energy of fission neutrons along with the position of the collision site are stored in an array called the fission diff --git a/examples/pincell_pulsed/run_pulse.py b/examples/pincell_pulsed/run_pulse.py new file mode 100644 index 0000000000..b6a61ad3d8 --- /dev/null +++ b/examples/pincell_pulsed/run_pulse.py @@ -0,0 +1,101 @@ +import matplotlib.pyplot as plt +import numpy as np +import openmc + +############################################################################### +# Create materials for the problem + +uo2 = openmc.Material(name="UO2 fuel at 2.4% wt enrichment") +uo2.set_density("g/cm3", 10.29769) +uo2.add_element("U", 1.0, enrichment=2.4) +uo2.add_element("O", 2.0) + +helium = openmc.Material(name="Helium for gap") +helium.set_density("g/cm3", 0.001598) +helium.add_element("He", 2.4044e-4) + +zircaloy = openmc.Material(name="Zircaloy 4") +zircaloy.set_density("g/cm3", 6.55) +zircaloy.add_element("Sn", 0.014, "wo") +zircaloy.add_element("Fe", 0.00165, "wo") +zircaloy.add_element("Cr", 0.001, "wo") +zircaloy.add_element("Zr", 0.98335, "wo") + +borated_water = openmc.Material(name="Borated water") +borated_water.set_density("g/cm3", 0.740582) +borated_water.add_element("B", 2.0e-4) # 3x the original pincell +borated_water.add_element("H", 5.0e-2) +borated_water.add_element("O", 2.4e-2) +borated_water.add_s_alpha_beta("c_H_in_H2O") + +############################################################################### +# Define problem geometry + +# Create cylindrical surfaces +fuel_or = openmc.ZCylinder(r=0.39218, name="Fuel OR") +clad_ir = openmc.ZCylinder(r=0.40005, name="Clad IR") +clad_or = openmc.ZCylinder(r=0.45720, name="Clad OR") + +# Create a region represented as the inside of a rectangular prism +pitch = 1.25984 +box = openmc.model.RectangularPrism(pitch, pitch, boundary_type="reflective") + +# Create cells, mapping materials to regions +fuel = openmc.Cell(fill=uo2, region=-fuel_or) +gap = openmc.Cell(fill=helium, region=+fuel_or & -clad_ir) +clad = openmc.Cell(fill=zircaloy, region=+clad_ir & -clad_or) +water = openmc.Cell(fill=borated_water, region=+clad_or & -box) + +# Create a model and assign geometry +model = openmc.Model() +model.geometry = openmc.Geometry([fuel, gap, clad, water]) + +############################################################################### +# Define problem settings + +# Set the mode +model.settings.run_mode = "fixed source" + +# Indicate how many batches and particles to run +model.settings.batches = 10 +model.settings.particles = 10000 + +# Set time cutoff (we only care about t < 100 seconds, see tally below) +model.settings.cutoff = {"time_neutron": 100} + +# Create the neutron pulse source (by default, isotropic direction, t=0) +space = openmc.stats.Point() # At the origin (0, 0, 0) +energy = openmc.stats.delta_function(14.1e6) # At 14.1 MeV +model.settings.source = openmc.IndependentSource(space=space, energy=energy) + +############################################################################### +# Define tallies + +# Create time filter +t_grid = np.insert(np.logspace(-6, 2, 100), 0, 0.0) +time_filter = openmc.TimeFilter(t_grid) + +# Tally for total neutron density in time +density_tally = openmc.Tally(name="Density") +density_tally.filters = [time_filter] +density_tally.scores = ["inverse-velocity"] + +# Add tallies to model +model.tallies = openmc.Tallies([density_tally]) + + +# Run the model +model.run(apply_tally_results=True) + +# Bin-averaged result +density_mean = density_tally.mean.ravel() / np.diff(t_grid) + +# Plot particle density versus time +fig, ax = plt.subplots() +ax.stairs(density_mean, t_grid) +ax.set_xscale("log") +ax.set_yscale("log") +ax.set_xlabel("Time [s]") +ax.set_ylabel("Total density") +ax.grid() +plt.show() diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 069d94c3b2..999b1b83f8 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -150,6 +150,7 @@ extern double source_rejection_fraction; //!< Minimum fraction of source sites extern int max_history_splits; //!< maximum number of particle splits for weight windows +extern int max_secondaries; //!< maximum number of secondaries in the bank extern int64_t ssw_max_particles; //!< maximum number of particles to be //!< banked on surfaces per process extern int64_t ssw_max_files; //!< maximum number of surface source files diff --git a/openmc/settings.py b/openmc/settings.py index ce3743ff5d..7bbc31c192 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -128,6 +128,10 @@ class Settings: Maximum number of times a particle can split during a history .. versionadded:: 0.13 + max_secondaries : int + Maximum secondary bank size + + .. versionadded:: 0.15.3 max_tracks : int Maximum number of tracks written to a track file (per MPI process). @@ -431,6 +435,7 @@ class Settings: self._weight_window_checkpoints = {} self._max_history_splits = None self._max_tracks = None + self._max_secondaries = None self._use_decay_photons = None self._random_ray = {} @@ -1137,6 +1142,16 @@ class Settings: cv.check_greater_than('max particle splits', value, 0) self._max_history_splits = value + @property + def max_secondaries(self) -> int: + return self._max_secondaries + + @max_secondaries.setter + def max_secondaries(self, value: int): + cv.check_type('maximum secondary bank size', value, Integral) + cv.check_greater_than('max secondary bank size', value, 0) + self._max_secondaries = value + @property def max_tracks(self) -> int: return self._max_tracks @@ -1673,6 +1688,11 @@ class Settings: elem = ET.SubElement(root, "max_history_splits") elem.text = str(self._max_history_splits) + def _create_max_secondaries_subelement(self, root): + if self._max_secondaries is not None: + elem = ET.SubElement(root, "max_secondaries") + elem.text = str(self._max_secondaries) + def _create_max_tracks_subelement(self, root): if self._max_tracks is not None: elem = ET.SubElement(root, "max_tracks") @@ -2073,6 +2093,11 @@ class Settings: if text is not None: self.max_history_splits = int(text) + def _max_secondaries_from_xml_element(self, root): + text = get_text(root, 'max_secondaries') + if text is not None: + self.max_secondaries = int(text) + def _max_tracks_from_xml_element(self, root): text = get_text(root, 'max_tracks') if text is not None: @@ -2194,6 +2219,7 @@ class Settings: self._create_weight_window_checkpoints_subelement(element) self._create_max_history_splits_subelement(element) self._create_max_tracks_subelement(element) + self._create_max_secondaries_subelement(element) self._create_random_ray_subelement(element, mesh_memo) self._create_use_decay_photons_subelement(element) self._create_source_rejection_fraction_subelement(element) @@ -2302,6 +2328,7 @@ class Settings: settings._weight_window_checkpoints_from_xml_element(elem) settings._max_history_splits_from_xml_element(elem) settings._max_tracks_from_xml_element(elem) + settings._max_secondaries_from_xml_element(elem) settings._random_ray_from_xml_element(elem) settings._use_decay_photons_from_xml_element(elem) settings._source_rejection_fraction_from_xml_element(elem) diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index 2685bbe98a..a2120a006d 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -127,30 +127,8 @@ void synchronize_bank() "No fission sites banked on MPI rank " + std::to_string(mpi::rank)); } - // Make sure all processors start at the same point for random sampling. Then - // skip ahead in the sequence using the starting index in the 'global' - // fission bank for each processor. - - int64_t id = simulation::total_gen + overall_generation(); - uint64_t seed = init_seed(id, STREAM_TRACKING); - advance_prn_seed(start, &seed); - - // Determine how many fission sites we need to sample from the source bank - // and the probability for selecting a site. - - int64_t sites_needed; - if (total < settings::n_particles) { - sites_needed = settings::n_particles % total; - } else { - sites_needed = settings::n_particles; - } - double p_sample = static_cast(sites_needed) / total; - simulation::time_bank_sample.start(); - // ========================================================================== - // SAMPLE N_PARTICLES FROM FISSION BANK AND PLACE IN TEMP_SITES - // Allocate temporary source bank -- we don't really know how many fission // sites were created, so overallocate by a factor of 3 int64_t index_temp = 0; @@ -165,33 +143,38 @@ void synchronize_bank() temp_delayed_groups, temp_lifetimes, 3 * simulation::work_per_rank); } - for (int64_t i = 0; i < simulation::fission_bank.size(); i++) { - const auto& site = simulation::fission_bank[i]; + // ========================================================================== + // SAMPLE N_PARTICLES FROM FISSION BANK AND PLACE IN TEMP_SITES - // If there are less than n_particles particles banked, automatically add - // int(n_particles/total) sites to temp_sites. For example, if you need - // 1000 and 300 were banked, this would add 3 source sites per banked site - // and the remaining 100 would be randomly sampled. - if (total < settings::n_particles) { - for (int64_t j = 1; j <= settings::n_particles / total; ++j) { - temp_sites[index_temp] = site; - if (settings::ifp_on) { - copy_ifp_data_from_fission_banks( - i, temp_delayed_groups[index_temp], temp_lifetimes[index_temp]); - } - ++index_temp; - } - } + // We use Uniform Combing method to exactly get the targeted particle size + // [https://doi.org/10.1080/00295639.2022.2091906] - // Randomly sample sites needed - if (prn(&seed) < p_sample) { - temp_sites[index_temp] = site; - if (settings::ifp_on) { - copy_ifp_data_from_fission_banks( - i, temp_delayed_groups[index_temp], temp_lifetimes[index_temp]); - } - ++index_temp; + // Make sure all processors use the same random number seed. + int64_t id = simulation::total_gen + overall_generation(); + uint64_t seed = init_seed(id, STREAM_TRACKING); + + // Comb specification + double teeth_distance = static_cast(total) / settings::n_particles; + double teeth_offset = prn(&seed) * teeth_distance; + + // First and last hitting tooth + int64_t end = start + simulation::fission_bank.size(); + int64_t tooth_start = std::ceil((start - teeth_offset) / teeth_distance); + int64_t tooth_end = std::floor((end - teeth_offset) / teeth_distance) + 1; + + // Locally comb particles in fission_bank + double tooth = tooth_start * teeth_distance + teeth_offset; + for (int64_t i = tooth_start; i < tooth_end; i++) { + int64_t idx = std::floor(tooth) - start; + temp_sites[index_temp] = simulation::fission_bank[idx]; + if (settings::ifp_on) { + copy_ifp_data_from_fission_banks( + idx, temp_delayed_groups[index_temp], temp_lifetimes[index_temp]); } + ++index_temp; + + // Next tooth + tooth += teeth_distance; } // At this point, the sampling of source sites is done and now we need to @@ -217,37 +200,6 @@ void synchronize_bank() finish = index_temp; #endif - // Now that the sampling is complete, we need to ensure that we have exactly - // n_particles source sites. The way this is done in a reproducible manner is - // to adjust only the source sites on the last processor. - - if (mpi::rank == mpi::n_procs - 1) { - if (finish > settings::n_particles) { - // If we have extra sites sampled, we will simply discard the extra - // ones on the last processor - index_temp = settings::n_particles - start; - - } else if (finish < settings::n_particles) { - // If we have too few sites, repeat sites from the very end of the - // fission bank - sites_needed = settings::n_particles - finish; - // TODO: sites_needed > simulation::fission_bank.size() or other test to - // make sure we don't need info from other proc - for (int i = 0; i < sites_needed; ++i) { - int i_bank = simulation::fission_bank.size() - sites_needed + i; - temp_sites[index_temp] = simulation::fission_bank[i_bank]; - if (settings::ifp_on) { - copy_ifp_data_from_fission_banks(i_bank, - temp_delayed_groups[index_temp], temp_lifetimes[index_temp]); - } - ++index_temp; - } - } - - // the last processor should not be sending sites to right - finish = simulation::work_index[mpi::rank + 1]; - } - simulation::time_bank_sample.stop(); simulation::time_bank_sendrecv.start(); diff --git a/src/finalize.cpp b/src/finalize.cpp index e38b0b251c..25b471a8bd 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -92,6 +92,7 @@ int openmc_finalize() settings::max_lost_particles = 10; settings::max_order = 0; settings::max_particles_in_flight = 100000; + settings::max_secondaries = 10000; settings::max_particle_events = 1'000'000; settings::max_history_splits = 10'000'000; settings::max_tracks = 1000; diff --git a/src/physics.cpp b/src/physics.cpp index 8ad1b99d75..f667fd586d 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -115,7 +115,7 @@ void sample_neutron_reaction(Particle& p) // Make sure particle population doesn't grow out of control for // subcritical multiplication problems. - if (p.secondary_bank().size() >= 10000) { + if (p.secondary_bank().size() >= settings::max_secondaries) { fatal_error( "The secondary particle bank appears to be growing without " "bound. You are likely running a subcritical multiplication problem " @@ -210,13 +210,23 @@ void create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx) site.particle = ParticleType::neutron; site.time = p.time(); site.wgt = 1. / weight; - site.parent_id = p.id(); - site.progeny_id = p.n_progeny()++; site.surf_id = 0; // Sample delayed group and angle/energy for fission reaction sample_fission_neutron(i_nuclide, rx, &site, p); + // Reject site if it exceeds time cutoff + if (site.delayed_group > 0) { + double t_cutoff = settings::time_cutoff[static_cast(site.particle)]; + if (site.time > t_cutoff) { + continue; + } + } + + // Set parent and progeny IDs + site.parent_id = p.id(); + site.progeny_id = p.n_progeny()++; + // Store fission site in bank if (use_fission_bank) { int64_t idx = simulation::fission_bank.thread_safe_append(site); @@ -1069,6 +1079,10 @@ void sample_fission_neutron( // set the delayed group for the particle born from fission site->delayed_group = group; + // Sample time of emission based on decay constant of precursor + double decay_rate = rx.products_[site->delayed_group].decay_rate_; + site->time -= std::log(prn(p.current_seed())) / decay_rate; + } else { // ==================================================================== // PROMPT NEUTRON SAMPLED diff --git a/src/physics_mg.cpp b/src/physics_mg.cpp index 5ebef9c141..4c28cb1795 100644 --- a/src/physics_mg.cpp +++ b/src/physics_mg.cpp @@ -139,8 +139,6 @@ void create_fission_sites(Particle& p) site.particle = ParticleType::neutron; site.time = p.time(); site.wgt = 1. / weight; - site.parent_id = p.id(); - site.progeny_id = p.n_progeny()++; // Sample the cosine of the angle, assuming fission neutrons are emitted // isotropically @@ -165,6 +163,24 @@ void create_fission_sites(Particle& p) // of the code, 0 is prompt. site.delayed_group = dg + 1; + // If delayed product production, sample time of emission + if (dg != -1) { + auto& macro_xs = data::mg.macro_xs_[p.material()]; + double decay_rate = + macro_xs.get_xs(MgxsType::DECAY_RATE, 0, nullptr, nullptr, &dg, 0, 0); + site.time -= std::log(prn(p.current_seed())) / decay_rate; + + // Reject site if it exceeds time cutoff + double t_cutoff = settings::time_cutoff[static_cast(site.particle)]; + if (site.time > t_cutoff) { + continue; + } + } + + // Set parent and progeny ID + site.parent_id = p.id(); + site.progeny_id = p.n_progeny()++; + // Store fission site in bank if (use_fission_bank) { int64_t idx = simulation::fission_bank.thread_safe_append(site); diff --git a/src/settings.cpp b/src/settings.cpp index afa42a3c5e..03d42bb9da 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -114,6 +114,7 @@ int max_order {0}; int n_log_bins {8000}; int n_batches; int n_max_batches; +int max_secondaries {10000}; int max_history_splits {10'000'000}; int max_tracks {1000}; ResScatMethod res_scat_method {ResScatMethod::rvs}; @@ -1144,6 +1145,11 @@ void read_settings_xml(pugi::xml_node root) weight_windows_on = get_node_value_bool(root, "weight_windows_on"); } + if (check_for_node(root, "max_secondaries")) { + settings::max_secondaries = + std::stoi(get_node_value(root, "max_secondaries")); + } + if (check_for_node(root, "max_history_splits")) { settings::max_history_splits = std::stoi(get_node_value(root, "max_history_splits")); diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index f078a5c6e5..0df80a2398 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -1624,8 +1624,7 @@ void score_general_mg(Particle& p, int i_tally, int start_index, tally.estimator_ == TallyEstimator::COLLISION) { if (settings::survival_biasing) { // Determine weight that was absorbed - wgt_absorb = p.wgt_last() * p.neutron_xs(p.event_nuclide()).absorption / - p.neutron_xs(p.event_nuclide()).total; + wgt_absorb = p.wgt_last() * p.macro_xs().absorption / p.macro_xs().total; // Then we either are alive and had a scatter (and so g changed), // or are dead and g did not change diff --git a/tests/regression_tests/adj_cell_rotation/results_true.dat b/tests/regression_tests/adj_cell_rotation/results_true.dat index b3df12e71f..ddb1546b5b 100644 --- a/tests/regression_tests/adj_cell_rotation/results_true.dat +++ b/tests/regression_tests/adj_cell_rotation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.403987E-01 1.514158E-03 +4.368327E-01 1.953533E-03 diff --git a/tests/regression_tests/albedo_box/results_true.dat b/tests/regression_tests/albedo_box/results_true.dat index 0f571f2459..dca80abcd8 100644 --- a/tests/regression_tests/albedo_box/results_true.dat +++ b/tests/regression_tests/albedo_box/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.590800E+00 4.251788E-03 +1.593206E+00 2.925742E-03 diff --git a/tests/regression_tests/asymmetric_lattice/results_true.dat b/tests/regression_tests/asymmetric_lattice/results_true.dat index 741327d80b..3d6b610a69 100644 --- a/tests/regression_tests/asymmetric_lattice/results_true.dat +++ b/tests/regression_tests/asymmetric_lattice/results_true.dat @@ -1 +1 @@ -b0ca1fb0436732188b1a199b3250ca9a33782f8fc379b0f7ff9c582e0c794b0a0470df063cafd0b05e802b26f61eaaf9ff5c0a8a672a933246acf49eed3ebf9f \ No newline at end of file +cc76769636be4f681137598cf366e978d7347425a1dfa1b293d17a28381b2b62595fb7f0d2f126dd06972ff9e79089a18dd53aba45fa2b1f316515b91fe6495a \ No newline at end of file diff --git a/tests/regression_tests/cmfd_feed/results_true.dat b/tests/regression_tests/cmfd_feed/results_true.dat index f5f22d9acd..1ef9624d4c 100644 --- a/tests/regression_tests/cmfd_feed/results_true.dat +++ b/tests/regression_tests/cmfd_feed/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.164262E+00 9.207592E-03 +1.181723E+00 9.944883E-03 tally 1: -1.156972E+01 -1.339924E+01 -2.136306E+01 -4.567185E+01 -2.859527E+01 -8.195821E+01 -3.470754E+01 -1.207851E+02 -3.766403E+01 -1.422263E+02 -3.778821E+01 -1.432660E+02 -3.573197E+01 -1.278854E+02 -2.849979E+01 -8.135515E+01 -2.073803E+01 -4.303374E+01 -1.112117E+01 -1.242944E+01 +1.169899E+01 +1.373251E+01 +2.142380E+01 +4.605511E+01 +2.968085E+01 +8.838716E+01 +3.561418E+01 +1.271206E+02 +3.777783E+01 +1.428817E+02 +3.805832E+01 +1.450213E+02 +3.439836E+01 +1.184892E+02 +2.852438E+01 +8.161896E+01 +2.088423E+01 +4.376204E+01 +1.076670E+01 +1.168108E+01 tally 2: -2.388054E+01 -2.875255E+01 -1.667791E+01 -1.403426E+01 -4.224771E+01 -8.942109E+01 -2.993088E+01 -4.490335E+01 -5.689839E+01 -1.625557E+02 -4.043633E+01 -8.212299E+01 -6.764024E+01 -2.297126E+02 -4.807902E+01 -1.161468E+02 -7.314835E+01 -2.684645E+02 -5.203584E+01 -1.359261E+02 -7.375727E+01 -2.733105E+02 -5.252944E+01 -1.386205E+02 -6.909571E+01 -2.397721E+02 -4.922548E+01 -1.217465E+02 -5.685978E+01 -1.621746E+02 -4.051938E+01 -8.237277E+01 -4.185562E+01 -8.784067E+01 -2.983570E+01 -4.467414E+01 -2.238373E+01 -2.520356E+01 -1.566758E+01 -1.234103E+01 +2.321241E+01 +2.702156E+01 +1.620912E+01 +1.317752E+01 +4.197404E+01 +8.845008E+01 +2.982666E+01 +4.469221E+01 +5.810089E+01 +1.695857E+02 +4.134123E+01 +8.588866E+01 +6.982488E+01 +2.447068E+02 +4.966939E+01 +1.238763E+02 +7.428421E+01 +2.767613E+02 +5.287955E+01 +1.403163E+02 +7.447402E+01 +2.785012E+02 +5.324628E+01 +1.423393E+02 +6.895164E+01 +2.381937E+02 +4.916366E+01 +1.211701E+02 +5.679253E+01 +1.617881E+02 +4.043125E+01 +8.204061E+01 +4.218618E+01 +8.933666E+01 +2.978592E+01 +4.456592E+01 +2.196426E+01 +2.435867E+01 +1.525576E+01 +1.175879E+01 tally 3: -1.609520E+01 -1.307542E+01 -1.033429E+00 -5.510889E-02 -2.877073E+01 -4.149542E+01 -1.964219E+00 -1.954692E-01 -3.896816E+01 -7.629752E+01 -2.484053E+00 -3.103733E-01 -4.634285E+01 -1.079367E+02 -2.974750E+00 -4.468223E-01 -5.007964E+01 -1.259202E+02 -3.181802E+00 -5.103621E-01 -5.058915E+01 -1.286193E+02 -3.249442E+00 -5.337712E-01 -4.744464E+01 -1.131026E+02 -3.067644E+00 -4.736335E-01 -3.900632E+01 -7.634433E+01 -2.443552E+00 -3.028060E-01 -2.874166E+01 -4.146375E+01 -1.810421E+00 -1.671667E-01 -1.509222E+01 -1.145579E+01 -1.014919E+00 -5.391053E-02 +1.563788E+01 +1.226528E+01 +1.053289E+00 +5.666942E-02 +2.870755E+01 +4.139654E+01 +1.838017E+00 +1.710528E-01 +3.978616E+01 +7.955764E+01 +2.560657E+00 +3.334449E-01 +4.780385E+01 +1.147770E+02 +3.139243E+00 +4.967628E-01 +5.106650E+01 +1.308704E+02 +3.170056E+00 +5.078920E-01 +5.123992E+01 +1.318586E+02 +3.211706E+00 +5.205979E-01 +4.729862E+01 +1.121695E+02 +3.068662E+00 +4.749488E-01 +3.898816E+01 +7.630564E+01 +2.516911E+00 +3.199696E-01 +2.865357E+01 +4.125742E+01 +1.852314E+00 +1.741116E-01 +1.467340E+01 +1.088460E+01 +9.268633E-01 +4.450662E-02 tally 4: -3.148231E+00 -4.974555E-01 +3.029754E+00 +4.613561E-01 0.000000E+00 0.000000E+00 -2.805439E+00 -3.982239E-01 -5.574031E+00 -1.561105E+00 +2.832501E+00 +4.049252E-01 +5.517243E+00 +1.527794E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.574031E+00 -1.561105E+00 -2.805439E+00 -3.982239E-01 -5.171038E+00 -1.344877E+00 -7.372031E+00 -2.725420E+00 +5.517243E+00 +1.527794E+00 +2.832501E+00 +4.049252E-01 +5.117178E+00 +1.316972E+00 +7.333303E+00 +2.701677E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.372031E+00 -2.725420E+00 -5.171038E+00 -1.344877E+00 -6.946847E+00 -2.424850E+00 -8.496610E+00 -3.627542E+00 +7.333303E+00 +2.701677E+00 +5.117178E+00 +1.316972E+00 +7.248464E+00 +2.641591E+00 +8.817788E+00 +3.905530E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.496610E+00 -3.627542E+00 -6.946847E+00 -2.424850E+00 -8.479501E+00 -3.607280E+00 -9.261869E+00 -4.305912E+00 +8.817788E+00 +3.905530E+00 +7.248464E+00 +2.641591E+00 +8.646465E+00 +3.749847E+00 +9.460948E+00 +4.495388E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.261869E+00 -4.305912E+00 -8.479501E+00 -3.607280E+00 -9.232858E+00 -4.278432E+00 -9.306384E+00 -4.348594E+00 +9.460948E+00 +4.495388E+00 +8.646465E+00 +3.749847E+00 +9.379341E+00 +4.415049E+00 +9.278640E+00 +4.320720E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.306384E+00 -4.348594E+00 -9.232858E+00 -4.278432E+00 -9.299764E+00 -4.347828E+00 -8.511976E+00 -3.639893E+00 +9.278640E+00 +4.320720E+00 +9.379341E+00 +4.415049E+00 +9.465746E+00 +4.498591E+00 +8.656146E+00 +3.760545E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.511976E+00 -3.639893E+00 -9.299764E+00 -4.347828E+00 -8.726086E+00 -3.819567E+00 -7.147277E+00 -2.562747E+00 +8.656146E+00 +3.760545E+00 +9.465746E+00 +4.498591E+00 +8.589782E+00 +3.700308E+00 +6.996002E+00 +2.456935E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.147277E+00 -2.562747E+00 -8.726086E+00 -3.819567E+00 -7.218790E+00 -2.612243E+00 -5.018287E+00 -1.263077E+00 +6.996002E+00 +2.456935E+00 +8.589782E+00 +3.700308E+00 +7.352050E+00 +2.714808E+00 +5.105164E+00 +1.312559E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.018287E+00 -1.263077E+00 -7.218790E+00 -2.612243E+00 -5.443494E+00 -1.487018E+00 -2.732334E+00 -3.773047E-01 +5.105164E+00 +1.312559E+00 +7.352050E+00 +2.714808E+00 +5.442756E+00 +1.486776E+00 +2.697305E+00 +3.675580E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.732334E+00 -3.773047E-01 -5.443494E+00 -1.487018E+00 -3.044773E+00 -4.655756E-01 +2.697305E+00 +3.675580E-01 +5.442756E+00 +1.486776E+00 +3.017025E+00 +4.571443E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.609029E+01 -1.306718E+01 -2.230601E+00 -2.559496E-01 -2.876780E+01 -4.148686E+01 -3.835952E+00 -7.456562E-01 -3.895738E+01 -7.625344E+01 -4.841024E+00 -1.197335E+00 -4.633595E+01 -1.079043E+02 -6.236821E+00 -1.963311E+00 -5.007472E+01 -1.258967E+02 -6.749745E+00 -2.297130E+00 -5.058336E+01 -1.285894E+02 -6.727612E+00 -2.315656E+00 -4.743869E+01 -1.130735E+02 -6.338193E+00 -2.042159E+00 -3.899838E+01 -7.631289E+01 -5.187573E+00 -1.359733E+00 -2.873434E+01 -4.144233E+01 -3.815610E+00 -7.367619E-01 -1.509020E+01 -1.145268E+01 -2.125767E+00 -2.341894E-01 +1.563588E+01 +1.226217E+01 +2.209027E+00 +2.507131E-01 +2.870034E+01 +4.137550E+01 +3.726620E+00 +7.021948E-01 +3.977762E+01 +7.952285E+01 +5.304975E+00 +1.427333E+00 +4.779747E+01 +1.147456E+02 +6.528302E+00 +2.151715E+00 +5.105366E+01 +1.308037E+02 +6.986782E+00 +2.467487E+00 +5.123380E+01 +1.318264E+02 +6.845633E+00 +2.383542E+00 +4.729296E+01 +1.121433E+02 +6.252695E+00 +1.977351E+00 +3.898236E+01 +7.628315E+01 +5.461495E+00 +1.528579E+00 +2.864576E+01 +4.123538E+01 +3.857301E+00 +7.581323E-01 +1.467047E+01 +1.088031E+01 +2.277024E+00 +2.679801E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.129918E+00 -1.143848E+00 -1.147976E+00 -1.151534E+00 -1.152378E+00 -1.148219E+00 -1.150402E+00 -1.154647E+00 -1.156159E+00 -1.160048E+00 -1.167441E+00 -1.168163E+00 -1.168629E+00 -1.164120E+00 -1.165051E+00 -1.169177E+00 +1.169107E+00 +1.175079E+00 +1.173912E+00 +1.175368E+00 +1.174026E+00 +1.181745E+00 +1.182261E+00 +1.183559E+00 +1.178691E+00 +1.179222E+00 +1.179017E+00 +1.172979E+00 +1.175043E+00 +1.173458E+00 +1.174152E+00 +1.171451E+00 cmfd entropy -3.224769E+00 -3.225945E+00 -3.227421E+00 -3.226174E+00 -3.224429E+00 -3.227049E+00 -3.230710E+00 -3.230315E+00 -3.226825E+00 -3.226655E+00 -3.226588E+00 -3.224155E+00 -3.223246E+00 -3.222640E+00 -3.223920E+00 -3.222838E+00 +3.207640E+00 +3.210547E+00 +3.212218E+00 +3.209573E+00 +3.211619E+00 +3.212126E+00 +3.213163E+00 +3.214288E+00 +3.215737E+00 +3.213677E+00 +3.214925E+00 +3.215612E+00 +3.216708E+00 +3.221454E+00 +3.219048E+00 +3.218387E+00 cmfd balance -3.90454E-03 -4.08089E-03 -3.46511E-03 -4.09535E-03 -2.62009E-03 -2.23559E-03 -2.54033E-03 -2.12799E-03 -2.25864E-03 -1.85766E-03 -1.49916E-03 -1.63471E-03 -1.48377E-03 -1.59800E-03 -1.37354E-03 -1.32853E-03 +4.88208E-03 +4.75139E-03 +3.15783E-03 +3.67091E-03 +2.99797E-03 +2.91060E-03 +2.06576E-03 +1.83482E-03 +1.56292E-03 +1.58659E-03 +2.32986E-03 +1.47376E-03 +1.46673E-03 +1.22627E-03 +1.31963E-03 +1.26456E-03 cmfd dominance ratio -5.539E-01 -5.537E-01 -5.536E-01 -5.515E-01 -5.512E-01 -5.514E-01 -5.518E-01 -5.507E-01 -5.500E-01 -5.497E-01 -5.477E-01 -5.461E-01 -5.444E-01 -5.445E-01 -5.454E-01 +5.467E-01 +5.453E-01 +5.458E-01 +5.436E-01 +5.442E-01 +5.406E-01 +5.401E-01 +5.413E-01 +4.995E-01 +5.396E-01 +5.409E-01 +5.414E-01 +5.423E-01 +5.456E-01 +5.442E-01 5.441E-01 cmfd openmc source comparison -9.875240E-03 -1.106163E-02 -9.847628E-03 -6.065921E-03 -5.772039E-03 -4.615656E-03 -4.244331E-03 -3.694299E-03 -3.545814E-03 -3.213063E-03 -3.467537E-03 -3.383489E-03 -3.697591E-03 -3.937358E-03 -3.369124E-03 -3.190359E-03 +9.587418E-03 +8.150978E-03 +6.677661E-03 +6.334727E-03 +5.153692E-03 +5.082964E-03 +4.633153E-03 +4.037383E-03 +3.528742E-03 +4.559089E-03 +3.517370E-03 +3.306117E-03 +2.913809E-03 +1.906045E-03 +1.932794E-03 +1.711341E-03 cmfd source -4.360494E-02 -8.397599E-02 -1.074181E-01 -1.294531E-01 -1.385611E-01 -1.407934E-01 -1.325191E-01 -1.044311E-01 -7.660359E-02 -4.263941E-02 +4.496492E-02 +7.869674E-02 +1.100280E-01 +1.354045E-01 +1.363339E-01 +1.380533E-01 +1.314512E-01 +1.077480E-01 +7.847306E-02 +3.884630E-02 diff --git a/tests/regression_tests/cmfd_feed_2g/results_true.dat b/tests/regression_tests/cmfd_feed_2g/results_true.dat index 2b61d9f4e8..e66eae13c4 100644 --- a/tests/regression_tests/cmfd_feed_2g/results_true.dat +++ b/tests/regression_tests/cmfd_feed_2g/results_true.dat @@ -1,112 +1,112 @@ k-combined: -1.035567E+00 9.463160E-03 +1.027434E+00 6.509170E-03 tally 1: -1.146535E+02 -1.315267E+03 -1.157458E+02 -1.340166E+03 -1.140491E+02 -1.301364E+03 -1.146589E+02 -1.315433E+03 +1.162758E+02 +1.352562E+03 +1.138125E+02 +1.295815E+03 +1.143712E+02 +1.308316E+03 +1.150293E+02 +1.323834E+03 tally 2: -4.319968E+01 -9.360083E+01 -6.373035E+01 -2.038056E+02 -1.889646E+02 -1.812892E+03 -1.024866E+02 -5.254528E+02 -4.323262E+01 -9.360200E+01 -6.363111E+01 -2.028178E+02 -1.849746E+02 -1.711533E+03 -1.034532E+02 -5.352768E+02 -4.296541E+01 -9.249656E+01 -6.346919E+01 -2.018659E+02 -1.888697E+02 -1.812037E+03 -1.025707E+02 -5.262261E+02 -4.691085E+01 -1.269707E+02 -6.299377E+01 -1.990497E+02 -1.853864E+02 -1.719984E+03 -1.023015E+02 -5.235858E+02 +4.284580E+01 +9.207089E+01 +6.335165E+01 +2.014931E+02 +1.894187E+02 +1.818190E+03 +1.033212E+02 +5.340768E+02 +4.282771E+01 +9.186295E+01 +6.295029E+01 +1.983895E+02 +1.834276E+02 +1.684375E+03 +1.022482E+02 +5.228403E+02 +4.330690E+01 +9.402038E+01 +6.395965E+01 +2.053163E+02 +1.851113E+02 +1.714198E+03 +1.030809E+02 +5.314535E+02 +4.337097E+01 +9.426435E+01 +6.417590E+01 +2.063443E+02 +1.846817E+02 +1.706518E+03 +1.027233E+02 +5.279582E+02 tally 3: -6.034963E+01 -1.827718E+02 +5.992726E+01 +1.803120E+02 0.000000E+00 0.000000E+00 -1.865665E-02 -4.244195E-05 -4.170941E+00 -8.769372E-01 -3.453368E+00 -5.989168E-01 +2.172646E-02 +4.414237E-05 +4.181401E+00 +8.912796E-01 +3.536506E+00 +6.287425E-01 0.000000E+00 0.000000E+00 -9.743205E+01 -4.749420E+02 -8.570316E-01 -3.807993E-02 -6.005903E+01 -1.807233E+02 +9.824432E+01 +4.828691E+02 +9.116848E-01 +4.231247E-02 +5.955090E+01 +1.775522E+02 0.000000E+00 0.000000E+00 -1.885450E-02 -3.653402E-05 -4.323863E+00 -9.447512E-01 -3.465465E+00 -6.022861E-01 +1.893222E-02 +3.288000E-05 +4.048183E+00 +8.291130E-01 +3.384041E+00 +5.742363E-01 0.000000E+00 0.000000E+00 -9.843481E+01 -4.846158E+02 -9.048150E-01 -4.205551E-02 -5.996660E+01 -1.802150E+02 +9.734253E+01 +4.738861E+02 +9.157632E-01 +4.329280E-02 +6.045835E+01 +1.835255E+02 0.000000E+00 0.000000E+00 -1.221444E-02 -2.263445E-05 -4.301287E+00 -9.309882E-01 -3.456076E+00 -5.992144E-01 +1.501842E-02 +1.896931E-05 +4.289989E+00 +9.251538E-01 +3.481357E+00 +6.071667E-01 0.000000E+00 0.000000E+00 -9.761231E+01 -4.765834E+02 -8.434644E-01 -3.728180E-02 -5.961891E+01 -1.783106E+02 +9.799829E+01 +4.803591E+02 +8.899390E-01 +4.078750E-02 +6.064531E+01 +1.842746E+02 0.000000E+00 0.000000E+00 -1.500709E-02 -3.541280E-05 -4.155669E+00 -8.713442E-01 -3.455342E+00 -6.006426E-01 +1.495496E-02 +3.082640E-05 +4.321537E+00 +9.371611E-01 +3.453767E+00 +5.983727E-01 0.000000E+00 0.000000E+00 -9.726798E+01 -4.733393E+02 -9.202611E-01 -4.390503E-02 +9.771776E+01 +4.777781E+02 +8.975444E-01 +4.157471E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -116,14 +116,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.943264E+00 -4.008855E+00 -3.661063E+01 -6.704808E+01 -8.945553E+00 -4.011707E+00 -3.696832E+01 -6.835286E+01 +8.840487E+00 +3.915792E+00 +3.700362E+01 +6.851588E+01 +8.756789E+00 +3.844443E+00 +3.672366E+01 +6.747174E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -132,14 +132,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.844569E+00 -3.924591E+00 -3.666726E+01 -6.726522E+01 -8.769637E+00 -3.855006E+00 -3.654115E+01 -6.680777E+01 +8.860460E+00 +3.940908E+00 +3.704658E+01 +6.864069E+01 +8.832046E+00 +3.916611E+00 +3.736239E+01 +6.982147E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -156,14 +156,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.945553E+00 -4.011707E+00 -3.696832E+01 -6.835286E+01 -8.943264E+00 -4.008855E+00 -3.661063E+01 -6.704808E+01 +8.756789E+00 +3.844443E+00 +3.672366E+01 +6.747174E+01 +8.840487E+00 +3.915792E+00 +3.700362E+01 +6.851588E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -180,14 +180,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.648474E+00 -3.752219E+00 -3.689442E+01 -6.808997E+01 -8.757378E+00 -3.850408E+00 -3.716920E+01 -6.909715E+01 +8.892576E+00 +3.964978E+00 +3.703525E+01 +6.860645E+01 +8.824229E+00 +3.906925E+00 +3.685909E+01 +6.796123E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -212,22 +212,22 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.783669E+00 -3.870748E+00 -3.687358E+01 -6.802581E+01 -8.755250E+00 -3.846298E+00 -3.660278E+01 -6.704349E+01 -8.769637E+00 -3.855006E+00 -3.654115E+01 -6.680777E+01 -8.844569E+00 -3.924591E+00 -3.666726E+01 -6.726522E+01 +9.050876E+00 +4.111409E+00 +3.656082E+01 +6.687580E+01 +9.042402E+00 +4.105842E+00 +3.687247E+01 +6.801050E+01 +8.832046E+00 +3.916611E+00 +3.736239E+01 +6.982147E+01 +8.860460E+00 +3.940908E+00 +3.704658E+01 +6.864069E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -252,14 +252,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.755250E+00 -3.846298E+00 -3.660278E+01 -6.704349E+01 -8.783669E+00 -3.870748E+00 -3.687358E+01 -6.802581E+01 +9.042402E+00 +4.105842E+00 +3.687247E+01 +6.801050E+01 +9.050876E+00 +4.111409E+00 +3.656082E+01 +6.687580E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -268,14 +268,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.757378E+00 -3.850408E+00 -3.716920E+01 -6.909715E+01 -8.648474E+00 -3.752219E+00 -3.689442E+01 -6.808997E+01 +8.824229E+00 +3.906925E+00 +3.685909E+01 +6.796123E+01 +8.892576E+00 +3.964978E+00 +3.703525E+01 +6.860645E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -301,133 +301,133 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -6.036829E+01 -1.828885E+02 -1.008777E+02 -5.091033E+02 -1.353211E+01 -9.188155E+00 -4.618716E+01 -1.067410E+02 -6.007789E+01 -1.808371E+02 -1.018892E+02 -5.192269E+02 -1.357961E+01 -9.247052E+00 -4.618560E+01 -1.067058E+02 -5.997882E+01 -1.802895E+02 -1.010597E+02 -5.108478E+02 -1.374955E+01 -9.502494E+00 -4.619500E+01 -1.067547E+02 -5.963392E+01 -1.783999E+02 -1.007134E+02 -5.074700E+02 -1.319398E+01 -8.734106E+00 -4.586295E+01 -1.052870E+02 +5.994898E+01 +1.804403E+02 +1.017670E+02 +5.181130E+02 +1.354160E+01 +9.220935E+00 +4.648971E+01 +1.081636E+02 +5.956983E+01 +1.776668E+02 +1.007226E+02 +5.073592E+02 +1.347883E+01 +9.120344E+00 +4.609907E+01 +1.063127E+02 +6.047337E+01 +1.836168E+02 +1.014777E+02 +5.150557E+02 +1.390508E+01 +9.722899E+00 +4.629251E+01 +1.072027E+02 +6.066027E+01 +1.843661E+02 +1.011648E+02 +5.120629E+02 +1.365982E+01 +9.372236E+00 +4.602994E+01 +1.060579E+02 cmfd indices 2.000000E+00 2.000000E+00 1.000000E+00 2.000000E+00 k cmfd -1.018115E+00 -1.022665E+00 -1.020323E+00 -1.020653E+00 -1.021036E+00 -1.020623E+00 -1.021482E+00 -1.025450E+00 -1.027292E+00 -1.028065E+00 -1.027065E+00 -1.024275E+00 -1.025309E+00 -1.026039E+00 -1.026700E+00 -1.023865E+00 +1.013488E+00 +1.024396E+00 +1.015533E+00 +1.009319E+00 +1.012726E+00 +1.014831E+00 +1.021757E+00 +1.022002E+00 +1.023619E+00 +1.020953E+00 +1.023910E+00 +1.027657E+00 +1.024501E+00 +1.023838E+00 +1.025464E+00 +1.022802E+00 cmfd entropy -1.998965E+00 -1.999214E+00 -1.999348E+00 -1.999366E+00 -1.999564E+00 -1.999453E+00 -1.999533E+00 -1.999630E+00 -1.999739E+00 -1.999588E+00 -1.999581E+00 -1.999719E+00 -1.999773E+00 -1.999764E+00 -1.999821E+00 -1.999843E+00 +1.998974E+00 +1.998742E+00 +1.999128E+00 +1.998952E+00 +1.998951E+00 +1.999439E+00 +1.999626E+00 +1.999826E+00 +1.999513E+00 +1.999451E+00 +1.999514E+00 +1.999590E+00 +1.999563E+00 +1.999604E+00 +1.999742E+00 +1.999736E+00 cmfd balance -5.73174E-04 -7.55398E-04 -1.46671E-03 -6.39625E-04 -8.19008E-04 -1.93449E-03 -1.15900E-03 -1.01690E-03 -5.62788E-04 -6.90450E-04 -6.01060E-04 -5.73418E-04 -4.37190E-04 -4.82966E-04 -4.09700E-04 -3.45096E-04 +9.79896E-04 +4.24873E-04 +8.05696E-04 +1.92071E-03 +3.70731E-04 +2.81424E-04 +8.28991E-04 +6.12217E-04 +5.29185E-04 +4.97799E-04 +3.09154E-04 +1.73703E-04 +2.56689E-04 +2.64938E-04 +1.96305E-04 +1.82702E-04 cmfd dominance ratio -6.264E-03 -6.142E-03 -5.987E-03 -6.082E-03 -5.895E-03 -5.939E-03 -5.910E-03 -5.948E-03 -6.013E-03 -6.017E-03 -6.024E-03 -6.008E-03 -5.976E-03 -5.987E-03 -5.967E-03 -5.929E-03 +6.304E-03 +6.246E-03 +6.159E-03 +6.249E-03 +6.101E-03 +6.155E-03 +6.010E-03 +6.177E-03 +6.349E-03 +6.241E-03 +6.244E-03 +6.249E-03 +6.270E-03 +6.272E-03 +6.278E-03 +6.290E-03 cmfd openmc source comparison -4.832872E-05 -6.552342E-05 -7.516800E-05 -7.916087E-05 -9.022260E-05 -8.574478E-05 -7.891622E-05 -7.281636E-05 -7.750571E-05 -6.565408E-05 -6.078665E-05 -5.834343E-05 -4.758176E-05 -5.723990E-05 -4.994116E-05 -4.116808E-05 +4.046094E-05 +5.979431E-05 +3.836521E-05 +4.577591E-05 +5.012911E-05 +2.114677E-05 +2.074571E-05 +3.042280E-05 +2.408163E-05 +2.434542E-05 +1.190699E-05 +9.499301E-06 +2.354221E-05 +2.937924E-05 +1.889875E-05 +1.913866E-05 cmfd source -2.455663E-01 -2.553511E-01 -2.512257E-01 -2.478570E-01 +2.489706E-01 +2.426801E-01 +2.532142E-01 +2.551351E-01 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat index 8fd8cdbb84..b39f82f96e 100644 --- a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.167865E+00 7.492213E-03 +1.170835E+00 5.423480E-03 tally 1: -1.146860E+01 -1.318884E+01 -2.161527E+01 -4.685283E+01 -2.951158E+01 -8.733566E+01 -3.521610E+01 -1.242821E+02 -3.774236E+01 -1.426501E+02 -3.727918E+01 -1.391158E+02 -3.377176E+01 -1.143839E+02 -2.904497E+01 -8.452907E+01 -2.090871E+01 -4.384549E+01 -1.078642E+01 -1.168086E+01 +1.205100E+01 +1.456707E+01 +2.183882E+01 +4.781179E+01 +2.844010E+01 +8.102358E+01 +3.356334E+01 +1.130832E+02 +3.660829E+01 +1.344973E+02 +3.697740E+01 +1.371500E+02 +3.400119E+01 +1.160196E+02 +2.839868E+01 +8.083199E+01 +2.140398E+01 +4.615447E+01 +1.118179E+01 +1.262942E+01 tally 2: -1.136810E+00 -1.292338E+00 -7.987303E-01 -6.379700E-01 -2.266938E+00 -5.139009E+00 -1.613483E+00 -2.603328E+00 -3.046349E+00 -9.280239E+00 -2.182459E+00 -4.763126E+00 -3.568068E+00 -1.273111E+01 -2.532456E+00 -6.413333E+00 -3.989504E+00 -1.591614E+01 -2.848301E+00 -8.112818E+00 -3.853133E+00 -1.484663E+01 -2.718493E+00 -7.390202E+00 -3.478138E+00 -1.209745E+01 -2.467281E+00 -6.087476E+00 -2.952220E+00 -8.715605E+00 -2.103261E+00 -4.423706E+00 -1.917459E+00 -3.676649E+00 -1.378369E+00 -1.899902E+00 -1.048240E+00 -1.098807E+00 -7.511947E-01 -5.642934E-01 +1.218245E+00 +1.484121E+00 +8.387442E-01 +7.034918E-01 +2.142134E+00 +4.588738E+00 +1.526727E+00 +2.330895E+00 +2.736157E+00 +7.486556E+00 +1.973921E+00 +3.896363E+00 +3.606244E+00 +1.300500E+01 +2.537580E+00 +6.439313E+00 +3.668958E+00 +1.346126E+01 +2.599095E+00 +6.755294E+00 +3.647982E+00 +1.330777E+01 +2.539750E+00 +6.450332E+00 +3.118921E+00 +9.727669E+00 +2.186447E+00 +4.780549E+00 +2.881110E+00 +8.300795E+00 +2.042635E+00 +4.172360E+00 +2.045602E+00 +4.184486E+00 +1.458384E+00 +2.126884E+00 +1.022124E+00 +1.044738E+00 +7.112678E-01 +5.059018E-01 tally 3: -7.701233E-01 -5.930898E-01 -4.481585E-02 -2.008461E-03 -1.547307E+00 -2.394158E+00 -1.226539E-01 -1.504398E-02 -2.106373E+00 -4.436806E+00 -1.450618E-01 -2.104294E-02 -2.437654E+00 -5.942157E+00 -1.521380E-01 -2.314598E-02 -2.754639E+00 -7.588038E+00 -1.745460E-01 -3.046629E-02 -2.623852E+00 -6.884601E+00 -1.851602E-01 -3.428432E-02 -2.376886E+00 -5.649588E+00 -1.615729E-01 -2.610582E-02 -2.021856E+00 -4.087900E+00 -1.533174E-01 -2.350622E-02 -1.333190E+00 -1.777397E+00 -7.076188E-02 -5.007243E-03 -7.258527E-01 -5.268622E-01 -3.656030E-02 -1.336656E-03 +8.048428E-01 +6.477720E-01 +6.603741E-02 +4.360940E-03 +1.466886E+00 +2.151755E+00 +1.002354E-01 +1.004713E-02 +1.909238E+00 +3.645189E+00 +1.202824E-01 +1.446786E-02 +2.443130E+00 +5.968886E+00 +1.627351E-01 +2.648270E-02 +2.492602E+00 +6.213064E+00 +1.910368E-01 +3.649506E-02 +2.437262E+00 +5.940245E+00 +1.568389E-01 +2.459843E-02 +2.104091E+00 +4.427200E+00 +1.450465E-01 +2.103848E-02 +1.965900E+00 +3.864762E+00 +1.367918E-01 +1.871199E-02 +1.402871E+00 +1.968047E+00 +1.061316E-01 +1.126391E-02 +6.832689E-01 +4.668565E-01 +4.599034E-02 +2.115112E-03 tally 4: -1.667432E-01 -2.780328E-02 +1.497312E-01 +2.241943E-02 0.000000E+00 0.000000E+00 -1.292567E-01 -1.670730E-02 -2.813370E-01 -7.915052E-02 +1.535839E-01 +2.358801E-02 +2.882052E-01 +8.306225E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.813370E-01 -7.915052E-02 -1.292567E-01 -1.670730E-02 -2.670549E-01 -7.131835E-02 -4.055324E-01 -1.644566E-01 +2.882052E-01 +8.306225E-02 +1.535839E-01 +2.358801E-02 +2.526805E-01 +6.384743E-02 +3.616220E-01 +1.307705E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.055324E-01 -1.644566E-01 -2.670549E-01 -7.131835E-02 -3.848125E-01 -1.480807E-01 -4.809430E-01 -2.313062E-01 +3.616220E-01 +1.307705E-01 +2.526805E-01 +6.384743E-02 +3.594306E-01 +1.291904E-01 +4.229730E-01 +1.789062E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.809430E-01 -2.313062E-01 -3.848125E-01 -1.480807E-01 -4.543918E-01 -2.064719E-01 -5.106133E-01 -2.607260E-01 +4.229730E-01 +1.789062E-01 +3.594306E-01 +1.291904E-01 +3.973299E-01 +1.578711E-01 +4.255879E-01 +1.811250E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.106133E-01 -2.607260E-01 -4.543918E-01 -2.064719E-01 -4.543120E-01 -2.063994E-01 -4.626328E-01 -2.140291E-01 +4.255879E-01 +1.811250E-01 +3.973299E-01 +1.578711E-01 +4.633933E-01 +2.147333E-01 +4.672837E-01 +2.183540E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.626328E-01 -2.140291E-01 -4.543120E-01 -2.063994E-01 -4.827759E-01 -2.330726E-01 -4.442622E-01 -1.973689E-01 +4.672837E-01 +2.183540E-01 +4.633933E-01 +2.147333E-01 +4.251073E-01 +1.807162E-01 +3.842922E-01 +1.476805E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.442622E-01 -1.973689E-01 -4.827759E-01 -2.330726E-01 -4.630420E-01 -2.144079E-01 -3.886524E-01 -1.510507E-01 +3.842922E-01 +1.476805E-01 +4.251073E-01 +1.807162E-01 +4.045096E-01 +1.636280E-01 +3.192860E-01 +1.019436E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.886524E-01 -1.510507E-01 -4.630420E-01 -2.144079E-01 -3.535870E-01 -1.250237E-01 -2.530312E-01 -6.402478E-02 +3.192860E-01 +1.019436E-01 +4.045096E-01 +1.636280E-01 +3.738326E-01 +1.397508E-01 +2.598153E-01 +6.750398E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.530312E-01 -6.402478E-02 -3.535870E-01 -1.250237E-01 -2.465524E-01 -6.078808E-02 -1.197152E-01 -1.433173E-02 +2.598153E-01 +6.750398E-02 +3.738326E-01 +1.397508E-01 +2.453191E-01 +6.018146E-02 +1.098964E-01 +1.207721E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.197152E-01 -1.433173E-02 -2.465524E-01 -6.078808E-02 -1.369631E-01 -1.875888E-02 +1.098964E-01 +1.207721E-02 +2.453191E-01 +6.018146E-02 +1.458094E-01 +2.126039E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.701233E-01 -5.930898E-01 -1.386250E-01 -1.921688E-02 -1.547307E+00 -2.394158E+00 -2.630277E-01 -6.918357E-02 -2.106373E+00 -4.436806E+00 -2.807880E-01 -7.884187E-02 -2.435849E+00 -5.933361E+00 -3.322060E-01 -1.103608E-01 -2.753634E+00 -7.582501E+00 -3.825922E-01 -1.463768E-01 -2.623852E+00 -6.884601E+00 -3.888710E-01 -1.512206E-01 -2.376886E+00 -5.649588E+00 -3.196217E-01 -1.021581E-01 -2.021856E+00 -4.087900E+00 -2.897881E-01 -8.397715E-02 -1.333190E+00 -1.777397E+00 -1.627110E-01 -2.647486E-02 -7.258527E-01 -5.268622E-01 -9.348666E-02 -8.739755E-03 +8.048428E-01 +6.477720E-01 +1.018934E-01 +1.038226E-02 +1.466886E+00 +2.151755E+00 +1.414681E-01 +2.001322E-02 +1.909238E+00 +3.645189E+00 +2.450211E-01 +6.003535E-02 +2.443130E+00 +5.968886E+00 +3.360056E-01 +1.128997E-01 +2.492602E+00 +6.213064E+00 +3.266277E-01 +1.066856E-01 +2.437262E+00 +5.940245E+00 +2.878100E-01 +8.283461E-02 +2.104091E+00 +4.427200E+00 +3.440457E-01 +1.183675E-01 +1.965900E+00 +3.864762E+00 +2.880615E-01 +8.297945E-02 +1.401955E+00 +1.965478E+00 +1.646479E-01 +2.710892E-02 +6.832689E-01 +4.668565E-01 +1.147413E-01 +1.316557E-02 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.149077E+00 -1.156751E+00 -1.158648E+00 -1.159506E+00 -1.156567E+00 -1.160259E+00 -1.150345E+00 -1.149846E+00 -1.151606E+00 -1.164544E+00 -1.174648E+00 +1.181376E+00 +1.176656E+00 +1.161939E+00 +1.163552E+00 +1.163035E+00 +1.170382E+00 +1.160597E+00 +1.154301E+00 +1.159007E+00 +1.148290E+00 +1.157088E+00 cmfd entropy -3.216173E+00 -3.228717E+00 -3.220402E+00 -3.214352E+00 -3.215636E+00 -3.213599E+00 -3.212854E+00 -3.213131E+00 -3.213196E+00 -3.205474E+00 -3.202869E+00 +3.246419E+00 +3.246511E+00 +3.252247E+00 +3.240919E+00 +3.237600E+00 +3.233990E+00 +3.234226E+00 +3.229356E+00 +3.224272E+00 +3.225381E+00 +3.226778E+00 cmfd balance -3.08825E-03 -1.42345E-03 -1.21253E-03 -1.17694E-03 -1.05901E-03 -9.29611E-04 -1.35587E-03 -1.13579E-03 -1.14964E-03 -1.29313E-03 -1.46566E-03 +4.18486E-03 +1.72126E-03 +1.10899E-03 +1.88170E-03 +1.31646E-03 +1.34128E-03 +1.57944E-03 +2.11251E-03 +1.79912E-03 +1.86000E-03 +1.47765E-03 cmfd dominance ratio 5.524E-01 -5.614E-01 -5.522E-01 -5.487E-01 -5.482E-01 -5.446E-01 -5.437E-01 -5.429E-01 -5.407E-01 -5.380E-01 -5.377E-01 +5.597E-01 +5.622E-01 +5.544E-01 +5.541E-01 +5.519E-01 +5.532E-01 +5.550E-01 +5.484E-01 +5.497E-01 +5.500E-01 cmfd openmc source comparison -1.586045E-02 -6.953134E-03 -6.860419E-03 -6.198467E-03 -5.142854E-03 -4.373354E-03 -5.564831E-03 -4.184765E-03 -1.867780E-03 -2.734784E-03 -2.523985E-03 +1.905464E-03 +4.145126E-03 +2.465876E-03 +2.346755E-03 +1.848120E-03 +3.263822E-03 +3.641639E-03 +4.031509E-03 +4.999010E-03 +6.640746E-03 +5.691414E-03 cmfd source -4.241440E-02 -8.226026E-02 -1.180811E-01 -1.328433E-01 -1.412410E-01 -1.424902E-01 -1.269340E-01 -1.096490E-01 -6.953251E-02 -3.455422E-02 +4.951338E-02 +8.478025E-02 +1.083132E-01 +1.301432E-01 +1.341190E-01 +1.445825E-01 +1.255119E-01 +1.063303E-01 +7.830158E-02 +3.840469E-02 diff --git a/tests/regression_tests/cmfd_feed_ng/results_true.dat b/tests/regression_tests/cmfd_feed_ng/results_true.dat index 153238bfeb..4ea1515f18 100644 --- a/tests/regression_tests/cmfd_feed_ng/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ng/results_true.dat @@ -1,208 +1,208 @@ k-combined: -1.005987E+00 1.354263E-02 +1.008852E+00 9.028695E-03 tally 1: -1.140273E+02 -1.301245E+03 -1.147962E+02 -1.319049E+03 -1.151426E+02 -1.326442E+03 -1.149265E+02 -1.321518E+03 +1.151271E+02 +1.325871E+03 +1.143934E+02 +1.309051E+03 +1.142507E+02 +1.306616E+03 +1.140242E+02 +1.300786E+03 tally 2: -3.462748E+01 -7.542476E+01 -5.129219E+01 -1.658142E+02 -1.034704E+01 -6.730603E+00 -8.672967E+00 -4.715295E+00 -1.344669E+02 -1.132019E+03 -7.262519E+01 -3.300787E+02 -3.447358E+01 -7.459545E+01 -5.075836E+01 -1.619570E+02 -1.080516E+01 -7.366369E+00 -8.908065E+00 -4.991975E+00 -1.354224E+02 -1.146824E+03 -7.300078E+01 -3.332531E+02 -3.432298E+01 -7.388666E+01 -5.096378E+01 -1.627979E+02 -1.053664E+01 -7.029789E+00 -8.826624E+00 -4.904429E+00 -1.388389E+02 -1.207280E+03 -7.376623E+01 -3.403211E+02 -4.383841E+01 -1.943331E+02 -5.165881E+01 -1.675923E+02 -1.059646E+01 -7.048052E+00 -8.763673E+00 -4.823505E+00 -1.378179E+02 -1.188104E+03 -7.431708E+01 -3.453746E+02 +3.403617E+01 +7.260478E+01 +5.031678E+01 +1.588977E+02 +1.003700E+01 +6.373741E+00 +8.514575E+00 +4.571811E+00 +1.413036E+02 +1.264708E+03 +7.321799E+01 +3.353408E+02 +3.354839E+01 +7.052647E+01 +4.895930E+01 +1.501243E+02 +9.972495E+00 +6.271276E+00 +8.436263E+00 +4.481319E+00 +1.353506E+02 +1.146040E+03 +7.309382E+01 +3.341751E+02 +3.389861E+01 +7.205501E+01 +5.005946E+01 +1.571210E+02 +1.041650E+01 +6.810868E+00 +8.839753E+00 +4.897617E+00 +1.344145E+02 +1.130242E+03 +7.270373E+01 +3.307223E+02 +3.347928E+01 +7.040185E+01 +4.940585E+01 +1.535767E+02 +9.898649E+00 +6.175319E+00 +8.406032E+00 +4.442856E+00 +1.374544E+02 +1.182191E+03 +7.334301E+01 +3.365399E+02 tally 3: -4.858880E+01 -1.488705E+02 +4.755532E+01 +1.419592E+02 0.000000E+00 0.000000E+00 -8.148667E-03 -1.337050E-05 +1.628248E-02 +3.680742E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.347376E+00 -7.045574E-01 -2.433484E+00 -3.727266E-01 +3.347160E+00 +7.104290E-01 +2.453669E+00 +3.797470E-01 0.000000E+00 0.000000E+00 -6.095478E+00 -2.332622E+00 +5.925795E+00 +2.220734E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.235421E-01 -1.205155E-03 -3.647699E-01 -8.953589E-03 +9.542527E-02 +1.118856E-03 +3.018759E-01 +6.371059E-03 0.000000E+00 0.000000E+00 -2.673965E+00 -4.517972E-01 +2.501316E+00 +3.938401E-01 0.000000E+00 0.000000E+00 -6.841105E+01 -2.929195E+02 -5.902473E-01 -2.307683E-02 -4.792291E+01 -1.444397E+02 +6.926265E+01 +3.001504E+02 +6.765221E-01 +2.991787E-02 +4.605523E+01 +1.328435E+02 0.000000E+00 0.000000E+00 -2.183275E-02 -8.061011E-05 +1.687782E-02 +3.921162E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.435826E+00 -7.480244E-01 -2.450829E+00 -3.800327E-01 +3.481608E+00 +7.705602E-01 +2.439374E+00 +3.779705E-01 0.000000E+00 0.000000E+00 -6.331358E+00 -2.530492E+00 +5.855806E+00 +2.162361E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.012941E-01 -8.217580E-04 -2.981274E-01 -5.863186E-03 +1.016677E-01 +9.263706E-04 +3.264878E-01 +7.385168E-03 0.000000E+00 0.000000E+00 -2.535628E+00 -4.048310E-01 +2.519730E+00 +3.986182E-01 0.000000E+00 0.000000E+00 -6.912003E+01 -2.987684E+02 -5.984862E-01 -2.386115E-02 -4.822881E+01 -1.458309E+02 +6.920950E+01 +2.996184E+02 +5.985719E-01 +2.368062E-02 +4.730723E+01 +1.403550E+02 0.000000E+00 0.000000E+00 -1.525590E-02 -3.794082E-05 +6.800415E-03 +1.163614E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.314494E+00 -6.944527E-01 -2.424209E+00 -3.691360E-01 +3.347607E+00 +7.085691E-01 +2.556997E+00 +4.109118E-01 0.000000E+00 0.000000E+00 -6.254897E+00 -2.474317E+00 +6.171063E+00 +2.391770E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.112542E-01 -1.051688E-03 -3.234880E-01 -7.156753E-03 +7.942016E-02 +5.628747E-04 +3.456912E-01 +7.940086E-03 0.000000E+00 0.000000E+00 -2.474142E+00 -3.837496E-01 +2.684459E+00 +4.546338E-01 0.000000E+00 0.000000E+00 -6.987095E+01 -3.053358E+02 -5.928782E-01 -2.368116E-02 -4.885415E+01 -1.499856E+02 +6.850588E+01 +2.936078E+02 +6.458806E-01 +2.672541E-02 +4.673301E+01 +1.374202E+02 0.000000E+00 0.000000E+00 -1.262416E-02 -2.486286E-05 +1.504681E-02 +4.202606E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.426826E+00 -7.480396E-01 -2.487209E+00 -3.903882E-01 +3.139138E+00 +6.206027E-01 +2.341735E+00 +3.454035E-01 0.000000E+00 0.000000E+00 -6.127303E+00 -2.364605E+00 +5.923755E+00 +2.216341E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.439007E-02 -1.082564E-03 -2.963491E-01 -5.652952E-03 +7.030156E-02 +4.283974E-04 +3.247594E-01 +7.133772E-03 0.000000E+00 0.000000E+00 -2.620696E+00 -4.311792E-01 +2.559691E+00 +4.119674E-01 0.000000E+00 0.000000E+00 -7.030725E+01 -3.091241E+02 -5.986966E-01 -2.352487E-02 +6.938051E+01 +3.012078E+02 +5.159565E-01 +1.730381E-02 tally 4: 0.000000E+00 0.000000E+00 @@ -216,18 +216,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.028624E+00 -3.105990E+00 -2.154648E+00 -2.948865E-01 -2.714077E+01 -4.607926E+01 -7.035506E+00 -3.118549E+00 -2.085916E+00 -2.730884E-01 -2.750091E+01 -4.731304E+01 +7.028166E+00 +3.103666E+00 +2.028371E+00 +2.606104E-01 +2.715466E+01 +4.614452E+01 +6.981028E+00 +3.059096E+00 +2.032450E+00 +2.610410E-01 +2.734281E+01 +4.675062E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -240,18 +240,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.170567E+00 -3.240715E+00 -2.131758E+00 -2.862355E-01 -2.747702E+01 -4.722977E+01 -7.068817E+00 -3.139275E+00 -2.095865E+00 -2.762179E-01 -2.737835E+01 -4.688689E+01 +6.969559E+00 +3.054867E+00 +2.042871E+00 +2.624815E-01 +2.766332E+01 +4.787778E+01 +7.022610E+00 +3.098329E+00 +2.109973E+00 +2.824233E-01 +2.733826E+01 +4.676309E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -276,18 +276,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.035506E+00 -3.118549E+00 -2.085916E+00 -2.730884E-01 -2.750091E+01 -4.731304E+01 -7.028624E+00 -3.105990E+00 -2.154648E+00 -2.948865E-01 -2.714077E+01 -4.607926E+01 +6.981028E+00 +3.059096E+00 +2.032450E+00 +2.610410E-01 +2.734281E+01 +4.675062E+01 +7.028166E+00 +3.103666E+00 +2.028371E+00 +2.606104E-01 +2.715466E+01 +4.614452E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -312,18 +312,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.103896E+00 -3.171147E+00 -2.095666E+00 -2.756673E-01 -2.711842E+01 -4.600196E+01 -7.197270E+00 -3.255501E+00 -2.046179E+00 -2.630301E-01 -2.729901E+01 -4.662030E+01 +6.782152E+00 +2.885448E+00 +1.951138E+00 +2.400912E-01 +2.739652E+01 +4.697696E+01 +6.873220E+00 +2.965563E+00 +1.999066E+00 +2.521586E-01 +2.732700E+01 +4.670990E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -360,30 +360,30 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.240906E+00 -3.296285E+00 -2.130816E+00 -2.850713E-01 -2.761433E+01 -4.771548E+01 -7.126427E+00 -3.199209E+00 -2.177254E+00 -2.998765E-01 -2.754936E+01 -4.748447E+01 -7.068817E+00 -3.139275E+00 -2.095865E+00 -2.762179E-01 -2.737835E+01 -4.688689E+01 -7.170567E+00 -3.240715E+00 -2.131758E+00 -2.862355E-01 -2.747702E+01 -4.722977E+01 +6.933695E+00 +3.028826E+00 +2.080336E+00 +2.719620E-01 +2.726925E+01 +4.650782E+01 +6.836291E+00 +2.935998E+00 +2.124868E+00 +2.841370E-01 +2.709685E+01 +4.591604E+01 +7.022610E+00 +3.098329E+00 +2.109973E+00 +2.824233E-01 +2.733826E+01 +4.676309E+01 +6.969559E+00 +3.054867E+00 +2.042871E+00 +2.624815E-01 +2.766332E+01 +4.787778E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -420,18 +420,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.126427E+00 -3.199209E+00 -2.177254E+00 -2.998765E-01 -2.754936E+01 -4.748447E+01 -7.240906E+00 -3.296285E+00 -2.130816E+00 -2.850713E-01 -2.761433E+01 -4.771548E+01 +6.836291E+00 +2.935998E+00 +2.124868E+00 +2.841370E-01 +2.709685E+01 +4.591604E+01 +6.933695E+00 +3.028826E+00 +2.080336E+00 +2.719620E-01 +2.726925E+01 +4.650782E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -444,18 +444,18 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.197270E+00 -3.255501E+00 -2.046179E+00 -2.630301E-01 -2.729901E+01 -4.662030E+01 -7.103896E+00 -3.171147E+00 -2.095666E+00 -2.756673E-01 -2.711842E+01 -4.600196E+01 +6.873220E+00 +2.965563E+00 +1.999066E+00 +2.521586E-01 +2.732700E+01 +4.670990E+01 +6.782152E+00 +2.885448E+00 +1.951138E+00 +2.400912E-01 +2.739652E+01 +4.697696E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -493,124 +493,124 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -4.859695E+01 -1.489217E+02 -8.528963E+00 -4.561881E+00 -7.144500E+01 -3.194467E+02 -1.120265E+01 -7.944038E+00 -4.009821E+00 -1.012575E+00 -3.235456E+01 -6.558658E+01 -4.794474E+01 -1.445671E+02 -8.782187E+00 -4.852477E+00 -7.195036E+01 -3.237389E+02 -1.075572E+01 -7.333822E+00 -4.084680E+00 -1.054714E+00 -3.267154E+01 -6.675266E+01 -4.824407E+01 -1.459220E+02 -8.679106E+00 -4.742342E+00 -7.266858E+01 -3.302641E+02 -1.094872E+01 -7.536318E+00 -3.935828E+00 -9.749543E-01 -3.319517E+01 -6.894791E+01 -4.886677E+01 -1.500624E+02 -8.614512E+00 -4.662618E+00 -7.321408E+01 -3.352172E+02 -1.095123E+01 -7.574359E+00 -3.885927E+00 -9.539315E-01 -3.334065E+01 -6.953215E+01 +4.757160E+01 +1.420561E+02 +8.379464E+00 +4.426892E+00 +7.205748E+01 +3.248178E+02 +1.047742E+01 +6.922945E+00 +3.879420E+00 +9.517577E-01 +3.297227E+01 +6.802001E+01 +4.607211E+01 +1.329402E+02 +8.295180E+00 +4.334618E+00 +7.205259E+01 +3.247324E+02 +1.059307E+01 +7.039382E+00 +3.783039E+00 +9.030658E-01 +3.288052E+01 +6.762048E+01 +4.731403E+01 +1.403940E+02 +8.728060E+00 +4.774750E+00 +7.152809E+01 +3.200993E+02 +1.074636E+01 +7.270116E+00 +4.007351E+00 +1.010562E+00 +3.249303E+01 +6.611829E+01 +4.674806E+01 +1.375015E+02 +8.265491E+00 +4.296947E+00 +7.226174E+01 +3.267127E+02 +1.079228E+01 +7.340408E+00 +3.843888E+00 +9.273339E-01 +3.300391E+01 +6.823122E+01 cmfd indices 2.000000E+00 2.000000E+00 1.000000E+00 3.000000E+00 k cmfd -1.026473E+00 -1.024183E+00 -1.023151E+00 -1.025047E+00 -1.019801E+00 -1.020492E+00 -1.015249E+00 -1.016714E+00 -1.016047E+00 -1.019687E+00 -1.020955E+00 +1.011190E+00 +1.010705E+00 +1.014132E+00 +1.015900E+00 +1.019132E+00 +1.022616E+00 +1.023007E+00 +1.022300E+00 +1.014692E+00 +1.007628E+00 +1.006204E+00 cmfd entropy -1.999640E+00 -1.999556E+00 -1.999484E+00 -1.999718E+00 -1.999697E+00 -1.999657E+00 -1.999883E+00 -1.999902E+00 -1.999977E+00 -1.999977E+00 -1.999906E+00 +1.999167E+00 +1.999076E+00 +1.998507E+00 +1.997924E+00 +1.997814E+00 +1.997752E+00 +1.997882E+00 +1.998074E+00 +1.998109E+00 +1.998301E+00 +1.998581E+00 cmfd balance -8.10090E-04 -1.28103E-03 -7.97200E-04 -5.82188E-04 -7.20670E-04 -7.31475E-04 -5.71904E-04 -6.14057E-04 -6.00142E-04 -5.47870E-04 -3.53604E-04 +9.30124E-04 +2.56632E-04 +3.62598E-04 +4.17543E-04 +5.25720E-04 +4.90208E-04 +3.61304E-04 +2.24090E-04 +1.86602E-04 +1.78395E-04 +6.42497E-05 cmfd dominance ratio -3.977E-03 -4.018E-03 -3.950E-03 -3.866E-03 -3.840E-03 -3.888E-03 -3.867E-03 -3.896E-03 -3.924E-03 -3.885E-03 -3.913E-03 +4.194E-03 +4.234E-03 +4.149E-03 +4.209E-03 +4.185E-03 +4.197E-03 +4.175E-03 +4.105E-03 +4.056E-03 +4.122E-03 +4.113E-03 cmfd openmc source comparison -4.787501E-05 -4.450525E-05 -2.532345E-05 -3.844307E-05 -4.821504E-05 -4.840760E-05 -3.739246E-05 -3.957960E-05 -4.521480E-05 -4.072007E-05 -2.532636E-05 +2.078995E-05 +2.415218E-05 +3.311536E-05 +3.598613E-05 +3.156455E-05 +2.737017E-05 +2.468500E-05 +2.514215E-05 +1.601626E-05 +1.424027E-05 +4.201148E-06 cmfd source -2.486236E-01 -2.531628E-01 -2.460219E-01 -2.521918E-01 +2.558585E-01 +2.597562E-01 +2.529866E-01 +2.313986E-01 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/cmfd_feed_rectlin/results_true.dat b/tests/regression_tests/cmfd_feed_rectlin/results_true.dat index 600b5d1528..a98f3fbd38 100644 --- a/tests/regression_tests/cmfd_feed_rectlin/results_true.dat +++ b/tests/regression_tests/cmfd_feed_rectlin/results_true.dat @@ -1,149 +1,149 @@ k-combined: -1.160561E+00 1.029736E-02 +1.157362E+00 9.651846E-03 tally 1: -1.089904E+01 -1.193573E+01 -2.026534E+01 -4.113383E+01 -2.723584E+01 -7.440537E+01 -3.309956E+01 -1.101184E+02 -3.659327E+01 -1.341221E+02 -3.780158E+01 -1.430045E+02 -3.520883E+01 -1.241772E+02 -2.961801E+01 -8.784675E+01 -2.182029E+01 -4.781083E+01 -1.180347E+01 -1.399970E+01 +1.160989E+01 +1.351117E+01 +2.127132E+01 +4.540172E+01 +2.903242E+01 +8.450044E+01 +3.443549E+01 +1.188763E+02 +3.678332E+01 +1.355586E+02 +3.760088E+01 +1.418740E+02 +3.433077E+01 +1.181837E+02 +2.861986E+01 +8.231285E+01 +2.182277E+01 +4.792086E+01 +1.138713E+01 +1.304425E+01 tally 2: -8.794706E+00 -3.939413E+00 -6.131113E+00 -1.913116E+00 -3.265522E+01 -5.364042E+01 -2.304238E+01 -2.672742E+01 -2.250225E+01 -2.541491E+01 -1.601668E+01 -1.288405E+01 -5.525355E+01 -1.531915E+02 -3.929637E+01 -7.748545E+01 -3.222711E+01 -5.216630E+01 -2.285375E+01 -2.623641E+01 -7.051908E+01 -2.495413E+02 -5.010064E+01 -1.259701E+02 -3.728726E+01 -6.974440E+01 -2.652872E+01 -3.530919E+01 -3.747306E+01 -7.058235E+01 -2.681415E+01 -3.613314E+01 -7.296802E+01 -2.669214E+02 -5.202502E+01 -1.356733E+02 -3.333947E+01 -5.579355E+01 -2.361733E+01 -2.800800E+01 -5.785916E+01 -1.680561E+02 -4.093282E+01 -8.410711E+01 -2.377151E+01 -2.842464E+01 -1.681789E+01 -1.423646E+01 -3.422028E+01 -5.880493E+01 -2.415199E+01 -2.930240E+01 -8.890608E+00 -3.986356E+00 -6.140159E+00 -1.897764E+00 +8.861425E+00 +3.953963E+00 +6.090757E+00 +1.866235E+00 +3.309260E+01 +5.493482E+01 +2.330765E+01 +2.725350E+01 +2.295343E+01 +2.647375E+01 +1.629166E+01 +1.334081E+01 +5.714234E+01 +1.640293E+02 +4.054051E+01 +8.261123E+01 +3.331786E+01 +5.565082E+01 +2.366345E+01 +2.807637E+01 +7.034800E+01 +2.485209E+02 +5.001286E+01 +1.256087E+02 +3.651223E+01 +6.686058E+01 +2.606851E+01 +3.408881E+01 +3.729833E+01 +6.997492E+01 +2.657970E+01 +3.553107E+01 +7.212382E+01 +2.611253E+02 +5.124647E+01 +1.318756E+02 +3.304529E+01 +5.486643E+01 +2.347504E+01 +2.771353E+01 +5.711252E+01 +1.640619E+02 +4.060288E+01 +8.298231E+01 +2.384078E+01 +2.855909E+01 +1.684046E+01 +1.426180E+01 +3.329487E+01 +5.573544E+01 +2.349871E+01 +2.776487E+01 +8.676886E+00 +3.814132E+00 +5.980976E+00 +1.815143E+00 tally 3: -5.925339E+00 -1.788596E+00 -3.912632E-01 -8.061838E-03 -2.215544E+01 -2.471404E+01 -1.465191E+00 -1.092622E-01 -1.542988E+01 -1.195626E+01 -1.022876E+00 -5.356825E-02 -3.792029E+01 -7.218149E+01 -2.370476E+00 -2.839465E-01 -2.200154E+01 -2.432126E+01 -1.360836E+00 -9.402424E-02 -4.824980E+01 -1.168447E+02 -3.124366E+00 -4.907460E-01 -2.557420E+01 -3.282066E+01 -1.725855E+00 -1.519830E-01 -2.577963E+01 -3.341077E+01 -1.654042E+00 -1.386845E-01 -5.008220E+01 -1.257610E+02 -3.223857E+00 -5.237360E-01 -2.273380E+01 -2.595325E+01 -1.438369E+00 -1.050840E-01 -3.938822E+01 -7.789691E+01 -2.648324E+00 -3.559703E-01 -1.623604E+01 -1.327214E+01 -1.058882E+00 -5.680630E-02 -2.325730E+01 -2.717892E+01 -1.584276E+00 -1.275868E-01 -5.937929E+00 -1.774847E+00 -3.866918E-01 -7.994353E-03 +5.847135E+00 +1.719612E+00 +3.960040E-01 +8.297721E-03 +2.245534E+01 +2.530222E+01 +1.468678E+00 +1.094031E-01 +1.571194E+01 +1.240597E+01 +1.004169E+00 +5.156464E-02 +3.901605E+01 +7.652715E+01 +2.648696E+00 +3.571840E-01 +2.275978E+01 +2.597555E+01 +1.456067E+00 +1.075035E-01 +4.821184E+01 +1.167725E+02 +3.105774E+00 +4.859873E-01 +2.519281E+01 +3.183845E+01 +1.595498E+00 +1.292133E-01 +2.560583E+01 +3.297409E+01 +1.673871E+00 +1.429651E-01 +4.930025E+01 +1.220909E+02 +3.206604E+00 +5.220919E-01 +2.255825E+01 +2.560134E+01 +1.422870E+00 +1.027151E-01 +3.910818E+01 +7.698933E+01 +2.568903E+00 +3.333385E-01 +1.620292E+01 +1.321173E+01 +1.068678E+00 +5.798793E-02 +2.264343E+01 +2.578648E+01 +1.503553E+00 +1.158411E-01 +5.751110E+00 +1.676910E+00 +3.450582E-01 +6.411784E-03 tally 4: -3.063235E+00 -4.714106E-01 +3.051764E+00 +4.671879E-01 0.000000E+00 0.000000E+00 -1.425705E+00 -1.043616E-01 -4.355515E+00 -9.538346E-01 +1.407008E+00 +1.004485E-01 +4.354708E+00 +9.506434E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -160,14 +160,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.355515E+00 -9.538346E-01 -1.425705E+00 -1.043616E-01 -3.859174E+00 -7.519499E-01 -6.350310E+00 -2.024214E+00 +4.354708E+00 +9.506434E-01 +1.407008E+00 +1.004485E-01 +3.852730E+00 +7.498016E-01 +6.382605E+00 +2.043123E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -184,14 +184,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -6.350310E+00 -2.024214E+00 -3.859174E+00 -7.519499E-01 -4.993073E+00 -1.258264E+00 -7.194275E+00 -2.596886E+00 +6.382605E+00 +2.043123E+00 +3.852730E+00 +7.498016E-01 +5.061607E+00 +1.288306E+00 +7.281209E+00 +2.659444E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -208,14 +208,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.194275E+00 -2.596886E+00 -4.993073E+00 -1.258264E+00 -6.786617E+00 -2.312259E+00 -8.306978E+00 -3.459668E+00 +7.281209E+00 +2.659444E+00 +5.061607E+00 +1.288306E+00 +7.096602E+00 +2.527474E+00 +8.632232E+00 +3.736665E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -232,14 +232,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.306978E+00 -3.459668E+00 -6.786617E+00 -2.312259E+00 -7.603410E+00 -2.905228E+00 -8.791222E+00 -3.882935E+00 +8.632232E+00 +3.736665E+00 +7.096602E+00 +2.527474E+00 +7.759456E+00 +3.019026E+00 +8.968687E+00 +4.037738E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -256,14 +256,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.791222E+00 -3.882935E+00 -7.603410E+00 -2.905228E+00 -8.867113E+00 -3.938503E+00 -9.302808E+00 -4.340042E+00 +8.968687E+00 +4.037738E+00 +7.759456E+00 +3.019026E+00 +8.749025E+00 +3.839161E+00 +9.126289E+00 +4.176440E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -280,14 +280,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.302808E+00 -4.340042E+00 -8.867113E+00 -3.938503E+00 -9.270113E+00 -4.306513E+00 -9.263471E+00 -4.302184E+00 +9.126289E+00 +4.176440E+00 +8.749025E+00 +3.839161E+00 +9.259277E+00 +4.304020E+00 +9.165726E+00 +4.216173E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -304,14 +304,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.263471E+00 -4.302184E+00 -9.270113E+00 -4.306513E+00 -9.348712E+00 -4.388570E+00 -8.977713E+00 -4.047349E+00 +9.165726E+00 +4.216173E+00 +9.259277E+00 +4.304020E+00 +9.433925E+00 +4.473551E+00 +8.910566E+00 +3.991458E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -328,14 +328,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.977713E+00 -4.047349E+00 -9.348712E+00 -4.388570E+00 -9.234380E+00 -4.280666E+00 -8.036978E+00 -3.239853E+00 +8.910566E+00 +3.991458E+00 +9.433925E+00 +4.473551E+00 +9.099397E+00 +4.154062E+00 +7.770126E+00 +3.029928E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -352,14 +352,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.036978E+00 -3.239853E+00 -9.234380E+00 -4.280666E+00 -8.713633E+00 -3.808850E+00 -7.160878E+00 -2.572915E+00 +7.770126E+00 +3.029928E+00 +9.099397E+00 +4.154062E+00 +8.575842E+00 +3.694998E+00 +6.934243E+00 +2.418570E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -376,14 +376,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.160878E+00 -2.572915E+00 -8.713633E+00 -3.808850E+00 -7.378538E+00 -2.732122E+00 -5.145728E+00 -1.329190E+00 +6.934243E+00 +2.418570E+00 +8.575842E+00 +3.694998E+00 +7.437526E+00 +2.780629E+00 +5.136923E+00 +1.331553E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -400,14 +400,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.145728E+00 -1.329190E+00 -7.378538E+00 -2.732122E+00 -6.660125E+00 -2.228506E+00 -4.087925E+00 -8.435381E-01 +5.136923E+00 +1.331553E+00 +7.437526E+00 +2.780629E+00 +6.648582E+00 +2.216687E+00 +4.050691E+00 +8.279789E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -424,14 +424,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.087925E+00 -8.435381E-01 -6.660125E+00 -2.228506E+00 -4.466295E+00 -1.002320E+00 -1.468481E+00 -1.099604E-01 +4.050691E+00 +8.279789E-01 +6.648582E+00 +2.216687E+00 +4.390906E+00 +9.686686E-01 +1.391624E+00 +9.861955E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -448,12 +448,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.468481E+00 -1.099604E-01 -4.466295E+00 -1.002320E+00 -3.139355E+00 -4.955456E-01 +1.391624E+00 +9.861955E-02 +4.390906E+00 +9.686686E-01 +3.113477E+00 +4.874296E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -473,164 +473,164 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -5.925339E+00 -1.788596E+00 -8.954773E-01 -4.217679E-02 -2.215054E+01 -2.470273E+01 -2.944747E+00 -4.443186E-01 -1.542658E+01 -1.195085E+01 -1.950262E+00 -1.946340E-01 -3.791137E+01 -7.214779E+01 -4.955741E+00 -1.254830E+00 -2.200054E+01 -2.431894E+01 -3.031040E+00 -4.685971E-01 -4.823946E+01 -1.167941E+02 -6.226321E+00 -1.956308E+00 -2.556930E+01 -3.280828E+01 -3.582546E+00 -6.505962E-01 -2.577249E+01 -3.339204E+01 -3.316825E+00 -5.676842E-01 -5.007249E+01 -1.257124E+02 -6.462364E+00 -2.120157E+00 -2.273285E+01 -2.595106E+01 -2.960964E+00 -4.496277E-01 -3.937362E+01 -7.783849E+01 -5.339336E+00 -1.449257E+00 -1.623315E+01 -1.326746E+01 -2.289661E+00 -2.698618E-01 -2.325250E+01 -2.716827E+01 -3.253010E+00 -5.413837E-01 -5.937929E+00 -1.774847E+00 -9.208589E-01 -4.421403E-02 +5.846103E+00 +1.718959E+00 +8.952028E-01 +4.184063E-02 +2.245226E+01 +2.529524E+01 +3.092645E+00 +4.848878E-01 +1.571095E+01 +1.240426E+01 +2.178244E+00 +2.438479E-01 +3.900638E+01 +7.648853E+01 +5.265574E+00 +1.401505E+00 +2.275895E+01 +2.597348E+01 +3.067909E+00 +4.810969E-01 +4.820213E+01 +1.167232E+02 +6.403602E+00 +2.070034E+00 +2.519091E+01 +3.183360E+01 +3.463531E+00 +6.097568E-01 +2.560388E+01 +3.296889E+01 +3.456252E+00 +6.101655E-01 +4.929539E+01 +1.220666E+02 +6.629094E+00 +2.223366E+00 +2.255498E+01 +2.559363E+01 +2.833426E+00 +4.150907E-01 +3.909813E+01 +7.694976E+01 +5.582222E+00 +1.584757E+00 +1.620082E+01 +1.320814E+01 +2.282196E+00 +2.703156E-01 +2.263498E+01 +2.576758E+01 +3.162736E+00 +5.145038E-01 +5.750110E+00 +1.676357E+00 +9.181679E-01 +4.562885E-02 cmfd indices 1.400000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.125528E+00 -1.145509E+00 -1.158948E+00 -1.171983E+00 -1.180649E+00 -1.184072E+00 -1.188112E+00 -1.183095E+00 -1.182269E+00 -1.175467E+00 -1.175184E+00 -1.172637E+00 -1.171593E+00 -1.175439E+00 -1.174650E+00 -1.176474E+00 +1.166740E+00 +1.184008E+00 +1.166534E+00 +1.155559E+00 +1.164960E+00 +1.163229E+00 +1.165897E+00 +1.170104E+00 +1.170207E+00 +1.168091E+00 +1.170940E+00 +1.174589E+00 +1.174609E+00 +1.171505E+00 +1.174456E+00 +1.178370E+00 cmfd entropy -3.607059E+00 -3.604890E+00 -3.601329E+00 -3.597776E+00 -3.597360E+00 -3.597387E+00 -3.595379E+00 -3.596995E+00 -3.600901E+00 -3.601832E+00 -3.601426E+00 -3.604521E+00 -3.602848E+00 -3.603875E+00 -3.605213E+00 -3.606699E+00 +3.594757E+00 +3.587018E+00 +3.590385E+00 +3.595101E+00 +3.592151E+00 +3.600294E+00 +3.602102E+00 +3.604941E+00 +3.605897E+00 +3.604880E+00 +3.601658E+00 +3.602551E+00 +3.600160E+00 +3.604540E+00 +3.604094E+00 +3.602509E+00 cmfd balance -4.46212E-03 -4.66648E-03 -5.04274E-03 -5.21553E-03 -3.92498E-03 -2.97185E-03 -2.79785E-03 -2.66951E-03 -2.17472E-03 -1.98009E-03 -1.77035E-03 -1.51281E-03 -1.52807E-03 -1.33341E-03 -1.18155E-03 -1.07752E-03 +5.52960E-03 +5.42154E-03 +3.62152E-03 +2.92850E-03 +4.08642E-03 +2.07444E-03 +2.03704E-03 +2.06886E-03 +2.09646E-03 +1.94256E-03 +2.02728E-03 +1.89830E-03 +1.83910E-03 +1.48140E-03 +1.47034E-03 +1.64452E-03 cmfd dominance ratio -6.136E-01 -6.127E-01 -6.137E-01 -6.102E-01 -6.067E-01 -6.061E-01 -6.031E-01 6.046E-01 -6.071E-01 -6.089E-01 -6.073E-01 -6.080E-01 -6.080E-01 +6.015E-01 +6.059E-01 +6.060E-01 +6.061E-01 +6.109E-01 +6.110E-01 +6.108E-01 +6.120E-01 +6.124E-01 +6.109E-01 6.090E-01 -6.092E-01 -6.094E-01 +6.116E-01 +6.137E-01 +6.117E-01 +6.131E-01 cmfd openmc source comparison -1.043027E-02 -1.278226E-02 -1.184867E-02 -1.017186E-02 -1.099696E-02 -7.955341E-03 -8.360344E-03 -6.875508E-03 -4.824018E-03 -4.915363E-03 -5.371647E-03 -4.593100E-03 -4.894955E-03 -4.928253E-03 -4.292171E-03 -4.018545E-03 +1.035187E-02 +9.394886E-03 +6.879487E-03 +7.236029E-03 +6.543528E-03 +3.600620E-03 +2.859638E-03 +2.230047E-03 +2.180643E-03 +1.638534E-03 +1.764349E-03 +1.621487E-03 +1.221762E-03 +1.626297E-03 +1.951813E-03 +9.584126E-04 cmfd source -1.600876E-02 -6.000305E-02 -4.248071E-02 -9.935789E-02 -5.768092E-02 -1.338593E-01 -7.417398E-02 -7.102984E-02 -1.382563E-01 -6.181889E-02 -1.142473E-01 -4.571447E-02 -6.864655E-02 -1.672206E-02 +1.677059E-02 +6.229453E-02 +4.278394E-02 +1.134852E-01 +6.231020E-02 +1.327286E-01 +6.808362E-02 +7.130954E-02 +1.362127E-01 +6.048013E-02 +1.094460E-01 +4.546687E-02 +6.403310E-02 +1.459510E-02 diff --git a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat index 9cc26b8cff..34cde1a46e 100644 --- a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.167869E+00 7.492916E-03 +1.162249E+00 5.812620E-03 tally 1: -1.146821E+01 -1.318787E+01 -2.161476E+01 -4.685066E+01 -2.951084E+01 -8.733116E+01 -3.521523E+01 -1.242762E+02 -3.774181E+01 -1.426460E+02 -3.727924E+01 -1.391162E+02 -3.377236E+01 -1.143877E+02 -2.904590E+01 -8.453427E+01 -2.090941E+01 -4.384824E+01 -1.078680E+01 -1.168172E+01 +1.153831E+01 +1.338142E+01 +2.155552E+01 +4.659071E+01 +2.813997E+01 +7.941672E+01 +3.270996E+01 +1.073664E+02 +3.639852E+01 +1.329148E+02 +3.729637E+01 +1.393474E+02 +3.443129E+01 +1.186461E+02 +2.832690E+01 +8.040998E+01 +2.177527E+01 +4.771147E+01 +1.146822E+01 +1.328252E+01 tally 2: -1.136805E+00 -1.292326E+00 -7.987282E-01 -6.379667E-01 -2.266961E+00 -5.139112E+00 -1.613498E+00 -2.603376E+00 -3.046379E+00 -9.280427E+00 -2.182480E+00 -4.763219E+00 -3.568101E+00 -1.273134E+01 -2.532478E+00 -6.413444E+00 -3.989532E+00 -1.591637E+01 -2.848319E+00 -8.112921E+00 -3.853139E+00 -1.484668E+01 -2.718497E+00 -7.390223E+00 -3.478134E+00 -1.209742E+01 -2.467279E+00 -6.087465E+00 -2.952214E+00 -8.715569E+00 -2.103257E+00 -4.423688E+00 -1.917446E+00 -3.676599E+00 -1.378361E+00 -1.899878E+00 -1.048230E+00 -1.098785E+00 -7.511876E-01 -5.642828E-01 +1.024353E+00 +1.049299E+00 +6.991057E-01 +4.887487E-01 +2.200432E+00 +4.841901E+00 +1.561655E+00 +2.438768E+00 +2.910400E+00 +8.470426E+00 +2.095155E+00 +4.389674E+00 +3.466006E+00 +1.201320E+01 +2.480456E+00 +6.152662E+00 +3.711781E+00 +1.377732E+01 +2.646019E+00 +7.001418E+00 +3.953648E+00 +1.563133E+01 +2.832759E+00 +8.024524E+00 +3.597870E+00 +1.294467E+01 +2.555396E+00 +6.530048E+00 +2.860871E+00 +8.184585E+00 +2.032282E+00 +4.130169E+00 +2.006740E+00 +4.027007E+00 +1.408150E+00 +1.982886E+00 +1.035163E+00 +1.071562E+00 +7.084068E-01 +5.018402E-01 tally 3: -7.701212E-01 -5.930866E-01 -4.481580E-02 -2.008456E-03 -1.547321E+00 -2.394203E+00 -1.226538E-01 -1.504395E-02 -2.106393E+00 -4.436893E+00 -1.450617E-01 -2.104289E-02 -2.437675E+00 -5.942260E+00 -1.521379E-01 -2.314593E-02 -2.754657E+00 -7.588135E+00 -1.745458E-01 -3.046622E-02 -2.623856E+00 -6.884619E+00 -1.851600E-01 -3.428423E-02 -2.376884E+00 -5.649579E+00 -1.615728E-01 -2.610576E-02 -2.021851E+00 -4.087882E+00 -1.533172E-01 -2.350617E-02 -1.333182E+00 -1.777374E+00 -7.076179E-02 -5.007231E-03 -7.258458E-01 -5.268521E-01 -3.656026E-02 -1.336653E-03 +6.713566E-01 +4.507196E-01 +5.581718E-02 +3.115557E-03 +1.508976E+00 +2.277009E+00 +1.139601E-01 +1.298690E-02 +2.035529E+00 +4.143377E+00 +1.221001E-01 +1.490843E-02 +2.385217E+00 +5.689262E+00 +1.500087E-01 +2.250260E-02 +2.546286E+00 +6.483574E+00 +1.546601E-01 +2.391975E-02 +2.726427E+00 +7.433407E+00 +1.686144E-01 +2.843081E-02 +2.466613E+00 +6.084179E+00 +1.558230E-01 +2.428079E-02 +1.951251E+00 +3.807379E+00 +1.197744E-01 +1.434590E-02 +1.347903E+00 +1.816842E+00 +9.419149E-02 +8.872037E-03 +6.840490E-01 +4.679231E-01 +5.000289E-02 +2.500289E-03 tally 4: -1.667426E-01 -2.780308E-02 +1.561665E-01 +2.438798E-02 0.000000E+00 0.000000E+00 -1.292556E-01 -1.670700E-02 -2.813401E-01 -7.915227E-02 +1.307011E-01 +1.708276E-02 +2.703168E-01 +7.307115E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.813401E-01 -7.915227E-02 -1.292556E-01 -1.670700E-02 -2.670582E-01 -7.132006E-02 -4.055365E-01 -1.644599E-01 +2.703168E-01 +7.307115E-02 +1.307011E-01 +1.708276E-02 +2.637619E-01 +6.957033E-02 +3.685390E-01 +1.358210E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.055365E-01 -1.644599E-01 -2.670582E-01 -7.132006E-02 -3.848164E-01 -1.480837E-01 -4.809472E-01 -2.313102E-01 +3.685390E-01 +1.358210E-01 +2.637619E-01 +6.957033E-02 +3.887017E-01 +1.510890E-01 +4.439407E-01 +1.970834E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.809472E-01 -2.313102E-01 -3.848164E-01 -1.480837E-01 -4.543959E-01 -2.064756E-01 -5.106174E-01 -2.607301E-01 +4.439407E-01 +1.970834E-01 +3.887017E-01 +1.510890E-01 +4.456116E-01 +1.985697E-01 +4.737035E-01 +2.243950E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.106174E-01 -2.607301E-01 -4.543959E-01 -2.064756E-01 -4.543155E-01 -2.064026E-01 -4.626331E-01 -2.140294E-01 +4.737035E-01 +2.243950E-01 +4.456116E-01 +1.985697E-01 +4.760577E-01 +2.266309E-01 +4.703245E-01 +2.212052E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.626331E-01 -2.140294E-01 -4.543155E-01 -2.064026E-01 -4.827763E-01 -2.330729E-01 -4.442611E-01 -1.973679E-01 +4.703245E-01 +2.212052E-01 +4.760577E-01 +2.266309E-01 +4.878056E-01 +2.379543E-01 +4.373120E-01 +1.912418E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.442611E-01 -1.973679E-01 -4.827763E-01 -2.330729E-01 -4.630415E-01 -2.144074E-01 -3.886521E-01 -1.510505E-01 +4.373120E-01 +1.912418E-01 +4.878056E-01 +2.379543E-01 +4.262194E-01 +1.816630E-01 +3.334152E-01 +1.111657E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.886521E-01 -1.510505E-01 -4.630415E-01 -2.144074E-01 -3.535862E-01 -1.250232E-01 -2.530293E-01 -6.402384E-02 +3.334152E-01 +1.111657E-01 +4.262194E-01 +1.816630E-01 +3.560156E-01 +1.267471E-01 +2.409954E-01 +5.807879E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.530293E-01 -6.402384E-02 -3.535862E-01 -1.250232E-01 -2.465508E-01 -6.078730E-02 -1.197139E-01 -1.433141E-02 +2.409954E-01 +5.807879E-02 +3.560156E-01 +1.267471E-01 +2.646501E-01 +7.003965E-02 +1.327244E-01 +1.761576E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.197139E-01 -1.433141E-02 -2.465508E-01 -6.078730E-02 -1.369614E-01 -1.875841E-02 +1.327244E-01 +1.761576E-02 +2.646501E-01 +7.003965E-02 +1.480567E-01 +2.192079E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.701212E-01 -5.930866E-01 -1.386254E-01 -1.921700E-02 -1.547321E+00 -2.394203E+00 -2.630318E-01 -6.918571E-02 -2.106393E+00 -4.436893E+00 -2.807911E-01 -7.884363E-02 -2.435870E+00 -5.933464E+00 -3.322093E-01 -1.103630E-01 -2.753652E+00 -7.582597E+00 -3.825961E-01 -1.463797E-01 -2.623856E+00 -6.884619E+00 -3.888719E-01 -1.512213E-01 -2.376884E+00 -5.649579E+00 -3.196211E-01 -1.021576E-01 -2.021851E+00 -4.087882E+00 -2.897873E-01 -8.397667E-02 -1.333182E+00 -1.777374E+00 -1.627096E-01 -2.647441E-02 -7.258458E-01 -5.268521E-01 -9.348575E-02 -8.739586E-03 +6.713566E-01 +4.507196E-01 +9.805793E-02 +9.615358E-03 +1.508976E+00 +2.277009E+00 +1.968348E-01 +3.874394E-02 +2.032573E+00 +4.131353E+00 +2.120922E-01 +4.498309E-02 +2.385217E+00 +5.689262E+00 +2.863031E-01 +8.196946E-02 +2.545200E+00 +6.478041E+00 +3.278920E-01 +1.075131E-01 +2.726427E+00 +7.433407E+00 +3.770758E-01 +1.421861E-01 +2.466613E+00 +6.084179E+00 +3.593230E-01 +1.291130E-01 +1.951251E+00 +3.807379E+00 +2.474112E-01 +6.121229E-02 +1.347903E+00 +1.816842E+00 +2.127109E-01 +4.524594E-02 +6.823620E-01 +4.656179E-01 +1.249863E-01 +1.562159E-02 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.149087E+00 -1.156777E+00 -1.158641E+00 -1.159507E+00 -1.156564E+00 -1.160257E+00 -1.150344E+00 -1.149854E+00 -1.151616E+00 -1.164575E+00 -1.174683E+00 +1.181365E+00 +1.176693E+00 +1.161946E+00 +1.163565E+00 +1.163043E+00 +1.169908E+00 +1.149155E+00 +1.142379E+00 +1.152957E+00 +1.137602E+00 +1.141883E+00 cmfd entropy -3.216202E+00 -3.228703E+00 -3.220414E+00 -3.214361E+00 -3.215642E+00 -3.213607E+00 -3.212862E+00 -3.213128E+00 -3.213189E+00 -3.205465E+00 -3.202859E+00 +3.246422E+00 +3.246496E+00 +3.252238E+00 +3.240920E+00 +3.237606E+00 +3.234301E+00 +3.234103E+00 +3.229918E+00 +3.226983E+00 +3.221321E+00 +3.223622E+00 cmfd balance -3.08825E-03 -1.42554E-03 -1.21448E-03 -1.17859E-03 -1.06034E-03 -9.30949E-04 -1.35713E-03 -1.13694E-03 -1.14938E-03 -1.29296E-03 -1.46518E-03 +4.18486E-03 +1.72126E-03 +1.10906E-03 +1.88158E-03 +1.31626E-03 +1.30818E-03 +1.77315E-03 +2.16148E-03 +1.67789E-03 +2.31333E-03 +1.94932E-03 cmfd dominance ratio -5.503E-01 -5.596E-01 5.505E-01 -5.471E-01 -5.468E-01 -5.427E-01 -5.421E-01 -5.412E-01 -5.389E-01 -5.371E-01 -5.329E-01 +5.580E-01 +5.610E-01 +5.526E-01 +5.519E-01 +5.499E-01 +5.504E-01 +5.504E-01 +5.475E-01 +5.465E-01 +5.477E-01 cmfd openmc source comparison -1.571006E-02 -6.945629E-03 -6.838511E-03 -6.183655E-03 -5.138825E-03 -4.362701E-03 -5.558586E-03 -4.188314E-03 -1.837101E-03 -2.737321E-03 -2.529244E-03 +1.902234E-03 +4.110960E-03 +2.452031E-03 +2.337951E-03 +1.838979E-03 +3.138637E-03 +2.684401E-03 +2.912891E-03 +2.823494E-03 +6.391584E-03 +5.904139E-03 cmfd source -4.240947E-02 -8.226746E-02 -1.180848E-01 -1.328470E-01 -1.412449E-01 -1.424870E-01 -1.269297E-01 -1.096476E-01 -6.953001E-02 -3.455212E-02 +4.488002E-02 +8.895136E-02 +1.085930E-01 +1.229651E-01 +1.330479E-01 +1.497140E-01 +1.309102E-01 +1.028556E-01 +7.738878E-02 +4.069397E-02 diff --git a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat index 5ff4a132fd..2e31b35bab 100644 --- a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.173626E+00 1.098719E-02 +1.158333E+00 1.402684E-02 tally 1: -1.101892E+01 -1.218768E+01 -2.036233E+01 -4.152577E+01 -2.937587E+01 -8.637268E+01 -3.502389E+01 -1.231700E+02 -3.804803E+01 -1.453948E+02 -3.822561E+01 -1.465677E+02 -3.456290E+01 -1.198651E+02 -2.904088E+01 -8.470264E+01 -2.111529E+01 -4.463713E+01 -1.147633E+01 -1.326012E+01 +1.169478E+01 +1.373162E+01 +2.192038E+01 +4.844559E+01 +2.913292E+01 +8.542569E+01 +3.446069E+01 +1.201782E+02 +3.624088E+01 +1.320213E+02 +3.569791E+01 +1.278170E+02 +3.340601E+01 +1.119165E+02 +2.908648E+01 +8.514603E+01 +2.175458E+01 +4.767916E+01 +1.171268E+01 +1.378033E+01 tally 2: -1.010478E+00 -1.021066E+00 -6.902031E-01 -4.763804E-01 -1.899891E+00 -3.609584E+00 -1.322615E+00 -1.749312E+00 -2.756419E+00 -7.597845E+00 -1.955934E+00 -3.825676E+00 -3.818740E+00 -1.458278E+01 -2.704746E+00 -7.315652E+00 -3.920857E+00 -1.537312E+01 -2.843144E+00 -8.083470E+00 -3.835060E+00 -1.470768E+01 -2.728705E+00 -7.445831E+00 -3.510590E+00 -1.232424E+01 -2.497237E+00 -6.236191E+00 -2.717388E+00 -7.384198E+00 -1.903638E+00 -3.623837E+00 -2.207863E+00 -4.874659E+00 -1.563588E+00 -2.444808E+00 -1.289027E+00 -1.661591E+00 -9.022714E-01 -8.140937E-01 +1.132414E+00 +1.282361E+00 +7.822980E-01 +6.119901E-01 +2.124428E+00 +4.513196E+00 +1.490832E+00 +2.222581E+00 +3.158472E+00 +9.975946E+00 +2.221665E+00 +4.935795E+00 +3.994786E+00 +1.595831E+01 +2.828109E+00 +7.998199E+00 +3.491035E+00 +1.218732E+01 +2.461223E+00 +6.057617E+00 +3.461784E+00 +1.198395E+01 +2.473337E+00 +6.117398E+00 +3.027132E+00 +9.163527E+00 +2.150455E+00 +4.624458E+00 +2.471217E+00 +6.106911E+00 +1.737168E+00 +3.017752E+00 +1.880969E+00 +3.538044E+00 +1.316574E+00 +1.733367E+00 +1.233103E+00 +1.520543E+00 +8.543318E-01 +7.298828E-01 tally 3: -6.593197E-01 -4.347024E-01 -5.216387E-02 -2.721069E-03 -1.266446E+00 -1.603885E+00 -8.298797E-02 -6.887003E-03 -1.888709E+00 -3.567222E+00 -1.398940E-01 -1.957033E-02 -2.616078E+00 -6.843867E+00 -1.588627E-01 -2.523735E-02 -2.733300E+00 -7.470927E+00 -1.944290E-01 -3.780262E-02 -2.643656E+00 -6.988917E+00 -1.612338E-01 -2.599633E-02 -2.410643E+00 -5.811199E+00 -1.754603E-01 -3.078631E-02 -1.838012E+00 -3.378288E+00 -1.126265E-01 -1.268473E-02 -1.500033E+00 -2.250100E+00 -1.102554E-01 -1.215626E-02 -8.750096E-01 -7.656418E-01 -6.757592E-02 -4.566505E-03 +7.540113E-01 +5.685330E-01 +6.367610E-02 +4.054646E-03 +1.436984E+00 +2.064922E+00 +8.961822E-02 +8.031425E-03 +2.132240E+00 +4.546449E+00 +1.356065E-01 +1.838913E-02 +2.726356E+00 +7.433016E+00 +1.780572E-01 +3.170438E-02 +2.379700E+00 +5.662970E+00 +1.544735E-01 +2.386206E-02 +2.383471E+00 +5.680933E+00 +1.568319E-01 +2.459624E-02 +2.047271E+00 +4.191318E+00 +1.662654E-01 +2.764418E-02 +1.673107E+00 +2.799287E+00 +1.132020E-01 +1.281468E-02 +1.271576E+00 +1.616906E+00 +7.546797E-02 +5.695415E-03 +8.249906E-01 +6.806094E-01 +5.660098E-02 +3.203671E-03 tally 4: -1.490605E-01 -2.221904E-02 +1.551630E-01 +2.407556E-02 0.000000E+00 0.000000E+00 -1.139233E-01 -1.297851E-02 -2.549497E-01 -6.499934E-02 +1.487992E-01 +2.214121E-02 +2.878091E-01 +8.283409E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.549497E-01 -6.499934E-02 -1.139233E-01 -1.297851E-02 -2.191337E-01 -4.801958E-02 -3.295187E-01 -1.085826E-01 +2.878091E-01 +8.283409E-02 +1.487992E-01 +2.214121E-02 +2.936596E-01 +8.623595E-02 +3.954149E-01 +1.563529E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.295187E-01 -1.085826E-01 -2.191337E-01 -4.801958E-02 -3.872400E-01 -1.499548E-01 -4.595835E-01 -2.112170E-01 +3.954149E-01 +1.563529E-01 +2.936596E-01 +8.623595E-02 +3.991153E-01 +1.592930E-01 +4.758410E-01 +2.264247E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.595835E-01 -2.112170E-01 -3.872400E-01 -1.499548E-01 -4.668106E-01 -2.179121E-01 -5.112307E-01 -2.613569E-01 +4.758410E-01 +2.264247E-01 +3.991153E-01 +1.592930E-01 +4.850882E-01 +2.353106E-01 +5.210840E-01 +2.715285E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.112307E-01 -2.613569E-01 -4.668106E-01 -2.179121E-01 -4.716605E-01 -2.224636E-01 -4.916148E-01 -2.416851E-01 +5.210840E-01 +2.715285E-01 +4.850882E-01 +2.353106E-01 +4.790245E-01 +2.294645E-01 +4.570092E-01 +2.088574E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.916148E-01 -2.416851E-01 -4.716605E-01 -2.224636E-01 -4.696777E-01 -2.205972E-01 -4.365150E-01 -1.905453E-01 +4.570092E-01 +2.088574E-01 +4.790245E-01 +2.294645E-01 +4.505886E-01 +2.030301E-01 +3.884038E-01 +1.508575E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -4.365150E-01 -1.905453E-01 -4.696777E-01 -2.205972E-01 -4.179902E-01 -1.747158E-01 -3.350564E-01 -1.122628E-01 +3.884038E-01 +1.508575E-01 +4.505886E-01 +2.030301E-01 +3.986999E-01 +1.589616E-01 +3.220889E-01 +1.037412E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -3.350564E-01 -1.122628E-01 -4.179902E-01 -1.747158E-01 -3.743487E-01 -1.401370E-01 -2.400661E-01 -5.763172E-02 +3.220889E-01 +1.037412E-01 +3.986999E-01 +1.589616E-01 +3.319083E-01 +1.101631E-01 +2.101261E-01 +4.415297E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.400661E-01 -5.763172E-02 -3.743487E-01 -1.401370E-01 -3.063657E-01 -9.385994E-02 -1.605078E-01 -2.576275E-02 +2.101261E-01 +4.415297E-02 +3.319083E-01 +1.101631E-01 +2.795459E-01 +7.814588E-02 +1.306499E-01 +1.706938E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -1.605078E-01 -2.576275E-02 -3.063657E-01 -9.385994E-02 -1.700639E-01 -2.892174E-02 +1.306499E-01 +1.706938E-02 +2.795459E-01 +7.814588E-02 +1.585507E-01 +2.513833E-02 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,119 +345,119 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -6.593197E-01 -4.347024E-01 -1.314196E-01 -1.727112E-02 -1.266446E+00 -1.603885E+00 -2.002491E-01 -4.009970E-02 -1.888709E+00 -3.567222E+00 -2.444522E-01 -5.975686E-02 -2.616078E+00 -6.843867E+00 -3.234935E-01 -1.046481E-01 -2.733300E+00 -7.470927E+00 -3.309500E-01 -1.095279E-01 -2.643656E+00 -6.988917E+00 -4.025014E-01 -1.620074E-01 -2.410643E+00 -5.811199E+00 -3.050040E-01 -9.302747E-02 -1.838012E+00 -3.378288E+00 -2.800764E-01 -7.844279E-02 -1.500033E+00 -2.250100E+00 -2.324765E-01 -5.404531E-02 -8.750096E-01 -7.656418E-01 -1.256919E-01 -1.579844E-02 +7.530237E-01 +5.670447E-01 +1.178984E-01 +1.390004E-02 +1.436984E+00 +2.064922E+00 +1.458395E-01 +2.126916E-02 +2.132240E+00 +4.546449E+00 +2.950109E-01 +8.703141E-02 +2.726356E+00 +7.433016E+00 +3.397288E-01 +1.154157E-01 +2.379700E+00 +5.662970E+00 +3.113206E-01 +9.692053E-02 +2.383471E+00 +5.680933E+00 +3.455611E-01 +1.194125E-01 +2.047271E+00 +4.191318E+00 +2.910986E-01 +8.473841E-02 +1.673107E+00 +2.799287E+00 +2.381996E-01 +5.673907E-02 +1.270672E+00 +1.614606E+00 +1.795241E-01 +3.222889E-02 +8.249906E-01 +6.806094E-01 +1.201397E-01 +1.443354E-02 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.166297E+00 -1.148237E+00 -1.162472E+00 -1.187078E+00 -1.188411E+00 -1.194879E+00 -1.216739E+00 -1.216829E+00 -1.196596E+00 -1.199223E+00 -1.211817E+00 +1.184474E+00 +1.188170E+00 +1.165127E+00 +1.135010E+00 +1.145439E+00 +1.158451E+00 +1.154420E+00 +1.179615E+00 +1.197843E+00 +1.181252E+00 +1.186316E+00 cmfd entropy -3.215349E+00 -3.225577E+00 -3.223357E+00 -3.208828E+00 -3.211072E+00 -3.206578E+00 -3.195799E+00 -3.198236E+00 -3.220074E+00 -3.230249E+00 -3.238015E+00 +3.243654E+00 +3.244091E+00 +3.249203E+00 +3.249952E+00 +3.245538E+00 +3.240838E+00 +3.238919E+00 +3.223131E+00 +3.216002E+00 +3.220324E+00 +3.224804E+00 cmfd balance -2.07468E-03 -2.39687E-03 -1.51020E-03 -2.07618E-03 -1.89367E-03 -2.00902E-03 -2.54856E-03 -2.43636E-03 -2.48527E-03 -3.07775E-03 -3.37967E-03 +4.21104E-03 +1.38052E-03 +1.34642E-03 +2.39255E-03 +2.07426E-03 +1.27927E-03 +2.26249E-03 +2.72103E-03 +2.71504E-03 +2.19156E-03 +1.91989E-03 cmfd dominance ratio -5.505E-01 -5.558E-01 -5.584E-01 -5.477E-01 -5.477E-01 -5.426E-01 -5.335E-01 -5.305E-01 -5.427E-01 +5.520E-01 +5.535E-01 +5.628E-01 +5.696E-01 +5.723E-01 +5.651E-01 +5.648E-01 +5.555E-01 +5.448E-01 +5.488E-01 5.484E-01 -5.465E-01 cmfd openmc source comparison -5.598628E-03 -1.162952E-02 -1.083004E-02 -1.037470E-02 -5.649750E-03 -5.137914E-03 -3.868209E-03 -1.208756E-02 -5.398131E-03 -8.119598E-03 -4.573105E-03 +1.713810E-03 +2.429503E-03 +4.526209E-03 +7.978149E-03 +3.320012E-03 +3.880041E-03 +1.580215E-02 +1.663452E-02 +1.878103E-02 +7.436342E-03 +3.724478E-03 cmfd source -4.219187E-02 -8.692096E-02 -1.061389E-01 -1.199181E-01 -1.377328E-01 -1.326161E-01 -1.345872E-01 -1.112871E-01 -7.569533E-02 -5.291175E-02 +4.688167E-02 +9.066303E-02 +1.150679E-01 +1.430247E-01 +1.370466E-01 +1.267615E-01 +1.244218E-01 +1.048774E-01 +7.083441E-02 +4.042108E-02 diff --git a/tests/regression_tests/cmfd_nofeed/results_true.dat b/tests/regression_tests/cmfd_nofeed/results_true.dat index 756aa45701..ea1a0230b9 100644 --- a/tests/regression_tests/cmfd_nofeed/results_true.dat +++ b/tests/regression_tests/cmfd_nofeed/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.172893E+00 8.095197E-03 +1.169143E+00 7.248013E-03 tally 1: -1.156995E+01 -1.347019E+01 -2.120053E+01 -4.531200E+01 -2.995993E+01 -8.997889E+01 -3.498938E+01 -1.226414E+02 -3.794510E+01 -1.442188E+02 -3.798115E+01 -1.446436E+02 -3.415954E+01 -1.171635E+02 -2.960329E+01 -8.785532E+01 -2.182231E+01 -4.782353E+01 -1.147379E+01 -1.321150E+01 +1.115130E+01 +1.249933E+01 +2.147608E+01 +4.643964E+01 +2.923697E+01 +8.598273E+01 +3.439175E+01 +1.189653E+02 +3.729169E+01 +1.395456E+02 +3.709975E+01 +1.380839E+02 +3.415420E+01 +1.168226E+02 +2.895696E+01 +8.419764E+01 +2.140382E+01 +4.646784E+01 +1.125483E+01 +1.275812E+01 tally 2: -2.345900E+01 -2.783672E+01 -1.627300E+01 -1.339749E+01 -4.127267E+01 -8.563716E+01 -2.934800E+01 -4.334439E+01 -5.742644E+01 -1.658158E+02 -4.092600E+01 -8.423842E+01 -6.740126E+01 -2.279288E+02 -4.796500E+01 -1.154602E+02 -7.340327E+01 -2.701349E+02 -5.235900E+01 -1.374186E+02 -7.387392E+01 -2.740829E+02 -5.277400E+01 -1.398425E+02 -6.733428E+01 -2.274414E+02 -4.800100E+01 -1.156206E+02 -5.794970E+01 -1.685421E+02 -4.124600E+01 -8.540686E+01 -4.257013E+01 -9.092401E+01 -3.014500E+01 -4.566369E+01 -2.300274E+01 -2.659051E+01 -1.613400E+01 -1.307448E+01 +2.275147E+01 +2.604974E+01 +1.587800E+01 +1.271197E+01 +4.191959E+01 +8.846441E+01 +2.966500E+01 +4.430669E+01 +5.699815E+01 +1.637359E+02 +4.037600E+01 +8.219353E+01 +6.656851E+01 +2.228703E+02 +4.718000E+01 +1.119941E+02 +7.334215E+01 +2.701014E+02 +5.223500E+01 +1.370726E+02 +7.394394E+01 +2.748295E+02 +5.273400E+01 +1.397334E+02 +6.931604E+01 +2.406234E+02 +4.949000E+01 +1.226886E+02 +5.799672E+01 +1.687992E+02 +4.142300E+01 +8.612116E+01 +4.320102E+01 +9.402138E+01 +3.068300E+01 +4.749148E+01 +2.295257E+01 +2.657057E+01 +1.606200E+01 +1.301453E+01 tally 3: -1.564900E+01 -1.239852E+01 -1.086873E+00 -6.047264E-02 -2.821700E+01 -4.006730E+01 -1.855830E+00 -1.755984E-01 -3.946300E+01 -7.833997E+01 -2.523142E+00 -3.210725E-01 -4.622500E+01 -1.072588E+02 -2.919735E+00 -4.340292E-01 -5.033400E+01 -1.270010E+02 -3.243022E+00 -5.318534E-01 -5.082400E+01 -1.297502E+02 -3.313898E+00 -5.546608E-01 -4.623700E+01 -1.072944E+02 -2.887766E+00 -4.203084E-01 -3.975000E+01 -7.934279E+01 -2.567158E+00 -3.333121E-01 -2.903500E+01 -4.237270E+01 -1.852070E+00 -1.733821E-01 -1.557800E+01 -1.219084E+01 -9.951884E-01 -5.121758E-02 +1.528200E+01 +1.177982E+01 +1.040687E+00 +5.586386E-02 +2.857900E+01 +4.113603E+01 +1.871515E+00 +1.774689E-01 +3.888800E+01 +7.626262E+01 +2.534433E+00 +3.274088E-01 +4.541400E+01 +1.037867E+02 +2.926509E+00 +4.319780E-01 +5.034500E+01 +1.273517E+02 +3.215813E+00 +5.215716E-01 +5.076100E+01 +1.295218E+02 +3.194424E+00 +5.165993E-01 +4.768100E+01 +1.138949E+02 +3.058255E+00 +4.732131E-01 +3.995800E+01 +8.015691E+01 +2.454286E+00 +3.044948E-01 +2.957000E+01 +4.412743E+01 +1.938963E+00 +1.908501E-01 +1.544000E+01 +1.202869E+01 +1.038073E+00 +5.487827E-02 tally 4: -3.111000E+00 -4.872850E-01 +3.086000E+00 +4.780160E-01 0.000000E+00 0.000000E+00 -2.794000E+00 -3.972060E-01 -5.520000E+00 -1.535670E+00 +2.739000E+00 +3.790990E-01 +5.478000E+00 +1.505928E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.520000E+00 -1.535670E+00 -2.794000E+00 -3.972060E-01 -5.071000E+00 -1.305697E+00 -7.303000E+00 -2.685365E+00 +5.478000E+00 +1.505928E+00 +2.739000E+00 +3.790990E-01 +5.094000E+00 +1.310476E+00 +7.282000E+00 +2.669810E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.303000E+00 -2.685365E+00 -5.071000E+00 -1.305697E+00 -7.015000E+00 -2.471981E+00 -8.545000E+00 -3.670539E+00 +7.282000E+00 +2.669810E+00 +5.094000E+00 +1.310476E+00 +6.987000E+00 +2.461137E+00 +8.487000E+00 +3.624153E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.545000E+00 -3.670539E+00 -7.015000E+00 -2.471981E+00 -8.431000E+00 -3.570057E+00 -9.224000E+00 -4.268004E+00 +8.487000E+00 +3.624153E+00 +6.987000E+00 +2.461137E+00 +8.250000E+00 +3.421824E+00 +9.022000E+00 +4.088536E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.224000E+00 -4.268004E+00 -8.431000E+00 -3.570057E+00 -9.217000E+00 -4.259749E+00 -9.305000E+00 -4.340149E+00 +9.022000E+00 +4.088536E+00 +8.250000E+00 +3.421824E+00 +9.300000E+00 +4.344142E+00 +9.262000E+00 +4.308946E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.305000E+00 -4.340149E+00 -9.217000E+00 -4.259749E+00 -9.374000E+00 -4.415290E+00 -8.611000E+00 -3.718227E+00 +9.262000E+00 +4.308946E+00 +9.300000E+00 +4.344142E+00 +9.267000E+00 +4.310941E+00 +8.487000E+00 +3.613257E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.611000E+00 -3.718227E+00 -9.374000E+00 -4.415290E+00 -8.515000E+00 -3.639945E+00 -7.056000E+00 -2.501658E+00 +8.487000E+00 +3.613257E+00 +9.267000E+00 +4.310941E+00 +8.682000E+00 +3.778194E+00 +7.123000E+00 +2.544345E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.056000E+00 -2.501658E+00 -8.515000E+00 -3.639945E+00 -7.385000E+00 -2.737677E+00 -5.194000E+00 -1.356022E+00 +7.123000E+00 +2.544345E+00 +8.682000E+00 +3.778194E+00 +7.421000E+00 +2.773897E+00 +5.198000E+00 +1.369216E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.194000E+00 -1.356022E+00 -7.385000E+00 -2.737677E+00 -5.436000E+00 -1.481654E+00 -2.756000E+00 -3.843860E-01 +5.198000E+00 +1.369216E+00 +7.421000E+00 +2.773897E+00 +5.567000E+00 +1.561013E+00 +2.763000E+00 +3.882750E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.756000E+00 -3.843860E-01 -5.436000E+00 -1.481654E+00 -3.030000E+00 -4.643920E-01 +2.763000E+00 +3.882750E-01 +5.567000E+00 +1.561013E+00 +3.106000E+00 +4.853380E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.564300E+01 -1.238861E+01 -2.090227E+00 -2.262627E-01 -2.821400E+01 -4.005826E+01 -3.870834E+00 -7.614623E-01 -3.945400E+01 -7.830326E+01 -5.290557E+00 -1.422339E+00 -4.621500E+01 -1.072116E+02 -6.144745E+00 -1.903309E+00 -5.032900E+01 -1.269756E+02 -6.867524E+00 -2.373593E+00 -5.081000E+01 -1.296784E+02 -6.456283E+00 -2.130767E+00 -4.623000E+01 -1.072613E+02 -5.931623E+00 -1.776451E+00 -3.974500E+01 -7.932288E+01 -5.339603E+00 -1.456812E+00 -2.902800E+01 -4.235232E+01 -4.102240E+00 -8.519551E-01 -1.557800E+01 -1.219084E+01 -2.137954E+00 -2.347770E-01 +1.527700E+01 +1.177204E+01 +2.285003E+00 +2.661382E-01 +2.857200E+01 +4.111506E+01 +4.126099E+00 +8.737996E-01 +3.887800E+01 +7.622094E+01 +5.121343E+00 +1.333837E+00 +4.540600E+01 +1.037492E+02 +6.160114E+00 +1.913665E+00 +5.033400E+01 +1.272949E+02 +6.859861E+00 +2.384476E+00 +5.075800E+01 +1.295055E+02 +6.929393E+00 +2.443364E+00 +4.767500E+01 +1.138658E+02 +6.385463E+00 +2.080293E+00 +3.995300E+01 +8.013651E+01 +5.620641E+00 +1.603844E+00 +2.956200E+01 +4.410395E+01 +3.952701E+00 +7.877105E-01 +1.543500E+01 +1.202080E+01 +2.203583E+00 +2.512936E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.129918E+00 -1.148352E+00 -1.143137E+00 -1.145795E+00 -1.147285E+00 -1.148588E+00 -1.148151E+00 -1.162118E+00 -1.165380E+00 -1.162851E+00 -1.163379E+00 -1.166986E+00 -1.167838E+00 -1.171743E+00 -1.170398E+00 -1.169773E+00 +1.169107E+00 +1.173852E+00 +1.181921E+00 +1.187733E+00 +1.185766E+00 +1.177020E+00 +1.181200E+00 +1.180088E+00 +1.180676E+00 +1.174948E+00 +1.174167E+00 +1.174935E+00 +1.169912E+00 +1.169058E+00 +1.170366E+00 +1.169774E+00 cmfd entropy -3.224769E+00 -3.222795E+00 -3.221174E+00 -3.222164E+00 -3.221025E+00 -3.220967E+00 -3.223497E+00 -3.219213E+00 -3.221679E+00 -3.222084E+00 -3.222281E+00 -3.222540E+00 -3.224614E+00 -3.224193E+00 -3.224925E+00 -3.224367E+00 +3.207640E+00 +3.212075E+00 +3.215463E+00 +3.219545E+00 +3.225225E+00 +3.227103E+00 +3.229048E+00 +3.228263E+00 +3.229077E+00 +3.229932E+00 +3.229351E+00 +3.228195E+00 +3.228493E+00 +3.227823E+00 +3.225830E+00 +3.227270E+00 cmfd balance -3.90454E-03 -4.33180E-03 -3.77057E-03 -3.16391E-03 -3.11765E-03 -2.59886E-03 -2.81060E-03 -3.25473E-03 -2.68544E-03 -2.01716E-03 -1.89350E-03 -1.79159E-03 -1.51353E-03 -1.48514E-03 -1.50207E-03 -1.44045E-03 +4.88208E-03 +4.63702E-03 +3.41158E-03 +2.99755E-03 +2.78360E-03 +3.31542E-03 +2.64344E-03 +2.04609E-03 +1.84340E-03 +1.65450E-03 +1.70816E-03 +1.69952E-03 +1.51417E-03 +1.32738E-03 +1.41435E-03 +1.01462E-03 cmfd dominance ratio -5.539E-01 -5.522E-01 -5.491E-01 -5.511E-01 -5.506E-01 -5.523E-01 -5.523E-01 +5.467E-01 +5.468E-01 +5.448E-01 +5.457E-01 +5.457E-01 +5.485E-01 +5.500E-01 +5.497E-01 +5.495E-01 +5.499E-01 +5.502E-01 +5.485E-01 +5.492E-01 +5.483E-01 5.473E-01 -5.478E-01 -5.461E-01 -5.462E-01 -5.459E-01 -5.475E-01 -5.463E-01 5.466E-01 -5.469E-01 cmfd openmc source comparison -9.875240E-03 -1.119358E-02 -8.513903E-03 -7.728971E-03 -5.993771E-03 -5.837301E-03 -4.861789E-03 -5.624038E-03 -4.297229E-03 -4.029732E-03 -3.669197E-03 -3.598834E-03 -3.023310E-03 -3.347346E-03 -2.943658E-03 -2.764986E-03 +9.587418E-03 +7.785087E-03 +6.798967E-03 +5.947641E-03 +4.980801E-03 +4.272665E-03 +4.073759E-03 +4.305612E-03 +3.572759E-03 +3.785830E-03 +3.766828E-03 +3.495462E-03 +3.017281E-03 +2.857633E-03 +2.858606E-03 +2.449010E-03 cmfd source -4.561921E-02 -7.896381E-02 -1.084687E-01 -1.264057E-01 -1.408942E-01 -1.438180E-01 -1.247333E-01 -1.100896E-01 -7.897187E-02 -4.203556E-02 +4.390084E-02 +7.966902E-02 +1.087889E-01 +1.263915E-01 +1.394331E-01 +1.383156E-01 +1.319970E-01 +1.051339E-01 +8.248244E-02 +4.388774E-02 diff --git a/tests/regression_tests/cmfd_restart/results_true.dat b/tests/regression_tests/cmfd_restart/results_true.dat index f5f22d9acd..1ef9624d4c 100644 --- a/tests/regression_tests/cmfd_restart/results_true.dat +++ b/tests/regression_tests/cmfd_restart/results_true.dat @@ -1,117 +1,117 @@ k-combined: -1.164262E+00 9.207592E-03 +1.181723E+00 9.944883E-03 tally 1: -1.156972E+01 -1.339924E+01 -2.136306E+01 -4.567185E+01 -2.859527E+01 -8.195821E+01 -3.470754E+01 -1.207851E+02 -3.766403E+01 -1.422263E+02 -3.778821E+01 -1.432660E+02 -3.573197E+01 -1.278854E+02 -2.849979E+01 -8.135515E+01 -2.073803E+01 -4.303374E+01 -1.112117E+01 -1.242944E+01 +1.169899E+01 +1.373251E+01 +2.142380E+01 +4.605511E+01 +2.968085E+01 +8.838716E+01 +3.561418E+01 +1.271206E+02 +3.777783E+01 +1.428817E+02 +3.805832E+01 +1.450213E+02 +3.439836E+01 +1.184892E+02 +2.852438E+01 +8.161896E+01 +2.088423E+01 +4.376204E+01 +1.076670E+01 +1.168108E+01 tally 2: -2.388054E+01 -2.875255E+01 -1.667791E+01 -1.403426E+01 -4.224771E+01 -8.942109E+01 -2.993088E+01 -4.490335E+01 -5.689839E+01 -1.625557E+02 -4.043633E+01 -8.212299E+01 -6.764024E+01 -2.297126E+02 -4.807902E+01 -1.161468E+02 -7.314835E+01 -2.684645E+02 -5.203584E+01 -1.359261E+02 -7.375727E+01 -2.733105E+02 -5.252944E+01 -1.386205E+02 -6.909571E+01 -2.397721E+02 -4.922548E+01 -1.217465E+02 -5.685978E+01 -1.621746E+02 -4.051938E+01 -8.237277E+01 -4.185562E+01 -8.784067E+01 -2.983570E+01 -4.467414E+01 -2.238373E+01 -2.520356E+01 -1.566758E+01 -1.234103E+01 +2.321241E+01 +2.702156E+01 +1.620912E+01 +1.317752E+01 +4.197404E+01 +8.845008E+01 +2.982666E+01 +4.469221E+01 +5.810089E+01 +1.695857E+02 +4.134123E+01 +8.588866E+01 +6.982488E+01 +2.447068E+02 +4.966939E+01 +1.238763E+02 +7.428421E+01 +2.767613E+02 +5.287955E+01 +1.403163E+02 +7.447402E+01 +2.785012E+02 +5.324628E+01 +1.423393E+02 +6.895164E+01 +2.381937E+02 +4.916366E+01 +1.211701E+02 +5.679253E+01 +1.617881E+02 +4.043125E+01 +8.204061E+01 +4.218618E+01 +8.933666E+01 +2.978592E+01 +4.456592E+01 +2.196426E+01 +2.435867E+01 +1.525576E+01 +1.175879E+01 tally 3: -1.609520E+01 -1.307542E+01 -1.033429E+00 -5.510889E-02 -2.877073E+01 -4.149542E+01 -1.964219E+00 -1.954692E-01 -3.896816E+01 -7.629752E+01 -2.484053E+00 -3.103733E-01 -4.634285E+01 -1.079367E+02 -2.974750E+00 -4.468223E-01 -5.007964E+01 -1.259202E+02 -3.181802E+00 -5.103621E-01 -5.058915E+01 -1.286193E+02 -3.249442E+00 -5.337712E-01 -4.744464E+01 -1.131026E+02 -3.067644E+00 -4.736335E-01 -3.900632E+01 -7.634433E+01 -2.443552E+00 -3.028060E-01 -2.874166E+01 -4.146375E+01 -1.810421E+00 -1.671667E-01 -1.509222E+01 -1.145579E+01 -1.014919E+00 -5.391053E-02 +1.563788E+01 +1.226528E+01 +1.053289E+00 +5.666942E-02 +2.870755E+01 +4.139654E+01 +1.838017E+00 +1.710528E-01 +3.978616E+01 +7.955764E+01 +2.560657E+00 +3.334449E-01 +4.780385E+01 +1.147770E+02 +3.139243E+00 +4.967628E-01 +5.106650E+01 +1.308704E+02 +3.170056E+00 +5.078920E-01 +5.123992E+01 +1.318586E+02 +3.211706E+00 +5.205979E-01 +4.729862E+01 +1.121695E+02 +3.068662E+00 +4.749488E-01 +3.898816E+01 +7.630564E+01 +2.516911E+00 +3.199696E-01 +2.865357E+01 +4.125742E+01 +1.852314E+00 +1.741116E-01 +1.467340E+01 +1.088460E+01 +9.268633E-01 +4.450662E-02 tally 4: -3.148231E+00 -4.974555E-01 +3.029754E+00 +4.613561E-01 0.000000E+00 0.000000E+00 -2.805439E+00 -3.982239E-01 -5.574031E+00 -1.561105E+00 +2.832501E+00 +4.049252E-01 +5.517243E+00 +1.527794E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -128,14 +128,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.574031E+00 -1.561105E+00 -2.805439E+00 -3.982239E-01 -5.171038E+00 -1.344877E+00 -7.372031E+00 -2.725420E+00 +5.517243E+00 +1.527794E+00 +2.832501E+00 +4.049252E-01 +5.117178E+00 +1.316972E+00 +7.333303E+00 +2.701677E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -152,14 +152,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.372031E+00 -2.725420E+00 -5.171038E+00 -1.344877E+00 -6.946847E+00 -2.424850E+00 -8.496610E+00 -3.627542E+00 +7.333303E+00 +2.701677E+00 +5.117178E+00 +1.316972E+00 +7.248464E+00 +2.641591E+00 +8.817788E+00 +3.905530E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -176,14 +176,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.496610E+00 -3.627542E+00 -6.946847E+00 -2.424850E+00 -8.479501E+00 -3.607280E+00 -9.261869E+00 -4.305912E+00 +8.817788E+00 +3.905530E+00 +7.248464E+00 +2.641591E+00 +8.646465E+00 +3.749847E+00 +9.460948E+00 +4.495388E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -200,14 +200,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.261869E+00 -4.305912E+00 -8.479501E+00 -3.607280E+00 -9.232858E+00 -4.278432E+00 -9.306384E+00 -4.348594E+00 +9.460948E+00 +4.495388E+00 +8.646465E+00 +3.749847E+00 +9.379341E+00 +4.415049E+00 +9.278640E+00 +4.320720E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -224,14 +224,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.306384E+00 -4.348594E+00 -9.232858E+00 -4.278432E+00 -9.299764E+00 -4.347828E+00 -8.511976E+00 -3.639893E+00 +9.278640E+00 +4.320720E+00 +9.379341E+00 +4.415049E+00 +9.465746E+00 +4.498591E+00 +8.656146E+00 +3.760545E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -248,14 +248,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -8.511976E+00 -3.639893E+00 -9.299764E+00 -4.347828E+00 -8.726086E+00 -3.819567E+00 -7.147277E+00 -2.562747E+00 +8.656146E+00 +3.760545E+00 +9.465746E+00 +4.498591E+00 +8.589782E+00 +3.700308E+00 +6.996002E+00 +2.456935E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -272,14 +272,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -7.147277E+00 -2.562747E+00 -8.726086E+00 -3.819567E+00 -7.218790E+00 -2.612243E+00 -5.018287E+00 -1.263077E+00 +6.996002E+00 +2.456935E+00 +8.589782E+00 +3.700308E+00 +7.352050E+00 +2.714808E+00 +5.105164E+00 +1.312559E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -296,14 +296,14 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -5.018287E+00 -1.263077E+00 -7.218790E+00 -2.612243E+00 -5.443494E+00 -1.487018E+00 -2.732334E+00 -3.773047E-01 +5.105164E+00 +1.312559E+00 +7.352050E+00 +2.714808E+00 +5.442756E+00 +1.486776E+00 +2.697305E+00 +3.675580E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -320,12 +320,12 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -2.732334E+00 -3.773047E-01 -5.443494E+00 -1.487018E+00 -3.044773E+00 -4.655756E-01 +2.697305E+00 +3.675580E-01 +5.442756E+00 +1.486776E+00 +3.017025E+00 +4.571443E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -345,144 +345,144 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -1.609029E+01 -1.306718E+01 -2.230601E+00 -2.559496E-01 -2.876780E+01 -4.148686E+01 -3.835952E+00 -7.456562E-01 -3.895738E+01 -7.625344E+01 -4.841024E+00 -1.197335E+00 -4.633595E+01 -1.079043E+02 -6.236821E+00 -1.963311E+00 -5.007472E+01 -1.258967E+02 -6.749745E+00 -2.297130E+00 -5.058336E+01 -1.285894E+02 -6.727612E+00 -2.315656E+00 -4.743869E+01 -1.130735E+02 -6.338193E+00 -2.042159E+00 -3.899838E+01 -7.631289E+01 -5.187573E+00 -1.359733E+00 -2.873434E+01 -4.144233E+01 -3.815610E+00 -7.367619E-01 -1.509020E+01 -1.145268E+01 -2.125767E+00 -2.341894E-01 +1.563588E+01 +1.226217E+01 +2.209027E+00 +2.507131E-01 +2.870034E+01 +4.137550E+01 +3.726620E+00 +7.021948E-01 +3.977762E+01 +7.952285E+01 +5.304975E+00 +1.427333E+00 +4.779747E+01 +1.147456E+02 +6.528302E+00 +2.151715E+00 +5.105366E+01 +1.308037E+02 +6.986782E+00 +2.467487E+00 +5.123380E+01 +1.318264E+02 +6.845633E+00 +2.383542E+00 +4.729296E+01 +1.121433E+02 +6.252695E+00 +1.977351E+00 +3.898236E+01 +7.628315E+01 +5.461495E+00 +1.528579E+00 +2.864576E+01 +4.123538E+01 +3.857301E+00 +7.581323E-01 +1.467047E+01 +1.088031E+01 +2.277024E+00 +2.679801E-01 cmfd indices 1.000000E+01 1.000000E+00 1.000000E+00 1.000000E+00 k cmfd -1.129918E+00 -1.143848E+00 -1.147976E+00 -1.151534E+00 -1.152378E+00 -1.148219E+00 -1.150402E+00 -1.154647E+00 -1.156159E+00 -1.160048E+00 -1.167441E+00 -1.168163E+00 -1.168629E+00 -1.164120E+00 -1.165051E+00 -1.169177E+00 +1.169107E+00 +1.175079E+00 +1.173912E+00 +1.175368E+00 +1.174026E+00 +1.181745E+00 +1.182261E+00 +1.183559E+00 +1.178691E+00 +1.179222E+00 +1.179017E+00 +1.172979E+00 +1.175043E+00 +1.173458E+00 +1.174152E+00 +1.171451E+00 cmfd entropy -3.224769E+00 -3.225945E+00 -3.227421E+00 -3.226174E+00 -3.224429E+00 -3.227049E+00 -3.230710E+00 -3.230315E+00 -3.226825E+00 -3.226655E+00 -3.226588E+00 -3.224155E+00 -3.223246E+00 -3.222640E+00 -3.223920E+00 -3.222838E+00 +3.207640E+00 +3.210547E+00 +3.212218E+00 +3.209573E+00 +3.211619E+00 +3.212126E+00 +3.213163E+00 +3.214288E+00 +3.215737E+00 +3.213677E+00 +3.214925E+00 +3.215612E+00 +3.216708E+00 +3.221454E+00 +3.219048E+00 +3.218387E+00 cmfd balance -3.90454E-03 -4.08089E-03 -3.46511E-03 -4.09535E-03 -2.62009E-03 -2.23559E-03 -2.54033E-03 -2.12799E-03 -2.25864E-03 -1.85766E-03 -1.49916E-03 -1.63471E-03 -1.48377E-03 -1.59800E-03 -1.37354E-03 -1.32853E-03 +4.88208E-03 +4.75139E-03 +3.15783E-03 +3.67091E-03 +2.99797E-03 +2.91060E-03 +2.06576E-03 +1.83482E-03 +1.56292E-03 +1.58659E-03 +2.32986E-03 +1.47376E-03 +1.46673E-03 +1.22627E-03 +1.31963E-03 +1.26456E-03 cmfd dominance ratio -5.539E-01 -5.537E-01 -5.536E-01 -5.515E-01 -5.512E-01 -5.514E-01 -5.518E-01 -5.507E-01 -5.500E-01 -5.497E-01 -5.477E-01 -5.461E-01 -5.444E-01 -5.445E-01 -5.454E-01 +5.467E-01 +5.453E-01 +5.458E-01 +5.436E-01 +5.442E-01 +5.406E-01 +5.401E-01 +5.413E-01 +4.995E-01 +5.396E-01 +5.409E-01 +5.414E-01 +5.423E-01 +5.456E-01 +5.442E-01 5.441E-01 cmfd openmc source comparison -9.875240E-03 -1.106163E-02 -9.847628E-03 -6.065921E-03 -5.772039E-03 -4.615656E-03 -4.244331E-03 -3.694299E-03 -3.545814E-03 -3.213063E-03 -3.467537E-03 -3.383489E-03 -3.697591E-03 -3.937358E-03 -3.369124E-03 -3.190359E-03 +9.587418E-03 +8.150978E-03 +6.677661E-03 +6.334727E-03 +5.153692E-03 +5.082964E-03 +4.633153E-03 +4.037383E-03 +3.528742E-03 +4.559089E-03 +3.517370E-03 +3.306117E-03 +2.913809E-03 +1.906045E-03 +1.932794E-03 +1.711341E-03 cmfd source -4.360494E-02 -8.397599E-02 -1.074181E-01 -1.294531E-01 -1.385611E-01 -1.407934E-01 -1.325191E-01 -1.044311E-01 -7.660359E-02 -4.263941E-02 +4.496492E-02 +7.869674E-02 +1.100280E-01 +1.354045E-01 +1.363339E-01 +1.380533E-01 +1.314512E-01 +1.077480E-01 +7.847306E-02 +3.884630E-02 diff --git a/tests/regression_tests/complex_cell/results_true.dat b/tests/regression_tests/complex_cell/results_true.dat index 3ce3d7cbc7..ddedb07ff0 100644 --- a/tests/regression_tests/complex_cell/results_true.dat +++ b/tests/regression_tests/complex_cell/results_true.dat @@ -1,11 +1,11 @@ k-combined: -2.564169E-01 4.095378E-03 +2.603220E-01 1.429366E-03 tally 1: -2.607144E+00 -1.360414E+00 -2.681079E+00 -1.439354E+00 -9.627534E-01 -1.855496E-01 -1.123751E-01 +2.624819E+00 +1.378200E+00 +2.730035E+00 +1.492361E+00 +1.013707E+00 +2.055807E-01 +1.123257E-01 2.530233E-03 diff --git a/tests/regression_tests/confidence_intervals/results_true.dat b/tests/regression_tests/confidence_intervals/results_true.dat index 6a906d07e7..8ca2566249 100644 --- a/tests/regression_tests/confidence_intervals/results_true.dat +++ b/tests/regression_tests/confidence_intervals/results_true.dat @@ -1,5 +1,5 @@ k-combined: -2.759923E-01 6.988588E-03 +2.850178E-01 9.646334E-03 tally 1: -6.167984E+01 -4.772717E+02 +6.234169E+01 +4.884167E+02 diff --git a/tests/regression_tests/cpp_driver/results_true.dat b/tests/regression_tests/cpp_driver/results_true.dat index 26f07842cd..09f188db6b 100644 --- a/tests/regression_tests/cpp_driver/results_true.dat +++ b/tests/regression_tests/cpp_driver/results_true.dat @@ -1,13 +1,13 @@ k-combined: -1.953962E+00 1.828426E-02 +1.874924E+00 2.180236E-02 tally 1: -9.607953E+01 -1.031898E+03 -2.853683E+01 -9.085469E+01 -9.745011E+01 -1.058928E+03 -2.220665E+02 -5.496813E+03 -2.220665E+02 -5.496813E+03 +9.484447E+01 +1.002269E+03 +2.746252E+01 +8.406603E+01 +9.833099E+01 +1.076376E+03 +2.206380E+02 +5.417609E+03 +2.206380E+02 +5.417609E+03 diff --git a/tests/regression_tests/dagmc/external/results_true.dat b/tests/regression_tests/dagmc/external/results_true.dat index cda6569378..9a6b481b7f 100644 --- a/tests/regression_tests/dagmc/external/results_true.dat +++ b/tests/regression_tests/dagmc/external/results_true.dat @@ -1,5 +1,5 @@ k-combined: -9.118190E-01 3.615552E-02 +1.083415E+00 5.991738E-02 tally 1: -8.430103E+00 -1.442878E+01 +8.862860E+00 +1.602117E+01 diff --git a/tests/regression_tests/dagmc/legacy/results_true.dat b/tests/regression_tests/dagmc/legacy/results_true.dat index cda6569378..9a6b481b7f 100644 --- a/tests/regression_tests/dagmc/legacy/results_true.dat +++ b/tests/regression_tests/dagmc/legacy/results_true.dat @@ -1,5 +1,5 @@ k-combined: -9.118190E-01 3.615552E-02 +1.083415E+00 5.991738E-02 tally 1: -8.430103E+00 -1.442878E+01 +8.862860E+00 +1.602117E+01 diff --git a/tests/regression_tests/dagmc/refl/results_true.dat b/tests/regression_tests/dagmc/refl/results_true.dat index 533c62a902..b49a4a7a49 100644 --- a/tests/regression_tests/dagmc/refl/results_true.dat +++ b/tests/regression_tests/dagmc/refl/results_true.dat @@ -1,5 +1,5 @@ k-combined: -2.035173E+00 3.967029E-02 +2.047107E+00 8.605767E-02 tally 1: -1.064492E+01 -2.301019E+01 +1.145034E+01 +2.636875E+01 diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 2fa79d831e..be1a17383c 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -48,6 +48,14 @@ 100 10 5 + + + -10.0 -10.0 -24.0 10.0 10.0 24.0 + + + true + + false diff --git a/tests/regression_tests/dagmc/universes/results_true.dat b/tests/regression_tests/dagmc/universes/results_true.dat index 76cbc9db0c..aacb7d1ab5 100644 --- a/tests/regression_tests/dagmc/universes/results_true.dat +++ b/tests/regression_tests/dagmc/universes/results_true.dat @@ -1,13 +1,13 @@ k-combined: -9.887663E-01 1.510336E-02 +9.719586E-01 3.630894E-02 tally 1: -4.340758E+00 -4.265459E+00 -4.712319E+00 -4.654778E+00 -4.151897E+00 -3.588090E+00 -2.965925E+00 -1.852746E+00 +4.463288E+00 +4.136647E+00 +4.769631E+00 +4.622840E+00 +4.315273E+00 +3.871129E+00 +4.091804E+00 +3.582192E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index 057a7b0d47..d68c6b11cf 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -11,81 +11,87 @@ pytestmark = pytest.mark.skipif( reason="DAGMC CAD geometry is not enabled.") -class DAGMCUniverseTest(PyAPITestHarness): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) +@pytest.fixture +def pin_lattice_model(): + ### MATERIALS ### + fuel = openmc.Material(name='no-void fuel') + fuel.set_density('g/cc', 10.29769) + fuel.add_nuclide('U234', 0.93120485) + fuel.add_nuclide('U235', 0.00055815) + fuel.add_nuclide('U238', 0.022408) + fuel.add_nuclide('O16', 0.045829) - ### MATERIALS ### - fuel = openmc.Material(name='no-void fuel') - fuel.set_density('g/cc', 10.29769) - fuel.add_nuclide('U234', 0.93120485) - fuel.add_nuclide('U235', 0.00055815) - fuel.add_nuclide('U238', 0.022408) - fuel.add_nuclide('O16', 0.045829) + cladding = openmc.Material(name='clad') + cladding.set_density('g/cc', 6.55) + cladding.add_nuclide('Zr90', 0.021827) + cladding.add_nuclide('Zr91', 0.00476) + cladding.add_nuclide('Zr92', 0.0072758) + cladding.add_nuclide('Zr94', 0.0073734) + cladding.add_nuclide('Zr96', 0.0011879) - cladding = openmc.Material(name='clad') - cladding.set_density('g/cc', 6.55) - cladding.add_nuclide('Zr90', 0.021827) - cladding.add_nuclide('Zr91', 0.00476) - cladding.add_nuclide('Zr92', 0.0072758) - cladding.add_nuclide('Zr94', 0.0073734) - cladding.add_nuclide('Zr96', 0.0011879) + water = openmc.Material(name='water') + water.set_density('g/cc', 0.740582) + water.add_nuclide('H1', 0.049457) + water.add_nuclide('O16', 0.024672) + water.add_nuclide('B10', 8.0042e-06) + water.add_nuclide('B11', 3.2218e-05) + water.add_s_alpha_beta('c_H_in_H2O') - water = openmc.Material(name='water') - water.set_density('g/cc', 0.740582) - water.add_nuclide('H1', 0.049457) - water.add_nuclide('O16', 0.024672) - water.add_nuclide('B10', 8.0042e-06) - water.add_nuclide('B11', 3.2218e-05) - water.add_s_alpha_beta('c_H_in_H2O') + model = openmc.Model() + model.materials = openmc.Materials([fuel, cladding, water]) - self._model.materials = openmc.Materials([fuel, cladding, water]) + ### GEOMETRY ### + # create the DAGMC universe + pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) - ### GEOMETRY ### - # create the DAGMC universe - pincell_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True) + # creates another DAGMC universe, this time with within a bounded cell + bound_pincell_universe = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe() + # uses the bound_dag_cell as the root argument to test the type checks in openmc.Geometry + bound_pincell_geometry = openmc.Geometry(root=bound_pincell_universe) + # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter + model.geometry = bound_pincell_geometry - # creates another DAGMC universe, this time with within a bounded cell - bound_pincell_universe = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe() - # uses the bound_dag_cell as the root argument to test the type checks in openmc.Geometry - bound_pincell_geometry = openmc.Geometry(root=bound_pincell_universe) - # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter - self._model.geometry = bound_pincell_geometry + # create a 2 x 2 lattice using the DAGMC pincell + pitch = np.asarray((24.0, 24.0)) + lattice = openmc.RectLattice() + lattice.pitch = pitch + lattice.universes = [[pincell_univ] * 2] * 2 + lattice.lower_left = -pitch - # create a 2 x 2 lattice using the DAGMC pincell - pitch = np.asarray((24.0, 24.0)) - lattice = openmc.RectLattice() - lattice.pitch = pitch - lattice.universes = [[pincell_univ] * 2] * 2 - lattice.lower_left = -pitch + left = openmc.XPlane(x0=-pitch[0], name='left', boundary_type='reflective') + right = openmc.XPlane(x0=pitch[0], name='right', boundary_type='reflective') + front = openmc.YPlane(y0=-pitch[1], name='front', boundary_type='reflective') + back = openmc.YPlane(y0=pitch[1], name='back', boundary_type='reflective') + # clip the DAGMC geometry at +/- 10 cm w/ CSG planes + bottom = openmc.ZPlane(z0=-10.0, name='bottom', boundary_type='reflective') + top = openmc.ZPlane(z0=10.0, name='top', boundary_type='reflective') - left = openmc.XPlane(x0=-pitch[0], name='left', boundary_type='reflective') - right = openmc.XPlane(x0=pitch[0], name='right', boundary_type='reflective') - front = openmc.YPlane(y0=-pitch[1], name='front', boundary_type='reflective') - back = openmc.YPlane(y0=pitch[1], name='back', boundary_type='reflective') - # clip the DAGMC geometry at +/- 10 cm w/ CSG planes - bottom = openmc.ZPlane(z0=-10.0, name='bottom', boundary_type='reflective') - top = openmc.ZPlane(z0=10.0, name='top', boundary_type='reflective') + bounding_region = +left & -right & +front & -back & +bottom & -top + bounding_cell = openmc.Cell(fill=lattice, region=bounding_region) - bounding_region = +left & -right & +front & -back & +bottom & -top - bounding_cell = openmc.Cell(fill=lattice, region=bounding_region) + model.geometry = openmc.Geometry([bounding_cell]) - self._model.geometry = openmc.Geometry([bounding_cell]) + # add a cell instance tally + tally = openmc.Tally(name='cell instance tally') + # using scattering + cell_instance_filter = openmc.CellInstanceFilter(((4, 0), (4, 1), (4, 2), (4, 3), (4, 4))) + tally.filters = [cell_instance_filter] + tally.scores = ['scatter'] + model.tallies = [tally] - # add a cell instance tally - tally = openmc.Tally(name='cell instance tally') - # using scattering - cell_instance_filter = openmc.CellInstanceFilter(((4, 0), (4, 1), (4, 2), (4, 3), (4, 4))) - tally.filters = [cell_instance_filter] - tally.scores = ['scatter'] - self._model.tallies = [tally] + # settings + model.settings.particles = 100 + model.settings.batches = 10 + model.settings.inactive = 5 + model.settings.output = {'summary' : False} + model.settings.source = openmc.IndependentSource( + space=openmc.stats.Box((-10., -10., -24.), (10., 10., 24.)), + constraints={'fissionable': True}, + ) - # settings - self._model.settings.particles = 100 - self._model.settings.batches = 10 - self._model.settings.inactive = 5 - self._model.settings.output = {'summary' : False} + return model -def test_univ(): - harness = DAGMCUniverseTest('statepoint.10.h5', model=openmc.Model()) + +def test_univ(pin_lattice_model): + harness = PyAPITestHarness('statepoint.10.h5', model=pin_lattice_model) harness.main() diff --git a/tests/regression_tests/density/results_true.dat b/tests/regression_tests/density/results_true.dat index c8e3b1ede8..42dc0c19f3 100644 --- a/tests/regression_tests/density/results_true.dat +++ b/tests/regression_tests/density/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.110057E+00 1.303260E-02 +1.082191E+00 3.064029E-02 diff --git a/tests/regression_tests/deplete_no_transport/test_reference_coupled_days.h5 b/tests/regression_tests/deplete_no_transport/test_reference_coupled_days.h5 index 5fdc656d97018b596147839415fa967031dc18e5..9757c9791be0030366544aaf515276409d1fec03 100644 GIT binary patch delta 250 zcmcaGlj*`trVUlrj7*!Wt>qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d?y` zFYxU3nKj~e3{cP}m3HXDWp;ZQ|M6taZh67#+!d;#c}L-@u1=2ZR_A0{v}>>PF&Det zlRLYuO&NUR?cWNmlWYt(c4j-fH;1`J$+;ti>$Gcesk6$S$Q3iM2RR3sJUGpA`=-;= zV?T^!9e+68n*6g{T~Y7AoEsW%5O)4tZG4Bhc#18|4Ra?u_Ly^Sn|{DEJm$8o#^lBx PamG`VXZ9Ggfb0YSug+EV delta 250 zcmcaGlj*`trVUlrj0~Hrt>qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d?y` zH}LHBnKj~e3{cQ2m3HXDWp;ZQ|Hov_Zh66~+!d;#c}L-@u1t>XR_A11v}>>PF&DdC zlRLYuO&!E5?B5EllWYt(c4j@hH;1`J$+<0s>$Gcesk8c?$Q3iM2RZwiJUGpA`=-qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d?y` zFYxU3nKj~e3{cP}m3HXDWp;ZQ|M6taZh67#+!d;#c}L-@u1=2ZR_A0{v}>>PF&Det zlRLYu>lyCF+pq3wQB~R_E^iCuVisI&aZ$eh-#V=p;i{&mlVlfMLAZ*i zcGk70aZ_wzuG|%HJ?z%+%YWelx*P5-K9A(!tx38kO(WUi9@uv4t=wD@W4mje6ISIo o-nPx&qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d?y` zH}LHBnKj~e3{cQ2m3HXDWp;ZQ|Hov_Zh66~+!d;#c}L-@u1t>XR_A11v}>>PF&DdC zlRLYu>l*?q>{oTQs4DG|au%HSDR_n8PbZ7nH)UqLlyv61{8gv7;*`^aBQ6b7lBYS{ zml2t{=haH5N7EiuNwN#BAY7$X zJL}rhxGAZ<-c$Ny$$ykpGR`=wj|w?rjhJ$5A3-0R&K6{vE7Z%39E7( nZ`qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d?y` zFYxU3nKj~e3{cP}m3HXDWp;ZQ|M6taZh67#+!d;#c}L-@u1=2ZR_A0{v}>>PF&Det zlRLYu>lyUp?SF;#t$8eR%Bdn>ppW_6Bqtr|eBSpVhn>!tPi9~9L&}LgoAa@zjgu26 z+ot(adqSK#J{iqlr+(2{L`*-;;IFNV#)?CS7F=y{xjXUl=Xpr3I@6T;@hXz5q&IA5 zv5cEy3v*>}jbPZ>f0zEk1!f#mJ}-&n;B)b8Tk<2=;U0J`D{lW=*w{{A@qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d?y` zH}LHBnKj~e3{cQ2m3HXDWp;ZQ|Hov_Zh66~+!d;#c}L-@u1t>XR_A11v}>>PF&DdC zlRLYu>l;KX?0<&#t$8eR%BeJ8ppW_6Bqtr|eBSpVhn-HDPi9~9L&}LgoAa@zjgu2Q z+ot(adqSK#KN-zmr+(2{L`*-;;IFNV>WV{$7F=y{xi|6h=Xpr3I@^@`@hXz5j5cg% zv5cEy3v*?EjbPZ>f0zEk1!f&nJ}-&n;PdfpTk<2=;U0J+D{lW=*x1fc@qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d?y` zFYxU3nKj~e3{cP}m3HXDWp;ZQ|M6taZh67#+!d;#c}L-@u1=2ZR_A0{v}>>PF&Det zlRLYu>lrHJ>@OZrx4it+(77d2Va;+yMdwS-ExQ#Ab~|ry6VrX~Fww<=Rzg{#936T=d0$i|OP^!tI-SS7z0$Gn{Z& z?G;d7zJ+(1EzFh03~XU(X{rox4TkGo{)(6!hx6MSk9z-e@j8mc?|$K8+AJX delta 353 zcmcaGlj*`trVUlrj0~Hrt>qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d?y` zH}LHBnKj~e3{cQ2m3HXDWp;ZQ|Hov_Zh66~+!d;#c}L-@u1t>XR_A11v}>>PF&DdC zlRLYu>l=2L*`Gb2Zh85sp>s>5!kXoZiq4muTXriL>~>z~CZ_w|VWzXD+1qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d?y` zFYxU3nKj~e3{cP}m3HXDWp;ZQ|M6taZh67#+!d;#c}L-@u1=2ZR_A0{v}>>PF&Det zlRLX@>Mz9E{|fC}^H}7RQ$@Z&AM>|KPCC;0yzfH}JDo9~%)aJ_loNY4=VMJ9Cnrv} zP4lJpggAA4GMc|m{i3son0}hUUt1TA6^9NjxZ2`!cjD#G^N<{MrYZH~RU}7AZ`jUa z88^ii=E&X}!Ly-Tzuv-2S()v7Nr;jr>-J+qR`) j(yL_tDB4Ng-0b85^bzNuqbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d?y` zH}LHBnKj~e3{cQ2m3HXDWp;ZQ|Hov_Zh66~+!d;#c}L-@u1t>XR_A11v}>>PF&DdC zlRLX@>RHO|e}?w0c`S0usWe}pkNMjqCmrd0-uEGgolcogW?%C|%85Oj^RcFllM_4J zrukBPLYz838O>j(e$iP(Oh3)wudR#fibIDMTy1f=H}Uf4c}R{r+m!n8Dw3m&Hf(3H zjGJN$b7X&w;MvfBm;S;9W*t*LFNx&d^YLt3@*~*c?tddIZvR`@*v?S$Mt-ZqZQHUi j=~Xg+6z!yMZg%nj`iS#S@_F-%&u!mNp4nr<4D=ZQKjU?D diff --git a/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 b/tests/regression_tests/deplete_no_transport/test_reference_source_rate.h5 index 3f3b4aa2ac5c2040059adee2acda433177ff4464..c9c7e9e363421792108b928ada201f80d20a67df 100644 GIT binary patch delta 188 zcmcaGlj*`trVUlrj7*!Wt>qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjW=*d@-m zezIVXJY(x*!=9GOYrDB48NlF!J&0-uNw7aWZO=1T#?MZNPPLr+IDMB>ljZ$sYkc20 z9cH@0p%UoqH0#fzmm)1$PCV*@9!JdUoTM&I%U!2_(Yb&_G=l%Ht;>!}JlhsrZE-=^ J(=UK-2LSZmL|y;@ delta 188 zcmcaGlj*`trVUlrj0~Hrt>qbk)NGsiKx(qJ-G3m*+MXZ8@pb@lyd9T%GRjQ;*d@-m zZn9vHJmZqdhCMBl*LHJ9wv+}kSoI1xGXTMX`f~dt)Al@bW&G^4?^MgFkJEQKHCo=E zw#N63(_y9?94dj%PP6_jdMVP9<;1Bj=yAln&PnppwA^*-7o7_@L?ihB+PZAM#ItR| O)fN|oJ^cdcb^rj;XGiV; diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_ext_source.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_ext_source.h5 index aa09e1bcf4e352f94798f2cc266718b5f77fcec1..3ed38f3d6ce3973fd63e7967b1246c8012ebf063 100644 GIT binary patch delta 573 zcmcbxnCZe|rVR`F>USrv(vX|WXU6~qyH0cH%&q$X=g+=t^ep6Lzb#Dua_|(E`n7U! z`OpUY8PRu^!TFp!5AV8dqXFkLXH|aMzsJTdai`9if9wC*N=+~R;`TwqZr%q@#>vMW z>+M2=7h3)}_}|vA%{uA8q-(a1430%d*ek#d;Kyj&d@wzFTe}eISsP{QfDBqBQp=`JI)^`&u;R?d{==2-s zn85i4+}(om7e3hUe7)&`_3n9-&-csvB%GdVFCu4QX!&=O^UBAH7Cgt6IE(*mwJO-W z!+B#-()4p%W;omJ+hwTxAkH~rf6|xw^SRCkbPHbShXuGq-=Fp1_xl4b?*bke6n-^y zop{ire!6Yfa~A z`G>st!}S=N;QSVAKG6xqjke{loDWa*Y_R=tvTbGL<5t_Jzg2Rbe=QTV4LP>`DVuYd qE#LJSX19KO*iJk+f&V#c|I6bKZ`L*S*BN4Zf-;Mza^!fgFR4sY~=W9JMXb+E@U<;F%eyzpw?}G$f ze)Gy%UgoEkBKXS}J_viL2_L6yOG&csZHnKpC?=%mLfnR=CAvFMvD9oBznV zqnB0S>Nofw-+U=(Kb)WN=XuMA3PU*m=_M_}>1EDPz99oc+Y7dX%{&%x1(U>L`t6%^ z;rwj^>$QDbKic0|`k<=UfA-|_{jxsMcTd!`B(0EYX%U5cO4Fn(^ugf(IDf*fXIeAUe%rtTVWP(z{T8K6xcp-+g@m2Oli~cY z_8Yz(KhX^5UsVyDSAC|*cGsRc8_S~`Y%_B{pSqdfZW}E*kxR;Ng`jP~r~K%tS{1f? n8cfoa<2`IA9-P4cX diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_feed.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_feed.h5 index 284d5cbe4ed05d7404222e70200aa0e0318cf2ad..a147022322a1887615f9000e41992c5c48d74b2a 100644 GIT binary patch delta 717 zcmcbxnCZe|rVR`F>gOe|(vX|WXU6~qYff|M%&q$X=kK^{^ep6Lzb#CDaqtwD`n7U! zdH)9c8PRu^!TCZv5AV8dqXFlOWL19JzsJTdd8f{qf9wC*GE6W2;`TwqZvF>O#>vMW z>+K?f7h3)}_}|vI%{uA8q-(b4430%d*ek#d;LOjF-de|O4|BlPRUiIo8!Ui3=;l_> z&-+*C!_{a1=9RFyw-3%Ybjg*zc-<7vKh5|))cc$#lyAtu(7IcD>$?e-a0MZIboz~R zOyGQP?ruT(3m@!@Uu}9|y?fr|^Zl~kA6`$k=Qw;%{8){FvvcdQXY9&)&ZVj=*Y*GQ zcUIMi-=o>4?fmA&+b2`DoO06kuX0?If5++kIY!TB^^49N8-L!}`Q6rK!!Iw<=~r7O zFJzOSctNZFTF2%|S(S*0C|s5`;f2h5xHBBre&uRhjfjW`SG13b{1t)A-=CGGc<$wL zIR8qJf2zn9B{*N%O<42R2Wz`Ka~{gSpZw4Eu=GCZ`cvw5m-XMRyYT`T5z3O0*{A0H zw|y(K@ZtBDS8XrUEGjZQpa?f$`}FH;U8>mO5mDqhlRNnoA|fiv^jAdgMp(Fe@4O_hH1m{Z83w SSj4ikALmS7KT(zi6cGSL_T?-9 delta 717 zcmcbxnCZe|rVR`F>Z>Q6k%(K#Z^r-yrhI=psusP0^GzNYw1>w{u!YGhz1Cv+_dx&NP4#dhn{A0^(k<|Wh-BsJr|M%h*dKBOW?0h+y;ObZUAK!c_Xg{3q_2+rZhYCYD|M(>>!RckrP`)7pL+cB+gUvh^a0Q`aG5z*U zx^VtBf%V$Htsm_@mprKI^`AZYe7~&sYnLPTmp{prCHEUR$1TG&#&!W<$Q2!!`1IB-Ej;N5!0{b+rRUf2={k~U!{g>uQ*)&PJ@EH%d-&? zv251r#m0Md;PMYsT&2IAGO^p5Gi%Br#(%aq@3aQkhilmFN&Hwn>mM*8mT*7TX*=`Z zwt{2n!_WCwZSQ>Ezqein5fMMv?y6B-%LI>z_act7zf3_y1n2dO2G`ao!!6ADq}sxh zz7Nj7>Gdal$rd9xfBV_aVvaLzP(CmsY;-j9-Sf@i3i5LuC RXJ+^N&Yiq|qAUw2A^@aa;FkaZ diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal.h5 index 271af24103cda8f8c4886da551422a824dcde360..3d48105d7b444cc16f5b6438f97f897d2c1657fd 100644 GIT binary patch delta 717 zcmcbxnCZe|rVR`F>dz&w(vX|WXU6~q2Tyb8%&q$X=Wn@d^ep6Lzb#Due()5Q`n7U! z`TPd^8PRu^!TIt#5AV8dqXFmhW>tRLzsJU|WT(!Vf9wC*>P;{H;`TwqZr%q@#>vMW z>+LFn7h3)}_}@05%{uA8q-(Yx430%d*ek#dV9C#s-de|O4|Bk$RUiIo8!Ui3==fI8 z&-+*C!_~L{=9RFyw-3$_cgdB$c-<7vf6Mqj)cc$#lyAtuuxPjT)^`&u;R;&z==2-s zn85kA+}(om7e3hcKic%bdiT7^=lf;7H{6|M&vy8p_^}!T=jcGby9shC&i7u-xMcat z$~pA#Y~B-YD$Z|SynQld%PA)V|0>5d`FEVopJViFR=?=XvGM1fo!@O;HvIAuoqn}t z@e^A&a^!z zm&5rcyWUx>09hxs&f_`!`Sj VXwNUzwei-J#go@hlw|=$1OPN1;b8y( delta 717 zcmcbxnCZe|rVR`F>gy++k%(K#Z^r-yDtv!CsusP0^9>&uw1>w{u!YGBzt&>;_dx+NQg9f*~E_{a92c~bksbysb}{@;sN=uvyBPlfvZ2^e|+<$p#5;Z|DWeAA1Vyt{JWR51gDodL-~db3=?0l9c<>YfGa2!i|My- z(uMQ43ar=mZT)CJaoK~aUjNyX&-crE#|Iv}INP{)7tx6Eos$?XLQE^liNG$9B=L2kMWFHSAOaoMeuQJJs6-)vVvY{?k8O zspAIh*B@Q6{eOIxY33&-xB*dIRqgfJZ19LU;gjhyOKT}SB8+d$GkZ555pgSi)EBKf zbOf%yE#J#=dW8|3-#w>-M>{qE$_GY7zQGThP)|#^g0zW8_ZB}jh4YuP%(^MC>7%{# SA|unRp9?3ipD4=$iUX#+2(vX|WXU6~qyH0cH%&q$X=Wn`e^ep6Lzb#CDd+-#N`n7U! z`IrX#8PRu^!TAb15AV8dqXFlC%dGsge~*n_-A;&oFv{}$u>Q15e|P`)7p!=l~VTi;Evge%D1qtkDk zV*=+pad!*KU-)4E>eHqN*1P9TKHo2!)37kyp6&2G@nbax&M|>}cN64PoNv6Camn(P zm2<@5*}Ny*RGdG&c>83^mQzj^{#A}^^6xmEKga0VtbWm%W8=>|JHOkyZ209RI{j*k z3(R9V(tYc89{BE5o9(gi=5`%t6VaSgOtzn$CLYwNcm9*T$@mvP+)a1mnv~+^B4SCo zZr5|hjT7L3GQY57;b(PGxcW^med7*YSOMn?x|uY2Emw#0S+bVLP7d<2GwSB&i_`gQ zJ4yO}r$L>DUE&)SKSN!BG{@MnWyivQn?6U1_U8ScdJQU#uY&hR_VsSVN zJeG>jY&!A(IU<(gR@u*yXVrqMe<&KNyDj`6oWDZ*mch47V>o|bqV#$FH-S(-FqR^g s=I%XEfruqnxjPE4$_?Qfo~}9FJWJrCy}=2UnHJG=Ca<3;%L0le0PHO5YybcN delta 746 zcmcbxnCZe|rVR`F>T4#Qk%(K#Z^r-yW_*7;susP0^K~8=w1>w{u!YIXz1Cv+_dx%a14#dhn{A2syJgNQRx~sM+|L?^s^eDg$*#B}e%Yiaxdzb^(xUF!D$zA|=kRAV# zbw@9&z}2tyKfd`=(0({S;m`Ay4;6-R{6&=+wTWB**-qGV;bF=3YqmGLJkO*^A);C4=!e+weTZ1P zCY7A2K5HS|LHcS*TLX*{f$E%~rnCOy0k{LQa}G}kWHf>Ew;UIGeQCQZln;!hYZ(Uu qcNJK|6-ZtZE_-kTVW3Cr%Slr*KH2}%S!Z)VVd3QU6J=RIu>=5#9qAhY diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_only_feed.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_only_feed.h5 index d080b447093018f62b3eced413db81fa606d3338..70a4a3d67a513287b449b1afb36556bf48bbff7b 100644 GIT binary patch delta 30 lcmcbxnCZe|rVVfUnI9~hG&#{#e&Pk8%?cCNFtPyo_5kbT4rc%W delta 30 lcmcbxnCZe|rVVfUnG5_5Pfm1|pLjuNv%-Wmj4VLDJpkRP4LJY+ diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_only_removal.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_only_removal.h5 index 36f89e0090b147be206c995014745f3e9cb6c884..b41218a9b295a14f08c076e026adb858b4cb5b0b 100644 GIT binary patch delta 30 lcmcbxnCZe|rVVfUnLWNvnw;n=Kk6 diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_with_ext_source.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_no_depletion_with_ext_source.h5 index f3b1b171ebcab9d99fb7b73f5b8273ac72187971..71bfdae11234c73d8c7e38e2f6883813cf73f85e 100644 GIT binary patch delta 30 lcmcbxnCZe|rVVfUnKN>yOipx_pLjuNv%-Wmj4VLDJpkM04G91M delta 30 lcmcbxnCZe|rVVfUnH}aGnVje - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/tests/regression_tests/deplete_with_transport/test_reference.h5 b/tests/regression_tests/deplete_with_transport/test_reference.h5 index e8478250be6497c4d6ada14ca8fd20ae217b4fc6..cc616e79102ff6121285cff1ecaecf84b7f932ce 100644 GIT binary patch literal 163736 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
soe6>?;W*IS5G<{kw%O8uQvW&aKBrTQC zCagDS`GYlIb3O1)fIR!)?8yw9Mxye3+qryVF1b|~JD^)=POjY&y1_;}fe=jGbm0EF zVq!&zl>Td$p8OH#%_?w7%X|shiB>Eh7GEIr2<;+wxb5+=`G z?6Y$3hbF>FskiEvG$&GY{PdCWlPt&@8=3luh&W=GV4s&`zLXLA&i?xoSb8RGxxaXp zzNF>stUW#^EIoTB=Qzok36P(kj+WKUZzSYmFU+zrolQPlXO<%A$QrM{!A_ElJ0c2+mDQFy_gH$4Y#iQa%|uDd&$Gq{vEwl3+t|T3 zYXnIb=R+Pd%$o@z#pP8cv*wYS(f$uV?X)0IiuX+Hr5aD1j6N_dOSY6aF|gM#ww^+_ zU7uq{NLrpW-MW+=KgUg4#?ABjO1vl$da!y<6OmUxb*)CcJvkxci`K*>CTX&9U;k>U zTSTA5`wz5sDyDSgt1N&;aB_dm3I0}^265JvT5N=@@}|#UFC+G#N&v|0^#1pMAk9KZjV|1e3^Z% zJe9@wUXQFs3}^Y{xjAK6^lnjdoyf$acDou0i$d&Ke)|G)q?-N3U{fY3E4{9JbIEn$ z$mYU#9ogkX%Gb&H=U93^=PUa&v?VQH>^{GhjdQh8{QBV60;KITW#!C$jYN{z+rSx* z=a2{buD;%T2$NjV6lOG7Etc4&dNgNeaxt+)tY6g=mY!Q8^X&4>B`xQQ;OZ7EJ=aTw zr_UWMMt;m}+I+1?GZ8i++|_rXGpW~CaOU;Z7UT?HH}8ZUvBZq|?n|RKR1!Hl(f-F- zdX}0s#0aWLTJFwu%r<4|$u$1-DC&j)d1{Z;yi-Io@pyMq<(`so1}Iet=1~AIRtkFHI)mCROO|>s3sMM#ZG57C5;$q}HzG!Twaw_gjl?*inNkU_r;{a*ZycSj zz$6P!*7OOfyGgi@ei5iVuZWmr<265yrN?dMhieuSSpF1ey=40%ad>d+lXdmPBiXR6 zocFE4-cJb_5iIJr3oFCsQ2$liI+ z@@IMR{cb~8ad>#mY=WJ~7&TWyL@dR~#JSJk`fP3_4s0*onEA$;lo}maMHn;5=J!tp zmmRx7M7_O{pk7izEIQpM;SNhrZJR`ScV$){yB@TQoma!|jT;nYCqSCz9B-J|(M+7X zE&E~1rdg!NYvc5)0R)-l(Y+!|{U(upRcO(L1to-x*K?)QEIs*k=X0mA@=s>c6(M7m z9@`u0b3`>nNjyBF$GKBY#JveiM-CjbfSe$7c4A_GR{RvU91U9%PaL}Cd|tPvoN!C- zKkX7rkEmMy%_V~+Er&}f8>j>G#;R$}!n0_59=(%x3` z&4g0uVjY7Sb4cU)pCYwgEy$f&G6NLb6Np8RUbGAuUqZ}U)hG2nOV6l|Tm6r+_?4F% z^oE_s(se6*yRQ@>oA%{Nx*TdEY}cKtpA1;dd=B?TTnQ zK}L_uxy#b?cDQkR+)znNCGpVPY(1-H$?cPB{6ZAgCAqerY$6O)?8Yk!+LI+`7s{_| zWRmLL_b$9L;}&uI!>HkD`h~>q6Y6K#dA`Bc%PD)Di+yy873X*VUyzNBw1xk5r>XJKCyhh7tpG$`dtSe_bbke+-PfyJv6Fj^p_3&Vl z2bo#-9?K^Zq0%+kqw|W0p6-z$&slmLmMawnSxQ=JX6yH6^YoDNk)^^58RV(cE=9xh zS^ik2=F3aXBpswuO9O^jkW)(^i6jh9AP)6gu{)hnO!P?|=n=!xBe{93Pxu%~%k5Vu z>}LDpv3u-A<6I%~?y3nhPnb0k+rDP4kbmn)`YPp%S0pe={V^Y;7l_9bt7J}lYMPc2 zhi4RzV)G(VcfR#l6G_XWyE50=^XXKH#X@~D1<8ZeCr>NiV$B!NPTHNs=8@YEXziJ+ zVnLqDe{@dRIe|D)p`7{Etd!`ZHf#!eov_M&vfMG&I$^Qv%p>f)5pZdR_?ciKa@v%) ziMJoO5GF3qeTt`5d8I%Cp(ZqY+X$sn!Y`1yw1}l=@Xq}f>ZX#G zJ5~E$Wv@3Tja*l=e}ypl?!e?oy8%taYxQxnCj~i?G9v3Q2%KY**Y0OD-wTcQ$l(EGJaOjH=-^C&Vq(n|yAHM{Q{P_^J_js}xFdB?}(6XPiv)Pszwd-swvFE3Md>UsaMgyp$H zQtmn{4xg=CA31%L5P5Ed&%Ok+X2LGncBY%8BPlj-?_p=wymO3@8(=awh6p+y`+m#G z62j&~vri_=pL_S8Dn*(}TIypBR_yq>SeMxHQ9_7xeZ0G5uw^4*f9;-A5Yv&&9emR9 z##?hT-oxZ@a#k!6Rd#jz(V7zCnyh5%BbJ`bRp)IBS@E1BrR2z7Z#0XGOAI?CKziOx z8vI_hnFyUEaAVYg*`!*(6aFifT966hXRnsB)~kDyE1d@}D<&qsnENG#rRVOB2uy=D z4?anbaw1rI%w_M-@3TpQEcQAx)Ba{NF;4jL`@WKk$){(>UAiYnkoRnb)Hju1CGxLt zsB(Ywo|so)^n$%Fs8}^){~=-4ymNNMaCRK7lKk*)x~&lD+a!?GytRd>AF}zu;XU)n zmiv?BM;;=`6LuFa?0t5N(5&q@&qBJ4FiJQ4BOm5o3QHWp>X(3<{8dAio;6vsF59#E zRU%(glE1u}n0-cn(Y!^o$v_p`!CG8In`htg<3)^^*glPFau>h}_hcnrCF>Lf5@(H=#HzkE&~3!HUDz z+c(@|?^7ZMJJnj(3XzKiBCo$KYa%v;yz3p3>qwg2cUSm4+JbZ&=yCt6W<1fnDs{yA zic;ds@fdG5-A$ya|n9jr+#&UXvSRh}1#* zf@2?75bDPkxvwA3K*6 zi@jlx#hRCoB&|3yMA-5D>|04Cy!E9G^Ip3Pl0}`H0b4c?1w%W$r^-swPjrytm`s8u)VPInE+`LQ) z%S$7VImNQ#Fzku@iuSugWYw8DkKzut5Yu|vAAT~`kvw`iyj#XOf-H!?p;ajrN36VB zKV_7ADdE~A()N<&PkmIxC3V*P)e#V?$;M~R#+y6EOvT91r%yi*5p5#O#`f?vIp<8C zXc*?*z}oLLZceto32u;+#Y5asQY;(=F(N z069rl%lddmBhfx=ySb6^98&G-m@&;$n52+;x&52Cc*0_&ejodTC4}T8=YV*Yo=JOe zD*CeWMnI!h6I)MCo!glANy22Vohdmow2>&Q(y3GsoKKcmRgbtmg7v&*x9FCGJ7NeE z*{$1S$FtUT+ByF0Ja498qd~C7tG%rF493#4TT*(^>&2{oIa>LeuWBZ8GNKpUKjut6 zI9d^F^TdMuqIzL*)WI7>TK)jt8tF>HHg_?Tz22DU`b~E107=U$7Ht>UdHz9yR`d1+ z!emBnebJi0CL(>yT|8l-6S<)OK;!NmOmaNqVNka-2}Jow;a6|YmJuKK$9}xU($g<< zeW5RFK2>gTI>H|J{oZjZ1KxKd4<=goYkl2FESo1i@wA&WxlK86@P+kEvfBE3Tk3~v z#9hn1?lbmO5DEMH41UJab8qtT==-ew*Pe>>{_OdEf~|kC%MC%2s9ShumtiyU;lcSc zG7WP{&#PuHy*F8qpA8pnoDdODR12<_kX>6sym21)BAcbB`f{{P5No{=JXLENThG(i z<8wtfHxmP{m>69D*h1_)m;O1u-&oRnh0kq6R{ZQ)?0RskdN#Rl(Qtv}NBNvMlysRk zkim+>NfL@LF0f>4D+qoys%v{PObz-x`?u>{d z>daGax%4k4lxhclD`ENbAidXo8`iq6y`xl+?awDq%ynsR5mF~L3b(t|L>$>F`#ef> zKKa^Vru~%x7UVZatJ}xgV~LxZ5}&m^%Lv~cFV)_#^t^wSV6%et{HN*Jcp-K?M;xAI z(X+1rxj|0mXwBs&;wH18-`8`q$hr~zr&&r^kk@2B%pBh>mN-8CjFjy7Vj}a(vwMLo zJwA?0w^gwADc;3fmb3NbZ+8#>C@M_8+AP>@v}zL(Uh{R5Kp!X4rJ-{BUe-D)tFQ0z z>8$lnL7C+VN53*6C1^(_dwm!$(r|AHE6?{hVXw}P=hL6(kA1!lJ+D55U(JJ?peFJAp zoSHrdjaS&?)}fICXuNjHceFcxMDG`5eB>s*T8iEm-3!}gCPCQZZ}M$=SB92hwPTfn z4CU1EapCnzYB?nSVwO&n{?=k_sMRLZyGN6-jfq;fZz`boTgN}t#jnyv=f|p6*iE_; zfWGhCFwb|g%Ed;`^Ks*QXJr-F`*8g4y}Q}$NDVrFA+YPn?lrwNaqaHy)7Hq9U?&2H zoRJmojcW%!)Rc}HhL37qQerx}5*wMJQgV`YzFlqb?%AqB=z0E;+P#kNzM=P1iYA^L zq(ss4{6)vC<$_vId@VMejT2``kLT+zq{dyJ?v#bs&B)el4)6e2E(CJn*@~ zmv5G-;Sq+}yUo^F;@u*ArZIQsG+@R{V^?`(#A4HzUMauv0r|6a!@fDQ|MY$EgNM8gHatN7h|8xJ z4)sCf;c>@yOa3>+uRtaHxpS83aN@~KdQij_87*AJ>g)TTgOH zDO%x*5_81dYiqFx)rYxO8Od10>f2G%kE8cHNmCftKUX4t-K~}wo1u-~Po+E)8Mj;+ z`M=)%#pe8+IF5Z~rC~K9i_rPphV$Md8m_A0y2@8)1$LBTy5(alt=_WEFN!#1mzFW{ zF`w4h_6w}W=C)aWnIV^gjW4k>dUylnL*FS;!F!*g^JddMWS%5=qI}qIt=gz>vrs-f zaN_Potx$x|M@OF;VQ&qNf6wNec{XR>NIYdnoRLgX8MaP&r`vNgP2AGjuUKDaG`>i& zN!M2IBR1>S{e`kCQZd&}*Va}%LgT$Qt>ZcVr}Hq09ljGva!~#mK*W5-wjjP=O`BpA zI_eh3{^gV3l#aTi^G)3|#LJ$ZHOK1}HOt$wORy}#XQL-{ABZp7He_hQ0xR6KQCg?& z{RiyorPhtdS0`b2(*~reuSDmUV(yO#-t(-LqyI)=(}>~s(D$9^%~SLLJP+aHlRS16 zqvSeAUPV>O?#O&`PJN-il7g^{1^&?1#CFYa*7q)B!xpU=qKunmej9JEg5$nhtK0F3 ztnb+!wKA#mNWqqF8QU`6Mv&89<5`&AeA!2w`m*6+-7`A;IQh>vCP5(Ay@FGpG0!{e z?Lc3S{KOWmm+_1$&iyZ&gI^Ad(8FV$hetPu6=SzuE-o9-I^S+TbkGXz1~Xi6`mxd7 z3|Ze3&rt{vxxywM;TW<25$b=!}xwAiQOjOO1zS8Ft88+pc+q8vbl&&IPYH60cU1F7|m@hb=q2 zb#qEcDrW9{{OizcwB9J26clqJ0G)r!w2BL9AH0{--(!BGSg&}|{5!QB>)(D7#k0nc zS!!xmP(ECkT`@VeR0&TNG;e*bQjV=WZ8zw%z?g7yX3g(p&!YS-X*jVU`x5s?C- zBx^(2ud##M)rPFT|V~+TVU{C+N6p!?oCG6Di$BvT}eHuRQDgNd= z(jWCGx07j>h+ZlDbt&+)I8hKOj<@CN16^<4C@t<5gJM^O{O+ogVX$yFt?9}?5O?!f z-DCSwpy<8dZekz8|DT-aQ;u&z`dn|sHb1V6{MUuf)UOdvNPpIMhJ+UAqj+`Lhh$-J zPo5&bFL9p79L5x2V8gd__v#106-U-b8O{>$vqea#hOr(Lpkam|AEhsHW-Ysrf8tFWPPHK+Jgl!~Z~GjD`eito z6|Vd$J_aMb+iQa4dx4ezg>8e0{4iu~%eIvy4ahZnr8q|U572rYLh@J72iKcKV&p!d z_^`xJC`|L#FUtC`L#NO0(MEWv{f2A#lo*;%kM~j->zogueEyf1yh>D54~2hoxwFg< zlX&0*`-YI}svgi8>gA;RgA0N!axABrWMTU^^+k{Uz2E|aps{>gF(AiyALt!H_SKdb zJoo-M+8+*bFBXx6>}#CmJ0G3>9Od_z7>pF3-9`Pb8SkWGCN@xi;M!0i_~M}k{m!(m z(5VjsTZJN(#8DxbbRj?Zs=N-|xbSC9{p1)ptjYA^-mP-LD|NlD&KcnwR%cvq(~SC0 zj=bsOFHS=JiZ@hWes8^u;(>u%4y}!yRh0cP{P9(3Zjv(ZIQ#!|LMc8{}+{?7*Vo=0s`>hMH zI9#`mRLJuf0-hBqJq3CtfS-@^+36oBJ{U0I+Bo}sj6$zzXHw5(4w^@xt#>-yD~J4n zUN6IR(ohQJ^9;jn0L~-NZs6YKz~XZ?)vacPUz!Yi&O7};c*qd8kRdaQ@X#&5Y1zL4;h}(_nVTR7 z!b7hQ^1t|%g(>_wILr(^WKoCQ*GCRYbq#@|Dt5KR%rz9}z9({QK^O8%oKSxJd=mKI zteDT%`wVO+7Cstqqy9^~joJ!bCv;!OS&qWDUHwR(PYp);sQyOhi&GoQ>0$h+pObbh z;a^0-J_4jF|Ye`;5l8CCnA zeze7wYx9X0wc&X3)}5D>d%+ynr4!ke67ZcmYfMm?Hhi!rTx{ycBDk5MuP^Uj03^4~ zPe^njdG~1xdAI*T{j^V;dYCPHuTuCKaV=LIAaMVGeMwdYVWD%9t`z=*%wL4vzK8lT zGk@*ATlGKy4$Vt%tvu5UM&h)AkR)rk!M9@cM7_$Im7~>bt3uDZOH#{>sq7 zgbU%x(y6+RQA2dTcy+jy_U-`kUlBY%KYlneP2p#ldds)-yO94f?No^~BKk-F$FK1l z)_^KL0JpCv@C-{1fFSV=H)<7eSZ8`9icw1s(la~!7AE?OB}AxPUa6D<-0D8Je+9ye zRIb-*yI9cqG^~>`_isAlXWz|qrSLcCK8g$Ue?7Owp!2DQ9kXuDQDh&*c=<9!7Y`dMojH;s)xUw5FRdUHqL-`8?y!s;%c5(Rt{aSl`4OO*L3?Rcx;= zao#ya!*?Iu)dWi8zkv_bZQ^L@w)ekc5l}neKB;ajP z4X1;Ay6~dG^f_hjWiUT;@X`&3A~2D9PDlC;@~4-u&q=fY$!{#}9=CJhL;Ps9EsRA7 zBYS7wtKPz8j`Szof^m!8f9^kX{pN9Zu1Xe4*CVhQlfkUdYNRe_`Z!F!{5c2d^k>2+>+~i@FVX`VOSPAKRRB& z)3NcN``iQ~6jL&{OHk-ZEI(w6;ZlZmiGNxQlKa6-SaU&ZyCe*)EH4XxM$BjRaq>Pg z9R+V|<1U^%TLLbbo*GCoK=Qh1aK`Sa4bq?R*0)wy6p?+ICgd{ji$(FxxUyQ=b$gUQ z>~It^Z`_UI{p@ecGO145@UD+=>|G+?a?kKZa;vf^3@)wkE{i9_gA(HpI?HCjt>NqP zA{!;3Iqn$is1NGjmO0-cIO6t~vc7VS}4 z!OeS3-!-9m;mM#gynSHsP;9d|zZCR0Bhztk9)OCno}H^|b6{e}n(T84Vm|aKSKcli zgg@qi-Tnp%tCaPo`cJ9Hq{LD7r~k|)(Kbnx&ol_yb?-_z${+p-cMp2%_#b)hGj-;z z-VKwM)T6bsd%^h0+gBF0iow79hmt*i=s?3}nvb@3$AFl6=(8cqd?3X1mBI2E(jVIw zwb%bLBY*KNfh!{KKGGkIKHfj=Bf{T&WB!1xYsg=`SYu}X5yL`RkFzvedZG7jSk{;1 z7RcKR=sfQj-rOz@1svZis5I$9E-Guo+j{?iWBWs~QO;sem|mU|QibqvUFLk&+$`c} zR(s&IurI>HbK>4Aca9)=n3#_hOZ6gtk~t?T&Pa$-_*p(qe=#*i0M{e~heV zwSSAyQr6G9)wyNp`4`IHx%;=BvwMW%4Po;^SK}2`_&zgr6;Aa5&oPnH8$QzTZ|{tf zq3j`eSWul`N@p5~r0k8RZ7BuYU9sO!AN*&3LgRbfcBe`EQx*&d(?mw%@tw-`|9#2U8v={LcNbAV;up0fI`-zKuOMys# zy0^|1Jk&vWcroCsx-AuiN^>!$JQ@RF$xWKUpjH%myT82H#H$O>{!t;oX9(QcCGz{_ftt{xUP)a>q0l)d!OuR2P&*(fOyN%FSd_hF59mmBniMf&7JAm7kr3A#1^^ckc-dUh=uh z(JDecV8B9g@|L$49FM3o@D9cy$1$pD@jIhH?rnFW{u=^xi$2z)kAb% zR;SgcV)=&R)zn`2$dm)g3pA^cg{~ui;TtqIdE!6*eetsUaO5LFsIp$$;n>{`%>_>S^pE#YdM`i)pfU5*P(RRfF5M;gZ7LF z?_NOu{mVWv?+Xvm`Lv>Saa&kCsz>#t)%|T1mWEa%*1tRzh`QUVk-n3;GU{dw6&t>{@Abc|Y*X(x`uln78*z$W1n#WuzY_oi{8^s$tLiR^LYNn&` zFT~vbHvQ{o%HIK{zw&baA^9`^a>%xJBkVd-j$1gUA8c>!ky*`0CQO_fJ2H0VAT&ZB33 zIG#lM^T?%7^4e_Hmav+S!sTmq)VWD z-tgo%?{;7G{~YhjRjT{>pi%h>o>b4<49C4g`bhv->mvW z(0!>iw8M4KCks-oMSJ2s94u zEqynK{Fg{Qm6=T<@?UWwa<`JwkpH^2-!Xck3DuVq9!Y8am_Yt3%=8m!`&|hNf5G4H zUAvJe1pmFKvJLpz50pATjn#zFA7UY7&j& zgR2d3KYXque5TSq%{b7A_D3g3+9c8z<-@;8w(sy_L-{(-6ocW#&nRDOaCwj%GHm})hEO~=R*gVbBOuk z@J@%%Iz)ehwZ(0_$ZI3un0RQ>;L&36>{5taJ|n{C1Mr}q&ph&9{ukcG3CSUR&bE)s zi?BiGWrx@=2Gd2zzbmI#^6Z)rqU_h0k3z3Wh&)`g(k3&q4}zAD=bUn(7!=wUx}HJO zg>noM3sidUwnSNC4e(ZJX_>Tzx|M9S;XVnf+_<33q@M^l^CMAA2HkG8K{u$*DO{$Ya`GOE0e%d2G zW-N*DgGd)sNvz!YDr8<}G20kgv~i@4Ed6kmM_h+aT)Q z1q_Oic^Q2lycGT5{~N{g(U)=!cRxq?^JsNeS-=Xd|8B;gu${CO6#k8Tltr75A$o?I zul|K>h{M_)(zw+^FW`=9{v^*&+^=HU|1*$BAI@2Xq)oBT0_h&hpR2aTz;rR2h3*xy z-`)4petcU){**dH!Hk6->5p2^U)}d>sD7cL)49G~0iEC9?8c6XIH7#N@s$j*fn$4M z+Yc_b9m9hl?tupTWU(}CqEoKanb(I)v|_pUJ%)kk%hy9XbOoS?hh+WxBJvkAW1d6F zT?h|7`8k5FE~9u%AD0NN>zJj;Z$HC%sbyvqAHMKtsYu8}`rg;EY{)aK4!^27O1#zU z1y`@XTqx>&N`>|(%QV(%avjMlUD8aa zD;?z%zNO07eR4tk7=POJ;d3UESG+{_dg5UeKijVbag9Azg-3#_?;J8E;`xt>T`g|n zaJuox+x{2&@MwD1{rfLw!1mC@tkX|Q!G*c*dcmj}t>15+#J!zN{J(kU%{k}I^Gd*H zoHFlBOgo3us+nuqZUpp>4N&0>Lpp!VQf9EkBUwJbuQ}m|6!-m-tT)D;NR0dcwHIT2 z(;JyJXQwbuAv}IR^aDgO%AcoC_FPnY#4a zS66)g`yVdT1{1uwsOFQPMj=MMRz1GtHiKpUl)lhF&`FiEwM*zAk?l<`I?@ny-i~rT z;^$+)AN`A6_;8w-i;16(oXYSZ=ABb6&sLh?&Y6sKDcZ%DDdwruxjc&npBUi#M$k#e zqczgXNn};kPg&atI=XfDcJE82!9SE^jhDABV4qEC4DjF!xJwnwQ?_p=c=bCDynQ|& zd!q0}mo|E@fmFHj8ch&vNL|PvLRzu(HQUk;nX{Jz7V_Tbc%K% za}ryB#K*cw&?)DSeV;W+BIj7KC-D<>z`IZ9+}r5zM1yk)NrH1&zaq`8cAe}tcQX-2|CK>0I)5j#ivWs zGGrv@u-$zIuN{uL<7P(2dHp3OcxBt+smX+VjQPR5g2vuiOo%q?U=zVl?J4Wr8{bIe zs|%xl7zjG$&bRlcP*LG`)_lkHs%Egu{mR-G<(+V48d=&OZ;WvxXGV7go>J^GcO$Ql z-xQ`7&WyJcbj+6KBqira%g32c@q+i4@U9wS^ zXEMRhHOrsDWQs7JtdZFPvuVuV@ATFdg3j;npYNLulgPUah2u8)S!ZIcjasF}8+~#t ztgp;t@AtOt?A3R}_lNB1R}2}nmr5!{|Gw!?zCR^Bd(9W-4RP=tJt#kou{L{vzWs+J?^dN?eUvq$`;>DOz_C7$6hzbmtm>eroKD^ z6W9|&y;qz1%+zeTTZi^YSD4}N6i)4w z3_gZ8k8mya_%`8hjdi#LM20AO$mab!oiBkzCM$@h1`~RCJL(z>`x6@c$d6r7O*V5_ z%(Z_U+b5jyMG3m(ua`{l+^@W|vM%{p^rYX-abkah_4PFd34TPT!bu!sBywMkNZ+QN z%KA{rH0jXb^xqe)j*iV>tUn~KX;-=9(q?(NR++}Q!h?xakdlWTbFYxFRG-CI7?{3g z5p?<+T$Q4*TYS;uzvtmI1&efuEa zAu_hb4Hq|e;$TcS!F_v`zmMN8!)D~H>sA|Pu+EC)ub&7yr@r+_XApC^KSzsmH|4&% zG?MDMl@|XaS~~a5mzX=#WjlGs(go*mteneTFv0)OMjfYqn~$Y@E$!rFAm(cm6A#4_ zbhdbS@}KM@k;kaUZc-6+nwO4MKOyMIe3B0`emaNAyKI#=&2+|nCXGiA-ZsJQM}9v& zHkFT^Nq9DtFFcJ^y!N{=M9{ejxlgnc`+S4f;yOJ+Cq+&8M@BClZm)9FCUnmNR+kw$ zawg6lzo(tAY9(Zfvrh(m8V}FMYGu9lrgP3>*~i2jdI>r=1gv|?>PX}r^-dNn1f6h8 zhZm08%a}zA)9bf1Ggxle52tumd)({b(79jggnfzJXr<>a#d>3;nx=TiG1o>x-c7kP zvIlN&A+eCfs4K~v_+!h^xIUsWj(tjK3Z+?_!rE^>R@K{WjCWMp?Of$1?7b;E$eYxJ zlYENYpS1N+^l;tvHNV4q68XsVZv9X~57#5wdWEd1@KYC#^u*FHV$W0x550)Gfb*4y zY-2Dm!-oxx?y)GBW93#0bPCIpm?!uAj=uyya`^mjnRyaf=F-?A6T#2fUYB`;;|%!3 z$(%Ry)brSOo!V8+98cVsmUcMfz6pNSo<+w^E(iOO?$6P4VIJG{f%U*If{rc?M}i>1 zPx1GNxJ`ed`u#o2G(9z5cF$G8nQ0Ew9v+_J{pf_Z2;5%P;4#JN+?z1Hx>9Uvk|98; zc?x^;>fniHg3k4hcpA$I5_wHSUT9N)5^s2h(Oc8t3}tnHX07M3w+g{$uc^4>%eCu` z+Onp2HnaVUpHjtGYn84|H!)|B(rTEu=?888_G_jQc&Pm@^yn6XPV3M9owi1cn1R#J z=-{w<%;ha}d!~mY4nt-p>^V(w)_3s*yPs5JhL>4H&nHe{?4S4Pyd&s5uQgYDP2gd3 z6Ytoj9{#O<)%&!D4)=Sx7Pwty0ps;K#ByMV8y?J;@8F$iip$MNtk*J^V&fmL0D6^K z%=vb$L@q(+;hQU_No^#ua9+;zJpEB}+|$&!i5y1!p#F(=u($FPtZ|zERd-EKq8kOZc^nS_z4-lA1b}-;z~3n~uO=v%;xCSgu4s`7Jml~pDp3n7YfikXZEvW(rC!YpJZ#3Mou;TdKepSnhl;LN-~>(d>Z@r?(Mg?2pd zrRZUc!$@XcE{S}~rm!=F&_ny5@fzX{#Qbd7)|p_5dFt%Wxy$K!_$9Vl9RWA1G%PCini__Ru?t1xhg3dVht|6(HM85vxOZTR~ zur;(aU}K=dpH3QuCHT%_rXP%%0=GEgym9-~pW2w<0(9YLfBw$LK972x39y^QvYaMp zJ2&}}wEe5SNFv`^>owpa=+JtCN0q0H@rVywUo6h&Vq8s`A02gOu&`DOyKaI`{703cSA_mF9IoB9X{Rvx zjkLy323%HSTa^jl0;Wt;E)h54j<@Y|l&CyxhSw(G?JTsI!{&AxmbVdf zVxQmbjrdF=)AF!=SR?e1v8=lNLERSIU7>Z~DsfLjs-iOc)svTSQlnw%r*|g!_@h$K zz$f`w!QPBhuJ`9K9}a)g=DKX|Cmy?4NceZfLPbV`pVXql%feQ)c;}AWOVKlPSW`Fk z7n<`I@%gH%z{RVkc*1e1E0-0B{fRg&>c3|iOBeRb-jw@Jt9Yf20TS7ONtAjMSEma! z!h;EWI9XT2)ctV=8`O)@;$yPHZGLdGAG>Od_X_;GzwojISLdOhfsc`2rggOs`y5YP z1!n$A?+&4d{@7QVIcEkueL4Kg{)$=5I`D2v=ZZV-ta4N1N}36-*DJ~IR+o*Li>w88 z^3P(W61`QMco=f$tooK(5;>vv71yR83=LGbEX=0DSHZf62Gu-9;-q`|{LMxD7W;!U zyBtmM_JhBAi^mJGvGXML_}nRs+Lh^QN8BE_)bMx0A?I zj#{mo{OpanGIDk|9iG&7KL0G^9F{$%@=8w68#fJans~m?6u-{7Y%*s+%n8n1GqwA< zfQiRiKI$OoaBYyg*xI_v!oY&ooOF!Ep z60~I=yEA?IkC~?jUVGahLl+RZ>UDh4?{5}nhw~N*vCm<96o$Pvw>@Jp}>$mbS$@c|4wC`py zF7sLNouCtFp!2em(C2Ns!Tp=KaSC^Mk@=IjZ-M^OIGflkmP+&RgtELFF5AJv=1JJs z2Az+<9o9U|^W)BuaKRajotleg(_hrHWV8(t`yAkx%)CiwhGQ0Ulv=>PKl!@7%V!=t zo|h5hz-fgyKHpdyu`|VM-31)iiz{%x1F0tp?;<_?>2xu-IEF<25cqo`g3!aXx^y-@ zYij&cV!HJewOQ;$xzTr`*%9A2?(WlJVS>jd(6$|0$j90&54$l5&0tBg?dLb`%hzoE z*vW2UPH_H;1}(wQ;mSyvf9^DR#3fKC95aXI6@g~=tn z-FBYpHF5r`GkK{?^)(OcVqA7A51GYoHq%9N66X|)qn^^8MI^Flm`CsCc_-~r9BpJv$vKVBStPTu5)?^!jG zrzMeV9NtoI?(@E*x{g>eEnb{<$F#|E4r|v{GF4e|#pj}v%!`~&aH|Wk2eX{=u~x&K zyHtsLzt$w~7Znh6{_YQt=pfFy%XHD@oBJbIKJQo@v=x6fV#s(udloZd!+6cY-SKL9 z;cN2LCipPZ$&i#2*_hdD|Gbmhv)JW7CBHZA-7pASDIJ$ z_R`|O=DFz%=*+Uduz@vpYNkEBGK;0bKHscvC!FW1PofYJhl{=Kk?bxm#Bw8o+g$HX zVO6_#__h*sj!%?_iV){Yo+wYpO`OM{>I}3+PGi+{Ctq6HPh;;mIFjQJTHsp8N~JC( zo8UU+;9JKg}`q9#_hVxk8>gTmFcNg5~aL~!!nZ&trk4yL+ z*HSER{SWs|yBX}(&$QMYg3ju%;k<9exnO`J$as-t z+W@C4&cYLE65M8jXT;=wBsrC0>ZNZ&&pw*QwpTu1A13Ie4TrpH=_1x;uByH1cRbFD zuzn@(X_+jWe9AC5i(T8VFx9Z=fpZMb)#Xo^;M}7f(>wBWFrA9Eu1I43JSWmcX!Cr* z{e+$rUP7Ex%p^*;6LebA-tH;-LyJdx-o81;IgdFD-YKYDGoMCf7vi|hX? ziZNFGOp;seELOjrnYDzVBQxD0+Vz7(-ag!j%5bs5&G5vTOXtB!SPrUY@YN zo9l(kxj#;NyJCzh-R>+Wm1beGj>jbVJ`wS(`h3JVLFabFN_*W)5;-w?VS3es#8%EqOw<7F*^wr!nmPlj#jgjC-&HYpBRwDkn$7D^vxh|%CVl#VG8Stx@ z5||=mX0a{<-_kAf9(ZI?a9zk*6MSOGtO|?I#=@Tbs2+Vm_<{N0q)or0|LGBL0AZ&k z*TmH}{jxtj7J(-f`QaAN%U^GjQ9i#!cz4OC@2H*={VtcxB}Mdiu&tFH z`qv9~4h|_z{t|>yM-}gm4HEM;ED35_|AxS_FOANkPdPa6<!DB1+VD(%s-0rJ#AuoR7 z{XV|{pWQY%Y}qQs@=k9892VX0Ewrx+m@4@>dI_WY)P(jYfr0<@=k%XW8?7RvdfCq| z1DV*0pFhR>=g^wY%M{{C=5^DLu}H72sV zP`zW1m7VY&(iO_*kF4o&6se+qq8&#aYNF^xVLk7MTDQf1V1CBbPo;$$F1EA^N6pB? zv}d$0>YsN5hqkX5SlG(J_K^kev|3ber7n&AVaSE#rOtfGz;PDItJ&#SB}hZ_H6IFP z#XiKN`W;in#WoHnDhhwaOol#>{4w}o`$|UCz5(!cyev*sNf<`f9w-a9z~QASZ87PH z9&ksP2OND^1~@t-G6cmDKQbOGPZLfeeyq4&&mO;k`1$UtNza#y>I+YVN)EDEA$gVG z#dlRTpn5g?TGhw5d-lLSop>dowjS`UZmHZ{T@?O%>t0cD8-r^c!69@u1K`jpl7wn> z5uiUXIcMz`NS7hgPdYu z*vWL)c{pFzPpd zoj6eAyCx4EJQ@6Ti1(CZv%Bj5*o(sKx5)|)MPxW_d@oE{X91LcYcBETQ+oa80pOrHYImHk64YcIA8fNnc$js{ z2!ox7AK|;QVOwL-Jg@T?j;?(ks9xAzUj&kWeZNB=h>G_3<)ICCohsthsvH4B^Fdutz7zoK=+1)VL+JZmJf-Zx>Z=s` zJ8pg1d#V!Y&w+gr&-gwddsk$3KD5|@{Kfv#KM7^r!j$hn$?&u|kSz!;15XRqp6Uk= z%wAZ-On&GZ`>)x#S`*U$+NI$BW)`sM)&*uWmV;N-#l@M0NPhxd`S*mKMExFn1(;t< zRU!S^#-ZSH;SZ{Rldt#Gf4+n4i$(bT(W{!Mzh*gp2eoUQ3|x|VdFg2M0C-ymXD)Mz zK$d&<%=b>?kdI}d(V5f_wqE%6Siijjgze!{GNnWKFGjDn&dc0LSsz<2Phg1|sz({qu=k__7>Dn^v%e#Pd|r?cnAEYsozR32o<;J-`%+j*7#4( z|4vqcyORQUo#^TViTJftQMyuql_mE*pyH*_lU2U)Q#Jzak5sdM*ZeC~kG9mZS7kbk z-XnKenJ(xJNB--v!6j{TU$nk!fzcz!4Yc8eg#r{H-Y@3Lq6^E|B?eXhZtTq&)`gGM zxUdr0F(9R}@;bq~7#z=d5~vV~%l*0}B(Gm~W3Gf}zkvod&zlZuI zO*gio_bj-DUeM)AXh44@3(?2h`a$rv6W#VHl5pRZwQP19eRwWXq4MmNQ7|7Wqi#G< z3OemVpE&P9_4Q?Hk$1zXsNcRTy#=fBNBwUsbEKXYo8cAP%5sR zE7lJf7G_uyoJ8S4Ih_x$y>a;d`;zqeKcm1}E0fJEtP~t+1!jA0B78nVDp@TxSfkKe z^ZyHKmJvRKfN8sL(;}4rV=3|PZgv+?{jCV?Z0>Vc(H7xpODb{;*DLtl6g`d3JR^-*(Pb9$GDXF0N?yfwmnZDXy$i zaLl64M|N5d`tL2g!J9$cN8viZUv8!ZMF0C|aFQDN$2%G0*++c;P}ch~HZu9KG@56@ z1+V|TDTDA~dj4i{aLNK!}>`Q=})nm_)5+O(w{3dXS_6d z(D~w;$j$er|Iwf2`Bl3D0fbLU_jj6x{?dbLhhH%!5q*{41ElvlTZ%&J=(L0Vt2q2J z>UmP0e+-D1%#jWg?-#r0YSP$TL+d>yqW5;sA%utGLO%20KElKGg_f~WMl{dz=FFYm zFH*?fX|7hEeVB^uz3xiQQ1wAU_^SP-rL|HocxmD|{Y6_GKJD%e?^e-;GHNk?Q_O?l z$QZcGwp0S13EWWVXGZoJbullCAp!O0NN5HtUGYQxIo(rqyR3=(Q2y6Xzr!RocEbq8 zV{TLh*`goN{yD@JeyaE=4_h9o%PoBB13Jk|jzIg-jqkEL``<^Vs&!e$F9PF>qyaD;CX7;re6wjNt%5FFX zAb)C;HJQe|p${cQe>F676Ys%QJbZCEP8cRz+%$^+tpkO?#Lia#K~Pc|eq(&C7;N2g zw(m>?iVwSg{c~gtL+52fuiesghfsW2eD3VuiF;^&ECNb3zD%L`kVXA@a*hJ(@4lt{ zXz*H_1U!>sQZZrK2b65x6BQ(d;F)v&zwiFhhLW|{q<5MP1DyvK#w#YvK->2?9u-xD z&;O+S5C7yw_?%>EZ4P7*KIiXIEcAYk;y0Beq%^s=$e&j7-#O4@kK)IngIBI<8e|KC}sFb3j{Jr5uo- z##sq&)NkjO9C>rgf9^9m{@vXrLk97~W%^Lu%KiXkRl5H3ylx+OaZ{_Zsb2)HKNmkc zK+OBp{Qd1r^L7Y`dAX#p9xehttfNJrGSPb9klaOQ{vdm|@4C!$ss-WmUJ?iA=h1Nr z{_s~!u|7P9{MUu+ib48C$X>Y>`@ACUWZ<6chTwV8UXYMpsy=r_4A$=pIOM@bhNq1@ zQ%dv(fm6Ip>G$XYaH{p|JAZSeKgoyN{w{JN`)c-SGoWEW@$=CG0p)f{=sX;5{Ve2} zF^Ufp6tn$#vL-3~h7CpWIhYXh8C(5x!ZLe7dkk~*S!Hqf&Osr@lU@&oTXaNF6a9*G zG-{9S`ij9%_vn>5?qhRsDe>^(;^!3_&uIY(U;fy z#s_PbkUTZ>3O$ln$xyH+{PX?|;yp^b{;+ROf-ubBffT)_Hhida*QO$R7_hsay2uk> z0)&cZcxl>D{DX%Xc$H8gJPhabv(42-`MSsj>D5E72oKGD$U>Kz^C`d>L~=Hc6OIPS=5HLUk;pz=Nko&JS88$+g=Io+l!v? z(?t5*@e!m-|EHfbl^JxK$|8Mc%RRLx>?>NomRO;Jx=$&EpL@20#!Pbve+>V4)D{x& z32rY|4N9UK01Mgmy;Vk%&^aPS?Q{Yewo4|YSKCa2*A^iPht4{|{eQxO4@O}Ce+54sG z{YyRPkUkHqO%?l=jZ*YABBX7`<`LSTr*CqN{_xIH{?D~n{AK2d1S~UVI8&zF2YB>P z?$B%!h0j?=Sk$$2VJdUS^SzN1!0!^zS>Z1wfMK?#bMNP##Qrs{a|mj`@OCz z0r=u_*m|_Q1`Knm{;B0V48Hh0dzWfg4hjT0$bRf-f9e^<{~oJB_O7B3`uZRZ+8^Dw zZvP@Z(7c9N$o@dJtv$roKO@$?}5 z`O0w3z|9u<_p1KK9;W9|yz$kRXNhK64BmPE$nx&@9x(Y_^_B{89{aNNT)W(o3=NHB z`a`g3z{1>jgclTpLv&{h%VH4zbZxcP?+QlwsP)GpEK0fve`Nd*_O@xG``U6(N}cm& zMfrIT`}U>?62eQZc)la&-pIhOs^7HpKNIh-#ec}@ekBZTe~;}?4%UGRM-M5=Q!fMR z_ZNM7UY3HB-=Fw5>mzynh-P{6i52Y+oBp--!~c1oZod@MdDcOcUsjb<)Y_0i{vtZw z>rw6!I`5n+;c^SBBHFfU9I1sxpGk;x5c+)6DfPIjE=+57B-Lfk0NdH7SQ^_> z5SP7PaOxtm_o1)ya=siWo z?WEYp) zm4UL7JHGSw_5u~#dVyP)q+n*LnK1tQAe0TejKBLl37U3k{D|IB0yY8g>NF{ z0kE#C`#x+~2wo9$b=EGy;TEGOCd#|1p&h;E3Dy!wDwcdlL~6ohZn z(nmius6vik?Cr|7V_-?PW;jTv6l_`1OX}Q#^yh1Z)r0rcXkMPvs!Y;!H`1Tq^xk*3 zGb8(1eJPYHpix8N=jjt8(hVnMe?lFF2A5S;;h2wnNhs(8GS3gB{i&0HS}smo`#26l z&)Ku3-hOjn{J7@#$-E-KK*PpX6DB~R_qFu6uevbO=O^JELbcD(yhc0gch#yV==^xJ zzO|Nx3(fCyTI#>Uv}7st-p@4*8N+?>Mo`w} zr70jPQ89bOy%b3I3&>phgzAg7CD&_|CeisK)Z0TD=RoHRALY78vs{GF;~5g%&q=6W z*85=KibEL6zaHhOn;_o!gb8MOx}P)p!26TCUHOT5RSq^msq?DDdz2yxs=-DRK+T(c z14NYo=favt*9QGMauZ88rA zk-x}ow2HiLB@esmOqedY^@2{tk?B|&QAlIRc>Iik9^|JJ(pn0VlS1mitssOV^>NYEAsE$nZ7r0 zo89ox{>zs4h#ynR^=?oqm0 z_fM-2sMkKR+{Pvbfo)sc#u6FkDt?9SOw*vh`ST^??o#lk`ax;`OSC^Nngu-P8&E!q z?Tl>Mp)#~TSB}X!`c_F$es5_g<-U0g%Ktpbc7J&JGm_`^BesvJR?OkjE$OiIoB_bw zWEx{bF9F8}L?XOh^&t11%T_}+qoC?W@BPBPWq`*ZD(!s&I**6**u<2O(EGD8!FoJ< z_M!aY5lKaZ$1&m*eykFVJN>c{Kk7L{XU;?+eoyZ-=)I*W3wJzqe0w0I7g&&_)g@nw zLC@gk+2@@4@T0`gwQav=!J-zkm`zYI5PsmD@b)!2571xKvclA+D8Cms`TF3|r4UN| zIc2%(yix5@|w6g!Fg#hlETmH<>h%r zGO7m@8OvUXpF#0+@TfcIn^6=$hw0W2zzdpiM&%QC#V8R!&uDzD$r6FK(l@@1e8eF4 z6`8xQZcl*ckC|zH@sxq9SIJvcRgr$0IR1PC6;ZuFa*)qqp%BSyU`8k}6QKT$QXAW# z%%IPd{pl}IIGT}%=zXwDO<-LVh84Un4UOdkK=I*5(#s)!GC9TAI>Hb?9Z)9Z&mzk(jT+(ePWk7_XKaxDJbZlP;>cNq&nKxWc}qUeP~@BE z`8}=LRtKIw`gL%yz7H^~JSw<bT#c&k=cu6=!c_*Rxndax))6(iFKD@yxEMSLA z!06rAW<8%0^#U=S=jVw0{)n63#OR0)SQH!fPh=D(y{%&{ZjyRz`_ z4@*KYmUQYFyoka1*Ph3uzD$FplUlS5B~?JdT5tKK5Q-0H9*on8<{^8RdcS{%=naI= zO%uc8YnjOZ27KESJldI0;V&X6WVR;&(fcf{IC+GSj|$IsnWyo6poW$uhL4EnxuWQm z1%BZ0>fqd-C42;2x%9{~s(JTX?V~8iM0Sdtt8ZBp$KmbP* zl`Il#CxO!!JvCpV{(g*yE+yz5TJN^Inx|&}Q-5!z?z~8CfZ~k{8s6)wbI9J^VvRjU z7?FQZF*p*CV2NZ=XfF3Z&0*Op{t{AyX85i7+QGP|qU$`JiL4<@Ga^|9Izg zK$v#^X5cb+QDs`7Q9Ot#qvs%)H*Q%DUHXdC74l4B>gWF0$)FVe*QuMTz;GNiQ zQu|{6|GYE)fAh|z>4z!v&YSsvq2^;+$L?R@YwX;>Dt?{o+<$TgQz>AZd#LA$E7|4+ znh99q+H$|UMt%_UP%2^q{LIVPgXDPW*~i4Zp~`kY&r}kbWy^cr??k_=CB0F{p`mpw zc=4`BXZ|F{sxx#=-QOG69J^}qh|3Z`b~kRHE~yYp?MzP{ZC}BZhqsuu5_II8R;yJa zN#y$}{BmCiI`%^CI|YPja1QHjRY&}0FpuwDv)cAo@dxxd7t7^{cc+_AEPbfR$G$e- z%LR4on4`#t)Cz)5g}qS-zaxo^D+kEd5_GCgF>?%yJL(O<^$1dGGNHp7>?X z{=arXmiWa4iN9VF`Ir#DpPxp?686>q@1ZGzPDJH3*UV%R8A#i_?;z+Hic;4$ou4A+ zOQ@2HMHaA2MSBW7{$E>f8CF&I{14M19tBa6ZV3qi0c&qyZ%PDFLE-=s0!k{SbP9@6 zqNtRJAR!Xc-6f%VAb{SeFQOvsC{QHzNYDde>-&ziL?B?6D`|6|2M~sKpulyxCu@FXo;j zkR8VcH&PBTfsrtiFWw^hKWVAmzvy1T)lQeC6$r&dvg}!NzmPX>(@6UZqoX8I zxt%UUg63+Z>pyMyhlmcdzA8B4fYy^eJO5Tk7ab6;za#8iicoV>HVxm}LSndoxb|S{ z63J8aR>k@;xh<&TeqeMycZ}``KUhPQ8zLIp+P0DJ=Slh#R1DF&_1nvdFO1M8rA{(s z*LHM?;!%@h&oV&|zq<2AdRbs~^4}>LbTB zy+CC~8;{z#lAaH!EksDwq(bVi?jo1}$uCf1>$ZW7}DH*Et z#{ATuMXbN?&6+IdpC{-LS>IHNKOQx;8IFE9TY_v=(No*0?jbkE11O6yI={n4xYE6G z@|i*Jk`MK8(V=Nwn41K>ymxN=H{&XDw@=ZQn(8rHnw}`tB8W$&COtG*-xVSpkHh69 z?(ZP(3Hqf67@eY5+gT67aq@OG3Mw5K9a@1@wuis5{&wYr+Y%J3NS@v7{n^$hXrsKU zOJXY?)ox_GDmze$>^?nJVG**6NSJ+LUdQMp_YFUNiSZ*`**(#P(XkLJ3o^Yyj>dWO zkgs9;z9;;RBuUE=z5d?1Ynw(Fjh&)9UA2q#iv@P747+V18D~y*Q(!H$#cllo@w4#Cfk44X& z0`{<4MEjSa2iC{LEFfZl>0ybXmU(U#2^y7~gf1qoB2Gk?UsPo|qEiNehE-hpXne!@ z%>?UW#7sE(d2jYMQaph3n!(n^OlA8>0_zhL`2NK5P!I3LzJ0wKK#CT>uetxLX%%r` z-bvVI^gw44x@c&h;n7%sIIZ3+53!Nh>%-F%q3>)arVh{hrXgM5BXyj-##1exK8#Lf zQj6$_m! zbwH(stT*Pa;Zd2|XHnUt)yR8+*0uzxZ6s{0G`kI>Q%uEBx{LLXgrx^t9s0pXcJHt^ zv`JAG^X3piuNB1NQ)Om^motid;j%HI!2Avw(R_n(5hA2shU;P6M+$93&Ng9mURYQ_ z%&s{3+fw+^3XG2WHC36QfPKV@h4`qE%?h$HrXv}d=!%L+Z;5$};!)K*)aSF6F+27U zKh4U%k5E>;pV-3aPz}5Z*1eCDw@}F>I`pSKrW5mgxn!u*8K=^u$Q49*Gl}^_xg+{) zrO0mZ4IZTpFrZywD?#oQlIbQfZzEq8XSerdKCIsd}!^YXw8l0l5lJlC6#B4z8y zZ5M5>g!&z1KZ4HL=n5W{r2RW@^iB`m#a$x*DAA6FD9&k2;eZ}CKS=W+@x{sGorCUb zVS3oxW^tSQ2`M_VW_NUEWCgK4+xFS;kqg?mFY7Lnf;6*c~pP=^H8h`&?#G~OI zCQvX}A<~z9RO{`N9pwElq0mFTabZF6-E+*YX4=_Hk70C5vrn91!1_!BbqCq;A*+aE z*IZ-RuoF7Js}Ld0hey-bBah6H79xy8z0UFG+lbOi%lx4}6>H!!>5oJr$1iP70x z_3~QP-bbi{Y#YyD@19pa-2S&|_yjFFlU(wt1CP#gl}X_oDv`!N)~8P1*+p<>uXCm` ze$2HhhXbDC{>^eR)FMd1n}w253;G`^0-b_{| z>d+4s5%DkukCCF;DS^^5H`fr(2hVq2(z>8>$q9jMLVBo%Ri#s?OEIGJL&yBL1Loh` zUj%eubm-gca0-q%c^)@D{u+$VBcTs`oX@FHt<`4_ERt7|$vJTbjTjFU@^tX{$Ek5%?7#$Mlv3EPlIQi+kyT^JlI!@QE-Yl7rp!_+_FVAE1 z3%>gtsUHw^Mb%T?jx-GGq8ikm)-^{8kkl+_WeYop-IHHaeq(fQ{P+CS$k5 zxalTOA+HQ0Dasw2d?FQl=a)E;yRz5P8Exe1OqBH0MSB^x&xKtnL=>|`5>9pPBI1(O zcmIc<`KW}WF@I4PO!f5eoR+*?eVuV<14&D?%H1$uLk6FE1PG9tp(1C$_q&JcVf~bK zln=FY(BZZMCM&g59v)D?3uB5S~tf_vS)Tyk(&X>!nVv@ zQE^!+-6J=!_s`dMN%XAqko3^IwB45b$cjTB+a9*AFHM?Rv)DPUfktHihoepud3?G@ ziH>kmy!KdFK{$t|A5jmwqg2M>ON`ujR6p`{O0GjLGM(&Q6#4N0A=2-&Ka_J|&6jzu z+ZfLDjqN_P^J~zj#NgAEs8H6IAGMZih-SQ-hFXXRnqmD88I;GPcjvnT)_C)gP>FoT zj3jIhlwjmd2}}>On55VHRj|Ir1t#1aM(0lS)ytZp2>pL6_=(i7Zjqb zAWII$qeM?FFKfIhL@qeh?yyJgA>Gz;Vu$$WT&w1WhYe2NH~Z%5A^veqIIH>mI2lUP zM$6qQgw3@O(mN2&b4Gcz{U(!7<59}tJ&IYIVx*?fsM;iS52<^6x_t;+*HjbjlLi-@ zyn6&+bPGnO`ePu+Cu=NjqIt1(Sr41f!()@3wd8`jXQijB{nSO31svQW)(a5d=Ys*H zbXc4g65x0oyV$TF-75tG!!UpT)v&z^;JYN z^;dveng<$qWQ^#ZI3BIc`_d=CU4Y!09JN8QK4c5~>b5*gJ_!^@J(aIx_IW}ysu`n0 z|8VHua2f@gdGF%j+p$&T^=G*x-kUC{%1FU7NfI8Fe{`81X39qtWfeSVi1rbK{;}o$ z!+p0WOOLY0$!FN68XWqa_=Tj5E>Q{;Kjv;Eh0VKp*IOj+Ywdzwt{*!y?1)F(i`!f| zALSulKe9D+4E7KTPJQ&y?=Y07skvi#!!%o$@$g*Kt*l-xD<(pZHmQj*A=uod?>9$Y zth=Dk8;h&nVK^xLlxhkoQ5n)dHTtadU=JzVSKm3rV}`~#{a-MBE)i;Ybr^pcSS_f2 zBOyZltfh1ek1ZoNR~V;rm!4qp6779MJzbRFr#Sm`ZVB@Kw??P?wLQdb%ID`IM(5%S zQYs5SEDsQqtY3}MNw$LK>ao1Uhq?PXCGM+8ElgSIJm8KJvKsM z&T?q@l!nc_$B<@@HoHfg)AeEar_)1gQ6m+-qQ5hoO14VSL&LKgOKTWT`272h zrXr??qTW4aCU>y+(_cD{H!Q6p|MsabNgi=Q+fK@2g*bR@p4-?lmH1-hVkskQ#_wGu z?by2@F^r%6eEnfk%^Y=jhoG$2T!UG48AGQ<98~92B^5;@9obPF$g8oJW95N>P zqK+UBVb1H1*O@^+`y;8xi-?&ku<9QR^~R=2h$GTViX40YsK$1HvrSzIuJK!av4vZP z)U-}5d&O2m5@%0v{1XHDbK3W4r)Md+4+`w6+N>%7`SV$Z+-J8(!S7{F%=qr*gZr{; z#;NVQQQ$r~IVk#ICsz#qYeskDPvQjB>s6EUJb)K|LH-dg`iR0dF4reMPhjsOJkM6` zEv$ilP#g4j-2nC5u?qWWB*ipgy_cselu|aI67uJ_B9}tPmqC3pqe=$NFaP(1@0XLS zcyuSh{nWNd3$-OS@AhO(6JtL-21Tn*{n4&wgU^3jedzF68ZK3xq1#KCftW^|u}+@~ zi2tr&Z|Nsc4>M6@R6iXI^rzyd@||3#dO%FD!`K4+Hld?pJmONm7Bn zS1iBlye%LLS8(bCHXt*QNA+qu_Y@y|F5D`y7Ey*>huxDKwCAB)gAN~Uyy~Eag=nF~ z0B|2*Y}QA)cLvn|YiUu74M>3cz{bB1M@ASyf5<4*#i4mKpCF&-clPB9&Vl;D3txY~ zu|CHP|DCemB@P{j79ce?rQ;m1?$_@S$7dP%tGUY^JFH&SMT0pn`$h#MBl1h$X93h} z@v`_xJ_rZ=DB9Q5+IQ9&ziYe-|Ll;1FRn-m5_L^LEyu6YUcma(&-+{Q=JtT~dOYP?ys`n#JNc*p z*RAis9)>O2tT*?9da!j_=R00$pdL?{sFgpF9o(PO-D^t+fqZ-nm%o?r0sX1e@)m~dfxXg~7bzEy z0`lQ#L$U^bg8RUGMI?_oDtO`J#hRiv#S@TIt>5F+9$q-ofu3aPgB;8dqrGX!H3fNa z_-A+wRzVbk17gx_V88D?`+e4@c$^@A$zUrBgc;bw$U&Sa|6d@Vf4}p}=?o$W-*?fE z(xq7ee#1p^@#~JK;PnP%L7{6LdUcf&VOZjT`}D}&pU6nTXY1aK{<}5`PAISjyBnl>J7D)j0OT{0k@2_3}^@_ROK7n7p1N~u$JI14U8`KA$$++;qmlV|N zU5S}kzio99KL7gVxz_U&(DG)>wEB5|__(s=dd$o3yJLhKtXsYdEJsaFDidIFEIF@;So|+xmMa9LZ7ggQb4$R63|0sP`M!w!+QDt{X)bmP;Il3n5tA2R6rz{r$o+9pr`2iwv0jq_rH7T z!`P2Z#b)_xb`-(>8_#g-^cVxYl;k-jC~VbC`1jC#b3qRQAn$(;^0UMY{BYE}s39EI zXEbZS;9Q!>4}S>m+|g~k4tsQbFp-&_gWkQiH@7RUhK}8wKcZ>{@Xzg7^V>R7pnhO7 zPcZSrBslL`bT2LaE(82ixrz5_GAkhP)8sI5m**a+SFEY|(czbS7H0C8SA;QKS`!>D zbDx6;W|Xt#92G_2sx1LIi<3)`bHPEXR3KHBd}u3I-gp`C`3o4IRc&J zgdd`;c{R0Q!uRH{NbpxLgZ_X4heTPi;XnNPz)5#K4F$DD^{ z`@@{|vG>Z8>a}U8RV$$)wfx;O6X0)dxqL2Tdj;fk*K~eSQy=(uhcWDt_#Xhzr{0t6 zpGgJ&E89eo^Kl@EKbCi1`W(<*fXNbEQ+s$OpdjCmk19`K{dBXTdcShzVdhHfRI=?E z$TuB%ctgJmQsr-*m6HJeOR<+$;6yj*A0e~EZIyHb|E|Ew3nA>m7lM3> zh&bAIn?S$wwT3INwhOMo*R4G%YxBn;Cijwc=1MO3dA^ua`AGy;xYh6e#A6D2@}MPd zHo6?rO>R0b9tF&vW`O)t!aie5}a_?kkdK(6 zX_BjXk^rw>_-UZs@B`r0Sk)bbksQc}@n@re<~4wi=P#YI?R`{8;NKX3`#{DD?59(F zX$@B#6Few;Rfa#|5A>AV-SSEo8|*WBCvNzrEX*kVQK=+n5qh(knyP}-pU-Am^aFkxy3FQd z_(46n*{i~St#5!IqjS$UV?Tp=KvmG2y@z?g{=9o-cCM8OoY(%BxF`w_MfmS`HALyx zIP~((t5l{1F4)~cm_ejY9#;DWYRbG z!GIgK)3=Wx5=P-w+cpxWlxYYX`^DliPz^Od-U_ud0`eap^t$}@CFn=Mako^@(t`N? zqw12wHFuyN_7k6(9A&|N)!pLk+&lv0{l4-K@2T4tVXa;I*LKm9kVP9;DRny!oa@n& zCj3nS?(aDDsOigJh<7NX$SJ!D;^B=xqk9(A>(fx3Ud%BYBj_hS^B!Zr37CiTtobzE z8AX7XnvIU)PS3w4e81xM>7~~&pqEriN2RSJ1S6kM&+lOK+;%8ab4aoGmL7&MT=7j4 zhh-{%8hCb2L+lAxl8<5U7srj9racXT_1u)n;^o^4A;k%PeA9b?-k2h^1@moF~Low3NS5WQ?{+$ zH0CcBZl4;igaR0vqo!|y^B#1*r(dRHo3LJT&UqScHgMi8o}L?H>I43rM0a<+=@F>E z4gJ!tZ;(ejzLLY>Dvyi#aY$OG3{H^o7gV;>LtPe&fsq&36qsDTMFu zfALV>Vg>k+LNaCiDFqAMP;>5c3jYM8cj2gB^9l`h$AcgduIYL5m9ndZMMR zj(57H;9o?$N+#B0P<5j{x8+%G_#4CDct>hQ3?CX>NX1P+Bp-tm@YWSjM4C6trxp;u zC9pBIcc%hG-9)=uw-NE`4*hA+vMoNJXAV0?K%bRgaN(Js7 z8|AOT-WwwFkv$@9#RGpWxErRLr~tEvjTh6?>_C0lZxaV-E1;JwJ@LHq%!KvOp`RUC z8-V>;T#i|e&jt1Nm9LVV%Jo6MvVNV$Y;y(VqgL`<1qA(py_99V6o)UCh8y3&-W<#` z5Z=+0Pa*Xz?0#jsi8n_X_GDtPOBJGq=iu}M2Io4cTil%Zr9ZHTzpu?wuPcH2|Ml{T z{43&MzZ4&Plibw+^4X(a+YB+SA*^TI^UYf;M-Z?46>==iU{Hs%X2o`}3GLA9z_zT} zJwCX1$9s~_RtaXTfPHJX?@=UcTp`eB_^feFJs!k6 zcf_16HUINImaytM2*8xM5y_iSV1NV^9M#=1w#?;XD|7 zZUdW-(fujp^55k($gc!tCF!ez>g~^q3iAW`!1Z=lk+Z;`+V9Bt(`_@Bm{X~x|j0%8rJWl7McH6Yy*1_j(qU}jSmm}u92otB0?UnXQM(k zGyXy$i&Xv@>s8P{O2sitcCemA9mNkcj3A$|XtE*ht^)F_n!e)_>!#v_-%H>7HfQ@2 z^v}}XsHP5N0Qtjq&!as`zXjmpK2fz_mDu~v?{lY)&+x#%#A#^#rpL7jiddEiSv(m|{7O7K7*uh2844XFBvYo?D& z4aCTs?=0rPMxbAN^=(xj0_`Wjh4SRVE=nu`Re05pe z3-l|TP#&%m4Y>lp@=IYb)*FL7q7~k&bqK)yMPsN<+jaOw4d+&a_By0Hm?L>vsvjkHe{lX``mV{y0iiG}6Za|NdSo_R7~yuwSh+Z96B+xnS++ zt#>)cCm`Jpy~*YYF8EBpb-+0+pGkSp{^TL+I#lq~JyPOl6}0wOW%fZm$Y)N5ho#_k zfWL@H{}bQ40r0BzAb&so%sSz`{bs%QL6p9nuz%LSPj${TfqdJ)5s#D+M@~5W#Ja?g z4d&lNJF}9Puz3PW1z+VF5%^Ee-Fst}d(gUBnQC1KhUcgMZcO@s{B>-e`reC-RRaAt z$3K64_zKK_2qwPBq+kK;Ps@HE(_l|3;rsoZeC8cLfXDnAP5;PwFu)A>PWQh32}muD z=I4W39B|FF3VuWJ3f$FO_P|eU4Z5*`G6<(tL3Ig_C7&Jx{_DcP`-yTDaK4z%ZFfc* z0RQ#gB6VBjF38XG+mjEXnLwX2<11@7XV1E)-wqMS70lXd> z-eq>Nrh&lE+a-GX)qypFez_KPg&8{u!ou1~#{bCvK#O0>yy`!kg@bGJ%(H!!;8c<` zJT5=FRY+mf0wFT0cH%=8$TJo z1-Tv3RZqTM1O25b@Lb3T@@d!qK`vVk^rxkd{yfSJ^v9;-ZZT3{n@hp6)kJmF+K^dNA5^u~N!1~i=29|Y6 z%Arr=-T!R=gIAS=CcFy10{=d3al#tc0``l$?rF}D4Uo@?7i#(Dr9eJHuMN9Ivw=O^ zX@2vv|0y3#KJcD~MdlBrJ%IeB-sgu8_-aymvHQW>_90xezB3TL>6Oa^!WGct=GrFf zNg$sjF=%G^8IX_kH4>QuZ6KfH0+W(62o)CT^m!#+BqMj!0g@$YR}Ev(A0 z9dX-*tH=I8OZ14m&naG5nx;&qB}NI>k$i4_`{4o<&&;&!aH$09>rJ#BYy~!$H+WS-+@4u>F})z(k&ff|=NAS1*Iap^HCH0Qs~sWVIG;~} z`19D7-QOvRCFa~AfQE&f#?Faf3K{_^``E&!Lg*QRbDuX@X1O?H4ERw{KKXv~Kl!o3Fh65HYQRtL%NaRy z8<0=14n(R)n}NQ6V?HVv>dys#3-dK>9sC2`D0A=$x8sHlmAYL@#^vEAiwA0?CM!^S za&}+A9F891M!j;_H~4FGS93e4r_&w+fxr(2)PUcCkQ=1TIP_Ujh`{*i(C zWx4-|5%e!LDrDD}nhU=E9;R&=9ECJ>a@PjSvH9@foUCsk1Wx{+4eae69BKQL) z@Ix}6+P_dF0$bCzM02u@Ls7#cUcX}mU}{qQ=;agF;bV`ynYmOppytT%s~IYl&@~bZ z>jgP*-uDgFp2PpCZ*lE|$@uSq^RAq3Cit2U=<5{MTcJag?Hsd?#JA)e$~w@ zt2YG3Ai9s9k%1LFaBHC7Q#L1gc>2Hz=QFzmebsdMc4My+y3liVIg%LQANO9$vae)d zzvzwI!bUBDeO{Ev3=j|o^E8k5NqG-Bf_U(l+R;aE1pz){JsJ}9j8PKSv`rk9rkjLj zGAf&gSp{L4;a?;wxk~WyrB=tF&~->Jb!W&Kn@=dVF#PfN6%a2^rwJIJO;{)Fe?*4A z#)D=MFGpwT%H0kG@$gK)&f_|nOv3jF8}U@AKgiD)YFWq*WBE%%z8Objm2pV0{;^P; z4=YUDOkXQ_1A;mFN0{w-7N93VcSH;@{QTQRrEuXrkWccRn(O@;z#cj^gtGAb2J&%c zm6krm1Mm$j76qT?0Ql#20#a@N3HYylZoE-a;RW~}g;ER)(>RnbX(H4}BLXkaTxc^l zP=R-Qy&pN)twP@n+$%-#mC)+xYeCfr@HYjqH+!~EgYyo5d+ZfZ2I7lNtUD}&c$I*+ z;?7K9FNT2pv*wTdZ`I-;e<-SO`CkSlR;PhJZVEJ=fS40w`g2cm!`!aFUeI(Ra7x(# z^^w{oDCVW;TD4CVMB3|oI_oGn4|jU>PdT7Kp9SeZK6e%e=Zi(2A#RIUkgz|-y5CQ{ zp$GPvHTRswNEpD6&h2e$ZTe?nMq1-IOXYFs%&W}L?u|UKc9xq2>AE9 zM38^Q1|dWH_ff=a$SN6w#oNA(5eE$ebaPq0Gq?LKC7v6D3jR z43XwSC5=+Pd!MuS-B0&@uICN+eSPn9{C?VZpR@K_YybE9uf6v<`_^__rj11Re%%@D zf8yc{VTRNnAK{O0;9uB!!9Om+I=t@!J_vv^5R{RWI75J?k$q1dT$cj+m4&Da(crrM zWNT{%Ly!UW!xG$P1dCFi%)teDlCtOm1?cjB8Ub5tD?4@vVZ6XN)5c-s@u&OJAYP$8 z7}q@+wtpBDV2Cq%vZ8yX$1)$!C0-0EaTbmKxMNA(7ohwDbYMj|^$&Ut%bpA%&*;W# zFV2|jxyWO=pSK4PXY^qSO0z0Z-rd8SCBU+%yv)OA#iHdtKu~}s!Ipu1gZ{SwzR3d~ zQGAo)$+s{nBQRWm-e^F)08lp{MSXzTB6u2APXPDjf#(IF9u6F=19k0<)CVchq3B?$ zt_z)U#hx^*T@wuc7KvU;wn+sXFKuBf1AA zNR29W@1Oh=@+}qMWeZC4697lR3kNVD4gjp448uP@2{1%iybx!2dbxY}vab9KFMvG7 z6;NRnQzlGg3NS<%>^AIw;sh8#s`@WK?ZB0SzsUp8PCnoP)XL2Zd7v*)f|7u8(V(8+ zi@IVC9ySCB{N@Fm|GDw%YMzGO?8%@qp8!LQA;VI-a>=3870d%LKXks^^%~?;SWl{L z0U49P%UVO@y z@7#)Cd_h^4UFDN7aFbv2llK710L`b)@j%!98UbE>k_T}FTk(re1t9;o^rtL! zl}{qTL4NTmRf#e{^9e=*U49P%UVNGl;t00o7oW5TQWk81y{_^JycXo!dQVD?@{i^d zj0C#;9s<1hl%U$V6~Fl8t4!Gm1NOSgC-A!B7w}1>)BAjQe#RUS)(*fyzsKtw7j&&N z0=)PnuGv|RUwjH2N7;#-K$TtP6L_5Q(|qdO+kdUW_l}kTh=K!@48(coE@lpAEB<>0Xg5Jo#nzoJ@q(s9iDfIp4eHgo$ex(NG zE5Fw3-nx{2dVTTx#>DUB8LxaO58?>=3V9FbS$O?NOUMiEa|vC|huwe!{Nht8I0r%V z=|@NUpVf{RpXP%&f@tuIPu%Bsy2>YboQYq2k}{$Yp!ozNfiAy?053izaGg8j7oWJ# zxpkFK;F#%8uh)5<7jrSC`SiW`q3?A@fES;{K^#G8e(@2A(CgisryzrAH7~sHl17jYCgezXdp174S2<|!^JZg&%R8m0h9{|^;F<5I99-r8r@mW z9Mm1gQr965y}^SasE_-5iNL+zwt(wqZXCLrm)O4>h5e6Tc_|;@4#$x`Z$;rv|NLtN zc;zKu5J#{T zoL*P?Gzd7zuldR43}pcFi5FfiT;~UWHD0{l*9Jy*_79EMU;lnU%PF1Z>G>8SMwfqu z0IztjoZMOZSI0Y?ZzI73o(=4EH9yDzH~Ezx3Z_#AV1A(a)HyEbT4w}!@yQ(go<}JC ztN8@?)#1Q^3;5muw8Q;90x+#G0s#M@95)}Mfxdh&uRysLP?rb&N&s^69jFgbE*R9K zX8?iUynuO$yMJBHOR}J!{K`w(GbsafUi!@g>NjzZS6<5J;w9uQNDDvhJ>(O29_T8c zS(m${Synolqi=<<6A@ZwXdd*@canon>a znhMM$fO!hq;hwj$ft)ztAC%+fV?K~`aHBpzxd2cP2mLAla&>?&P)>dxb;H~f2>j*+ zTsL#~ud8`U0rZn!c_|v;N#~{CJfMCP_ju(c2QFSh-rD^lzagKv^FUYm)Q``6Vl1W% z(0uwu1OGp+h8LeA7j^D9zxXtN0c9r;*y}2v`U5xlH9y&TQwC^0b&dzR_SXpT;#13# z&hq@?Qv%5U1;Acc`7{8y$uB-tE~gC8eCiwzbnUMZ;Ke6fpU(2Xnon>aS_I5kf_Vzs z;hwiDfm|@)AC%+fBYe)23cer%<+%S2Lmkjp1m+(oC%%-rq0QBQApYAGaNW%9cUSWg z_%*A1I~Qs0OF>8HrQa@ueoKdV<)xxko!y1Jwd;KOhii~e;VUQ=slZ-W`J@Ou;MY7K z=ua7-`Sim>{f}zMi%*6ijvyHP;!_>S|5CtSSNQ~g-8jGaRIrZb6N~}6{Cfm=@hJer z5!AphK3T4zEVuxBUFDN9aFAbo^4>%lpyww5G+lfb0bYE{-_W_)ujUinhqeGSzF^%4 z?QpLH|M;c#EZJ-@pFuh9`Ar<$kOw@4a@@RyeMe z%}XkvgZ#=%saq)nbYA*hBkA|@i&tKn58?=V3wisi_o3RGDGRp1URU{~3LNAYpQLtB z253IPNTAE_A;61I3EMlj;uoKMw^4S&fW5BrNe#HkFFv^hQ3hx}b&dzR_SXpT;*&Ut zBiM>xe98v-zj7C4sjGZa2M+R!Pc3^X12mstB+%ve5a7ip2N*!0@vr6+wGS0#$V0_o z-3P1O>p*32!w$@6P>y?k(*`%f0Z*YEH*XEWjXIDwpq%_}s>9}>|K{LEU`%0+{E z{(kDZGF337`gE4#{`=iP?3WdAAIj}_SMw71vrc?_A8LDm>M{%~`g`lYECl{174gbT zb%1ZM(~ysL@WM})kWbwF?kb-&fgk*u=flD%12mt0a=`x~&3W<362uXNfnR*${(FmE z<&ze0kY9YNJVF_u`2-_@F29EWFFpl>ID&2Y#V78+OWIXFX#)rO#V2L(`^jiN!APLX z?;*g8PesQ&xBAt5g4*GqV>1F5j6rDvN>fmRKR3e|3hL&d1b=pkF~pF%Fa#(Z0u&Ab z3WorNLx92|K;aOea0pO11Sm8D`iy`+BcRU+=raQPjDS8Ppw9^CGXnaIfIefO&lu=4 z2KtPFK4YNI80a$w`iy}-W1!C%=raNOOn^QUpw9&8GXeTcfIbtT&jjc*0s2gUK2xC2 z6zDSr`b>d7Q=rcj=raZSOo2XApwATOGXwg}fIc&z&kX1@1NzK>J~N=t4Cpfh`pkg7 zp+MhIpl>M92jkKg#KV88p!d=LDWv~@+M%Aai7B z`U#&4aR2@GuCBXuKnH$y-9_{MzZD7pKkV{aPZ>sb_8;=huJh#|u0fvEf!|{+1?+W| zC%V9cpXCX!-(y^Gkuner?9hDr;UWJ=G~~sn01!tI1b*?!@;qh11=#BMt(Lmtd$P>y?k^9DEO1D--TZr=KW8wp_kfpSHl z&H()n05|O7DLkN@FQ|uIqpk;n8{yYG%VmRlxNhe5 zyQ_K00NCSKUXlVh(0S?K9N2%j7_YpP0Qd&sfqVq%177~&67q?g-(BU?VBi72_~Zhf z$I*QH;i3LVHRQ!7aS%rk41V#6dmij6pA7lTr)cmTo8}XY1iJhl0=)R-0OAO?T9KEX(!%kLq;i%+&7j$m7U@rnD~ zOIP^>j;ryFPv*H40yLjsB+%ve5a7k9Fs}1jznV|*Tw4NAoDJd@+NlF|sXWU2RB%H+ zpQ=MSOHg-tL|xAYH|9U?EEf#w(NC%C`9Ln=S!cN-P-ncLt``6~@t2+D3_;!QHFf>J z^%FiPXr z;0M3nI~0I?NAu|?2mBw>oEM)0Kpa6B_{AsgdAh570$=Cg+x(;r=6#w^FcRqUdkFC2 zQ$AQtSh9Ph+T7mii?G%7|OMmKm5x5Z!;v33k zgL-8VC07Y<)V=GhPrjI{o0n2$9gwpu>nt}P)B`K1>%aR?xDVxi&eYYsG#qr4UwO#| zj0c^Ue)ov_J^bU9m&8FFK`#M~8Fui(PnM8R+R4#;1{2wK^~*|^pgYr4{6Se zPYxiCAPoHC6ZibvRX&a6GoKihlmVJgFcRqUdkFC2QzX~Akzah`UZ-}IPZ;PNzvd^q z_mlyePv46o`W{4p7oS?Hp#)X(i%$t4{}%vzUF8!F+~gOZDr+eNG@m-h16})T1bFeu zwx+ZEujUhcuG0b(2LoO~JKQ{D2vYtOf%yW;iGQH3YXg79ft+t0bsfrugL-N`bzKU` zWqKRMw4kmkJjWXLto@rzH~^J-W5WW{Gb6|_Wz z2=SBMi4~@ybi{K^#GEVIHu97k;vYeB#a*UF8!K z_`xqeNr_NBr}^}g1O5+b&Wle8!jM4}5U}>E`Q$4|X$}MSy2>YOKJ&>%oaWO%gbKf; zo4oiW4&n$J;TNB>LH@54qbzilPd0q!Q%g^pPcR1P^6wGg#V3azkU^9VSo>A;6a4)J zhG5@l2j(eghkM>K2Xf(ne^8E_kCs5L4&(zUC*O_wWDfde381l4?%Y3LP!Ch3uG>-t zBV4VsTsEjzY5;-%QUTY^-2LlnUK$1b|M_*Z0E3M*{PoY!zi0^x|NLH5N&USMLB=<( ze-K9TK9rm?xL|2W)!}$RIlBDcL;&WcXwW^FcY+5~alno;_9yN*Gc=;^+nGQ)p-ysA z45>dfMw$aTF8Fx;y&O9kN}?t4&bUdD5HB*aRh~74aPUT{-Y&) zz6LV|9dA$%27XX%U@%%hd_y^9S?ZHzU#f&WbCIX&P%aSEBl}TTl!4>f{X5Im zfx46;Z26--{Li$5^AVBiOawTL^!ymlpdMa4QwDjB<{69-y8Ipjym*!k=1qIAI8uYTSbJc!a94eTL){20%mpGeP-@eJzW#k0U6lmxv$`}-K9B^V4|JTnLH z(IG}K?tT@|pkC5vh%x(bV~lbiVrm9T_U|GeOMlox+2zk*|3taqiBfAmFw@niWF>Y?6; z3h+FCD{pYF2s)|lr8m!Y@nY9O;KE!_A0O6hd``aN z@EBrJKb=<~Vs!ae2=K})E?hi? ztc7v)SGu}#4f26IFLad;&@Tao2sQVD3jz#k#Vi26|Ax*PP+r3IbT{BMJdO_aao-nW zoj7LSlUBCiobNN~!7%v-4)%$#uCnh7QnX~%l>g8yBq-v-q?EFMvj4MHv(1XL{T0q{MFzrzErm;VkIDA#p-wEyr&NKiC#@?Yb_Rt+#>i*|KI^@sX@ z`LURF%yOBh>mna;$7{u$MV{^+u*!hvG2sR3h$n+{{f~2+teYO5^E|v(x-MD)nlATT z?7>#)vt-4xIUdgJ)0}@;aQEkCS3-iqEpDC1hihD1{=)lTf9YTGpb!)Q-yec_!2UuUV7=@8mk0e9GGBuF z|EIqD{`yXKLF2!R2aGp}2dw`D9^QTk5B4X((ccXZYWxJi?=OJy0de^8{tHHKLjC_! zehTcu=<#0^ejmURn3Bif$p5u%icJhgT`$x*wj}rWYUYFHEtcQc=K|y^Exs=Y#D3d? zy?$mtlZSBwOG}xqxm>W5!U4AXcTvgC?%WRMv%j;RAVNt(d+_@Qf7dRO=xhPDgZ|nA z1#sOY{&x!L`!oVH0yF|N0yF|N0yF|N0yF|N0yF~uFa&t*BLm>ZyNh_phf_N;*dFfB z{#`ZVg`L}X-u3;xmKFu71+)+MiGSaclBk^4*&=KY`@y}>gwphW^WR07mZK4%5ug#E z5ug#E5ug#E5ug#E5ug#E5%^y~fY}YD;J>*~@a3^Tp!Ws5$C$oDBS0fSBS0fSBS0fSBk(H_;I(f2yXUeAVBHAi;B#GW zpCZA!5z4{!9k*N&Dc-SuaNa%{npsZ`OywJl2KudhqAQnQl!ZKqEjSKqEjS@GB6|@2#7*pftk@mQW|G z!!q4&*u=}nBgp))xDY%{k~!JYZ{K23dnPY=Uf2J>>4E*=E(hMao$;o}3o>|6#<%Gg zORV7iirUl#=i4NhwLAPD7oV8&KaUTL4_HDRU>%nK-^LyK4a@&_zo32Yl8!?P5jak; zggC)EEa^C;^8JtE1KV+zbR1HMz&L{?#0l16Nyi}_hySE?6pVXV{;%)?_Jg~m^C5)@ z9B)`coM0W6bUvi>A)OBy49Evq{(s{I@Rr`6fqxq2kv;M^A}! z>M_^XJvibt0NHA`GA5Qz_X-ga4lE|NV2HMAFehTK;PfeS!uu{2&Q!h*r+;Vu|bx!-#B#TIG0bx%4 zvBLul_fo_&)96X(8tw4dy^ zV;XpTRqxd;DwSB{9P4FDnjDEG}#R5T2-Fk2M(kToT z{Jyla?8N3W>}pJuf8hyPJa1Zn&DCN0c(+S?i)}s@W4)%h78*WH!wy`3QTej3Jg2?+ zPGQRsO@vQYuUS^cy$^8g-;Q4U?SgPEr(S&ce22wogwGVic~_5%qy7bFT~e53W{bZm z3LBf0T#22K@@w}$t&Pj99Cf?qs13d<0GmY><$!Ba#z^^C{4GV{Vz@upjA zaWk$iU2{R|bVENOAn}TYBKr^9jwI zy361_@7`VA#j!vA^uX1=<~=$0r)<9?w>mS9Q$M_D$i9?A-8pq~j=Yn+`cypP$$H<= zq6+Md(%_g}^MUw~(An)ab1~fc$d(Z7O9iGVm*{VDIs=Q&Q#riSM}gD+`GjpVuU!-4 zjF;<@s-3324s!hIxi?|yqbZ0#>jf;Cn;zcgwDV_)5@pXFAZa*75^HQ2={@n`9cT(e8;q!N}RhFYBc^RYlnL4gHl`(?B z@ke}|nC7=2o@UwK%XUNjQjBmtyv(ydUe7!by?1^E z_Gsvsv%)cItZ}+K&qJ5MWm3N7^*d65Jyo05`q1$KF13GnlWn@V-agL$CC&z-m5Q zC|fwH;10qko?9*>@R$9g4@V^yWA_XV>#sgY$JRYoxaK4DjiWyxUTtDVPBuqhTa0wT zu{M+s`!Zja%q)7(kr%5KFJFN9aO6#c4E<*%D{<<%uZLaQrZE(E9eampttrKf_AZ)H zf1o#hnONA?=4^n!4Q`%xxULjS^;6vN*e4BJec25&$AYN?5;5v<>%p#rePx1{qYe~_K@%0D>17(icZ91W!%}Q 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 bH@12 5 1200 - + 1000000 -10 -10 -5 10 10 5 diff --git a/tests/regression_tests/particle_restart_eigval/test.py b/tests/regression_tests/particle_restart_eigval/test.py index f9d22edb8a..bad3f158c0 100644 --- a/tests/regression_tests/particle_restart_eigval/test.py +++ b/tests/regression_tests/particle_restart_eigval/test.py @@ -2,5 +2,5 @@ from tests.testing_harness import ParticleRestartTestHarness def test_particle_restart_eigval(): - harness = ParticleRestartTestHarness('particle_11_254.h5') + harness = ParticleRestartTestHarness('particle_8_60.h5') harness.main() diff --git a/tests/regression_tests/periodic/results_true.dat b/tests/regression_tests/periodic/results_true.dat index 2189597e11..626004b16b 100644 --- a/tests/regression_tests/periodic/results_true.dat +++ b/tests/regression_tests/periodic/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.623300E+00 2.572983E-02 +1.624889E+00 1.108153E-02 diff --git a/tests/regression_tests/periodic_6fold/results_true.dat b/tests/regression_tests/periodic_6fold/results_true.dat index e60182809a..04aa308781 100644 --- a/tests/regression_tests/periodic_6fold/results_true.dat +++ b/tests/regression_tests/periodic_6fold/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.858730E+00 6.824588E-03 +1.848492E+00 2.933785E-03 diff --git a/tests/regression_tests/periodic_hex/results_true.dat b/tests/regression_tests/periodic_hex/results_true.dat index 584089a15d..eff00b6e16 100644 --- a/tests/regression_tests/periodic_hex/results_true.dat +++ b/tests/regression_tests/periodic_hex/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.284468E+00 2.781588E-02 +2.285622E+00 2.576768E-03 diff --git a/tests/regression_tests/photon_production_fission/results_true.dat b/tests/regression_tests/photon_production_fission/results_true.dat index b17b3621a0..af325d4b02 100644 --- a/tests/regression_tests/photon_production_fission/results_true.dat +++ b/tests/regression_tests/photon_production_fission/results_true.dat @@ -1,12 +1,12 @@ k-combined: -2.278476E+00 6.220292E-02 +2.297165E+00 1.955494E-02 tally 1: -2.664071E+00 -2.369250E+00 +2.696393E+00 +2.423937E+00 0.000000E+00 0.000000E+00 -2.664071E+00 -2.369250E+00 +2.696393E+00 +2.423937E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -18,52 +18,52 @@ tally 1: 0.000000E+00 0.000000E+00 tally 2: -2.640755E+00 -2.326201E+00 -4.245217E+08 -6.012128E+16 +2.672029E+00 +2.380251E+00 +4.288244E+08 +6.130569E+16 0.000000E+00 0.000000E+00 -2.640755E+00 -2.326201E+00 -4.245217E+08 -6.012128E+16 +2.672029E+00 +2.380251E+00 +4.288244E+08 +6.130569E+16 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.675918E+05 -9.365733E+09 +1.711908E+05 +9.769096E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.675918E+05 -9.365733E+09 +1.711908E+05 +9.769096E+09 0.000000E+00 0.000000E+00 tally 3: -2.657846E+00 -2.354717E+00 -4.245217E+08 -6.012128E+16 +2.649127E+00 +2.339294E+00 +4.288244E+08 +6.130569E+16 0.000000E+00 0.000000E+00 -2.657846E+00 -2.354717E+00 -4.245217E+08 -6.012128E+16 +2.649127E+00 +2.339294E+00 +4.288244E+08 +6.130569E+16 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.675918E+05 -9.365733E+09 +1.711908E+05 +9.769096E+09 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.675918E+05 -9.365733E+09 +1.711908E+05 +9.769096E+09 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/ptables_off/results_true.dat b/tests/regression_tests/ptables_off/results_true.dat index 1652088ce8..3742748625 100644 --- a/tests/regression_tests/ptables_off/results_true.dat +++ b/tests/regression_tests/ptables_off/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.978318E-01 1.560055E-03 +2.968228E-01 1.770320E-03 diff --git a/tests/regression_tests/quadric_surfaces/results_true.dat b/tests/regression_tests/quadric_surfaces/results_true.dat index 382c4241e0..6fb569f522 100644 --- a/tests/regression_tests/quadric_surfaces/results_true.dat +++ b/tests/regression_tests/quadric_surfaces/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.193830E+00 1.824184E-02 +1.216213E+00 2.789559E-02 diff --git a/tests/regression_tests/random_ray_adjoint_fixed_source/results_true.dat b/tests/regression_tests/random_ray_adjoint_fixed_source/results_true.dat index 7178e2f111..e9aa9015b3 100644 --- a/tests/regression_tests/random_ray_adjoint_fixed_source/results_true.dat +++ b/tests/regression_tests/random_ray_adjoint_fixed_source/results_true.dat @@ -6,4 +6,4 @@ tally 2: 9.482551E+08 tally 3: 1.956327E+05 -7.654469E+09 +7.654468E+09 diff --git a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat index a0d7fc545f..c7584ab647 100644 --- a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.796949E-01 1.055316E-02 +7.797820E-01 1.054725E-02 diff --git a/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat b/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat index ebf510cfc7..d544a27df6 100644 --- a/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.375068E-01 7.015839E-03 +7.356667E-01 6.637270E-03 diff --git a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat index 2f444fad3c..75a10a2247 100644 --- a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.499679E-01 8.107614E-03 +7.551716E-01 8.117378E-03 diff --git a/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat b/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat index c6ce6aab94..f27ad46b46 100644 --- a/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat +++ b/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.152917E-01 1.430362E-02 +7.201808E-01 1.506596E-02 diff --git a/tests/regression_tests/random_ray_fixed_source_linear/linear/results_true.dat b/tests/regression_tests/random_ray_fixed_source_linear/linear/results_true.dat index 2fc08d0a42..e90d6bfdcb 100644 --- a/tests/regression_tests/random_ray_fixed_source_linear/linear/results_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_linear/linear/results_true.dat @@ -1,6 +1,6 @@ tally 1: -2.339085E+00 -2.747304E-01 +2.339086E+00 +2.747305E-01 tally 2: 1.089827E-01 6.069324E-04 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 index 831eac5019..4d2fb6c579 100644 --- 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 @@ -83,7 +83,7 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.073356E+02 +1.073355E+02 4.630895E+02 1.263975E+01 6.427678E+00 @@ -107,7 +107,7 @@ tally 1: 2.388612E-03 5.941898E-01 1.414866E-02 -5.319555E+01 +5.319554E+01 1.134034E+02 1.967517E-01 1.551313E-03 @@ -122,7 +122,7 @@ tally 1: 8.044764E+01 2.602455E+02 3.474828E-01 -4.908567E-03 +4.908566E-03 9.665057E-01 3.797493E-02 1.561720E+02 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 index 49813144d2..bf602d3e2d 100644 --- 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 @@ -23,7 +23,7 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -5.235812E+01 +5.235813E+01 1.099243E+02 0.000000E+00 0.000000E+00 @@ -72,12 +72,12 @@ tally 1: 0.000000E+00 0.000000E+00 9.495275E+01 -3.613372E+02 +3.613373E+02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -5.799250E+01 +5.799251E+01 1.356178E+02 0.000000E+00 0.000000E+00 @@ -86,7 +86,7 @@ tally 1: 1.066414E+02 4.570291E+02 1.254014E+01 -6.325640E+00 +6.325641E+00 3.052020E+01 3.746918E+01 4.977302E+01 @@ -107,7 +107,7 @@ tally 1: 2.371074E-03 5.920173E-01 1.404478E-02 -5.299862E+01 +5.299863E+01 1.125576E+02 1.959914E-01 1.539191E-03 @@ -118,11 +118,11 @@ tally 1: 5.781230E-02 1.341759E-04 1.430525E-01 -8.215326E-04 +8.215327E-04 7.995734E+01 2.570099E+02 3.452934E-01 -4.844058E-03 +4.844059E-03 9.604162E-01 3.747587E-02 1.556795E+02 diff --git a/tests/regression_tests/random_ray_halton_samples/results_true.dat b/tests/regression_tests/random_ray_halton_samples/results_true.dat index 7eb307da05..b62398935b 100644 --- a/tests/regression_tests/random_ray_halton_samples/results_true.dat +++ b/tests/regression_tests/random_ray_halton_samples/results_true.dat @@ -21,7 +21,7 @@ tally 1: 3.807294E-03 2.376683E+00 1.151027E+00 -8.060902E-02 +8.060903E-02 1.323179E-03 1.961862E-01 7.837693E-03 @@ -109,7 +109,7 @@ tally 1: 1.195422E-03 1.864967E-01 7.080943E-03 -7.105765E+00 +7.105766E+00 1.025960E+01 8.287512E-02 1.396474E-03 @@ -133,9 +133,9 @@ tally 1: 7.031793E-01 4.562478E+00 4.165199E+00 -2.870213E+00 +2.870214E+00 1.650126E+00 -4.244068E-01 +4.244069E-01 3.608745E-02 1.032921E+00 2.137598E-01 @@ -151,7 +151,7 @@ tally 1: 1.251254E-03 1.906210E-01 7.411654E-03 -7.162706E+00 +7.162707E+00 1.042515E+01 8.273831E-02 1.391799E-03 diff --git a/tests/regression_tests/random_ray_k_eff/results_true.dat b/tests/regression_tests/random_ray_k_eff/results_true.dat index a21929d53b..37eca77f3c 100644 --- a/tests/regression_tests/random_ray_k_eff/results_true.dat +++ b/tests/regression_tests/random_ray_k_eff/results_true.dat @@ -24,8 +24,8 @@ tally 1: 7.808142E-02 1.242278E-03 1.900346E-01 -7.358490E-03 -7.134948E+00 +7.358491E-03 +7.134949E+00 1.034824E+01 8.272647E-02 1.391871E-03 @@ -41,7 +41,7 @@ tally 1: 3.449537E+01 1.764293E-01 6.225586E-03 -4.907292E-01 +4.907293E-01 4.816400E-02 7.567715E+00 1.145439E+01 @@ -114,7 +114,7 @@ tally 1: 8.322052E-02 1.408294E-03 2.025446E-01 -8.342070E-03 +8.342071E-03 2.094832E+01 8.816715E+01 3.234739E-02 @@ -150,15 +150,15 @@ tally 1: 7.951819E-02 1.286690E-03 1.935314E-01 -7.621556E-03 -7.119586E+00 +7.621557E-03 +7.119587E+00 1.030023E+01 8.428175E-02 1.442931E-03 2.051274E-01 8.547243E-03 2.046758E+01 -8.418767E+01 +8.418768E+01 3.181946E-02 2.034766E-04 7.873502E-02 diff --git a/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat b/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat index 535db3b551..83209044ba 100644 --- a/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat +++ b/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat @@ -1,7 +1,7 @@ k-combined: 8.379203E-01 8.057199E-03 tally 1: -5.080171E+00 +5.080172E+00 5.167984E+00 1.880341E+00 7.079266E-01 @@ -16,7 +16,7 @@ tally 1: 1.692643E+00 5.794069E-01 5.445214E-02 -5.995212E-04 +5.995213E-04 1.325256E-01 3.551193E-03 2.372336E+00 @@ -35,10 +35,10 @@ tally 1: 8.394042E+01 3.100485E-02 1.932097E-04 -7.671933E-02 +7.671934E-02 1.182985E-03 1.313652E+01 -3.451847E+01 +3.451846E+01 1.764978E-01 6.230420E-03 4.909196E-01 @@ -56,7 +56,7 @@ tally 1: 0.000000E+00 0.000000E+00 1.820058E+00 -6.729238E-01 +6.729239E-01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -96,7 +96,7 @@ tally 1: 4.104063E-01 3.377132E-02 9.988468E-01 -2.000404E-01 +2.000405E-01 1.660506E+00 5.567967E-01 5.427391E-02 @@ -147,13 +147,13 @@ tally 1: 3.699815E-03 2.368737E+00 1.143184E+00 -7.950085E-02 +7.950086E-02 1.286135E-03 1.934892E-01 -7.618268E-03 +7.618269E-03 7.119767E+00 1.030095E+01 -8.427627E-02 +8.427628E-02 1.442764E-03 2.051141E-01 8.546249E-03 diff --git a/tests/regression_tests/random_ray_linear/linear/results_true.dat b/tests/regression_tests/random_ray_linear/linear/results_true.dat index 6617c78216..4c0e14370e 100644 --- a/tests/regression_tests/random_ray_linear/linear/results_true.dat +++ b/tests/regression_tests/random_ray_linear/linear/results_true.dat @@ -24,7 +24,7 @@ tally 1: 5.733016E-01 1.643671E-02 1.395301E+00 -9.736091E-02 +9.736092E-02 4.539598E+01 1.030472E+02 5.263055E-01 @@ -44,7 +44,7 @@ tally 1: 2.008092E+00 2.022988E-01 4.188246E+01 -8.843468E+01 +8.843469E+01 0.000000E+00 0.000000E+00 0.000000E+00 @@ -111,7 +111,7 @@ tally 1: 9.671931E-02 4.539193E+01 1.030326E+02 -5.345253E-01 +5.345254E-01 1.428719E-02 1.300944E+00 8.463057E-02 diff --git a/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/results_true.dat b/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/results_true.dat index 2fc08d0a42..e90d6bfdcb 100644 --- a/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/results_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/results_true.dat @@ -1,6 +1,6 @@ tally 1: -2.339085E+00 -2.747304E-01 +2.339086E+00 +2.747305E-01 tally 2: 1.089827E-01 6.069324E-04 diff --git a/tests/regression_tests/reflective_plane/results_true.dat b/tests/regression_tests/reflective_plane/results_true.dat index a1acfaad7e..a4d6edb677 100644 --- a/tests/regression_tests/reflective_plane/results_true.dat +++ b/tests/regression_tests/reflective_plane/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.276857E+00 8.776678E-03 +2.279066E+00 4.793565E-03 diff --git a/tests/regression_tests/resonance_scattering/results_true.dat b/tests/regression_tests/resonance_scattering/results_true.dat index 8316e720e2..72f0933b83 100644 --- a/tests/regression_tests/resonance_scattering/results_true.dat +++ b/tests/regression_tests/resonance_scattering/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.462509E+00 2.205413E-02 +1.462428E+00 1.828903E-02 diff --git a/tests/regression_tests/rotation/results_true.dat b/tests/regression_tests/rotation/results_true.dat index 0fb8ba981f..6db3d329a0 100644 --- a/tests/regression_tests/rotation/results_true.dat +++ b/tests/regression_tests/rotation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.175600E-01 1.117465E-02 +4.459219E-01 1.899168E-02 diff --git a/tests/regression_tests/salphabeta/results_true.dat b/tests/regression_tests/salphabeta/results_true.dat index d5c7f66e90..75a81075e9 100644 --- a/tests/regression_tests/salphabeta/results_true.dat +++ b/tests/regression_tests/salphabeta/results_true.dat @@ -1,2 +1,2 @@ k-combined: -8.694866E-01 2.033328E-02 +8.628529E-01 3.120924E-02 diff --git a/tests/regression_tests/score_current/results_true.dat b/tests/regression_tests/score_current/results_true.dat index ff939301d0..6bb74445ce 100644 --- a/tests/regression_tests/score_current/results_true.dat +++ b/tests/regression_tests/score_current/results_true.dat @@ -1,274 +1,490 @@ k-combined: -2.298294E-01 3.256961E-01 +7.729082E-01 3.775399E-02 tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.150000E-01 -2.753000E-03 -1.820000E-01 -6.756000E-03 +1.200000E-01 +2.924000E-03 +1.740000E-01 +6.270000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.110000E-01 -2.601000E-03 -1.530000E-01 -4.865000E-03 -1.910000E-01 -7.535000E-03 +1.200000E-01 +3.044000E-03 +1.510000E-01 +4.615000E-03 +1.710000E-01 +6.067000E-03 0.000000E+00 0.000000E+00 -7.100000E-02 -1.079000E-03 -1.500000E-01 -4.606000E-03 -1.820000E-01 -6.756000E-03 -1.150000E-01 -2.753000E-03 -1.610000E-01 -5.383000E-03 -1.230000E-01 -3.141000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.951000E-03 -2.600000E-01 -1.366400E-02 -1.930000E-01 -7.573000E-03 -0.000000E+00 -0.000000E+00 -8.500000E-02 -1.533000E-03 -2.040000E-01 -8.426000E-03 -1.230000E-01 -3.141000E-03 -1.610000E-01 -5.383000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.250000E-01 -3.311000E-03 -1.620000E-01 -5.346000E-03 -1.860000E-01 -6.932000E-03 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.083000E-03 -1.630000E-01 -5.617000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.800000E-01 -7.002000E-03 -2.980000E-01 -1.815000E-02 -1.530000E-01 -4.865000E-03 -1.110000E-01 -2.601000E-03 -1.890000E-01 -7.605000E-03 -1.330000E-01 -3.743000E-03 -1.790000E-01 -6.495000E-03 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.718000E-03 -2.160000E-01 -9.662000E-03 -2.980000E-01 -1.815000E-02 -1.800000E-01 -7.002000E-03 -2.650000E-01 -1.435500E-02 -1.590000E-01 -5.285000E-03 -2.600000E-01 -1.366400E-02 -1.370000E-01 -3.951000E-03 -2.670000E-01 -1.469300E-02 -1.940000E-01 -7.678000E-03 -2.390000E-01 -1.155500E-02 -0.000000E+00 -0.000000E+00 -2.410000E-01 -1.255900E-02 -5.510000E-01 -7.358900E-02 -1.590000E-01 -5.285000E-03 -2.650000E-01 -1.435500E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.346000E-03 -1.250000E-01 -3.311000E-03 -1.870000E-01 -7.083000E-03 +6.500000E-02 +9.390000E-04 1.410000E-01 -3.999000E-03 -2.040000E-01 -8.438000E-03 +4.001000E-03 +1.740000E-01 +6.270000E-03 +1.200000E-01 +2.924000E-03 +1.830000E-01 +6.879000E-03 +1.310000E-01 +3.541000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.750000E-01 +6.659000E-03 +2.820000E-01 +1.605400E-02 +1.980000E-01 +7.932000E-03 +0.000000E+00 +0.000000E+00 +9.400000E-02 +1.912000E-03 +2.200000E-01 +9.958000E-03 +1.310000E-01 +3.541000E-03 +1.830000E-01 +6.879000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.110000E-01 +2.639000E-03 +1.360000E-01 +3.890000E-03 +1.770000E-01 +6.551000E-03 +0.000000E+00 +0.000000E+00 +6.700000E-02 +9.310000E-04 +1.570000E-01 +4.975000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.480000E-01 +4.910000E-03 +2.720000E-01 +1.490600E-02 +1.510000E-01 +4.615000E-03 +1.200000E-01 +3.044000E-03 +1.800000E-01 +6.720000E-03 +1.050000E-01 +2.285000E-03 +1.790000E-01 +6.499000E-03 0.000000E+00 0.000000E+00 9.300000E-02 -1.829000E-03 -2.240000E-01 -1.015800E-02 +1.927000E-03 +2.160000E-01 +9.418000E-03 +2.720000E-01 +1.490600E-02 +1.480000E-01 +4.910000E-03 +2.680000E-01 +1.445800E-02 +1.480000E-01 +4.488000E-03 +2.820000E-01 +1.605400E-02 +1.750000E-01 +6.659000E-03 +2.510000E-01 +1.283100E-02 +1.870000E-01 +7.731000E-03 +2.340000E-01 +1.105000E-02 +0.000000E+00 +0.000000E+00 +2.110000E-01 +9.215000E-03 +5.470000E-01 +7.228300E-02 +1.480000E-01 +4.488000E-03 +2.680000E-01 +1.445800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.360000E-01 +3.890000E-03 +1.110000E-01 +2.639000E-03 +1.540000E-01 +4.804000E-03 +1.280000E-01 +3.302000E-03 +2.200000E-01 +9.834000E-03 +0.000000E+00 +0.000000E+00 +9.900000E-02 +2.127000E-03 +1.860000E-01 +7.198000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.430000E-01 +4.337000E-03 +1.580000E-01 +5.104000E-03 +1.050000E-01 +2.285000E-03 +1.800000E-01 +6.720000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.860000E-01 +7.178000E-03 +0.000000E+00 +0.000000E+00 +7.000000E-02 +1.020000E-03 +1.610000E-01 +5.237000E-03 +1.580000E-01 +5.104000E-03 +1.430000E-01 +4.337000E-03 +1.580000E-01 +5.254000E-03 +1.230000E-01 +3.091000E-03 +1.870000E-01 +7.731000E-03 +2.510000E-01 +1.283100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.980000E-01 +7.934000E-03 +0.000000E+00 +0.000000E+00 +9.500000E-02 +1.949000E-03 +2.150000E-01 +9.289000E-03 +1.230000E-01 +3.091000E-03 +1.580000E-01 +5.254000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.280000E-01 +3.302000E-03 +1.540000E-01 +4.804000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.640000E-01 +5.424000E-03 +0.000000E+00 +0.000000E+00 +6.200000E-02 +8.020000E-04 +1.500000E-01 +4.588000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.700000E-01 +5.884000E-03 +2.280000E-01 +1.084800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.856000E-03 +2.250000E-01 +1.047100E-02 +1.410000E-01 +4.001000E-03 +6.500000E-02 +9.390000E-04 +1.360000E-01 +3.852000E-03 +6.400000E-02 +8.700000E-04 +2.280000E-01 +1.084800E-02 +1.700000E-01 +5.884000E-03 +2.230000E-01 +1.001100E-02 +1.410000E-01 +4.185000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.980000E-01 +8.038000E-03 +5.030000E-01 +5.613900E-02 +2.200000E-01 +9.958000E-03 +9.400000E-02 +1.912000E-03 +2.140000E-01 +9.376000E-03 +7.300000E-02 +1.091000E-03 +1.410000E-01 +4.185000E-03 +2.230000E-01 +1.001100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.808000E-03 +2.340000E-01 +1.119400E-02 +1.570000E-01 +4.975000E-03 +6.700000E-02 +9.310000E-04 +1.600000E-01 +5.134000E-03 +5.300000E-02 +6.110000E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.310000E-01 +1.084100E-02 +5.390000E-01 +6.215100E-02 +2.250000E-01 +1.047100E-02 +1.540000E-01 +4.856000E-03 +2.280000E-01 +1.059800E-02 +1.600000E-01 +5.214000E-03 +2.160000E-01 +9.418000E-03 +9.300000E-02 +1.927000E-03 +2.510000E-01 +1.271500E-02 +1.030000E-01 +2.229000E-03 +5.390000E-01 +6.215100E-02 +2.310000E-01 +1.084100E-02 +4.700000E-01 +4.972200E-02 +2.190000E-01 +9.821000E-03 +5.030000E-01 +5.613900E-02 +1.980000E-01 +8.038000E-03 +5.100000E-01 +5.929000E-02 +2.140000E-01 +9.406000E-03 +5.470000E-01 +7.228300E-02 +2.110000E-01 +9.215000E-03 +5.160000E-01 +5.892200E-02 +2.550000E-01 +1.480500E-02 +2.190000E-01 +9.821000E-03 +4.700000E-01 +4.972200E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.340000E-01 +1.119400E-02 +1.540000E-01 +4.808000E-03 +2.170000E-01 +9.509000E-03 +1.600000E-01 +5.156000E-03 +1.860000E-01 +7.198000E-03 +9.900000E-02 +2.127000E-03 +2.290000E-01 +1.058700E-02 +9.000000E-02 +1.780000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.550000E-01 +4.913000E-03 +2.380000E-01 +1.153400E-02 +1.600000E-01 +5.214000E-03 +2.280000E-01 +1.059800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.610000E-01 +5.237000E-03 +7.000000E-02 +1.020000E-03 +1.410000E-01 +4.071000E-03 +6.100000E-02 +8.350000E-04 +2.380000E-01 +1.153400E-02 +1.550000E-01 +4.913000E-03 +2.320000E-01 +1.100400E-02 +1.460000E-01 +4.498000E-03 +2.140000E-01 +9.406000E-03 +5.100000E-01 +5.929000E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.150000E-01 +9.289000E-03 +9.500000E-02 +1.949000E-03 +1.870000E-01 +7.267000E-03 +1.030000E-01 +2.543000E-03 +1.460000E-01 +4.498000E-03 +2.320000E-01 +1.100400E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.156000E-03 +2.170000E-01 +9.509000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.500000E-01 -4.522000E-03 -1.630000E-01 -5.439000E-03 -1.330000E-01 -3.743000E-03 -1.890000E-01 -7.605000E-03 +4.588000E-03 +6.200000E-02 +8.020000E-04 +1.290000E-01 +3.487000E-03 +6.000000E-02 +8.060000E-04 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +1.090000E-01 +2.437000E-03 +1.650000E-01 +5.655000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.065000E-03 +1.570000E-01 +4.999000E-03 +6.400000E-02 +8.700000E-04 +1.360000E-01 +3.852000E-03 +1.750000E-01 +6.299000E-03 +0.000000E+00 +0.000000E+00 1.650000E-01 -5.615000E-03 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.191000E-03 -1.550000E-01 -5.011000E-03 -1.630000E-01 -5.439000E-03 -1.500000E-01 -4.522000E-03 -1.680000E-01 -5.966000E-03 -1.290000E-01 -3.515000E-03 -1.940000E-01 -7.678000E-03 -2.670000E-01 -1.469300E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.810000E-01 -6.765000E-03 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.694000E-03 -2.070000E-01 -8.673000E-03 -1.290000E-01 -3.515000E-03 -1.680000E-01 -5.966000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.410000E-01 -3.999000E-03 -1.870000E-01 -7.083000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.870000E-01 -7.213000E-03 -0.000000E+00 -0.000000E+00 -8.200000E-02 -1.536000E-03 -1.760000E-01 -6.550000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.750000E-01 -6.163000E-03 -2.570000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.914000E-03 -2.350000E-01 -1.135900E-02 -1.500000E-01 -4.606000E-03 -7.100000E-02 -1.079000E-03 -1.530000E-01 -4.837000E-03 -5.600000E-02 -7.260000E-04 -2.570000E-01 -1.347100E-02 -1.750000E-01 -6.163000E-03 -2.460000E-01 -1.235000E-02 -1.420000E-01 -4.326000E-03 +5.655000E-03 +1.090000E-01 +2.437000E-03 +1.480000E-01 +4.674000E-03 +1.320000E-01 +3.548000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +1.440000E-01 +4.282000E-03 +2.190000E-01 +9.683000E-03 +7.300000E-02 +1.091000E-03 +2.140000E-01 +9.376000E-03 1.830000E-01 -7.133000E-03 -5.110000E-01 -5.696100E-02 -2.040000E-01 -8.426000E-03 -8.500000E-02 -1.533000E-03 -2.100000E-01 -8.928000E-03 -9.100000E-02 -1.807000E-03 -1.420000E-01 -4.326000E-03 -2.460000E-01 -1.235000E-02 +6.803000E-03 +0.000000E+00 +0.000000E+00 +1.320000E-01 +3.548000E-03 +1.480000E-01 +4.674000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -277,376 +493,160 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +1.350000E-01 +3.895000E-03 1.430000E-01 -4.207000E-03 -2.120000E-01 -9.278000E-03 -1.630000E-01 -5.617000E-03 -7.100000E-02 -1.083000E-03 -1.770000E-01 -6.293000E-03 -7.900000E-02 -1.495000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.081000E-02 -5.200000E-01 -5.835000E-02 -2.350000E-01 -1.135900E-02 -1.560000E-01 -4.914000E-03 -2.370000E-01 -1.142300E-02 -1.360000E-01 -3.882000E-03 -2.160000E-01 -9.662000E-03 -1.080000E-01 -2.718000E-03 -2.090000E-01 -8.841000E-03 -1.030000E-01 -2.271000E-03 -5.200000E-01 -5.835000E-02 -2.300000E-01 -1.081000E-02 -5.110000E-01 -5.615900E-02 -2.430000E-01 -1.228300E-02 -5.110000E-01 -5.696100E-02 -1.830000E-01 -7.133000E-03 -5.130000E-01 -6.002100E-02 -2.420000E-01 -1.209200E-02 -5.510000E-01 -7.358900E-02 -2.410000E-01 -1.255900E-02 -5.140000E-01 -5.890200E-02 -2.100000E-01 -1.004600E-02 -2.430000E-01 -1.228300E-02 -5.110000E-01 -5.615900E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.120000E-01 -9.278000E-03 -1.430000E-01 -4.207000E-03 -2.380000E-01 -1.133600E-02 -1.640000E-01 -5.444000E-03 -2.240000E-01 -1.015800E-02 -9.300000E-02 -1.829000E-03 -1.950000E-01 -7.705000E-03 -1.030000E-01 -2.191000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.878000E-03 -2.230000E-01 -1.049900E-02 -1.360000E-01 -3.882000E-03 -2.370000E-01 -1.142300E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.550000E-01 -5.011000E-03 -7.100000E-02 -1.191000E-03 -1.510000E-01 -4.845000E-03 -6.400000E-02 -9.460000E-04 -2.230000E-01 -1.049900E-02 -1.680000E-01 -5.878000E-03 -2.490000E-01 -1.255900E-02 -1.280000E-01 -3.448000E-03 -2.420000E-01 -1.209200E-02 -5.130000E-01 -6.002100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.070000E-01 -8.673000E-03 -1.080000E-01 -2.694000E-03 -2.000000E-01 -8.202000E-03 -9.600000E-02 -2.024000E-03 -1.280000E-01 -3.448000E-03 -2.490000E-01 -1.255900E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.444000E-03 -2.380000E-01 -1.133600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.760000E-01 -6.550000E-03 -8.200000E-02 -1.536000E-03 -1.670000E-01 -5.653000E-03 -4.900000E-02 -5.630000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.626000E-03 -1.510000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.855000E-03 -1.610000E-01 -5.233000E-03 -5.600000E-02 -7.260000E-04 -1.530000E-01 -4.837000E-03 -1.610000E-01 -5.261000E-03 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.831000E-03 -1.320000E-01 -3.626000E-03 -1.490000E-01 -4.731000E-03 -1.320000E-01 -3.514000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.921000E-03 -2.410000E-01 -1.168300E-02 -9.100000E-02 -1.807000E-03 -2.100000E-01 -8.928000E-03 -2.090000E-01 -8.775000E-03 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.514000E-03 -1.490000E-01 -4.731000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.150000E-01 -2.891000E-03 -1.560000E-01 -5.154000E-03 -7.900000E-02 -1.495000E-03 -1.770000E-01 -6.293000E-03 +4.297000E-03 +5.300000E-02 +6.110000E-04 1.600000E-01 -5.352000E-03 +5.134000E-03 +1.380000E-01 +4.220000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.610000E-01 -5.273000E-03 -2.310000E-01 -1.098100E-02 -1.610000E-01 -5.233000E-03 -1.370000E-01 -3.855000E-03 -1.760000E-01 -6.482000E-03 -1.340000E-01 -3.882000E-03 +1.900000E-01 +7.412000E-03 +2.420000E-01 +1.208400E-02 +1.570000E-01 +4.999000E-03 +1.230000E-01 +3.065000E-03 +1.730000E-01 +6.279000E-03 +1.330000E-01 +3.621000E-03 1.030000E-01 -2.271000E-03 -2.090000E-01 -8.841000E-03 -1.830000E-01 -6.761000E-03 -0.000000E+00 -0.000000E+00 -2.310000E-01 -1.098100E-02 -1.610000E-01 -5.273000E-03 -2.620000E-01 -1.380600E-02 -1.700000E-01 -5.970000E-03 -2.410000E-01 -1.168300E-02 -1.550000E-01 -4.921000E-03 -2.250000E-01 -1.014100E-02 -1.370000E-01 -3.805000E-03 +2.229000E-03 +2.510000E-01 +1.271500E-02 2.100000E-01 -1.004600E-02 -5.140000E-01 -5.890200E-02 -2.320000E-01 -1.093000E-02 +8.970000E-03 0.000000E+00 0.000000E+00 -1.700000E-01 -5.970000E-03 -2.620000E-01 -1.380600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -5.154000E-03 -1.150000E-01 -2.891000E-03 -1.430000E-01 -4.163000E-03 -1.120000E-01 -2.640000E-03 -1.030000E-01 -2.191000E-03 -1.950000E-01 -7.705000E-03 -1.760000E-01 -6.392000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.200000E-02 -1.822000E-03 -1.370000E-01 -3.843000E-03 -1.340000E-01 -3.882000E-03 -1.760000E-01 -6.482000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.400000E-02 -9.460000E-04 -1.510000E-01 -4.845000E-03 -1.800000E-01 -6.520000E-03 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.843000E-03 -9.200000E-02 -1.822000E-03 -1.300000E-01 -3.604000E-03 -1.170000E-01 -2.789000E-03 -1.370000E-01 -3.805000E-03 -2.250000E-01 -1.014100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.600000E-02 -2.024000E-03 +2.420000E-01 +1.208400E-02 +1.900000E-01 +7.412000E-03 +2.610000E-01 +1.399900E-02 2.000000E-01 -8.202000E-03 -1.820000E-01 -6.660000E-03 +8.410000E-03 +2.190000E-01 +9.683000E-03 +1.440000E-01 +4.282000E-03 +2.690000E-01 +1.478100E-02 +1.540000E-01 +4.986000E-03 +2.550000E-01 +1.480500E-02 +5.160000E-01 +5.892200E-02 +2.310000E-01 +1.098900E-02 +0.000000E+00 +0.000000E+00 +2.000000E-01 +8.410000E-03 +2.610000E-01 +1.399900E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.430000E-01 +4.297000E-03 +1.350000E-01 +3.895000E-03 +1.760000E-01 +6.534000E-03 +1.170000E-01 +2.807000E-03 +9.000000E-02 +1.780000E-03 +2.290000E-01 +1.058700E-02 +2.080000E-01 +8.854000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.305000E-03 +1.760000E-01 +6.598000E-03 +1.330000E-01 +3.621000E-03 +1.730000E-01 +6.279000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.100000E-02 +8.350000E-04 +1.410000E-01 +4.071000E-03 +1.800000E-01 +6.574000E-03 +0.000000E+00 +0.000000E+00 +1.760000E-01 +6.598000E-03 +1.230000E-01 +3.305000E-03 +1.690000E-01 +6.135000E-03 +1.220000E-01 +3.344000E-03 +1.540000E-01 +4.986000E-03 +2.690000E-01 +1.478100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.030000E-01 +2.543000E-03 +1.870000E-01 +7.267000E-03 +1.690000E-01 +5.731000E-03 +0.000000E+00 +0.000000E+00 +1.220000E-01 +3.344000E-03 +1.690000E-01 +6.135000E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 1.170000E-01 -2.789000E-03 -1.300000E-01 -3.604000E-03 +2.807000E-03 +1.760000E-01 +6.534000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.120000E-01 -2.640000E-03 -1.430000E-01 -4.163000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.900000E-02 -5.630000E-04 -1.670000E-01 -5.653000E-03 -1.670000E-01 -5.701000E-03 +6.000000E-02 +8.060000E-04 +1.290000E-01 +3.487000E-03 +1.790000E-01 +6.747000E-03 0.000000E+00 0.000000E+00 tally 2: @@ -660,12 +660,12 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -1.150000E-01 -2.753000E-03 +1.200000E-01 +2.924000E-03 0.000000E+00 0.000000E+00 -1.820000E-01 -6.756000E-03 +1.740000E-01 +6.270000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -676,256 +676,160 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -1.110000E-01 -2.601000E-03 +1.200000E-01 +3.044000E-03 0.000000E+00 0.000000E+00 -1.530000E-01 -4.865000E-03 +1.510000E-01 +4.615000E-03 0.000000E+00 0.000000E+00 -1.910000E-01 -7.535000E-03 +1.710000E-01 +6.067000E-03 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.100000E-02 -1.079000E-03 -0.000000E+00 -0.000000E+00 -1.500000E-01 -4.606000E-03 -0.000000E+00 -0.000000E+00 -1.820000E-01 -6.756000E-03 -0.000000E+00 -0.000000E+00 -1.150000E-01 -2.753000E-03 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.383000E-03 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.141000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.951000E-03 -0.000000E+00 -0.000000E+00 -2.600000E-01 -1.366400E-02 -0.000000E+00 -0.000000E+00 -1.930000E-01 -7.573000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.500000E-02 -1.533000E-03 -0.000000E+00 -0.000000E+00 -2.040000E-01 -8.426000E-03 -0.000000E+00 -0.000000E+00 -1.230000E-01 -3.141000E-03 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.383000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.250000E-01 -3.311000E-03 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.346000E-03 -0.000000E+00 -0.000000E+00 -1.860000E-01 -6.932000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.083000E-03 -0.000000E+00 -0.000000E+00 -1.630000E-01 -5.617000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.800000E-01 -7.002000E-03 -0.000000E+00 -0.000000E+00 -2.980000E-01 -1.815000E-02 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.865000E-03 -0.000000E+00 -0.000000E+00 -1.110000E-01 -2.601000E-03 -0.000000E+00 -0.000000E+00 -1.890000E-01 -7.605000E-03 -0.000000E+00 -0.000000E+00 -1.330000E-01 -3.743000E-03 -0.000000E+00 -0.000000E+00 -1.790000E-01 -6.495000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.718000E-03 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.662000E-03 -0.000000E+00 -0.000000E+00 -2.980000E-01 -1.815000E-02 -0.000000E+00 -0.000000E+00 -1.800000E-01 -7.002000E-03 -0.000000E+00 -0.000000E+00 -2.650000E-01 -1.435500E-02 -0.000000E+00 -0.000000E+00 -1.590000E-01 -5.285000E-03 -0.000000E+00 -0.000000E+00 -2.600000E-01 -1.366400E-02 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.951000E-03 -0.000000E+00 -0.000000E+00 -2.670000E-01 -1.469300E-02 -0.000000E+00 -0.000000E+00 -1.940000E-01 -7.678000E-03 -0.000000E+00 -0.000000E+00 -2.390000E-01 -1.155500E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.410000E-01 -1.255900E-02 -0.000000E+00 -0.000000E+00 -5.510000E-01 -7.358900E-02 -0.000000E+00 -0.000000E+00 -1.590000E-01 -5.285000E-03 -0.000000E+00 -0.000000E+00 -2.650000E-01 -1.435500E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.620000E-01 -5.346000E-03 -0.000000E+00 -0.000000E+00 -1.250000E-01 -3.311000E-03 -0.000000E+00 -0.000000E+00 -1.870000E-01 -7.083000E-03 +6.500000E-02 +9.390000E-04 0.000000E+00 0.000000E+00 1.410000E-01 -3.999000E-03 +4.001000E-03 0.000000E+00 0.000000E+00 -2.040000E-01 -8.438000E-03 +1.740000E-01 +6.270000E-03 +0.000000E+00 +0.000000E+00 +1.200000E-01 +2.924000E-03 +0.000000E+00 +0.000000E+00 +1.830000E-01 +6.879000E-03 +0.000000E+00 +0.000000E+00 +1.310000E-01 +3.541000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.750000E-01 +6.659000E-03 +0.000000E+00 +0.000000E+00 +2.820000E-01 +1.605400E-02 +0.000000E+00 +0.000000E+00 +1.980000E-01 +7.932000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.400000E-02 +1.912000E-03 +0.000000E+00 +0.000000E+00 +2.200000E-01 +9.958000E-03 +0.000000E+00 +0.000000E+00 +1.310000E-01 +3.541000E-03 +0.000000E+00 +0.000000E+00 +1.830000E-01 +6.879000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.110000E-01 +2.639000E-03 +0.000000E+00 +0.000000E+00 +1.360000E-01 +3.890000E-03 +0.000000E+00 +0.000000E+00 +1.770000E-01 +6.551000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.700000E-02 +9.310000E-04 +0.000000E+00 +0.000000E+00 +1.570000E-01 +4.975000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.480000E-01 +4.910000E-03 +0.000000E+00 +0.000000E+00 +2.720000E-01 +1.490600E-02 +0.000000E+00 +0.000000E+00 +1.510000E-01 +4.615000E-03 +0.000000E+00 +0.000000E+00 +1.200000E-01 +3.044000E-03 +0.000000E+00 +0.000000E+00 +1.800000E-01 +6.720000E-03 +0.000000E+00 +0.000000E+00 +1.050000E-01 +2.285000E-03 +0.000000E+00 +0.000000E+00 +1.790000E-01 +6.499000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -933,11 +837,659 @@ tally 2: 0.000000E+00 0.000000E+00 9.300000E-02 -1.829000E-03 +1.927000E-03 0.000000E+00 0.000000E+00 -2.240000E-01 -1.015800E-02 +2.160000E-01 +9.418000E-03 +0.000000E+00 +0.000000E+00 +2.720000E-01 +1.490600E-02 +0.000000E+00 +0.000000E+00 +1.480000E-01 +4.910000E-03 +0.000000E+00 +0.000000E+00 +2.680000E-01 +1.445800E-02 +0.000000E+00 +0.000000E+00 +1.480000E-01 +4.488000E-03 +0.000000E+00 +0.000000E+00 +2.820000E-01 +1.605400E-02 +0.000000E+00 +0.000000E+00 +1.750000E-01 +6.659000E-03 +0.000000E+00 +0.000000E+00 +2.510000E-01 +1.283100E-02 +0.000000E+00 +0.000000E+00 +1.870000E-01 +7.731000E-03 +0.000000E+00 +0.000000E+00 +2.340000E-01 +1.105000E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.110000E-01 +9.215000E-03 +0.000000E+00 +0.000000E+00 +5.470000E-01 +7.228300E-02 +0.000000E+00 +0.000000E+00 +1.480000E-01 +4.488000E-03 +0.000000E+00 +0.000000E+00 +2.680000E-01 +1.445800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.360000E-01 +3.890000E-03 +0.000000E+00 +0.000000E+00 +1.110000E-01 +2.639000E-03 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.804000E-03 +0.000000E+00 +0.000000E+00 +1.280000E-01 +3.302000E-03 +0.000000E+00 +0.000000E+00 +2.200000E-01 +9.834000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.900000E-02 +2.127000E-03 +0.000000E+00 +0.000000E+00 +1.860000E-01 +7.198000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.430000E-01 +4.337000E-03 +0.000000E+00 +0.000000E+00 +1.580000E-01 +5.104000E-03 +0.000000E+00 +0.000000E+00 +1.050000E-01 +2.285000E-03 +0.000000E+00 +0.000000E+00 +1.800000E-01 +6.720000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.860000E-01 +7.178000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.000000E-02 +1.020000E-03 +0.000000E+00 +0.000000E+00 +1.610000E-01 +5.237000E-03 +0.000000E+00 +0.000000E+00 +1.580000E-01 +5.104000E-03 +0.000000E+00 +0.000000E+00 +1.430000E-01 +4.337000E-03 +0.000000E+00 +0.000000E+00 +1.580000E-01 +5.254000E-03 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.091000E-03 +0.000000E+00 +0.000000E+00 +1.870000E-01 +7.731000E-03 +0.000000E+00 +0.000000E+00 +2.510000E-01 +1.283100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.980000E-01 +7.934000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.500000E-02 +1.949000E-03 +0.000000E+00 +0.000000E+00 +2.150000E-01 +9.289000E-03 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.091000E-03 +0.000000E+00 +0.000000E+00 +1.580000E-01 +5.254000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.280000E-01 +3.302000E-03 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.804000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.640000E-01 +5.424000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.200000E-02 +8.020000E-04 +0.000000E+00 +0.000000E+00 +1.500000E-01 +4.588000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.700000E-01 +5.884000E-03 +0.000000E+00 +0.000000E+00 +2.280000E-01 +1.084800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.856000E-03 +0.000000E+00 +0.000000E+00 +2.250000E-01 +1.047100E-02 +0.000000E+00 +0.000000E+00 +1.410000E-01 +4.001000E-03 +0.000000E+00 +0.000000E+00 +6.500000E-02 +9.390000E-04 +0.000000E+00 +0.000000E+00 +1.360000E-01 +3.852000E-03 +0.000000E+00 +0.000000E+00 +6.400000E-02 +8.700000E-04 +0.000000E+00 +0.000000E+00 +2.280000E-01 +1.084800E-02 +0.000000E+00 +0.000000E+00 +1.700000E-01 +5.884000E-03 +0.000000E+00 +0.000000E+00 +2.230000E-01 +1.001100E-02 +0.000000E+00 +0.000000E+00 +1.410000E-01 +4.185000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.980000E-01 +8.038000E-03 +0.000000E+00 +0.000000E+00 +5.030000E-01 +5.613900E-02 +0.000000E+00 +0.000000E+00 +2.200000E-01 +9.958000E-03 +0.000000E+00 +0.000000E+00 +9.400000E-02 +1.912000E-03 +0.000000E+00 +0.000000E+00 +2.140000E-01 +9.376000E-03 +0.000000E+00 +0.000000E+00 +7.300000E-02 +1.091000E-03 +0.000000E+00 +0.000000E+00 +1.410000E-01 +4.185000E-03 +0.000000E+00 +0.000000E+00 +2.230000E-01 +1.001100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.808000E-03 +0.000000E+00 +0.000000E+00 +2.340000E-01 +1.119400E-02 +0.000000E+00 +0.000000E+00 +1.570000E-01 +4.975000E-03 +0.000000E+00 +0.000000E+00 +6.700000E-02 +9.310000E-04 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.134000E-03 +0.000000E+00 +0.000000E+00 +5.300000E-02 +6.110000E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.310000E-01 +1.084100E-02 +0.000000E+00 +0.000000E+00 +5.390000E-01 +6.215100E-02 +0.000000E+00 +0.000000E+00 +2.250000E-01 +1.047100E-02 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.856000E-03 +0.000000E+00 +0.000000E+00 +2.280000E-01 +1.059800E-02 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.214000E-03 +0.000000E+00 +0.000000E+00 +2.160000E-01 +9.418000E-03 +0.000000E+00 +0.000000E+00 +9.300000E-02 +1.927000E-03 +0.000000E+00 +0.000000E+00 +2.510000E-01 +1.271500E-02 +0.000000E+00 +0.000000E+00 +1.030000E-01 +2.229000E-03 +0.000000E+00 +0.000000E+00 +5.390000E-01 +6.215100E-02 +0.000000E+00 +0.000000E+00 +2.310000E-01 +1.084100E-02 +0.000000E+00 +0.000000E+00 +4.700000E-01 +4.972200E-02 +0.000000E+00 +0.000000E+00 +2.190000E-01 +9.821000E-03 +0.000000E+00 +0.000000E+00 +5.030000E-01 +5.613900E-02 +0.000000E+00 +0.000000E+00 +1.980000E-01 +8.038000E-03 +0.000000E+00 +0.000000E+00 +5.100000E-01 +5.929000E-02 +0.000000E+00 +0.000000E+00 +2.140000E-01 +9.406000E-03 +0.000000E+00 +0.000000E+00 +5.470000E-01 +7.228300E-02 +0.000000E+00 +0.000000E+00 +2.110000E-01 +9.215000E-03 +0.000000E+00 +0.000000E+00 +5.160000E-01 +5.892200E-02 +0.000000E+00 +0.000000E+00 +2.550000E-01 +1.480500E-02 +0.000000E+00 +0.000000E+00 +2.190000E-01 +9.821000E-03 +0.000000E+00 +0.000000E+00 +4.700000E-01 +4.972200E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.340000E-01 +1.119400E-02 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.808000E-03 +0.000000E+00 +0.000000E+00 +2.170000E-01 +9.509000E-03 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.156000E-03 +0.000000E+00 +0.000000E+00 +1.860000E-01 +7.198000E-03 +0.000000E+00 +0.000000E+00 +9.900000E-02 +2.127000E-03 +0.000000E+00 +0.000000E+00 +2.290000E-01 +1.058700E-02 +0.000000E+00 +0.000000E+00 +9.000000E-02 +1.780000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.550000E-01 +4.913000E-03 +0.000000E+00 +0.000000E+00 +2.380000E-01 +1.153400E-02 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.214000E-03 +0.000000E+00 +0.000000E+00 +2.280000E-01 +1.059800E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.610000E-01 +5.237000E-03 +0.000000E+00 +0.000000E+00 +7.000000E-02 +1.020000E-03 +0.000000E+00 +0.000000E+00 +1.410000E-01 +4.071000E-03 +0.000000E+00 +0.000000E+00 +6.100000E-02 +8.350000E-04 +0.000000E+00 +0.000000E+00 +2.380000E-01 +1.153400E-02 +0.000000E+00 +0.000000E+00 +1.550000E-01 +4.913000E-03 +0.000000E+00 +0.000000E+00 +2.320000E-01 +1.100400E-02 +0.000000E+00 +0.000000E+00 +1.460000E-01 +4.498000E-03 +0.000000E+00 +0.000000E+00 +2.140000E-01 +9.406000E-03 +0.000000E+00 +0.000000E+00 +5.100000E-01 +5.929000E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.150000E-01 +9.289000E-03 +0.000000E+00 +0.000000E+00 +9.500000E-02 +1.949000E-03 +0.000000E+00 +0.000000E+00 +1.870000E-01 +7.267000E-03 +0.000000E+00 +0.000000E+00 +1.030000E-01 +2.543000E-03 +0.000000E+00 +0.000000E+00 +1.460000E-01 +4.498000E-03 +0.000000E+00 +0.000000E+00 +2.320000E-01 +1.100400E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.600000E-01 +5.156000E-03 +0.000000E+00 +0.000000E+00 +2.170000E-01 +9.509000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -949,19 +1501,19 @@ tally 2: 0.000000E+00 0.000000E+00 1.500000E-01 -4.522000E-03 +4.588000E-03 0.000000E+00 0.000000E+00 -1.630000E-01 -5.439000E-03 +6.200000E-02 +8.020000E-04 0.000000E+00 0.000000E+00 -1.330000E-01 -3.743000E-03 +1.290000E-01 +3.487000E-03 0.000000E+00 0.000000E+00 -1.890000E-01 -7.605000E-03 +6.000000E-02 +8.060000E-04 0.000000E+00 0.000000E+00 0.000000E+00 @@ -972,220 +1524,100 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 +1.090000E-01 +2.437000E-03 +0.000000E+00 +0.000000E+00 +1.650000E-01 +5.655000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.065000E-03 +0.000000E+00 +0.000000E+00 +1.570000E-01 +4.999000E-03 +0.000000E+00 +0.000000E+00 +6.400000E-02 +8.700000E-04 +0.000000E+00 +0.000000E+00 +1.360000E-01 +3.852000E-03 +0.000000E+00 +0.000000E+00 +1.750000E-01 +6.299000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 1.650000E-01 -5.615000E-03 +5.655000E-03 0.000000E+00 0.000000E+00 +1.090000E-01 +2.437000E-03 0.000000E+00 0.000000E+00 +1.480000E-01 +4.674000E-03 0.000000E+00 0.000000E+00 -7.100000E-02 -1.191000E-03 +1.320000E-01 +3.548000E-03 0.000000E+00 0.000000E+00 -1.550000E-01 -5.011000E-03 0.000000E+00 0.000000E+00 -1.630000E-01 -5.439000E-03 0.000000E+00 0.000000E+00 -1.500000E-01 -4.522000E-03 0.000000E+00 0.000000E+00 -1.680000E-01 -5.966000E-03 -0.000000E+00 -0.000000E+00 -1.290000E-01 -3.515000E-03 -0.000000E+00 -0.000000E+00 -1.940000E-01 -7.678000E-03 -0.000000E+00 -0.000000E+00 -2.670000E-01 -1.469300E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.810000E-01 -6.765000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.694000E-03 -0.000000E+00 -0.000000E+00 -2.070000E-01 -8.673000E-03 -0.000000E+00 -0.000000E+00 -1.290000E-01 -3.515000E-03 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.966000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.410000E-01 -3.999000E-03 -0.000000E+00 -0.000000E+00 -1.870000E-01 -7.083000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.870000E-01 -7.213000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.200000E-02 -1.536000E-03 -0.000000E+00 -0.000000E+00 -1.760000E-01 -6.550000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.750000E-01 -6.163000E-03 -0.000000E+00 -0.000000E+00 -2.570000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.914000E-03 -0.000000E+00 -0.000000E+00 -2.350000E-01 -1.135900E-02 -0.000000E+00 -0.000000E+00 -1.500000E-01 -4.606000E-03 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.079000E-03 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.837000E-03 -0.000000E+00 -0.000000E+00 -5.600000E-02 -7.260000E-04 -0.000000E+00 -0.000000E+00 -2.570000E-01 -1.347100E-02 -0.000000E+00 -0.000000E+00 -1.750000E-01 -6.163000E-03 -0.000000E+00 -0.000000E+00 -2.460000E-01 -1.235000E-02 -0.000000E+00 -0.000000E+00 -1.420000E-01 -4.326000E-03 0.000000E+00 0.000000E+00 +1.440000E-01 +4.282000E-03 0.000000E+00 0.000000E+00 +2.190000E-01 +9.683000E-03 0.000000E+00 0.000000E+00 +7.300000E-02 +1.091000E-03 0.000000E+00 0.000000E+00 +2.140000E-01 +9.376000E-03 0.000000E+00 0.000000E+00 1.830000E-01 -7.133000E-03 +6.803000E-03 0.000000E+00 0.000000E+00 -5.110000E-01 -5.696100E-02 0.000000E+00 0.000000E+00 -2.040000E-01 -8.426000E-03 0.000000E+00 0.000000E+00 -8.500000E-02 -1.533000E-03 +1.320000E-01 +3.548000E-03 0.000000E+00 0.000000E+00 -2.100000E-01 -8.928000E-03 -0.000000E+00 -0.000000E+00 -9.100000E-02 -1.807000E-03 -0.000000E+00 -0.000000E+00 -1.420000E-01 -4.326000E-03 -0.000000E+00 -0.000000E+00 -2.460000E-01 -1.235000E-02 +1.480000E-01 +4.674000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1204,456 +1636,24 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 +1.350000E-01 +3.895000E-03 +0.000000E+00 +0.000000E+00 1.430000E-01 -4.207000E-03 +4.297000E-03 0.000000E+00 0.000000E+00 -2.120000E-01 -9.278000E-03 -0.000000E+00 -0.000000E+00 -1.630000E-01 -5.617000E-03 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.083000E-03 -0.000000E+00 -0.000000E+00 -1.770000E-01 -6.293000E-03 -0.000000E+00 -0.000000E+00 -7.900000E-02 -1.495000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.081000E-02 -0.000000E+00 -0.000000E+00 -5.200000E-01 -5.835000E-02 -0.000000E+00 -0.000000E+00 -2.350000E-01 -1.135900E-02 -0.000000E+00 -0.000000E+00 -1.560000E-01 -4.914000E-03 -0.000000E+00 -0.000000E+00 -2.370000E-01 -1.142300E-02 -0.000000E+00 -0.000000E+00 -1.360000E-01 -3.882000E-03 -0.000000E+00 -0.000000E+00 -2.160000E-01 -9.662000E-03 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.718000E-03 -0.000000E+00 -0.000000E+00 -2.090000E-01 -8.841000E-03 -0.000000E+00 -0.000000E+00 -1.030000E-01 -2.271000E-03 -0.000000E+00 -0.000000E+00 -5.200000E-01 -5.835000E-02 -0.000000E+00 -0.000000E+00 -2.300000E-01 -1.081000E-02 -0.000000E+00 -0.000000E+00 -5.110000E-01 -5.615900E-02 -0.000000E+00 -0.000000E+00 -2.430000E-01 -1.228300E-02 -0.000000E+00 -0.000000E+00 -5.110000E-01 -5.696100E-02 -0.000000E+00 -0.000000E+00 -1.830000E-01 -7.133000E-03 -0.000000E+00 -0.000000E+00 -5.130000E-01 -6.002100E-02 -0.000000E+00 -0.000000E+00 -2.420000E-01 -1.209200E-02 -0.000000E+00 -0.000000E+00 -5.510000E-01 -7.358900E-02 -0.000000E+00 -0.000000E+00 -2.410000E-01 -1.255900E-02 -0.000000E+00 -0.000000E+00 -5.140000E-01 -5.890200E-02 -0.000000E+00 -0.000000E+00 -2.100000E-01 -1.004600E-02 -0.000000E+00 -0.000000E+00 -2.430000E-01 -1.228300E-02 -0.000000E+00 -0.000000E+00 -5.110000E-01 -5.615900E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.120000E-01 -9.278000E-03 -0.000000E+00 -0.000000E+00 -1.430000E-01 -4.207000E-03 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.133600E-02 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.444000E-03 -0.000000E+00 -0.000000E+00 -2.240000E-01 -1.015800E-02 -0.000000E+00 -0.000000E+00 -9.300000E-02 -1.829000E-03 -0.000000E+00 -0.000000E+00 -1.950000E-01 -7.705000E-03 -0.000000E+00 -0.000000E+00 -1.030000E-01 -2.191000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.878000E-03 -0.000000E+00 -0.000000E+00 -2.230000E-01 -1.049900E-02 -0.000000E+00 -0.000000E+00 -1.360000E-01 -3.882000E-03 -0.000000E+00 -0.000000E+00 -2.370000E-01 -1.142300E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.550000E-01 -5.011000E-03 -0.000000E+00 -0.000000E+00 -7.100000E-02 -1.191000E-03 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.845000E-03 -0.000000E+00 -0.000000E+00 -6.400000E-02 -9.460000E-04 -0.000000E+00 -0.000000E+00 -2.230000E-01 -1.049900E-02 -0.000000E+00 -0.000000E+00 -1.680000E-01 -5.878000E-03 -0.000000E+00 -0.000000E+00 -2.490000E-01 -1.255900E-02 -0.000000E+00 -0.000000E+00 -1.280000E-01 -3.448000E-03 -0.000000E+00 -0.000000E+00 -2.420000E-01 -1.209200E-02 -0.000000E+00 -0.000000E+00 -5.130000E-01 -6.002100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.070000E-01 -8.673000E-03 -0.000000E+00 -0.000000E+00 -1.080000E-01 -2.694000E-03 -0.000000E+00 -0.000000E+00 -2.000000E-01 -8.202000E-03 -0.000000E+00 -0.000000E+00 -9.600000E-02 -2.024000E-03 -0.000000E+00 -0.000000E+00 -1.280000E-01 -3.448000E-03 -0.000000E+00 -0.000000E+00 -2.490000E-01 -1.255900E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.640000E-01 -5.444000E-03 -0.000000E+00 -0.000000E+00 -2.380000E-01 -1.133600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.760000E-01 -6.550000E-03 -0.000000E+00 -0.000000E+00 -8.200000E-02 -1.536000E-03 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.653000E-03 -0.000000E+00 -0.000000E+00 -4.900000E-02 -5.630000E-04 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.626000E-03 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.855000E-03 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.233000E-03 -0.000000E+00 -0.000000E+00 -5.600000E-02 -7.260000E-04 -0.000000E+00 -0.000000E+00 -1.530000E-01 -4.837000E-03 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.261000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.831000E-03 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.626000E-03 -0.000000E+00 -0.000000E+00 -1.490000E-01 -4.731000E-03 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.514000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.921000E-03 -0.000000E+00 -0.000000E+00 -2.410000E-01 -1.168300E-02 -0.000000E+00 -0.000000E+00 -9.100000E-02 -1.807000E-03 -0.000000E+00 -0.000000E+00 -2.100000E-01 -8.928000E-03 -0.000000E+00 -0.000000E+00 -2.090000E-01 -8.775000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.320000E-01 -3.514000E-03 -0.000000E+00 -0.000000E+00 -1.490000E-01 -4.731000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.150000E-01 -2.891000E-03 -0.000000E+00 -0.000000E+00 -1.560000E-01 -5.154000E-03 -0.000000E+00 -0.000000E+00 -7.900000E-02 -1.495000E-03 -0.000000E+00 -0.000000E+00 -1.770000E-01 -6.293000E-03 +5.300000E-02 +6.110000E-04 0.000000E+00 0.000000E+00 1.600000E-01 -5.352000E-03 +5.134000E-03 +0.000000E+00 +0.000000E+00 +1.380000E-01 +4.220000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1668,232 +1668,248 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -1.610000E-01 -5.273000E-03 +1.900000E-01 +7.412000E-03 0.000000E+00 0.000000E+00 -2.310000E-01 -1.098100E-02 +2.420000E-01 +1.208400E-02 0.000000E+00 0.000000E+00 -1.610000E-01 -5.233000E-03 +1.570000E-01 +4.999000E-03 0.000000E+00 0.000000E+00 -1.370000E-01 -3.855000E-03 +1.230000E-01 +3.065000E-03 0.000000E+00 0.000000E+00 -1.760000E-01 -6.482000E-03 +1.730000E-01 +6.279000E-03 0.000000E+00 0.000000E+00 -1.340000E-01 -3.882000E-03 +1.330000E-01 +3.621000E-03 0.000000E+00 0.000000E+00 1.030000E-01 -2.271000E-03 +2.229000E-03 0.000000E+00 0.000000E+00 -2.090000E-01 -8.841000E-03 -0.000000E+00 -0.000000E+00 -1.830000E-01 -6.761000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.310000E-01 -1.098100E-02 -0.000000E+00 -0.000000E+00 -1.610000E-01 -5.273000E-03 -0.000000E+00 -0.000000E+00 -2.620000E-01 -1.380600E-02 -0.000000E+00 -0.000000E+00 -1.700000E-01 -5.970000E-03 -0.000000E+00 -0.000000E+00 -2.410000E-01 -1.168300E-02 -0.000000E+00 -0.000000E+00 -1.550000E-01 -4.921000E-03 -0.000000E+00 -0.000000E+00 -2.250000E-01 -1.014100E-02 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.805000E-03 +2.510000E-01 +1.271500E-02 0.000000E+00 0.000000E+00 2.100000E-01 -1.004600E-02 +8.970000E-03 0.000000E+00 0.000000E+00 -5.140000E-01 -5.890200E-02 0.000000E+00 0.000000E+00 -2.320000E-01 -1.093000E-02 0.000000E+00 0.000000E+00 +2.420000E-01 +1.208400E-02 0.000000E+00 0.000000E+00 +1.900000E-01 +7.412000E-03 0.000000E+00 0.000000E+00 -1.700000E-01 -5.970000E-03 -0.000000E+00 -0.000000E+00 -2.620000E-01 -1.380600E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.560000E-01 -5.154000E-03 -0.000000E+00 -0.000000E+00 -1.150000E-01 -2.891000E-03 -0.000000E+00 -0.000000E+00 -1.430000E-01 -4.163000E-03 -0.000000E+00 -0.000000E+00 -1.120000E-01 -2.640000E-03 -0.000000E+00 -0.000000E+00 -1.030000E-01 -2.191000E-03 -0.000000E+00 -0.000000E+00 -1.950000E-01 -7.705000E-03 -0.000000E+00 -0.000000E+00 -1.760000E-01 -6.392000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.200000E-02 -1.822000E-03 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.843000E-03 -0.000000E+00 -0.000000E+00 -1.340000E-01 -3.882000E-03 -0.000000E+00 -0.000000E+00 -1.760000E-01 -6.482000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.400000E-02 -9.460000E-04 -0.000000E+00 -0.000000E+00 -1.510000E-01 -4.845000E-03 -0.000000E+00 -0.000000E+00 -1.800000E-01 -6.520000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.843000E-03 -0.000000E+00 -0.000000E+00 -9.200000E-02 -1.822000E-03 -0.000000E+00 -0.000000E+00 -1.300000E-01 -3.604000E-03 -0.000000E+00 -0.000000E+00 -1.170000E-01 -2.789000E-03 -0.000000E+00 -0.000000E+00 -1.370000E-01 -3.805000E-03 -0.000000E+00 -0.000000E+00 -2.250000E-01 -1.014100E-02 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.600000E-02 -2.024000E-03 +2.610000E-01 +1.399900E-02 0.000000E+00 0.000000E+00 2.000000E-01 -8.202000E-03 +8.410000E-03 +0.000000E+00 +0.000000E+00 +2.190000E-01 +9.683000E-03 +0.000000E+00 +0.000000E+00 +1.440000E-01 +4.282000E-03 +0.000000E+00 +0.000000E+00 +2.690000E-01 +1.478100E-02 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.986000E-03 +0.000000E+00 +0.000000E+00 +2.550000E-01 +1.480500E-02 +0.000000E+00 +0.000000E+00 +5.160000E-01 +5.892200E-02 +0.000000E+00 +0.000000E+00 +2.310000E-01 +1.098900E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-01 +8.410000E-03 +0.000000E+00 +0.000000E+00 +2.610000E-01 +1.399900E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.430000E-01 +4.297000E-03 +0.000000E+00 +0.000000E+00 +1.350000E-01 +3.895000E-03 +0.000000E+00 +0.000000E+00 +1.760000E-01 +6.534000E-03 +0.000000E+00 +0.000000E+00 +1.170000E-01 +2.807000E-03 +0.000000E+00 +0.000000E+00 +9.000000E-02 +1.780000E-03 +0.000000E+00 +0.000000E+00 +2.290000E-01 +1.058700E-02 +0.000000E+00 +0.000000E+00 +2.080000E-01 +8.854000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.305000E-03 +0.000000E+00 +0.000000E+00 +1.760000E-01 +6.598000E-03 +0.000000E+00 +0.000000E+00 +1.330000E-01 +3.621000E-03 +0.000000E+00 +0.000000E+00 +1.730000E-01 +6.279000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +6.100000E-02 +8.350000E-04 +0.000000E+00 +0.000000E+00 +1.410000E-01 +4.071000E-03 +0.000000E+00 +0.000000E+00 +1.800000E-01 +6.574000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.760000E-01 +6.598000E-03 +0.000000E+00 +0.000000E+00 +1.230000E-01 +3.305000E-03 +0.000000E+00 +0.000000E+00 +1.690000E-01 +6.135000E-03 +0.000000E+00 +0.000000E+00 +1.220000E-01 +3.344000E-03 +0.000000E+00 +0.000000E+00 +1.540000E-01 +4.986000E-03 +0.000000E+00 +0.000000E+00 +2.690000E-01 +1.478100E-02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.030000E-01 +2.543000E-03 +0.000000E+00 +0.000000E+00 +1.870000E-01 +7.267000E-03 +0.000000E+00 +0.000000E+00 +1.690000E-01 +5.731000E-03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.220000E-01 +3.344000E-03 +0.000000E+00 +0.000000E+00 +1.690000E-01 +6.135000E-03 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 -1.820000E-01 -6.660000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1901,11 +1917,11 @@ tally 2: 0.000000E+00 0.000000E+00 1.170000E-01 -2.789000E-03 +2.807000E-03 0.000000E+00 0.000000E+00 -1.300000E-01 -3.604000E-03 +1.760000E-01 +6.534000E-03 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1916,32 +1932,16 @@ tally 2: 0.000000E+00 0.000000E+00 0.000000E+00 -1.120000E-01 -2.640000E-03 +6.000000E-02 +8.060000E-04 0.000000E+00 0.000000E+00 -1.430000E-01 -4.163000E-03 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -4.900000E-02 -5.630000E-04 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.653000E-03 -0.000000E+00 -0.000000E+00 -1.670000E-01 -5.701000E-03 +1.290000E-01 +3.487000E-03 +0.000000E+00 +0.000000E+00 +1.790000E-01 +6.747000E-03 0.000000E+00 0.000000E+00 0.000000E+00 diff --git a/tests/regression_tests/seed/results_true.dat b/tests/regression_tests/seed/results_true.dat index bcd7118253..ff34071c10 100644 --- a/tests/regression_tests/seed/results_true.dat +++ b/tests/regression_tests/seed/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.069730E-01 2.632099E-03 +3.015003E-01 5.094212E-03 diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat index 673d27c8af..951075bbb9 100644 --- a/tests/regression_tests/source/results_true.dat +++ b/tests/regression_tests/source/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.959436E-01 2.782384E-03 +3.034717E-01 2.799386E-03 diff --git a/tests/regression_tests/source_file/results_true.dat b/tests/regression_tests/source_file/results_true.dat index 264e3d580d..359e0526e6 100644 --- a/tests/regression_tests/source_file/results_true.dat +++ b/tests/regression_tests/source_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.983135E-01 5.116978E-03 +2.827397E-01 1.150437E-03 diff --git a/tests/regression_tests/source_mcpl_file/results_true.dat b/tests/regression_tests/source_mcpl_file/results_true.dat index 264e3d580d..3ba1a45200 100644 --- a/tests/regression_tests/source_mcpl_file/results_true.dat +++ b/tests/regression_tests/source_mcpl_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.983135E-01 5.116978E-03 +2.827397E-01 1.150438E-03 diff --git a/tests/regression_tests/sourcepoint_batch/results_true.dat b/tests/regression_tests/sourcepoint_batch/results_true.dat index 2770f25ed1..3665bdd08d 100644 --- a/tests/regression_tests/sourcepoint_batch/results_true.dat +++ b/tests/regression_tests/sourcepoint_batch/results_true.dat @@ -1,3 +1,3 @@ k-combined: -3.074376E-01 3.049465E-03 -3.667754E+00 -7.701697E+00 2.213664E+00 +2.920435E-01 9.109227E-04 +1.101997E+00 -8.197502E+00 4.294606E+00 diff --git a/tests/regression_tests/sourcepoint_latest/results_true.dat b/tests/regression_tests/sourcepoint_latest/results_true.dat index bbf03de943..97b997ae6b 100644 --- a/tests/regression_tests/sourcepoint_latest/results_true.dat +++ b/tests/regression_tests/sourcepoint_latest/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 diff --git a/tests/regression_tests/sourcepoint_restart/results_true.dat b/tests/regression_tests/sourcepoint_restart/results_true.dat index b6d85872d1..c20b5f2a0a 100644 --- a/tests/regression_tests/sourcepoint_restart/results_true.dat +++ b/tests/regression_tests/sourcepoint_restart/results_true.dat @@ -1,46 +1,14 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 tally 1: 1.300000E-02 -4.700000E-05 -5.741381E-03 -9.030024E-06 +3.900000E-05 +5.833114E-03 +7.476880E-06 0.000000E+00 0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.420000E-04 -1.268989E-02 -3.464490E-05 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -1.000000E-03 -1.000000E-06 -1.535009E-03 -1.224718E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -3.200000E-02 -2.760000E-04 -1.248507E-02 -3.714039E-05 -0.000000E+00 -0.000000E+00 -9.208601E-04 -4.708050E-07 +1.164000E-03 +5.072152E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -49,602 +17,26 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.900000E-02 -7.500000E-05 -8.218811E-03 -1.462963E-05 +2.100000E-02 +1.110000E-04 +1.108363E-02 +2.889480E-05 0.000000E+00 0.000000E+00 -9.070399E-04 -2.743247E-07 -0.000000E+00 -0.000000E+00 -9.047443E-04 -8.185622E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.200000E-02 -5.000000E-05 -3.938144E-03 -5.245641E-06 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 -5.897816E-04 -3.478423E-07 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -2.000000E-02 -1.260000E-04 -9.079852E-03 -2.657486E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.010000E-04 -1.336346E-02 -3.645780E-05 -0.000000E+00 -0.000000E+00 -2.102710E-03 -1.524522E-06 -1.000000E-03 -1.000000E-06 -9.083133E-04 -4.632477E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.090000E-04 -1.334578E-02 -3.590708E-05 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -1.000000E-03 -1.000000E-06 -1.530605E-03 -1.035684E-06 +5.861433E-04 +3.435640E-07 2.000000E-03 2.000000E-06 -6.082927E-04 -1.850231E-07 -1.400000E-02 -4.200000E-05 -7.257468E-03 -1.221578E-05 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -8.980536E-04 -4.507660E-07 +2.043490E-03 +1.793389E-06 2.000000E-03 -4.000000E-06 -0.000000E+00 -0.000000E+00 -9.000000E-03 -2.700000E-05 -5.193169E-03 -1.187321E-05 -0.000000E+00 -0.000000E+00 -3.054379E-04 -9.329231E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.400000E-05 -5.170002E-03 -7.361546E-06 -0.000000E+00 -0.000000E+00 -6.003287E-04 -1.802529E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.720000E-04 -1.699195E-02 -6.267008E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.980000E-04 -1.338750E-02 -4.565234E-05 -0.000000E+00 -0.000000E+00 -9.183134E-04 -4.676871E-07 -1.000000E-03 -1.000000E-06 -1.537188E-03 -2.362946E-06 -2.000000E-03 -4.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.950000E-04 -1.178615E-02 -3.130999E-05 -0.000000E+00 -0.000000E+00 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -1.179563E-03 -1.391369E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.500000E-05 -5.706064E-03 -9.729293E-06 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -9.000000E-06 -1.516642E-03 -1.579637E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.897816E-04 -3.478423E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.970000E-04 -1.274851E-02 -3.511219E-05 -0.000000E+00 -0.000000E+00 -9.057666E-04 -4.601298E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.800000E-02 -7.600000E-05 -8.803642E-03 -1.730938E-05 -0.000000E+00 -0.000000E+00 -3.074376E-04 -9.451786E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.830000E-04 -1.245316E-02 -3.378176E-05 -0.000000E+00 -0.000000E+00 -6.016020E-04 -1.810324E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -6.090190E-04 -1.854692E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.900000E-02 -8.700000E-05 -8.781239E-03 -1.676750E-05 -0.000000E+00 -0.000000E+00 -6.128755E-04 -1.878102E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.500000E-02 -2.930000E-04 -1.372494E-02 -4.750881E-05 -0.000000E+00 -0.000000E+00 -9.090396E-04 -2.755502E-07 -0.000000E+00 -0.000000E+00 -5.897816E-04 -3.478423E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -3.700000E-02 -3.270000E-04 -1.492073E-02 -5.134793E-05 -0.000000E+00 -0.000000E+00 -6.134225E-04 -3.762872E-07 -1.000000E-03 -1.000000E-06 -3.074376E-04 -9.451786E-08 -1.000000E-03 -1.000000E-06 -6.148751E-04 -3.780714E-07 -3.500000E-02 -2.810000E-04 -1.728232E-02 -6.621096E-05 -0.000000E+00 -0.000000E+00 -1.214477E-03 -3.688425E-07 -0.000000E+00 -0.000000E+00 -1.481145E-03 -1.482321E-06 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -8.000000E-03 -1.800000E-05 -3.359923E-03 -3.081200E-06 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -3.660087E-03 -3.561493E-06 -0.000000E+00 -0.000000E+00 -9.203130E-04 -4.713637E-07 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.500000E-02 -2.630000E-04 -1.425810E-02 -4.231681E-05 -0.000000E+00 -0.000000E+00 -1.516059E-03 -4.597939E-07 -0.000000E+00 -0.000000E+00 -1.221752E-03 -1.492677E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.110000E-04 -1.184871E-02 -2.918189E-05 -0.000000E+00 -0.000000E+00 -6.016020E-04 -1.810324E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.600000E-02 -6.600000E-05 -7.879913E-03 -1.566560E-05 -0.000000E+00 -0.000000E+00 -9.039098E-04 -2.724298E-07 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -9.000000E-03 -1.900000E-05 -4.256120E-03 -4.431220E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.200000E-05 -2.739774E-03 -2.333986E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.400000E-02 -6.800000E-05 -7.182805E-03 -1.822340E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.300000E-05 -5.734575E-03 -9.207711E-06 -0.000000E+00 -0.000000E+00 -6.070193E-04 -1.842437E-07 -0.000000E+00 -0.000000E+00 -8.846723E-04 -7.826452E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 +2.000000E-06 +2.930717E-04 +8.589100E-08 2.000000E-02 -8.800000E-05 -9.416733E-03 -2.020354E-05 -0.000000E+00 -0.000000E+00 -6.003287E-04 -1.802529E-07 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -0.000000E+00 -0.000000E+00 -3.015814E-04 -9.095135E-08 -7.000000E-03 -1.500000E-05 -2.413278E-03 -1.439032E-06 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -4.226919E-03 -4.173413E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.590000E-04 -1.125341E-02 -3.890966E-05 -0.000000E+00 -0.000000E+00 -5.964722E-04 -1.779119E-07 -0.000000E+00 -0.000000E+00 -8.846723E-04 -7.826452E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.200000E-02 -2.260000E-04 -1.458976E-02 -4.416780E-05 -0.000000E+00 -0.000000E+00 -1.814806E-03 -9.096012E-07 -1.000000E-03 -1.000000E-06 -6.031628E-04 -3.638054E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.050000E-04 -1.241089E-02 -3.545088E-05 -0.000000E+00 -0.000000E+00 -1.515620E-03 -1.191731E-06 -0.000000E+00 -0.000000E+00 -6.121491E-04 -1.873641E-07 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.600000E-05 -3.936862E-03 -3.749154E-06 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-02 -4.700000E-05 -5.084641E-03 -9.248485E-06 +9.000000E-05 +9.334862E-03 +1.853104E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -658,45 +50,93 @@ tally 1: 0.000000E+00 0.000000E+00 2.500000E-02 -1.770000E-04 -1.021860E-02 -3.099521E-05 +1.430000E-04 +1.110224E-02 +2.872840E-05 0.000000E+00 0.000000E+00 -3.074376E-04 -9.451786E-08 +5.833203E-04 +1.701353E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +1.100000E-05 +1.752967E-03 +1.027501E-06 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 0.000000E+00 0.000000E+00 -9.086007E-04 -4.570977E-07 -2.000000E-03 -2.000000E-06 -3.054379E-04 -9.329231E-08 -1.500000E-02 -5.300000E-05 -7.584986E-03 -1.188822E-05 0.000000E+00 0.000000E+00 -6.128755E-04 -1.878102E-07 -1.000000E-03 -1.000000E-06 -6.108758E-04 -3.731692E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 1.800000E-02 -8.600000E-05 -6.672457E-03 -1.369871E-05 +7.600000E-05 +7.300761E-03 +1.254112E-05 0.000000E+00 0.000000E+00 -6.141488E-04 -1.885896E-07 +5.841969E-04 +1.706438E-07 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-02 +1.820000E-04 +1.518122E-02 +4.757233E-05 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +2.000000E-03 +2.000000E-06 +2.631167E-03 +3.503358E-06 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +2.500000E-02 +1.390000E-04 +9.343205E-03 +1.910189E-05 +0.000000E+00 +0.000000E+00 +2.039724E-03 +1.271217E-06 +1.000000E-03 +1.000000E-06 +5.861433E-04 +3.435640E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.400000E-02 +1.340000E-04 +1.080336E-02 +2.533338E-05 +0.000000E+00 +0.000000E+00 +2.914595E-04 +8.494867E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -705,46 +145,14 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.100000E-02 -2.700000E-05 -3.927884E-03 -3.728010E-06 +1.400000E-02 +5.200000E-05 +6.711472E-03 +1.216306E-05 0.000000E+00 0.000000E+00 -3.074376E-04 -9.451786E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -1.900000E-05 -4.217645E-03 -4.306910E-06 -0.000000E+00 -0.000000E+00 -6.128755E-04 -1.878102E-07 +5.847809E-04 +1.709846E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -754,37 +162,89 @@ tally 1: 0.000000E+00 0.000000E+00 1.700000E-02 -7.700000E-05 -7.235504E-03 -1.301737E-05 +7.900000E-05 +6.413106E-03 +1.186604E-05 0.000000E+00 0.000000E+00 -3.054379E-04 -9.329231E-08 -0.000000E+00 -0.000000E+00 -1.531736E-03 -8.439742E-07 -3.000000E-03 -3.000000E-06 -3.074376E-04 -9.451786E-08 -9.000000E-03 -1.900000E-05 -3.018298E-03 -2.174671E-06 +5.861433E-04 +3.435640E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.141488E-04 -1.885896E-07 +0.000000E+00 +0.000000E+00 +2.900000E-02 +1.770000E-04 +1.314196E-02 +3.678739E-05 +0.000000E+00 +0.000000E+00 +1.167073E-03 +5.110971E-07 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 1.000000E-03 1.000000E-06 -3.074376E-04 -9.451786E-08 +0.000000E+00 +0.000000E+00 +2.900000E-02 +1.830000E-04 +1.372758E-02 +4.360498E-05 +0.000000E+00 +0.000000E+00 +5.858090E-04 +1.715862E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.200000E-02 +1.000000E-04 +9.631311E-03 +2.001285E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.829191E-04 +3.397947E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +1.800000E-05 +4.094439E-03 +4.622331E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.170949E-03 +1.371123E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +9.000000E-03 +5.100000E-05 +4.664405E-03 +1.087264E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -797,14 +257,362 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.200000E-02 +1.300000E-04 +9.644227E-03 +2.300481E-05 +0.000000E+00 +0.000000E+00 +8.771587E-04 +4.270487E-07 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.500000E-02 +1.630000E-04 +1.257283E-02 +3.946813E-05 +0.000000E+00 +0.000000E+00 +1.171259E-03 +8.583084E-07 +0.000000E+00 +0.000000E+00 +1.462299E-03 +1.112414E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.400000E-02 +1.400000E-04 +1.138156E-02 +3.565057E-05 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.100000E-05 +4.383252E-03 +6.073597E-06 +0.000000E+00 +0.000000E+00 +8.707460E-04 +7.581986E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +3.500000E-05 +6.410606E-03 +1.066242E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +8.756564E-04 +4.254898E-07 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +1.600000E-02 +6.000000E-05 +7.287540E-03 +1.279808E-05 +0.000000E+00 +0.000000E+00 +5.822922E-04 +1.695337E-07 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +3.400000E-02 +2.820000E-04 +1.603656E-02 +6.229803E-05 +0.000000E+00 +0.000000E+00 +1.460479E-03 +7.689660E-07 +1.000000E-03 +1.000000E-06 +1.165972E-03 +6.797578E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.900000E-02 +8.500000E-05 +7.880322E-03 +1.387762E-05 +0.000000E+00 +0.000000E+00 +8.755466E-04 +4.261064E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +2.400000E-05 +4.666802E-03 +4.926489E-06 +0.000000E+00 +0.000000E+00 +5.829191E-04 +3.397947E-07 +0.000000E+00 +0.000000E+00 +8.759908E-04 +4.256857E-07 2.000000E-03 2.000000E-06 -1.203204E-03 -7.241295E-07 +0.000000E+00 +0.000000E+00 +1.500000E-02 +5.900000E-05 +8.180347E-03 +1.622409E-05 +0.000000E+00 +0.000000E+00 +2.902487E-04 +8.424429E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.390000E-04 +7.593262E-03 +1.708292E-05 +0.000000E+00 +0.000000E+00 +1.750169E-03 +1.193182E-06 +1.000000E-03 +1.000000E-06 +1.461465E-03 +7.684663E-07 +2.000000E-03 +4.000000E-06 +2.914595E-04 +8.494867E-08 +2.300000E-02 +1.350000E-04 +9.639670E-03 +2.161898E-05 +0.000000E+00 +0.000000E+00 +8.781869E-04 +4.288534E-07 +0.000000E+00 +0.000000E+00 +8.707460E-04 +7.581986E-07 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.100000E-02 +1.090000E-04 +9.045520E-03 +2.171457E-05 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +7.000000E-05 +1.167023E-02 +2.840320E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +5.854747E-04 +3.427806E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +1.171618E-03 +6.863446E-07 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.300000E-02 +4.500000E-05 +6.428153E-03 +9.064469E-06 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +9.000000E-05 +8.185938E-03 +1.967120E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.300000E-05 +4.665341E-03 +5.426897E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-03 +4.000000E-06 +3.497088E-03 +3.563633E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +9.000000E-06 +2.333045E-03 +1.870613E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +2.200000E-05 +6.413648E-03 +1.136518E-05 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.000000E-02 +1.200000E-04 +7.007604E-03 +1.379504E-05 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +1.700000E-02 +7.900000E-05 +7.281401E-03 +1.600845E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -818,9 +626,9 @@ tally 1: 0.000000E+00 0.000000E+00 7.000000E-03 -1.500000E-05 -4.818843E-03 -6.474375E-06 +1.900000E-05 +3.218959E-03 +4.543526E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -833,46 +641,10 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.400000E-02 -1.180000E-04 -1.088639E-02 -2.567229E-05 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.300000E-02 -5.100000E-05 -6.002667E-03 -1.149916E-05 -0.000000E+00 -0.000000E+00 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 +9.000000E-03 +1.900000E-05 +4.380921E-03 +4.182826E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -885,6 +657,42 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +2.100000E-02 +1.050000E-04 +9.932207E-03 +2.153598E-05 +0.000000E+00 +0.000000E+00 +5.854747E-04 +3.427806E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +7.400000E-05 +7.301011E-03 +1.358176E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.804973E-04 +3.369772E-07 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.610000E-04 +9.647933E-03 +2.657983E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -897,14 +705,110 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.300000E-02 -4.700000E-05 -5.486562E-03 -7.965488E-06 +9.000000E-03 +1.900000E-05 +2.915422E-03 +2.203274E-06 +0.000000E+00 +0.000000E+00 +8.775182E-04 +4.280701E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +9.000000E-06 +2.044244E-03 +1.796182E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +9.000000E-05 +6.718632E-03 +1.203946E-05 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +2.700000E-05 +4.675703E-03 +5.128811E-06 +0.000000E+00 +0.000000E+00 +2.914595E-04 +8.494867E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +2.914595E-04 +8.494867E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 -3.054379E-04 -9.329231E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -914,13 +818,9 @@ tally 1: 0.000000E+00 0.000000E+00 8.000000E-03 -1.800000E-05 -3.334317E-03 -3.609712E-06 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 +2.600000E-05 +4.670349E-03 +6.133014E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -929,20 +829,120 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.000000E-02 -1.080000E-04 -9.741552E-03 -2.552400E-05 0.000000E+00 0.000000E+00 -3.015814E-04 -9.095135E-08 0.000000E+00 0.000000E+00 -1.800986E-03 -1.622276E-06 -1.000000E-03 -1.000000E-06 +1.500000E-02 +6.100000E-05 +8.751735E-03 +1.922421E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.400000E-02 +5.000000E-05 +6.126605E-03 +9.620966E-06 +0.000000E+00 +0.000000E+00 +5.835031E-04 +1.702381E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-03 +2.000000E-06 +5.847809E-04 +1.709846E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-03 +2.000000E-06 +8.719569E-04 +4.219258E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.700000E-05 +4.085939E-03 +4.936434E-06 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.500000E-05 +5.846700E-03 +9.739696E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.300000E-02 +3.900000E-05 +6.128455E-03 +1.013669E-05 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -962,11 +962,11 @@ tally 1: 0.000000E+00 0.000000E+00 tally 2: -5.818100E-01 -6.772558E-02 -6.344749E-01 -8.054355E-02 -3.690180E+00 -2.724752E+00 -4.102635E+01 -3.367908E+02 +5.554367E-01 +6.170503E-02 +6.055520E-01 +7.334109E-02 +3.526894E+00 +2.488065E+00 +3.925114E+01 +3.081807E+02 diff --git a/tests/regression_tests/statepoint_batch/__init__.py b/tests/regression_tests/statepoint_batch/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/regression_tests/statepoint_batch/geometry.xml b/tests/regression_tests/statepoint_batch/geometry.xml deleted file mode 100644 index bc56030e18..0000000000 --- a/tests/regression_tests/statepoint_batch/geometry.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tests/regression_tests/statepoint_batch/materials.xml b/tests/regression_tests/statepoint_batch/materials.xml deleted file mode 100644 index 2472a74717..0000000000 --- a/tests/regression_tests/statepoint_batch/materials.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/tests/regression_tests/statepoint_batch/results_true.dat b/tests/regression_tests/statepoint_batch/results_true.dat deleted file mode 100644 index f5c855d777..0000000000 --- a/tests/regression_tests/statepoint_batch/results_true.dat +++ /dev/null @@ -1,2 +0,0 @@ -k-combined: -3.048864E-01 1.689118E-03 diff --git a/tests/regression_tests/statepoint_batch/settings.xml b/tests/regression_tests/statepoint_batch/settings.xml deleted file mode 100644 index e2f8dad47b..0000000000 --- a/tests/regression_tests/statepoint_batch/settings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - eigenvalue - 10 - 5 - 1000 - - - - -4 -4 -4 4 4 4 - - - - diff --git a/tests/regression_tests/statepoint_batch/test.py b/tests/regression_tests/statepoint_batch/test.py deleted file mode 100644 index 323b28fc65..0000000000 --- a/tests/regression_tests/statepoint_batch/test.py +++ /dev/null @@ -1,18 +0,0 @@ -from tests.testing_harness import TestHarness - - -class StatepointTestHarness(TestHarness): - def __init__(self): - super().__init__(None) - - def _test_output_created(self): - """Make sure statepoint files have been created.""" - sps = ('statepoint.03.h5', 'statepoint.06.h5', 'statepoint.09.h5') - for sp in sps: - self._sp_name = sp - TestHarness._test_output_created(self) - - -def test_statepoint_batch(): - harness = StatepointTestHarness() - harness.main() diff --git a/tests/regression_tests/statepoint_restart/results_true.dat b/tests/regression_tests/statepoint_restart/results_true.dat index aebc971f49..b919b30005 100644 --- a/tests/regression_tests/statepoint_restart/results_true.dat +++ b/tests/regression_tests/statepoint_restart/results_true.dat @@ -1,66 +1,18 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 tally 1: 1.300000E-02 -4.700000E-05 +3.900000E-05 1.300000E-02 -4.700000E-05 -5.741381E-03 -9.030024E-06 +3.900000E-05 +5.833114E-03 +7.476880E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.600000E-02 -1.420000E-04 -2.600000E-02 -1.420000E-04 -1.268989E-02 -3.464490E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -1.535009E-03 -1.224718E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -3.200000E-02 -2.760000E-04 -3.200000E-02 -2.760000E-04 -1.248507E-02 -3.714039E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.208601E-04 -4.708050E-07 +1.164000E-03 +5.072152E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -73,900 +25,36 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.900000E-02 -7.500000E-05 -1.900000E-02 -7.500000E-05 -8.218811E-03 -1.462963E-05 +2.100000E-02 +1.110000E-04 +2.100000E-02 +1.110000E-04 +1.108363E-02 +2.889480E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.070399E-04 -2.743247E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.047443E-04 -8.185622E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.200000E-02 -5.000000E-05 -1.200000E-02 -5.000000E-05 -3.938144E-03 -5.245641E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 +5.861433E-04 +3.435640E-07 2.000000E-03 -4.000000E-06 -5.897816E-04 -3.478423E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -2.000000E-02 -1.260000E-04 -2.000000E-02 -1.260000E-04 -9.079852E-03 -2.657486E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.010000E-04 -3.100000E-02 -2.010000E-04 -1.336346E-02 -3.645780E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.102710E-03 -1.524522E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -9.083133E-04 -4.632477E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.090000E-04 -2.300000E-02 -1.090000E-04 -1.334578E-02 -3.590708E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -1.530605E-03 -1.035684E-06 +2.000000E-06 +3.000000E-03 +5.000000E-06 +2.043490E-03 +1.793389E-06 2.000000E-03 2.000000E-06 2.000000E-03 2.000000E-06 -6.082927E-04 -1.850231E-07 -1.400000E-02 -4.200000E-05 -1.400000E-02 -4.200000E-05 -7.257468E-03 -1.221578E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.980536E-04 -4.507660E-07 -2.000000E-03 -4.000000E-06 -2.000000E-03 -4.000000E-06 -0.000000E+00 -0.000000E+00 -9.000000E-03 -2.700000E-05 -9.000000E-03 -2.700000E-05 -5.193169E-03 -1.187321E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.054379E-04 -9.329231E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.400000E-05 -1.000000E-02 -2.400000E-05 -5.170002E-03 -7.361546E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.003287E-04 -1.802529E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.720000E-04 -2.800000E-02 -1.720000E-04 -1.699195E-02 -6.267008E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.800000E-02 -1.980000E-04 -2.800000E-02 -1.980000E-04 -1.338750E-02 -4.565234E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.183134E-04 -4.676871E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -1.537188E-03 -2.362946E-06 -2.000000E-03 -4.000000E-06 -2.000000E-03 -4.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.950000E-04 -2.900000E-02 -1.950000E-04 -1.178615E-02 -3.130999E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.179563E-03 -1.391369E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.500000E-05 -1.500000E-02 -6.500000E-05 -5.706064E-03 -9.729293E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.000000E-03 -9.000000E-06 -3.000000E-03 -9.000000E-06 -1.516642E-03 -1.579637E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.897816E-04 -3.478423E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.970000E-04 -2.900000E-02 -1.970000E-04 -1.274851E-02 -3.511219E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.057666E-04 -4.601298E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.800000E-02 -7.600000E-05 -1.800000E-02 -7.600000E-05 -8.803642E-03 -1.730938E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.074376E-04 -9.451786E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.900000E-02 -1.830000E-04 -2.900000E-02 -1.830000E-04 -1.245316E-02 -3.378176E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.016020E-04 -1.810324E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -6.090190E-04 -1.854692E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.900000E-02 -8.700000E-05 -1.900000E-02 -8.700000E-05 -8.781239E-03 -1.676750E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.128755E-04 -1.878102E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.500000E-02 -2.930000E-04 -3.500000E-02 -2.930000E-04 -1.372494E-02 -4.750881E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.090396E-04 -2.755502E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.897816E-04 -3.478423E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -3.700000E-02 -3.270000E-04 -3.700000E-02 -3.270000E-04 -1.492073E-02 -5.134793E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.134225E-04 -3.762872E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -3.074376E-04 -9.451786E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -6.148751E-04 -3.780714E-07 -3.500000E-02 -2.810000E-04 -3.500000E-02 -2.810000E-04 -1.728232E-02 -6.621096E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.214477E-03 -3.688425E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.481145E-03 -1.482321E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -8.000000E-03 -1.800000E-05 -8.000000E-03 -1.800000E-05 -3.359923E-03 -3.081200E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -7.000000E-03 -1.500000E-05 -3.660087E-03 -3.561493E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.203130E-04 -4.713637E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -3.015814E-04 -9.095135E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.500000E-02 -2.630000E-04 -3.500000E-02 -2.630000E-04 -1.425810E-02 -4.231681E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.516059E-03 -4.597939E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.221752E-03 -1.492677E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.110000E-04 -2.300000E-02 -1.110000E-04 -1.184871E-02 -2.918189E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.016020E-04 -1.810324E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.600000E-02 -6.600000E-05 -1.600000E-02 -6.600000E-05 -7.879913E-03 -1.566560E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.039098E-04 -2.724298E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.067112E-04 -9.407179E-08 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -9.000000E-03 -1.900000E-05 -9.000000E-03 -1.900000E-05 -4.256120E-03 -4.431220E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.000000E-03 -1.200000E-05 -6.000000E-03 -1.200000E-05 -2.739774E-03 -2.333986E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.400000E-02 -6.800000E-05 -1.400000E-02 -6.800000E-05 -7.182805E-03 -1.822340E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.500000E-02 -6.300000E-05 -1.500000E-02 -6.300000E-05 -5.734575E-03 -9.207711E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.070193E-04 -1.842437E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.846723E-04 -7.826452E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 +2.930717E-04 +8.589100E-08 2.000000E-02 -8.800000E-05 +9.000000E-05 2.000000E-02 -8.800000E-05 -9.416733E-03 -2.020354E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.003287E-04 -1.802529E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.031628E-04 -3.638054E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.015814E-04 -9.095135E-08 -7.000000E-03 -1.500000E-05 -7.000000E-03 -1.500000E-05 -2.413278E-03 -1.439032E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -7.000000E-03 -1.500000E-05 -7.000000E-03 -1.500000E-05 -4.226919E-03 -4.173413E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.300000E-02 -1.590000E-04 -2.300000E-02 -1.590000E-04 -1.125341E-02 -3.890966E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -5.964722E-04 -1.779119E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -8.846723E-04 -7.826452E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.200000E-02 -2.260000E-04 -3.200000E-02 -2.260000E-04 -1.458976E-02 -4.416780E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.814806E-03 -9.096012E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -6.031628E-04 -3.638054E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.100000E-02 -2.050000E-04 -3.100000E-02 -2.050000E-04 -1.241089E-02 -3.545088E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.515620E-03 -1.191731E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.121491E-04 -1.873641E-07 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 -0.000000E+00 -0.000000E+00 -1.000000E-02 -2.600000E-05 -1.000000E-02 -2.600000E-05 -3.936862E-03 -3.749154E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.100000E-02 -4.700000E-05 -1.100000E-02 -4.700000E-05 -5.084641E-03 -9.248485E-06 +9.000000E-05 +9.334862E-03 +1.853104E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -986,65 +74,401 @@ tally 1: 0.000000E+00 0.000000E+00 2.500000E-02 -1.770000E-04 +1.430000E-04 2.500000E-02 +1.430000E-04 +1.110224E-02 +2.872840E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.833203E-04 +1.701353E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +1.100000E-05 +5.000000E-03 +1.100000E-05 +1.752967E-03 +1.027501E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +7.600000E-05 +1.800000E-02 +7.600000E-05 +7.300761E-03 +1.254112E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.841969E-04 +1.706438E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-02 +1.820000E-04 +3.000000E-02 +1.820000E-04 +1.518122E-02 +4.757233E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +2.000000E-03 +2.000000E-06 +2.000000E-03 +2.000000E-06 +2.631167E-03 +3.503358E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +2.500000E-02 +1.390000E-04 +2.500000E-02 +1.390000E-04 +9.343205E-03 +1.910189E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.039724E-03 +1.271217E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +5.861433E-04 +3.435640E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.400000E-02 +1.340000E-04 +2.400000E-02 +1.340000E-04 +1.080336E-02 +2.533338E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.914595E-04 +8.494867E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.400000E-02 +5.200000E-05 +1.400000E-02 +5.200000E-05 +6.711472E-03 +1.216306E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.847809E-04 +1.709846E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.700000E-02 +7.900000E-05 +1.700000E-02 +7.900000E-05 +6.413106E-03 +1.186604E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.900000E-02 1.770000E-04 -1.021860E-02 -3.099521E-05 +2.900000E-02 +1.770000E-04 +1.314196E-02 +3.678739E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.074376E-04 -9.451786E-08 +1.167073E-03 +5.110971E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -9.086007E-04 -4.570977E-07 -2.000000E-03 -2.000000E-06 -2.000000E-03 -2.000000E-06 -3.054379E-04 -9.329231E-08 -1.500000E-02 -5.300000E-05 -1.500000E-02 -5.300000E-05 -7.584986E-03 -1.188822E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.128755E-04 -1.878102E-07 +5.861433E-04 +3.435640E-07 1.000000E-03 1.000000E-06 1.000000E-03 1.000000E-06 -6.108758E-04 -3.731692E-07 +0.000000E+00 +0.000000E+00 +2.900000E-02 +1.830000E-04 +2.900000E-02 +1.830000E-04 +1.372758E-02 +4.360498E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.858090E-04 +1.715862E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.800000E-02 -8.600000E-05 -1.800000E-02 -8.600000E-05 -6.672457E-03 -1.369871E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.141488E-04 -1.885896E-07 +0.000000E+00 +0.000000E+00 +2.200000E-02 +1.000000E-04 +2.200000E-02 +1.000000E-04 +9.631311E-03 +2.001285E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.829191E-04 +3.397947E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +1.800000E-05 +8.000000E-03 +1.800000E-05 +4.094439E-03 +4.622331E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.170949E-03 +1.371123E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +9.000000E-03 +5.100000E-05 +9.000000E-03 +5.100000E-05 +4.664405E-03 +1.087264E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.200000E-02 +1.300000E-04 +2.200000E-02 +1.300000E-04 +9.644227E-03 +2.300481E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.771587E-04 +4.270487E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.500000E-02 +1.630000E-04 +2.500000E-02 +1.630000E-04 +1.257283E-02 +3.946813E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.171259E-03 +8.583084E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.462299E-03 +1.112414E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.400000E-02 +1.400000E-04 +2.400000E-02 +1.400000E-04 +1.138156E-02 +3.565057E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.100000E-05 +9.000000E-03 +2.100000E-05 +4.383252E-03 +6.073597E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.707460E-04 +7.581986E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1058,129 +482,89 @@ tally 1: 0.000000E+00 0.000000E+00 1.100000E-02 -2.700000E-05 +3.500000E-05 1.100000E-02 -2.700000E-05 -3.927884E-03 -3.728010E-06 +3.500000E-05 +6.410606E-03 +1.066242E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.074376E-04 -9.451786E-08 0.000000E+00 0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -9.000000E-03 -1.900000E-05 -9.000000E-03 -1.900000E-05 -4.217645E-03 -4.306910E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.128755E-04 -1.878102E-07 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.700000E-02 -7.700000E-05 -1.700000E-02 -7.700000E-05 -7.235504E-03 -1.301737E-05 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -3.054379E-04 -9.329231E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -1.531736E-03 -8.439742E-07 -3.000000E-03 -3.000000E-06 -3.000000E-03 -3.000000E-06 -3.074376E-04 -9.451786E-08 -9.000000E-03 -1.900000E-05 -9.000000E-03 -1.900000E-05 -3.018298E-03 -2.174671E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -6.141488E-04 -1.885896E-07 1.000000E-03 1.000000E-06 1.000000E-03 1.000000E-06 -3.074376E-04 -9.451786E-08 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 +8.756564E-04 +4.254898E-07 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +1.600000E-02 +6.000000E-05 +1.600000E-02 +6.000000E-05 +7.287540E-03 +1.279808E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.822922E-04 +1.695337E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +3.400000E-02 +2.820000E-04 +3.400000E-02 +2.820000E-04 +1.603656E-02 +6.229803E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.460479E-03 +7.689660E-07 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +1.165972E-03 +6.797578E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.900000E-02 +8.500000E-05 +1.900000E-02 +8.500000E-05 +7.880322E-03 +1.387762E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.755466E-04 +4.261064E-07 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1193,20 +577,348 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +8.000000E-03 +2.400000E-05 +8.000000E-03 +2.400000E-05 +4.666802E-03 +4.926489E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +5.829191E-04 +3.397947E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +8.759908E-04 +4.256857E-07 2.000000E-03 2.000000E-06 2.000000E-03 2.000000E-06 -1.203204E-03 -7.241295E-07 +0.000000E+00 +0.000000E+00 +1.500000E-02 +5.900000E-05 +1.500000E-02 +5.900000E-05 +8.180347E-03 +1.622409E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.902487E-04 +8.424429E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.300000E-02 +1.390000E-04 +2.300000E-02 +1.390000E-04 +7.593262E-03 +1.708292E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.750169E-03 +1.193182E-06 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +1.461465E-03 +7.684663E-07 +2.000000E-03 +4.000000E-06 +2.000000E-03 +4.000000E-06 +2.914595E-04 +8.494867E-08 +2.300000E-02 +1.350000E-04 +2.300000E-02 +1.350000E-04 +9.639670E-03 +2.161898E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.781869E-04 +4.288534E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.707460E-04 +7.581986E-07 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.100000E-02 +1.090000E-04 +2.100000E-02 +1.090000E-04 +9.045520E-03 +2.171457E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +7.000000E-05 +1.800000E-02 +7.000000E-05 +1.167023E-02 +2.840320E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +5.854747E-04 +3.427806E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000000E-03 +5.000000E-06 +3.000000E-03 +5.000000E-06 +1.171618E-03 +6.863446E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.300000E-02 +4.500000E-05 +1.300000E-02 +4.500000E-05 +6.428153E-03 +9.064469E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +9.000000E-05 +1.800000E-02 +9.000000E-05 +8.185938E-03 +1.967120E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.300000E-05 +9.000000E-03 +2.300000E-05 +4.665341E-03 +5.426897E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +4.000000E-03 +4.000000E-06 +4.000000E-03 +4.000000E-06 +3.497088E-03 +3.563633E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +9.000000E-06 +5.000000E-03 +9.000000E-06 +2.333045E-03 +1.870613E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +8.000000E-03 +2.200000E-05 +8.000000E-03 +2.200000E-05 +6.413648E-03 +1.136518E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +2.000000E-02 +1.200000E-04 +2.000000E-02 +1.200000E-04 +7.007604E-03 +1.379504E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.861433E-04 +3.435640E-07 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +0.000000E+00 +0.000000E+00 +1.700000E-02 +7.900000E-05 +1.700000E-02 +7.900000E-05 +7.281401E-03 +1.600845E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1226,11 +938,11 @@ tally 1: 0.000000E+00 0.000000E+00 7.000000E-03 -1.500000E-05 +1.900000E-05 7.000000E-03 -1.500000E-05 -4.818843E-03 -6.474375E-06 +1.900000E-05 +3.218959E-03 +4.543526E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1249,18 +961,16 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.400000E-02 -1.180000E-04 -2.400000E-02 -1.180000E-04 -1.088639E-02 -2.567229E-05 +9.000000E-03 +1.900000E-05 +9.000000E-03 +1.900000E-05 +4.380921E-03 +4.182826E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.067112E-04 -9.407179E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1273,24 +983,22 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -1.300000E-02 -5.100000E-05 -1.300000E-02 -5.100000E-05 -6.002667E-03 -1.149916E-05 0.000000E+00 0.000000E+00 +2.100000E-02 +1.050000E-04 +2.100000E-02 +1.050000E-04 +9.932207E-03 +2.153598E-05 0.000000E+00 0.000000E+00 -3.015814E-04 -9.095135E-08 0.000000E+00 0.000000E+00 +5.854747E-04 +3.427806E-07 0.000000E+00 0.000000E+00 -3.067112E-04 -9.407179E-08 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1301,22 +1009,36 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.948908E-04 -8.696057E-08 +1.800000E-02 +7.400000E-05 +1.800000E-02 +7.400000E-05 +7.301011E-03 +1.358176E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.948908E-04 -8.696057E-08 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +5.804973E-04 +3.369772E-07 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 0.000000E+00 0.000000E+00 +2.300000E-02 +1.610000E-04 +2.300000E-02 +1.610000E-04 +9.647933E-03 +2.657983E-05 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1335,28 +1057,162 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 +9.000000E-03 +1.900000E-05 +9.000000E-03 +1.900000E-05 +2.915422E-03 +2.203274E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 +8.775182E-04 +4.280701E-07 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.300000E-02 -4.700000E-05 -1.300000E-02 -4.700000E-05 -5.486562E-03 -7.965488E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.054379E-04 -9.329231E-08 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.000000E-03 +9.000000E-06 +5.000000E-03 +9.000000E-06 +2.044244E-03 +1.796182E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.800000E-02 +9.000000E-05 +1.800000E-02 +9.000000E-05 +6.718632E-03 +1.203946E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.927374E-04 +8.569516E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.100000E-02 +2.700000E-05 +1.100000E-02 +2.700000E-05 +4.675703E-03 +5.128811E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.914595E-04 +8.494867E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +2.914595E-04 +8.494867E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.000000E-03 +1.000000E-06 +1.000000E-03 +1.000000E-06 +2.920435E-04 +8.528942E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1370,17 +1226,11 @@ tally 1: 0.000000E+00 0.000000E+00 8.000000E-03 -1.800000E-05 +2.600000E-05 8.000000E-03 -1.800000E-05 -3.334317E-03 -3.609712E-06 -0.000000E+00 -0.000000E+00 -0.000000E+00 -0.000000E+00 -2.948908E-04 -8.696057E-08 +2.600000E-05 +4.670349E-03 +6.133014E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1393,28 +1243,178 @@ tally 1: 0.000000E+00 0.000000E+00 0.000000E+00 -2.000000E-02 -1.080000E-04 -2.000000E-02 -1.080000E-04 -9.741552E-03 -2.552400E-05 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.015814E-04 -9.095135E-08 +0.000000E+00 +0.000000E+00 +1.500000E-02 +6.100000E-05 +1.500000E-02 +6.100000E-05 +8.751735E-03 +1.922421E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.400000E-02 +5.000000E-05 +1.400000E-02 +5.000000E-05 +6.126605E-03 +9.620966E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.835031E-04 +1.702381E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-03 +2.000000E-06 +2.000000E-03 +2.000000E-06 +5.847809E-04 +1.709846E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.000000E-03 +2.000000E-06 +2.000000E-03 +2.000000E-06 +8.719569E-04 +4.219258E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.700000E-05 +9.000000E-03 +2.700000E-05 +4.085939E-03 +4.936434E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.930717E-04 +8.589100E-08 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.000000E-03 +2.500000E-05 +9.000000E-03 +2.500000E-05 +5.846700E-03 +9.739696E-06 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.300000E-02 +3.900000E-05 +1.300000E-02 +3.900000E-05 +6.128455E-03 +1.013669E-05 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.851152E-04 +1.711804E-07 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.172287E-03 +1.374256E-06 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.800986E-03 -1.622276E-06 -1.000000E-03 -1.000000E-06 -1.000000E-03 -1.000000E-06 0.000000E+00 0.000000E+00 0.000000E+00 @@ -1442,11 +1442,11 @@ tally 1: 0.000000E+00 0.000000E+00 tally 2: -5.818100E-01 -6.772558E-02 -6.344749E-01 -8.054355E-02 -3.690180E+00 -2.724752E+00 -4.102635E+01 -3.367908E+02 +5.554367E-01 +6.170503E-02 +6.055520E-01 +7.334109E-02 +3.526894E+00 +2.488065E+00 +3.925114E+01 +3.081807E+02 diff --git a/tests/regression_tests/statepoint_sourcesep/results_true.dat b/tests/regression_tests/statepoint_sourcesep/results_true.dat index bbf03de943..97b997ae6b 100644 --- a/tests/regression_tests/statepoint_sourcesep/results_true.dat +++ b/tests/regression_tests/statepoint_sourcesep/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 diff --git a/tests/regression_tests/stride/results_true.dat b/tests/regression_tests/stride/results_true.dat index a654111500..825de37667 100644 --- a/tests/regression_tests/stride/results_true.dat +++ b/tests/regression_tests/stride/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.978080E-01 6.106774E-03 +2.953207E-01 2.874356E-03 diff --git a/tests/regression_tests/surface_source/surface_source_true.h5 b/tests/regression_tests/surface_source/surface_source_true.h5 index d056d7328405bedf704f8690fd3b8056ec8aa101..2c2a19038fc1b6d9c7785e8a7f591e9e5c7fd959 100644 GIT binary patch delta 17120 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 Tbzz-5f4SO>oo}#+&4TX#jWsSQ delta 17152 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 diff --git a/tests/regression_tests/surface_source/surface_source_true.mcpl b/tests/regression_tests/surface_source/surface_source_true.mcpl index 7c819ac9bd02179ed93a1cd94b6fd8237a7b0893..ca4b7c2c4257c88baff2f9bd1c2a756fdfde92bf 100644 GIT binary patch delta 3894 zcmZYAF>tbX9l&wlQkyDTth9|vl`6!jspWl375k#1qVg(lrETs^l`2-Od0X02<*lir z#)^uX-r;-CkZJ~o3>h-yybKH(7&2sFV93CbfgwYBmw_Pz-ethgxthE0eg1II|Bm19 z8FKc|yWaWNUH3ngfBNRttLdBXhTikPzbkj{k6(G<&b0?0f8xnUebc!8!tLvgH(tG7 zfBnVRUaeMMd;Qw=NB;ls+EssdYRNl=}AUA1+gp|YW5Ft3&> z8fZt+yOY6$WoERkb)D-->Gvjsh?-i_p}Gp+lMK$d%#^mYrv5$u2pV(ApriwBDs*o$ z7<2L78$sY)*NJ*cye}EdSYtu^>gZA<<=>wS;@Z%$RyEb0a^YkUQ(ILHwX69Ln42wT zHBd#-51N@}PPomC&b6-eeP(8phl(g1F*ldl#9rifW$hn|+)GoNeOCB??*aLRJD)+d{DKD7Q{Dbzv3Wppp ztBG35JY)ylW>n`&&)dmEH-aXQd_H7E;g6V|%iL1e`IKi|`l$Jx8(iZ7`wV@|?9N4& zxT(N-%o8pu5i>Un>~WtnUb3eA!*&u|2;P1;5sZA^^Es}mR+am>eXz}#E>u~=&lWE@;Jl)ru@jcL z!);D@&WzHZH9wm?;vpjnf6n||W|vz$<0(^GS~5QyJW$^`^r#&;msE7#WWW=RofDt8 z1Lqp++-HxMoH75H9XM~W!()yZOWBKam8;z49xqZ0!G9i01lg#oi`b9%o8TQ zXnq!0XHOmHOU;~X%xBE6edlA282gg>ovU1Bn|qvU=$upbNqb?77aVY2(d%YshC5v6 zghwnZlC=}Au&Z1UNENYH|&NjwmIOC(Yzfvms#ODcX-4J)8Dig z=M`?V%X6MFqSUv{&ov&h&#>mcZGM)x#Z8`a%q1-r%+ERx*kedD6;-%les*}m5fh4k z$8NaFeQxlQ$IL7CT{~fwQ|>aS3$>Lknwu@oYeyALG*ITIooHQU9cf#Ur_9Y2rqxwb zXF62sd*;@fmetpm=1S&fiA!pfZUkcTBsaKjyiG;P!KgpyYg@O@)5orLfLL^;FbMfeJtL zW7uIrBh?fy`!QVQC8x}5_jxac7u;j^M_vwFjQMWB9HT$>l2~S&M;tOz@nSr)!V0_G z;Tb1P{lrW1>>AhE=QihF@Pb%k+OwN%a?C?6{?v{7B6K*i`NAq)? zG53yGWu#@7T;T<~%(`>N7E^z+ORh2MPM>AY{n;*A;yE{&c4y2c7yn{*)){uE$7RmA z#X{Tc>~P7Q5gUyE)%-ee4taLZxyUI4=Kf}OwwZ8e$QtMWZhp3S$pQ23L^sUO43Al6 f%$;>sxy@Z3@q*{fx*K`hE}7;IS2$tw?N|N_q0^+p delta 3830 zcmXBSF>tbX9l&whVnrJ*ucZ|&w$wbasMu1AN)?q_RIJp}9;Z=bMMX<1RaB~}VvQPY zREE4f8KRegAwz}?@yw7RLxv0)GGxdQ?=moOCj&zU1_lN{cfNPu`~080&p*fSN4EcY z=YRik=dI_SsaCStCoAK--uC~0w{Jas$9=b-xc`pq?VaHEYVfa<<{e?>&LB){OKn~2 zNWon}|E?fxsjNe7YOX7lB0-o^PfcCwK*_fU;fxIywXY3Lb)mxDL733G>N?k+ZtmU; zci$0&Yntdxxo8l^v>YvmryOYEok2KejaltzRU@4!^R6I_s-vog+E)6WAUtM-ZB=xn zt$Tw0f~g(L478~$wUm0d(b?pj2P|o(o{H}=I`^5>R1FpGH8$6I!E+{5zjrCTKeiaI z#Ek9vj5mzk3c|eeGS@iZF2|fO`(EpCUS*d%JmrWBsws1y6|lpojunYp11sF-7KglM zTEYF+!4{9=K_7=IYp&7**1;?FoKu=TP!5}Hyw5tg&r42OR6SvI?(u>*Oep_;YvCH# zdB$_bJ`jX)=NwnqKwUahEroFt6OA)v(Jmo-(F|!1%0jz#Wb`Vpf?Ye-%7Y$2qEFRTcTL@mb-JTTJU( zZ3T}Soh=?d8uT$&S*5fUu*WN2GNt54jL!xSxX&4p0E`^E3w5M4|&Nslbv%?`JC%xgweQSg+t zu*Jitf)huar@Uc7`OjGi*Lcn|#ufX# zm2jE69B{%hbIN|fnCd#8@RZS_6*yN}ag$rT z;x$vx*ot$LEgtZYGtOCJv1BdW;Ds)olT3Wc_^flEdz|uy1?9hNe6I1FXN)WM72|W6 zyBu)BF>}h6jm}k`@`MYDe%0u#a);X-amb81NqbY}Q%Op4N4vbLF2mw$`+w-RH|;tZHQEW#%+c zS7V(j`+||Rs+vx;qv(r9W|f&2gMW8kT#1C!Z}>1OeA9=~y6QUDp5n_s3|E$y!l#xO z!(Gp7n&?cqZ~0Et)v1=X@NFN8HIBK%tVUW@<~u$VJB;dBRYg|pTU*-pe9hpymaIb! z{cO&(pO;?pJ+a3lUcMCc{a5mPz9%-g$$d_ByWHS} z7tH;@YP{QJou}O6!Vj&6HRip$!!?e0#!SO%yxZY2k2zrEN7lj$v)kLw>>X&$N|$o zH9p&1aOa4%R?z>M4SFnd#7$;gxnhT@whgk$14Ue$vBKidZIK(i<^==y62GuT)_KT1 z&UwR0>*SuihUgEdL zXPt*U=bZ7b@!jod#rcxEOu9E=gSp=son20O%7Xg~ZyKL9?s11B-8kpn&HUaf+2I+F z8FM$XW}QrPz&6J`V)o6T{|B4&Ysx&~CZn!ivC7mRZIVq6dBBRRGj6f?C!=$Nfjbv$ zF|lrR);Z@MOYYpT$NZm-&ow69Ib(ydzZjp(oN~Z|J7cc1_Lg;Wm2r1YxWed$RkF$n zx0!Qi$S%`=wMw?R;LZ`VZw39o*`&uZN8Dt_l`D3b`nyfC$%rcloT=hm>{$Ufc+J3_ UmJT&n$$LFrD(Rhu_Is`W0l@o@)c^nh diff --git a/tests/regression_tests/surface_source_write/case-01/results_true.dat b/tests/regression_tests/surface_source_write/case-01/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-01/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-01/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-01/surface_source_true.h5 index 82dca4d032eec7395fe8697247c7dc4fb01f51e1..a43646158be4af47fc9ed18b9c2e2246ca57e35e 100644 GIT binary patch delta 6332 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

8Ps3wt{)|lwChWr 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 PQlfn_{VsfZ4t)1X13I-#{y zh6Y23NZICX+)5-FzFT|HcfUQo=l!Gix_;O1`*gMMwb%67_r2~l+{+VfptpHGw-7gO z_QB(E>^Q#fN&3eO?Ws|w=Fq>>%bjQm7MhHr$!o0C1PhK0H(R!xmd{7)UyO~KVM5Ed zFw@t^QEJlrr%PHfZuvZF3Qy1YKl%Ta1q}4j@2+A))0*y26*NDi8{^PHf8V_>j(c`{ zd3?{J`z1oJ@E^)WG=F9GYhIiZt$!{Yp7PJt-P6S{(A$OHJwGMEN%>FbQ-9a&caHCQ z$u$3Gq0I~y7HUmbS_gE=hErmjEm=x&d^d{prIr6Xv6RyPtc?QxT}4{?A~8VGV)j9B z>v(YMW+?3gX=T)W+Lxb*pS2C5)%)M8$-g%KSzCWvHToF;Yb$Eb|I0d37Q62c)r)9f zejyL+~<4H-<#6L;3w^V z%;KXs4*T~EG29`4Usp$WXPnWG6@HTbv5og`UqAP~o{TwV@{{^MX8qWfgW}Dz^M;j` z_4~xa)8-i)ixbVAy;uL(b}`NSXDb^gySbWg-=W7s>4EP1-n9ApW1Ig=|9cAz%{wSs z82<%`B^-M1`r;d;w!jnamsm#YAFKmi7bJ$3a(4j^;Tw-W@^!-xmD6#gnzg8=kBN)E zvWyP3{xF!8^s$%>n_E|@azW&n}I`Y@Ga&Ta-;9!(P!*I{C*=@q$8PeB%^SlqruGHhd85d?+U(88#(y;i3a*@^^8lfyEr`cX4>;5Z_b3i^I#r>HBtb z8XoEd^+ye#57bXE)*Yb(dwVo2YvA^t(bzqGL*SI~J_pW*EZDtrbCt}zC8%J}rR~j^ z)?oVed?rqb^^v4`X3v47xyAL{r0(zQA!S7*JiO^A3Z>qIikSNS!;kyGjBWZ1z@B9|1 zrG%a-^B_U)r$UgNM}$VUIyT86Mkpa6HKAYc6DDUBlid!hSBQQ&%#O(P1=&njw=?u{ zBd04o!*>BZi;jTrU-eM=-eio(%P#1UBz67Gb^{a%LHKqH;pQKVxlJp}%|a(n%?p*hZQ)r(MFrI)}ouv(;|zXybK zd`wA`=!B!CJ~rV(MyUFg#({j9<(M36h9=a+@8Z}naTJ$s*)R0&8%R#_7yfqe8)JNW zSG>@Zp6CEhT&1MzT5o|;&A@!g4_$CpunF!l3x#(+nRCZWHy7cBNGYM%Kea_ z+OH(@1wn(Hz{ouoY`@;a#Q9x*;LOB1o0}DMM{gm4Z+SAGtL7($U+Y{sUUFk_5LWps ziQJ56fUh>L%%9wm4Ms>R(QmhIK~sbBSG?(7i|N%6b~~?D#`SuCCoDZGbE8*|2uc%WtXCwr!`*HH*UX*t(QWGT z)xX*on9qq1t_VBStIog-56Ko`U z&zteBT|K~)Un~libigYI>bn-JZAXQw!xYPZv7a)Zt5&jo(%&e^jwH8)<~>QBTd&)t z#YlbSl=ZrBAx?K)BVZZnk5eAwoh` zlLk^4cKae}C{chr06!qo8zw39CWtla<)7IDFrqo(jc~Ch8ku|DNPvXB|A8j}gno>I~c8|_+B)UwlC4nMXebtFrkyi5){RQ8w&Gchu9&y#z$p$@Onufe z>C^J5(&pI25L_7A-E~rUoWXfq*&cXAqY{X&Vte6ox(-yDXOP{K24T_S%Mx6hEzvLQ zR;|(wl*i<#Fmd_<-k0huo&e1$(w0HmV+_9z-L2?QQ`8H5*Bu2u5AH+#7=fZ4mF-ZT zsOqq$V+m^2Ky-EQ--O9gW#Sk-daKP6IUfn^G%dUxO1X6Z{@@AC0ZlhkgX_W0gek=} zg)e}>qYY0q&J4m$j@8e~i;p0jN@530MO`pC>P(z1Vm3Z|+s2?A>%bEBxViY$F7sNo zEJq%SzFoJZ1CLOP@dV45bY6}NO+YS5?Sa8xuR(E*z@p;ueh3yj#eR+ALZ8@V56?fQ zjma@(;uO8v@3Dz*9H?bVcFSxaGyGul&Pm5&wr4PbjB87qsR54lRrxADL(o$VM!LQ} zjr_H2tfzn229v`amt=QqM4j?20j343{?y?A%;2OQJ)`*Tnuk%+nTn|+R3 za=KU=9J$#)hDP;(Of~DwCpWsF(jqeplkoetYIn43Tw8M1v%T>)V&AoI` z^8qVEpP;>cJNt~t<=ikV}f+U}dGk$2;#o);ETlychYXwWusHeM6mO`A)8Ch z^_0S}Thj+?JZb>(xp&Pi?;)78RC1?Mp9ZSGoTOW5jvZ$?F>!{^pIUUNbr3q<2G@}I zA%@+St#&+>`luD2H%s9bNa%rqW(Mc?2ET_FPai(@5%8ni>XX}-$EskC&u%6T2;6de zM`8=mw%rKHQginqM;-?gWL$}Wg}XT^$fOq#-s`R-IK6=mZktwmcgdk<1M`4em?$QP zIc}U$o7!I7%!PdY&@pPo&xTNc2A;s4RE5{EDhG}RJJO6EM**3IV)vIGCc~v(SKLn= zX-Av|+=KJ}#NOwene_23LL1CFKEsHc+N(EDa4|UH;rmJ?1fRlY*5Kgs;I|;{wSZ2f z!XV`B&yjOKu^oNn!D=#1#Ewgt?|aA8tDfYQ<->#GEZajV`yE{$|3BXOXAQN1z3VwE z(7#*YV`DEam(AU<0__m)_F0AA2JK;)ZP*;<``*G*Qso!B35Z$=+Gjlb%<$`v)rkkR z-Vwp&4^K1tJAyerd`x!J@@)3^7-vD)xmkIp z#&{WaOBGaTw?6d}$Uat=s3Hx3+`5B}n~ECYt?@3NMFD2#r2}cFUyDz|S+7{)B)Ai8;;qFT>xI$kuO!aSZIFpuYady=9HlF zmXfa*A|ao)WocASG3M!MVz=Kxmo~t=>sjEtkan=coNz2LxC1`BT$o^RrU03*(tEtk z0sGv`9MAd8cgsj>!x4_NdbO*@&-sBHJIjWtvA07YN$Nm_5;LUv<*tHd{5Q1M~R?XVyYRMEbJKcsR!ranqcb_$CpvY$>2vhGWtVb~4m+;9>JdJIpH_|*f;L%_MMZD@2U8QRJ>NnI3_ zLj%70SS<5fhp7+qyEh@1ESH778GtWV39?07&iO%I(6TIY-aB|^nag&2wK}l%vB-gk zs{K&iZE1nm-_mG=!60eWRF}b-y+5Sixy`=ku#Kh<{d}#lPFqLy1`d%H?s_29P|DB; zo(ULF&$tUr?s{-!hTR1!a>5O^O%#2+S6YX@RzgLeTue^IWz1YR1Arm|HBD z+$xp}ny>f-<%TrF&KjMwfyT0^=7AR@LdF1de3Ru0li5XrqyBpn@d2C&YVP%M@Fm z+4nGie1?(@yDyx_6IPq}1|42A7uQed7%X}_k8)nyw|TrFJsjSP^bfWmcfiGN)n_Y@ ziJ@l-t<8IVAtiopKjl&iIUT6;96aC9^7ti6gnN8EQ!dx{ z!R=p*W~5iFK&|DTdD{GfBlM#(lr&#mq+gLH9uYcZu~p4$ZlBXkecN$5v;!Q`T4y3K zzZr5jRGu{|r^H@~BInm1Kri#TEhQGmX^G|XIUx4Ehwocn*UIGuJww>@a<-Yg&%`=wHa%jZ9 z_NyKm*zqa-K9T-@4d*(eU=EHR$m@=lb8B!CsCwcFl}jqw6!q?dfClOK*mobG#&NX| z{$2f$OLpS|1!sAbySuY9nL`CrALjeS)8qp?=cVD0s)yQv0$*_qPExVe*L$(=K+}_B zDmUGp!+cAGW0k@Hw8-U(^H#G!QJ36DqQBS|nC}zgS|(HcD_ICrGav7-_&7IzVzf)r z?mc)1z3v51=w*BWDMt=US@@7(w65nDe%UT$!Tx7iWE<@DdOg)JjL)X*2OjSat zrGtdT0=I;JCIY)Dg}?&J`zUnIc#EP(pnW&UcX2fNB>DziRugsp+qe_PMP0A{cI6(J zCT_AmAU}!8q3?4nbWmZ$Ao=kZuqI5cMsFAOoILyf&O!xwW3?^qK>lk{cVk>9IF!}+ fIbtUfR=hm1DWH4{y87gfrX|1|kOEHDC< diff --git a/tests/regression_tests/surface_source_write/case-03/results_true.dat b/tests/regression_tests/surface_source_write/case-03/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-03/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-03/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 index 04a6ac9a387d5bd34e4d46fc533e90171d779238..4dd5f821af92dd98395a8df31af2a81fab8a8ba4 100644 GIT binary patch delta 14582 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

9~Z3h2uxPwu_`YUdKuQ+}EC2UHt6_FFSG|=04 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

gACz3xS$)7QvAJ4q~sq5iSLU?Z+ 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 diff --git a/tests/regression_tests/surface_source_write/case-05/results_true.dat b/tests/regression_tests/surface_source_write/case-05/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-05/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-05/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-05/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-05/surface_source_true.h5 index 1a2f54d765811bd10a2758e20a11b7ea1f242ae5..ee00af3895c349d60d786af1aedef39e05e24d20 100644 GIT binary patch delta 16296 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�lp<>eX^b&3mYrD{$fj>-rU*C?yw^oiS*X%R9fMk$&7Gu}cswxAnZQh7{L zQKM|1qbiF=@vbHO17WrN2rcO3wFG>k&5V@FRc?%K+mXHIoa?4* zCdkf&hlY>%H6s>Ifgg#5nG6F19XlySl%IB>qVw5_~`3}ptR3|ttk7-8V)ga)XB7c9PV@|cF9rb)mHxVmw~_Wh&BBTWL%o7k#JvnN!GfIq$_K9V(91S89SdYp2~ zB-JNk(wPsnmUYq9Cg6C8{@ROviPWY9Dei)iyu00JdK{+ch@Z0&XanluK5;pnZ2%bWwhTVe24hz+kBjHeAmbf} ztxe9M3-PDMn}sgkKNBuGC_n1~)eL^Xa|lOTOc;`_^oUXR#=Q+l~`ddq$Ao{C-CKJGc38=tFHcq30eE+s%QVFL2x#C z6VkW209-!B*!sQl2S}~3EGkLTMq5o~PB<%5YZ>Y?f?w2*l_;VI@D|!@zyG_>vC-+C z{!+~O$A)7ER+2%XRcXYOpp@bPu;Y&m}1AMLjhKV_B9(R&DeLJ zK~x#|wz_I0@>VbSq9|YZEU6Vv1^B%6y`_$N=t2Rvf2`(M#KrvwJ{#hBCeda7=@iiD z-rx|X&Opk|@EVa%9|HHY$Dcc!R)C!i9KX(my@Pr0y}MKO{vfaN`Cs1tM_&d6+q<(H zoaoEKf0d{KpQWBn@aT^(B;n9A+|C3s9iMl^1e#S8tMdX+UiF%_Xhy0gxHQbA0|L_;TNDT1e^;6hR)OR z7}ZNV$xyeJA)xeGCg5g!_%%Yj4|+|pr2J%wg92;!L`ZnGfxy5$bLv7$Xe8lD#AZtI zva~025&bus;YGh+USIf6DalP2JPD>>riLQS$fHKz)Z8btOG=a4$;*W8ejjqYlMQkR6VR9 zN*S8r?|Om;@qfxsUh1;I5!KQ9i8KTRh#4ECyZ(Z)>EUndwhw|22PSlhDX#$=XV7`$ zQ$N8~-4N%`l_sdmp$|{~O*1|^oga4;pGUhEdy zVAlt3CuWh1MH9dWuT?d>>J`zf_;+4E{?VDAsvSB!SQIY(2a?3Lp9;G<2tJ)Z`BcrI z73jQP(RFvG6r}9psYkkcVfKn&#z-s?Db2F{RJx5?8dE*Gl1{rTr)E`u!zu9P#{D>M z9xUF-f#E=>4I_;}fpjZ#8_pV3D&;wTx;X$cIzJWIzu16kwC@;TrudGMR8(96I$Rz9 z`Wox>85o$RKf9u_eTkn)gEZ>+7GDJ;@5>WH4QpU`47!!^%m7d{tU2s|b_|hRnf!L! zKe&Q)xI6Cb@3y|cK%$A+NXNJO|6Oy20olzQakZwQ4cd@azLXm1fw=hC(!z_y;LX~3 z*H>kh=QDnBJZT#wQaZUtn9*VcjIj7ZZ;h4-hr2jNCnxl1=URKqj- zi(CrgNie0zu`AtK2d%bU*;zs3Cza*G)R6eTAwWaqbjZUx|g z@c39{AK>e+N!fzi3jz~2rG{4HQQmS!34ELpR{Duh4<>%bYPjRX6k{=}KSk;6X5h*{ zKb=p){K%X2gFpOOH;CcUjKO8KLh0PDt+#ypKtRkc(uhhLOm7VzjLBg}%|<+5TIg6{ z%on5DT~>Oheki009&6m@I1*b7Z4*UQocDIauM!G9NAf%24y&LNju%OQ@xew52NiDA zEBTdIdXg5lMu{(=Xm<=>ycO)x3hzw3L)~2`VTSS7u*lE>utN7Vi|O%3;L4(?ANMX5 zAO%{X=HXwEt;NE=dXYimHC`InPtaz;m+c)TO&1*!>Zm|8va2d#XLA@k>c%P_S zf}10Q$cOLlX>X~3?~5YKc;5HIy8-dl2EHkP(U)6&jeO<*#NGOb#g!@WH$-~S4PgV} zOQ9i6%9_i3VDN;^i2TMs*BhZXW9^Iez+-c z&n>~8mBfA2-~M=V<&xf{N5hpSg#+y{?e%@)NLVE#xZl_sg>*wZ(Se4YuPTABI+~V| z_7SW6B#5s~&2SHhqoy=Ut)crJOHV;%l@LY}P0U6*-64>~E;b16x5|mZ=6W~~c{6r% zS`S{ZT8`)qs%8>mUETj@ue@QxA3w6&;k=k=hdLwZM1&;3qd%fa`s-7v^oZ@}XBJpGU$1(O1Pl|yEWb0z7CO`uZnkiA-+ z8G6)$l^r#u9`LC(t<0j{OhhRHz;zK_2{b>+(%G{a7kq}Pb7CpJ$lExwpwHTI5Pxr^ zYr8}ahc3YoZy*}b2KHhgD3 zau)Ys`1_yepGul-gPIBI2H6?$Fx&l}{>Zytus(FLTL#69NTAWYFhyeR9>vcnSOPx6`BNVk=f9#&R%yKr;zq8wR(kCrbZx*IE6o!jBW7&eR zuCehh5d8|9?Rtiv33b3XmH1sUqCKF2v-oulx(R)Dx>R|CjvA(~3Z1@x-BtLUO2#nz zCj}38DmXJDB*D4MGr5_t?Zsop_e$NM_H4K6m)cJ7URRcrr0 z;jW{@z0S~HsZ~1)r6himdcioxRu1hiAJ5uH0MDl{c%^;2;EmGm8oy6nAUyi@k&61$ z$Y;C3%EIjzFh8tc#ARLlOc`R)mEmF_ZP!ix=uG~xgiEp-KC?mQb}5wUQH%Du{1x(z zPM7pv7=l&fvPyQGN~kzq+VdvM28^w$RJQW-pqpgae}Y~4B7u3zIAo!O9>_^xk3b{vS4)*vg_t-O#rj|GY)ZfCXW=XR}L~6c68X zbJZN$I7nGxthgHSb)aHbcKsk{K1i5L6`gleM{64l#xg%Gze!goPFtGcCW+`)+KQq< z=gYqHO<#=oXFz?p{7!EJY{w({x~_LF&+Y{$H7^0L^fYLCOCa02v<D^&QzdIc%GBIY?QB93L19vgDxud+D9^fb`8XT}nEX&$N^m{Blq z=?6LG!f!n4YQX8ggHY;mHN0A-nEgC)7AY2(5oF&@ebYcKskEs!adu4`IVNO4!?~=f zwuoM6ytP(#o)Q5Af4&nN&!&MPm(8ac4*vv=grk4ftY3jzY(6Y=HyFWe(ph*tsEfQX zcTa0Q*YcO~^LA7I(N&jn5S%mV}Iqwtk{6O?H7 z5IyGD0q*zPg~t!JgBK?)DypPO$Why;(%p0B*pjl54wq@)j&DyZX0fH}Gvm!eldjB& zXuRbb$9>((hm;S$rSgO7 zOv6Rxmevp2kc|}R7~lGlGzC13`5#@oT@H7r#pms+9)fv(TMvC zyD%eR3wq^T67j8|0=7>X(HWgox~t}8`!HtoQ&oFspR#UPfwkSH#r?xB61xg6^dy}`-hq2 zF0cKq6Hu9PU=?%l%#uGyPSLNvE3#z4!s9Zh{dzj#HMj9&k^blSJ=Qg3JQ^EF_ z3sTGbD*XjVd9aLx)thEG6l3N6+<3V<=YDU5dfy&^iD&gJ+x})jX5Gx=+T4v`S5+<3 z`e-wB3VEjaM|cya@6rXwk{`rV%u;)=;gRWIfjjIB+ZNr=hM1RY_N}w11UtF*U%;8P zgLA~zIn%~&!1%55b-0W&Dtz_1=$mII815!IKP2ptsDvJj2u;jJvWR9@ExXJ_>gh1= z7>j=baL+^r1j;(#HvO~dyDWR4&2BBD3Hy!cmOZvU%9^Iw!PAtwzMX#kTvwsF0$wS6 zwEc}L9w8?(rSU&%0yi8(R*g5O1BX+LW>z`_AT03bPXRtt)O583W15c%wxn#P)2{fG zi|+i#UrW}K%qpu3xl{8%f|rB3^89C5#NOJZk~0i1O}@lIj`O3+5Z1ug|S%1&7Vcaa{)_(IC0&W^2oc5-Vs2(Jgea67r2dRQE8DXks>` z?d}zMju+j)B9r*35y z)Qy#>*XnUrm<8e2Eiy>B!GK(r4lVv0O$PISVwLjETES$c!kFs%PQVZvESZ=+2d*g; z#;F#hU<;E4opxKIqr>cLm@(~kORF=HAQR&3|2!|$p$m|DgCA$Fpy1Zpz8tvO44#UH zec^SU0U}+I-go-bv4x2q*Ed}X*SdDOAZNW-aVoGBkDRmRJ# zl+eRHasj?i zQ~eO|yWF0>&W;waDw;`r)x&VN)8QtpV&aa7XGLgYHbhUyrpYMc7dU4fI<(!O4^%h) zp5zSw3D~>lL(l2fgU%bQz7vsZXwp)xoMYT6vRETIiV+zLKrvwHQ}z>9j+h@;TdI^unzE ze4WWu)VCe5X7cx0x(&k34{+jKy>(!Iz3^$vmK1PW(^OkBnyzSU_jXjvvJLqs@ zuWa>h*fEOXs(A++i!cp?bH7Y>g(!Eysc#R4Li}1_>8Ur9C!5J&04=yVbnP&b^%Z3F zRh_~(wS#JPNGAWaIImIg*oNmu$GJJcuqxUzp_vRVuj$1zGxS68=7LQ-$}(X=jc#9I ztrPP7q4kz87w=+L(`)xzK6PWy%yK4i%7;1mvW!CHl9gw3xd*fgE<9K*GYncvVlC7t zSGVe+zZzY3v!l{)imE1$BA9kNi76`ubxCEet4}rvPl4RDyZ71aM_}14hTxK0{ct>K z;48oLSMYn2>$;BlCV2dg{s+O|lIVHsJQiko>Lovw;&yb-%dS3r#F%#qXhq9*DQv_l z9MWcoKYKqh<-gyPs%nIcZ3Sr-Srx@%GIyVD+;uA=Yl7a&*4^ zTsj$q9erQ83s;8iZS?w{$-)7){~@Ku0Axn z#z3+*@Ai}8u7QEFRuxCnx`FZ@-qK@~8zwhD3+{?DcY(HF+Qs*)SpPS$!iuK-Z^E#2 zB0YDDy)V#2BB3oA2KyK{x|R^ zLtS^h(O;OxqeIDdXX2Si$x_MQu~h?5bBsLs!M+X*^1iLDDE<#On`1keSJ6qG}!m z2AqUnI8AX@V(EJL^w5_<-E{2r z6v=ykpF^KzE2zTFTv+=d0%XLTcWCdT)GE54ev?X*kVr&}_om@K>{Y^UqPn9Q-sZ?R zgDn|+n3U4gLAlX<66-zNFZc_7Rn(Ng4Ka|i9UEAaZHM7kHS`c8V*yZf2^7(k$Oe|P z4RvngD^a_@8_B$JdJF3#b#HMb;+)LzDq@3IPH<5VT#KhcCj#z1F~w=I-$Hi}rBO}y zec>PVe;Q9BDZ;px0|wf^KI#%1>p0*&+Nqk>0O;H`{LNq$=a=#?UT zp4p;?mZbd7_~{^ry%X5KfI=kgRm1O0JL2%ncLP?GyDbG}@$-4k&evj>SP+TXarcVq z2}r7?5qZtXuC0T>wK zt8VO_YGguaKSQ}uypj?es9Xb?jr}I)O^ZOx<8A4xCkDWtfIIsRrPssNJdMK8hzEUa zIU6wTv3$;7;^vat!_zhER~^M_ACkvp(d2W|G)%ee{gIQq6OJCWU_8&<0~uaqq{Xr) zgTC|J+l+Ns(a?#yJHv39qf3W}CEPxV5^0HU%DzhdLpiETB}{}LV?ZQM`l3N&Z-7SC zh@aocFl5`4u03WF3BIoj;T5*kK|3-e?i?Oa!4473lolyrZB?7CH8r!q+d^)`C_^Xk zZkG9Q@J9o9V3WmtRHzq(r87%O**C&Z`5`xQDs)k$&k8F%?ykpz#ImH-;^*r7uY&)& zRD#(?hK3Q<>Ln$SZbJODIqP@$K=$m(_rfIbZu&)IV$l!)3H3KcFLR>892awvt#lWH zL?t;Zm0T6o`L&;$7)WE%V^B|!NJnb9c&e><}lQavyyj%C7$C?a} z@d;E^m2?2fYM*>&_BQZR$M9AD-WN!nzEWOy`!>wqOI^zS>Jr*t|M`KAkAC7{!*fATZ5E_bsm zb>A%MYe=f{@YsdDuR$EIR=aOAXCnFe9n6st$%FNbK0bv$b>L}*fYFt8gOIB~Uir{9 zD>T@8PHTv~jLS*Ky9w>G+|+{i@VFGt%9rwfh4wWY>5PBFnV6wguwS3G2+eGSpSK=k zci-Fvi_mtlE-z{HEoi$OP0@F$3ge=~4SdIPg>enmbA>S4xj59b4S~dtyJy4^?jhcUymJZ5R z#nhZ-u_+#fA{@8 zH^TT5=@1Mv@a>{UamUTAjUMg=N6v$gRHMJ(9_V1^(QSei^GcmZhajjD;*dI_HUNcI zKHcxFYJu$Zy;9Toiyp;iBr;v_LJu%CYyRCjI}6-Al5T$v{SE>i*2Jzz%K`bnJf2=p z8G`D!oNFGtXd?D|xE|<6aH?m3G_R`w<9ia$Y=$ zl@dVtzr;3g{AZ2frvYGpM~@HS)@UrRF>dh}p6p!1gpkud91e8-28%|UM4OCS!D*M6 z_dlfjzF~?n4`&7PU;;#;9;s<#Wxp2rqoe=mgwH?kG zIJ!DAcf!!N_hmNZ1~6hOd};d?BXq|}@7gv0q<{c5kr?EE2afTN!WTbo@63P1h>-0= zELV({0=qjsuZyz>pzz$tskYi$;P`4{Yx6aEbWf|&Nj(}0m3H*~K%vpS!Iz#elWzB4 zCYId64s-uc+<8a7T?@Mlrx>jCj624_}J5g94W`k2gU|3us@<45LIp zShe$rgpPg@>`do+FCou^sy$%n9Q-FFs}_T?wCwY4lonV2F$D&U8BWW{V3+fxNy+j| zy)H6{&_5XTkhctm$POP7SltKDx?H)Ew9^FrblZ_fj)J?iJk$3tz04bn%=2R;4NN3U z7kpl>;nej7CnpNXFeUAy&D-cw;9?ithu7-^ezDeRn;I2RYw_k5vw!>`gpr5#kH+WDiUe-olWMA|Pr$7nvt zyE()en=%M5=}J8^K3)yqkbQhFne0WBJIr5C3yxtWi5Q)YCB@tKJUvtePwoABpoo_d zp?%GUyxF3E^W(V`pnKRlU;S_;_@rt{in=!hR@y6E@GezBPuNNRUD$$_xJlo5l(nj}>rkyxHl2CvkVjIVU~0c49W2;}b`gatF&=fA`tsLPqZj;m-K zqNep~YDRK*CUkZ({{V-lvu+3mj=^TRyZUdA4?*9*zqM;Ks^CHIsaY<~FrZ?6P|-ep z7}3R9@k;#TI|(X^SHAcWhHZm@Pn>bJT}uNzn|NbH@OC-4e9m~VZqgsVP1^ZbvUdpf zS30tsu=hjW+pala(Y+i28p@8ksit2Q^}rAn+0XQViS%v2DR?HT9X6LFzaAX!fE`z4 z&Z}8A!q(KPn9yecv2^!Oy0&5riz5x?_POA8yxJ&?=-|EAiN}-T97RSyQ~Kp@N#|>l zm485!zpA%Xw3@(4AsNR5k>f!1pp@6za4HIQjgg>>WBMkWEL*!W@QL%$#2w1j%wil# z#ToZbH>K8qLmlBCybh3|tojcgGge9inf)fe`3vE|Nk|U8@OyqC2dM8|=yBT&39}ER zO2J4=(#v^!Z22c$@)Eord2I+jBwGfkh(&=rE2djI1**UXrHz4mBp-rfFRm18u;TzR zl8yF4haOnRQBp{czYI&RO%XG{ho%@wsak*Vxy+T&pWS>;b*c*@&)J_pqWmWx;hooh zc8^7Y{R6%$`F~J4k1218s0^X`lkl=(!|qe9;G&YudC80K;h5Dvma&R{xOIPAMRIZ- zIBF*srju6%og3@eYT6CZ=chLBc^5`)tD^dI4V^#t@!3lU_58)u3zOcHdFpU0Q0u;R z@jfmE7MkT*60=>d>!A0V1o+W^fJ@cD`s;XSkPcUkxfCZ|@|xHtIQ9-c~&;O?g+ZPN=6wa*Rp?KDEoB}x^3c<+{5q(RW zYFMA(x!x&~166`$zb zpjyU4@?geooSVpm!8<-M<;eFyweps{=bt*DkJOYK>WZMLs!8n*L@n(6El(@4uUz|B zBR32B*PI*+YQmBJtW7LR81II?_6=mc7i4f8MY1PyNlfGJ<9SG~!u0N?I3`VG}6qH=Ne!#3LGHPne1<%8l+e2|ptMgGi-`&`$3j>;(B$Ez z0VYy4@5Z9YSHpnuiL(9Hqygx4_a*nAmVEfj*r)8XOFh^dTvheB-2@dmy4}ejZu!4D zuBFmhGA`imYx#K~z+@YCZKfSQd9`{ceorHaxj%JvUE%=XEBV9WbNL~Zy0jrBY?NUl5&>T86t>8LBeIlS0$1xmyRWIDYvL=$tC-} zow2lVMWGZ*tENQ@q0;g_bIxoXCuC0wzBL5HY8jZrkq0l*5$b>!)|L3?ePSyDn0^S z$I~g*NP@s7aD}T^!{yNQ=#*N-O^-(ttq052Y^H9N7(lLQYZ8*G^k9lTVyMr9F!W() zom+lCOPY@4Y4cK^qYqQ|BRzbKs)1x}tNW|*>m z!0Y4qcr!XAe|X=u$0B%rL>%7Wr~C$D@wA`fX=3q)KgAo0#T(&x_GCKrxHRBkHKCtK zkLnZ{8X9((osSs>lfo9vXi)02tw9u7hZ#i@NxTkEg(15`{=KDKByXrs5UauDr?~qrSi?|7i(PcsauEqRm=QKeI$hR|_Yto* zZD6Rd>YGIc(VMsg3tYls8#;tuO?b9gR6-pFulUDHZ=s0dnK(SqmJXdRylHw;6n@nf zhF*5M*X_cLg1K314wm#=rC$p$qo5M;m~na*L%N9|Cd6^(z_gUcPx9uDpX?;?UpL@h zWQiLId}ro57lv{bZ~kUQyopC(g-a@%ONajZ`t-sM?1>1JJFr&ArUK*9!=<{Oy_a~X{p-6vXF#o5{j8=(p_rZl%|yme=Ak$A$G$PDI> zX`DY=rw6z2^Lb6cznq(1+!ga`2o3sl*qUwL0_c9w&i2C((WQBn0X-`^(IZ19K=Z>( zRA-!8dRcQWnDKW|c$h0-7U;M#jw?^#27vS0^9W^l*O@^+gm)qk?OP-BxR>n~-_VWv8t@X~Iy5KP(jCNTjJrUQ%tkLPmkt`%=5erH?_Ske)9YxUZ zFg`w17ttvW2y+pk0TzpN8jU295x5B3DU&FjM+0%^&SEJSia{^(nBoLlZ#CCrc>gP8Qz3UPq9F+(UkZ= z^Wu+O-c?iS+L`6q!(fr!;^PM*8vyJRF8{Ez6uo_>vto5t2XIbny`Erv8|-V4TUgcf z7IY3Se9?agX3n3vcu94Fs-OqGxxTEBPuB)g$9@2kb1z&+D_($KvDmFp@yu(~5-t?o zJ}?wh^!uMOc?!a5(AO8H*dm#}M65nYj}J=}gs0yZS?bFYLHUwVMBV$AVrygJwv@}o zbm5E|=m$e@E^=HEClz52miWPxuZWsIuLtS=Fm$41ap6}-Y|`RyCDQz1iXu|)PYClP zyTpb0lZ5$;MJ*$tmXT3}eCi6Aau0D^!4nm|0)`&RsukAG6j=(YFwAtsFn|!Xf=q;q z3Lv=)5Q_>Fq6qhOfiTn-oqB)lS`}e+;2;}!-!@K|nX8!bhdOEn!;};xD40+d zO!i6m;9#IQWJU-93L%4V`JrTCv``qbT$6Ys>*Q2n1(QQz%5kJTl$We-3^V`LWRyC0SfQZph$0>mo8(fTIgRL> zzYH_3f>!WwxxRiq%Y#`RkP*97+o1D7XK7;);gV=8Mp0b!;xe#N^iD|GgTNqD0u zanmc{MXFZ=Xv+@EKSaOu2>gl7H~Mr=0@O@X0XRoJ)$(>KFCWgaa&<%%1n>ak1P@SIFZL2rY|I} zbNB9kkdPXq7dqklFIh@c_d4rg`*^HjaCP$kPwEtKb(Y?nImgllLH_+3_I!sy^yq;{ zSsRsVfy3g@_LW8*V9)Q*oG0$eM{5_IJs!Ein0c|caf+FUIt7xtvDU_nQ%+srvu(1M zf7^HTukWg-UQQT9cOBC@-|BD&r8Q6PTCn#cdhM-hgx%}csEtxyiA2Lp=348Ani|B{ zOB}b3iX`6hgTC$QLv8%NV6SWp(U?nw=$ulac+*%?w41qh>?OA;wRd zMQW+U&6dh~sY~hm+IxZ3W>0uc0Mxh2^&IQ~<_;?dNfIsw8#)WNGd^dHx$ZA?$R8<)JTNP~UQs z5~msjTA3N$uxUW!vJSK5o6FE4RSoJ>4hO_rjGQ^9#$=w5yY@w&P>1uX@pz?2@l)B) zyQRqH^o|*&Q$hlr7^hxS^bO>k z@UBRY_ySaia-9Mm-9(F(eZUfzCKRp=tm&J68FjSZ20gyWL8*x`%`_)Prr-At&6n6$ zKmTKq%v<&{eV4oDP4s0E=gxD}&%6$lVE>9Y<>p}j3l@HQiszTi>$Kng7}_v|?ogZT zPdi_N65&wU*Ikc2c;wWCre?0msXNqy8g5>Y8Nc`$nwRgts(Ne;WAbrLKgboE_jre6 zW00VYEGX`N(}!{*J9w{+MILWt#T|Obd^`UCIB6M6${}yJ0UgI2Jsa&;?cFZnuRyX+nMxM%gpnSGXwkq>vS)FuBgd-&q?+-ZvJNV6g( zJ>2pGy4`H^gCfacw9KkFdY$wm;MC7A<=QuwmsZRcrGa_r7z_XSM;)PTWi4G@v?O0Z&g9PGs(n>^R*= zaO2IOK}vkxo|XMqACCZwD@Kh^qDp~_;&k^&&LG%-_9E*^);ln@$>Tq675^u_;BxC>KVX$65u-HYTgFk&Ts=O`@R~{%s%QJS@ zOFgIom3fhSJ+#_E(fhLN?S?u`Yv~AoS!_`7&u}!6ax53duQvoEgg0V4js4A`>X=pS z!?tck$J~1vd@o9pf%I*rK^-RLE>$A&jw9(xexcKyzwi>uXm7N5KR5yu3(>``uj@hN z1+AwN^>;!(oRmf6feuj%F)BJpaGc*oB*tg@K;mOq#n zT}kXY&bBom&1TP(B2EK(W_Z)B`M2MKv{s&B#KMB2fzvBPvSVen>$wYkk1ol4q@1)dlEvh1Q!21el2ZJ@UPYq~P1K>Yx z);_07bhU0xX>{!oM$F98a~g|T!t*|x9-El@pt?wmA@=~LXbR34k6_@fE`N6E^FbJu+AW?6P@ zg<@u_krex^b3>vQsIz&kT1T9-#G6JGMqRG;-VX4&Dz}GZ->86H< z=nIDfvoC6~n7cH;$0Uh#kskN(&g$az!CN=$DU4~xt)E*$ntsXRnroWz55~ej7}P`R zx3Qo;$6JwW_D|==i_akX{6KlvCz6VDwRe04Z%x$}-rfCKFtXU7z@hNSPHQ?O-h z2k}*o*>j=0xk0v)xb5;#MCYk=UPzJ6X_8U9J7o7nur1f+3#azQJPU zD%ucw)7$Lf{O%F-$iIITNVzwlO|IVe_ZO6*HS6v_(55HN_6;3+| zGEA`SF_lTOE|y@gZnqAJ+YhnRIUZa6x;cQM6!L6Q{&Un(=RXtW$OhEBw_rrUqlhs% z^pKVA8+XBm&yW;(klvwiMli&l(EVzjf4>Bqcuf5zZ%W6A-^(K&+>HZXX)E>oa9ekXxr>4sqhmmsGVNzhpBSS z=uX8C@6tkW+xpk;4 z^X!syoN9Dm)_W*Ru^p{j<+5XrTO}wMx98xB42W5k|6s-0$xDCAJ5ZYu?QPzJ>R88m z=1{()Y4oY^^#`9pnL-_BeP%YeW^g*-tZ5T)ExQtxT+RV)YrAtC3cfLXbpGIMKv(>f zclDK<(z$Wn=)I@a#wKb#yw1f=Fn+ z+@VB^qS8i%M0N>@0@(?56@;pRhNy4`a+eAM-SL)Jho8?t*GZ|8oG&=| zq4b=;`iyyKnkonMR7J$XbB5~AnkuvIe06cLV+}gq&p6Q{_?+U_;L9;G>ygq z_u}Af%HFUARX6!y7Y@|gemLNx^PACljGblVF)$il(l`XezLe$?3F7#gO9Pz}**TAZdT@SoC>q* zQA>R?7~}X9vO~HC>il8gLJ0K}y3&Bt$Grv!^#xjKKnkew1&GLLi12}@ICmfkjwZo@ z4e8W7Xrv*jqbbDE5}~6d#L*tfA>GoA5omhc<@8gtyV+?=G&r6h<`~nV(6rurmH3-= z2HZE6#?0UN6A1n;6FMZTmvH@|0Dl51imx-OzK%$~?x=iSk$k;T`FbMx`UIb4Mu#2; zEk5{`^iPII(Hx(^hn=S9;vlamY{fynp!wVC1(~%tC=f{Ub7V3C!8-mudjt* z%_t-P^reU8Eu@A4iPBgn1Kt;He=W{(dX@F~`mgucJC!wOrl_@G;vLhjOf9Yg@!LHL z@@Jbd>}8x1)SXfJ4daL`H$#tDF`<*Wn$%nH=}tUJLl0#(GBjS2K6I7Gt^b|hC42lT50^EamBNG1`}BqszqHU89T z`MKu&9Znby78PaId{biZH(?bx7&oM?<-b{r-xJ$e2t@hcfPb#O2|t|aIQZ7o+9t-{ zjz99W*$8C+rCGJw8)h>J>kKpm{@te2NSi+Fa^W(bEj4q(15bXiRCGvJv3 zJ#w1#9j0r|ykH$UYgFBR=MI#%y8QxS>*Mw29&f-7Lv{yVR5gOxjHeali>rZ^p2gq2 zwoTaG|I*^tfI6^>o@a69V;}tVn$Ob9;Vz@D@>04;Liq++cLBGxnuHDz+P-)u@SlMY2mx4)RDw2+_IIZOmf+Aj9m@}>zt zZ`2Wl+K+}HWV$+w%mWv89wg17LplbGLRy9&Tari{7m?Y`6p=Pe&aiSHT}CEl%TFK2 zZ2hCIyAKb8-5(t~er0{Y6#n|49VvbXGk`-+p6P1^myh3WbMX3rwI7fSx<5c?%=Jh; zv`$l>Hw*|zP?GaBn`vNYwdfv3{-nWShaT2BFX;NCZf8Y>Ro@#tE~?}(@O05ht^i6q z_R#o$wN!SiM8D^dCCQaewMQ#m$7?GBN1xc%|@y z1~u1+@dr2Aoqckyb0;$;$piV#pZiEHqIWnZqE(NPOtRH zY7+HoJ~xv&&xx^n^KTZ{1K2ILUO)L4R<-(e+?!?X*lDLr$#7ITCSBbgD;3s)K_`za znGstH4%&`0pM?4{6c0#zbbcnyOK3kK-AEO$>_N5XyzSVf`z?ii`=0($*M8i__W3(h zP=yVgRn5~6fi^xkoFREthQGe#`yo_ol)8ZI{Q}g>k10qZMr0v++m9*0S}4pSQ(@sk z1p4-1+rG=CbpBGs!oiyCFP`We1%6hV__Iq+q(7&ACHf=Ki8A++K9`C7O<6zAF+~{x zq_F_uCJAGKLdF6`vK9%k774RR`(cX^>Pht4B95twMfmzYMyce(RKYcNG5e}3b}?xx zNLYw4wM3}7B_dhDd=}X}yaZpqBa@1h*DCNw=K>C@ge;Rj*P_OcjAF2eaoie=P`9B) z!KAaL!fldmAR!2K9eN~$B!vo-2>Z)~jqO^BKrP{WZf2%T=8xc)r3lpmwG8D1%QF;# z!d{vwWIi?LbMiwGsys?v#^LBLLmK1$gljwF?KUSDh`C zZPVdzS{5!xAd^|U;O2f~-ljzYJ+gucEtV;4IU-Al5Y^AknLRe*o@nSmiNm3%MpHz21!Lj4f^0zia!A9;y2> z(7N!j3dD>(rbO8o!x5C=Jl|g05n!771yoUXfi)de775e-s5|F}Wdi0mg+0@VQ=G8w zJf*>${7nPk;^~*S#eJK&eqr;U@oQS|wu8+%v*8w(2OwsHSlzSdFTwT7xn)nTS~EVG z$KQ%8WnU=~b|H>Ut~|#ctoiwkN=f_&>`7v?rDciuA7$&D4I+X}P1xZjb~!v} zldZFCFDIB3)-9*#r87@I1&_wR=t|$;3`$IlN>i`aVg0+eUy0st$@sOW-AobJ<>t3E zM~}*R9{HBNX+`D$SdEoVcTgDvlQ8X%x?#4M$})10h=k$kqH|UQNU=xv(Px2}$Ph7E zv*~j1@X3B))igEWs3nC}oFCa`l-B`{-RV6Qq`xRK8&E_f)={wWR@^ zvvter*)S2lJEC0f-xGSiT{8 zwQA0Bte{r;Y|G+yOgm4#I4I~X_WXcR_L>bT;EmGltF60-*mc#HeFPEqE2i^nMNrBh zcIvjp@m;+G{CE@>FCKJm!UE3KD%qq#46qK7~#3hR344_h5K8^+w9o&Dz4TZ3K6M@=M? z8ZbH9zYo*2Td>G}$!l*V&tod)i_<1V)`PgX#Y2{AlNh};i|%1um%I6wWgl;BPWEP4 z?3`bV*}kUiE>FD;{-lzQoJe!Q?=HAUCtL-O#c)BvNx{k|ht65cgfySUOerPrG>Hgt z&&1q7O%U&PcF>T3lWU@{7oQm94hXB>NcT%i=_e3epg@^5?KMU{I$`?`uSUR-`Jy^D zV+@0_Z%dLrIjKbI&U^esb7PX*q$LQB+YNVQ+y-1<+iLSBz_Px439mu$)W?B9-;K; zy;V9E$xI1SF{;9JBj!(RSArSsuP&Bo3q)R?i2TE&eXIbF&!9lE=-;MR3hPfQMl9_I zY7+YCS3yX3D^1Pjxm_Jb!Zf)3$bg*PRx11_-RyT+ zja_VARr0W@fPRf+Lb2ZUjgh7{SfC`#FRlo5Unzum@3SN2h1g8QL-z%XZ8<~)Ejm)PA@_RFOJs2z0vEvP8 zMb#N%Ft=m!@9%rpI(4H78}*=q>>H6U1rc{W)&ZL=g~r5za&T>-{5!a@8M~v=fq?5Pk(*N7^rgTnI^z~i?WzIBto^q=sUG0@q*Bp58 z0(XbsjS>T?BBZ-#!=ObE)(=YlK6YMCo~ujyqpsB_-!=(+%Hwraq^^$rw4$NCu zJ;UhgXKtZ`dseJhkZoG26g6KXyHD~ot+(Gw%avx&>I3k3X*6Y^^l z`|g!T-T)SN%YIOy<`cI(z}5PUz$?%TEd7`flH~9TYsz5E6Wi1VOdMXVirxGT)>Y2A z;wj))SaKblCHzZeO}6i(opk)+S%Lq!)T068i~CKD%bwrM7|$`Dq!{f;vpUxN+Y8=oYX$ zV=u?+m(re5B*BOtGkMlOd!0wsrO4jj`r|%}m#vBgFUO{=ZTh1wvun*+Hybxz zxy1ih8_k5;wAJ@p%roXK+S=?eDm*Pe{I28B3v6wTXJFU4$0##e4~opW5Se#%I&X*x zrcFcVj{OJ2>afFoHyF!9zGL}L509oNwE+d&jgrpmYCwpjiT(K-*8%)sdeWSf5_sNY z^=KuEGjEa678;FI|7^H&Xc$YL-Y}{D%z4aJCa7F}Y~LSs=|hys*(Kh*s0r)#{j%?V z{^UD$?aA1$1EIY@G3T+gSYHLW`XMlP|J!;j%{JM6Pi7@p{qVAQx%(FoKY4Oux=k@0 zT=8ztBKNRSb=USh-uXSIAG0`Orug<)4=8Qf_{=J52;|Rl^e#{B1Pj!TEl;<>Kyl}< zjVEX1V}I2={MmXx688DIxa9q(s8My-FMo3O;7}hn2Ix&ObLs=jHb^s*&JP1q37=1f zneEuJZs+CHwj3}vV0yQ7;cNVwK2yK)X*e8J?R}{tZO^E>;xZ5IOP2IuoEie>jIUGB z^{NI-?k+sl?oj~_HxA8O{=5!k7#g*oc5B8~JgO@M|2zhh(&xvR{8h%=Qwzs;&MQsk z-?Sc{E~WNfLNm)AJBHdmp$^r8^nY(0v39M*a?8@6%I7v?iMz9_W=3BFV$pJzI!4b& z)opo0$-6PR1>5*u$5Qyk&^56PTJ@}R0c4^{|3hd#7V^NQcsxe4*PwQZAD;O@x ZGW~B#GSJ)n@9qo(Vl%43UYmve{vZ9g!(IRY diff --git a/tests/regression_tests/surface_source_write/case-07/results_true.dat b/tests/regression_tests/surface_source_write/case-07/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-07/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-07/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-07/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-07/surface_source_true.h5 index f84a5c4c5b6d8cb4ad3f720e40580f6309998d57..60527c99bc259a790c1f71ca36c7a00bef7fdf3f 100644 GIT binary patch delta 16301 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 delta 16328 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 diff --git a/tests/regression_tests/surface_source_write/case-08/results_true.dat b/tests/regression_tests/surface_source_write/case-08/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-08/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-08/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-08/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-08/surface_source_true.h5 index 1fd302a7cd429beaee0a203ec8e5f1da09cb09d9..3088597c08e1b4af24b1004f8d62e66bd18d6631 100644 GIT binary patch delta 16492 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 delta 16528 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 P!D9IFE&iy17We-E%q{pF diff --git a/tests/regression_tests/surface_source_write/case-09/results_true.dat b/tests/regression_tests/surface_source_write/case-09/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-09/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-09/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-09/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-09/surface_source_true.h5 index af832f060cbfbfd6f25fd6cd2049a5bfef55e307..81cdbfb0fe8919edb309daee668fd689fc71507b 100644 GIT binary patch delta 15744 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 delta 15900 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 Uq2BhUB_p9~^Oh3&ubP(s0|V?-tpET3 diff --git a/tests/regression_tests/surface_source_write/case-11/results_true.dat b/tests/regression_tests/surface_source_write/case-11/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-11/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-11/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-11/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-11/surface_source_true.h5 index 0edb06c88e9a4ba368a72bb0a16b698553dee244..b5b6036201bede37dac2749563dcd68620584009 100644 GIT binary patch delta 1887 zcmZ9Mc|4SP9LLQebC4W^bu3zGRGY;*qu(=<=7nD6$|jO?T^m-Hb{8q7EsGvfvt5YF zhNeSN{DxdvOU@A;j+!;OCQS{k%zB3LdNt2Kzt`{gyngTJ^Z9nEq zgb~Pkatn{%o%4i10=|ig&Mwm;_M0?^-_cS?#^DOl^CVq@SS&^#keCYVJ(p`C9UIWg zBn`=#0hx(U&_^T5I+AS~nTcyb+sO+T1oOKWs4Zn-w?b75jir2tn?UmxPdF4N{=O4R zp)OpeQ<=D2G>)q4IsY}^MOo5?ams$MD`Ofi>`9zGefS?~I!D3N{XMf=F7^RWgX)x? z2tF8X`Y5*Zdk&wxix{_x^hPfGH@xOOsJeSY$C zd1t~B*SIhJullpg5Z$hQOBOmA4OO^#PVI*dm)x|$0l zT&$LiMJ{1+1)s!LO7$~Q1&E@zQ^>6 zHc3EYiEho_TwfGWBoTSY$i06vhhBO>ENx4~ATVy?L6v)JYK z7O))?9G>hSfOYG85evUINIPw&a9chL5nM0|b~(OFiVcuayGs9qyPrb?49H{c>UN)5 z!VlP;YMkMBK|Q5`;lNGh(B9{ATZG;OoZ8W!f)6S|3Nm)*-)2r>MZg-0D4C%|RW(fm zw^_*haLcs3{28Q_aq&$jcz_*2-I;fV2evg@-K(#<1?scX(?aYbkw+)LkBzkzN@s{H zqpjuNU&e(55&Rq!K2pU}Ko(w;5dUhw!pcN%$h=U?B3$Bu>-xbzSQYT#Y;Ux>i9!ze zkQti8(wWAzVf`eFEzqg|e3bG`YL%m$%F%DzE&z{6_)asQZ1^B3q~USmBseD!UhGY7 z04|v}uGM?#jPMb0iuqdM(tm@BdA7MPiu#X7CnDLo-1fUS-b1^0fw|P6F_6!D8*Q)K z3Ea(aR^F$3K-8{l9b57bfR{xyqLUjLpev{}tSi-IOuJ^RTdg}R0E=ch8ssyqUpwX? zHM0E98LeLM>K~%x3d2UgHRPgkYU99-5@f)&bYyH&Ec~s(MjoA1mIR_FnQ&hsDFtt| z40-LhFNTma0!Zhx{iF5x@Yu>ypM=hwr5JRh_cjg|kAsHvYF1YZ#_V)?T(_GiSjc}Wa<)g_fID}D|>9@?p0zWX(N)nd7g$t{9U2Gjg4tNGyI zrN?2LghL=1-m*IB)Q-?P1YH0C delta 2822 zcmZvec|4SB8^>piWrk$QdXg;(bq-1yr2Cn?UP3BDC0nPom*td5l4Pl*Je4JBDoxrL zSqt4$O%madElXw?g9+Is$=l3$eBR@8o`0^-eLv6r{rs-qbzS#NhF;97D|#YC)ocS_ z0!beyeDrgY2|fgo3|aJtxQghGr2W1*DiYy%JPS=Gsu9lMaA+aXR-)Kxp$bxKf!-!6 z3HCHewjzf#(SxMLf@KWJ7SBX$NWueyzg8pg};9PG#a z^DO#+9oM03Ooa)RGIP$BDfGa$b2ZIYK^#CM+dmu))Im!0>)mz6htXps0aj`rmgbsa zZqYUb-E-b3=6;tzgs+LnLQdFWMS2P>VlBGQ^XP|a1uCySJwL(POS+Gb1SW$fx#wA5 zBBoIw`L9@Y!mzcaswk4w8usk<%_&SZqeEA-hxe`%co)gwtV|jq{+jx!(5+lRk?K*D zzb8(iTnI`q7n;DYg*5s~QrVRAHS}WKem0CB&!Oz~nSg~G-e038^Z^<2Ut-qBT7i$4 zp812EX88hL%8cZu79mi|~wRkpzZto5*NxS78MgbVIk8>bsl;9pG_P*fJ417f?s~cJwN> zfY68<>jjh~F#YXD0rc)d+ohD8e>piHYi|DL9CRwcOkilWpHEyLg=1{q*d4AV-2fwX z9BU5ecLM_t*~+8-9biwmy>!j-D`0JSerT?uI6zraivPwfu_W&`8ycSD4h_&>`Bc^vc$@QkUe9J0JSwM9^YH@*Xx5)%ijq3OeN)Q}rdK-B zWUl|FyK@VAMq1G9q}dXQ&PJ>>mSwMg+o#6{KI?UEc#9H{N*g1*Ye6Sikyv!|TQCWd9n4chDiJV~UaJr+BBl1Hq zz3!3=Gf4ztxm|XU8L9-X@jVYKiu<6-^k85|VV3% zhj3f^ft;Gi64&+?c;ad7pwgwk!I_{9{Y?{RVP=*~ie~Qs{8H;K=I0iUY&w6!;34{w1EKSrS87eF<`h) z%YS9^2;W$KkE;KpPB>hLrR~%Wtx7Q1o^^l54bQ;pciLYmh8i^h6Il)sD;D1Y@iLR` zT?!w;YJH1H56whyH2qw~DiR)`RH7o^CUrqG6^gE-SN66*-71m%)7iDaWZ=N$@-PIC)Fs_+4+G?Bi|8b=xOBTi>4}5spEVIe{L;i zy~bvvw{0S|W1GaB$Hb<;9%qkpA@|}1V>cBZ7%>absV`#z_4L>(b?0h$<*XygV6g%c zLZ)rr`XiEmeetpDXR%oD%x&oNvEl&Xn#ibjB2P9Z^S}!2Hp!g^JWyU1lwD`{4$Rm; z6|o3m!w9eEBTJhYNYbuO)2l&SFsvQMn~for7Ic~h0hz@j$F3{$l9O;q+R>E1Gy0xE zYL%y@+QetrN?rXVyZa05Ka_Z#6IzXosH*yxY+_>XNzJ7yi(boS+2|hS(U3vL`^m<46rIG{_k5rE2XdWqcvlH0KA3gaG1AIuLpCl z>u~_tY&yxrbIuHed>*O)5?cbEH|CvRlH3EXx{%ISX>p)z3X{s%x*L(Sdh#GOsg{rB zx3Pwxd8Dt|w1yQ+FcK*Xrz+7-DDK5N{-~q{dPU-nrd1Vzdm8IbrcwKVld{H=pZZCN zZ29yJce7b-Sjcsne9epzN2b(j0&OO7h;W~X%oH7=n;3Ni^Yl3Q0?&pgs-SM- zqE@K-uFs63q(zY;eM<93O0kqTVZ7OBl<26-P@jUcIL5niUt?P51l;3l5MM~Z7hMU{7A2cO~=#6t8e}-PK}BIf>GPO~uCebzk%=W$$^|{{aQqMX&$> diff --git a/tests/regression_tests/surface_source_write/case-12/results_true.dat b/tests/regression_tests/surface_source_write/case-12/results_true.dat index d793a7e421..ad927bdf30 100644 --- a/tests/regression_tests/surface_source_write/case-12/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-12/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.752377E-02 6.773395E-03 +4.929000E-02 8.212396E-03 diff --git a/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 index ea81a8250956ba2f3da07bde3332e13963cd26d7..ca5eda8e2f347a1fc88b05db6690ad5b6d3a2a51 100644 GIT binary patch literal 33344 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 MnYIUOOW3*p1=$pDP5=M^ literal 33344 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 S)+dnMzTq}Zl@F~h?f(H)kZg?r diff --git a/tests/regression_tests/surface_source_write/case-13/results_true.dat b/tests/regression_tests/surface_source_write/case-13/results_true.dat index d793a7e421..ad927bdf30 100644 --- a/tests/regression_tests/surface_source_write/case-13/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-13/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.752377E-02 6.773395E-03 +4.929000E-02 8.212396E-03 diff --git a/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 index 08bd809852152200e5449745616feef691f46778..ca5eda8e2f347a1fc88b05db6690ad5b6d3a2a51 100644 GIT binary patch literal 33344 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 MnYIUOOW3*p1=$pDP5=M^ literal 33344 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 Q0?F+gZo^dh(CX6uAE<_K5&!@I diff --git a/tests/regression_tests/surface_source_write/case-14/results_true.dat b/tests/regression_tests/surface_source_write/case-14/results_true.dat index d793a7e421..ad927bdf30 100644 --- a/tests/regression_tests/surface_source_write/case-14/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-14/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.752377E-02 6.773395E-03 +4.929000E-02 8.212396E-03 diff --git a/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 index 50cddcc70cd27df73f37a288d86a906d7e7694fe..c9900bd9c0469d3b171f863f0518d6c94e966027 100644 GIT binary patch literal 33344 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 LX?w7?gq{0eR8MbD literal 33344 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 TdaX|&xqZWJm?|GyUE2QxR|Ib8 diff --git a/tests/regression_tests/surface_source_write/case-15/results_true.dat b/tests/regression_tests/surface_source_write/case-15/results_true.dat index d793a7e421..ad927bdf30 100644 --- a/tests/regression_tests/surface_source_write/case-15/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-15/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.752377E-02 6.773395E-03 +4.929000E-02 8.212396E-03 diff --git a/tests/regression_tests/surface_source_write/case-15/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-15/surface_source_true.h5 index 3e15017a16626a9a66d903daf1721a97dc3c4058..5bdb39b2a703fa7cdb17a153a688cb0ea7664f1c 100644 GIT binary patch delta 17 YcmaDL@IYXL2s_I?%~KhhCD=U}0X^3S1ONa4 delta 17 YcmaDL@IYXL2s=ysjEuC+66_v~06HE8kN^Mx diff --git a/tests/regression_tests/surface_source_write/case-16/results_true.dat b/tests/regression_tests/surface_source_write/case-16/results_true.dat index a97be70cae..cd0619c1fe 100644 --- a/tests/regression_tests/surface_source_write/case-16/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-16/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.496403E+00 3.891283E-02 +1.403371E+00 1.456192E-02 diff --git a/tests/regression_tests/surface_source_write/case-16/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-16/surface_source_true.h5 index 49f67e8205608e848f0130ed65b472ff98eee046..79ac8e1a65e38b5b4c38de45c29da9f3579a35aa 100644 GIT binary patch literal 33344 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 J^epFt{|~;VRf_-s literal 33344 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 NWw4>&FGk7_{y#Mh($ diff --git a/tests/regression_tests/surface_source_write/case-19/results_true.dat b/tests/regression_tests/surface_source_write/case-19/results_true.dat index a97be70cae..cd0619c1fe 100644 --- a/tests/regression_tests/surface_source_write/case-19/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-19/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.496403E+00 3.891283E-02 +1.403371E+00 1.456192E-02 diff --git a/tests/regression_tests/surface_source_write/case-19/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-19/surface_source_true.h5 index f4261451dd4832b3ebf2e4f014543c850f8f35de..db8a49dceeb20ebdc3e0c1b8db765cafed5a4052 100644 GIT binary patch delta 17 YcmaDL@IYXL2s_I|%~KhhCD=U}0X^~t2LJ#7 delta 17 YcmaDL@IYXL2s=yKjEuC+66_v~06JX-mjD0& diff --git a/tests/regression_tests/surface_source_write/case-20/results_true.dat b/tests/regression_tests/surface_source_write/case-20/results_true.dat index 7ccce7cc3a..44293cf091 100644 --- a/tests/regression_tests/surface_source_write/case-20/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-20/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.149925E+00 2.542255E-01 +1.266853E+00 4.552028E-02 diff --git a/tests/regression_tests/surface_source_write/case-20/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-20/surface_source_true.h5 index fa8a4e628728deb4c4d75b03cd31f0aefe6d132c..01d2abf61cf8a41876d664d1aa505a967e7559cb 100644 GIT binary patch literal 33344 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

`BTVz zMB)c?1qpIG95ua!pEsVu;}p{9 z#_cYhfCb4xjcWC{`%mhpT$(D17i8z$d9tvt z8ho#&DRBQf2v1mhowJjS1A2ZLM4YaK$B*K3!aP^_q71u$(dVFjXKR|VesD>?+PAf% z31+Vb-Lp{`fxm*C`D?4&;Jz=rJ1-C=BPy>w)FW>35X>JfJiGa6O1{sx0+X7B2&*Z&Y!Xj1B^Cvgz~u>-!zsX$VxDOPUCSdE-qe@ zbpH-nsY^$`kKo#)9C9Xh_XNI!jva&i?O!Xw!|870mM0UiM&^)mm&65Gd zqpH*%i4*Pz<8x9vn=ZvX?}EJz!6oTzIL<`|p-1jP-@xMdYFPE*Y(OWje%1W?Bovbu zd}tF$gl3Yu^~oxJgrFW>JUy~(k@1Z#*%gGzd!&naQ z!J)vTqe(zW;iH)MXcPEz-u|rIt8qABlQnD2n+&+Y@b7yLKHAbQwpWHAB#U@ z!o?|w((+m+*Sew2@2LhckqlTo=UH!PFaj4$?VbchBj}OH??P+-!36W?44&Qio6guC zmHY-A{oV8r99)1Kn<+7}m0yi-8a2a%6_&Yz`Q@ZX<#u%&w5_A;z< zs7n9bL+uzF2cgBs&ZNJ}1W}K8 zTs#LG;MChF{*Eqyro9$n&lAf=(67(qaRjxgkN%(~au=#UOP41)ld?O%H zepJX+(hc8xlxs?&hTy^(i97J*1>~`9WU&AH?Q=*R4v71kEkNcntGRD#xcliPgR{dv>#X^Z{Wo?q!m}HRSP$u4 zK!RE2_Btw1hKp0sJ)hUO(>(yVK(dTjm}$y{=-3GRh#8kE#L>+M4)k?G6tF89Fdl5(FvmjjSg?^nDedmR0KxKc8tgDj3 z=5WWwyDzmE0l8-fw(m1zw6o8JgrbY#v96$++ossY$LK%6)5i@Mf$Z zRtrj>9uw+;^YsQ_=8yLwdx7iAzA<@%9P=%}X8QIj#q+DGBXCvp@VTddaDE+fO&k4j zp%}!$y1=NS=Wx<%I(W!_655}?ImmFX1OY33(}CmL=cISa7>`&kg6Jw&rj96Fzw!8! z#~jgOeQ;-@jzV-MGM0p{8lbn$IYOK?5L}r8 zPoC*fSGl}C-tMmtCFan1W9?DjX1Mp+vbfuWPT=k(^sX2+3=Oq9B`=(0MssEaAL@-f zOpvn`H`vOi1fsT&7ktK{O(MId&o$gQI}gV{^sniAf%5ycqW+{BsP<}#)@bh#+-;Gi zwWpyT@kCQRXgW){9^LZ2EzXJVrtY-aDUcjdvuJ68Yll2{a6M(3+YfGxaYzYTm&2KN zONQ0v15kWCb5t|_IZ(eYB^KGpPEZd%hxR#Z#`za-q2STsfk>%2xMep#sw!)-6A@7F zt4Gf1@8#fX&+}&iB9m}r%;`z|t3&ANW7CCUf`sEpWLrWu)7`vfjQek|&zEj@E+1)_ z#^%ql#;OZvgbIMF;=X&r5~DEZtBA8T=z@=8BH83`WB@38&C=C>`y7{_wl&Cb3-JAD z#$D(^j@iIdV#IIdc*G7(K#kSI!WpWGaHWJaSpQfx^evz@+c&_B2poUgU8g~qL%ykF zD+#F2DcyO004}h3)E`bG$84-$pYQBO%{!%$1rJaj&stUa32Pfh1n;cR7pJ>iGd|!G z380S{Gl9sJ*N?x%QNjN5Y7cYb7%&KznMRW&smO9;ufkP!PrLzTTcZ} zVEsDA%rP@lu^Ce6$ZNgoD}!9O#*Vp_jKPX8t9kks=^*2VUH5)p!sC1KIl02M;hcOZ z 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 I=Y?4Z0NP<`Z~y=R diff --git a/tests/regression_tests/surface_source_write/case-21/results_true.dat b/tests/regression_tests/surface_source_write/case-21/results_true.dat index 7ccce7cc3a..44293cf091 100644 --- a/tests/regression_tests/surface_source_write/case-21/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-21/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.149925E+00 2.542255E-01 +1.266853E+00 4.552028E-02 diff --git a/tests/regression_tests/surface_source_write/case-21/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-21/surface_source_true.h5 index ed87ce849f788a346f99843aa263565fd326040c..4e5dcb446c26e85f1f763b75e4a33e490c1ba01d 100644 GIT binary patch delta 17 YcmaDL@IYXL2s_Io%~KhhCD=U}0X_Q$2mk;8 delta 17 YcmaDL@IYXL2s=yWjEuC+66_v~06KUDng9R* diff --git a/tests/regression_tests/surface_source_write/case-a01/results_true.dat b/tests/regression_tests/surface_source_write/case-a01/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-a01/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-a01/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 index 4a86235679085a07458904653a5b63f162059dea..8dc148ee07eb33d6374387e557b35914f5fa2003 100644 GIT binary patch delta 3450 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 S3!@oVZf5V?%PoXBH~tSAEx4rs delta 3364 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 diff --git a/tests/regression_tests/surface_source_write/case-d01/results_true.dat b/tests/regression_tests/surface_source_write/case-d01/results_true.dat index 7fb415cb15..26b9e30a3b 100644 --- a/tests/regression_tests/surface_source_write/case-d01/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-d01/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.263843E-01 3.193920E-02 +9.288719E-01 6.877101E-03 diff --git a/tests/regression_tests/surface_source_write/case-d01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-d01/surface_source_true.h5 index 8f8cd604dc7d685af08c32e69922749b6ad01654..9a66315ffe508938cf4b2499f980718982314636 100644 GIT binary patch delta 9388 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 delta 9466 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 Hqv8I4L9t>9 delta 18778 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 aQMJeStOfD{|Cz_a|9q$Cvjm9y`~LvP#Sf?e diff --git a/tests/regression_tests/surface_source_write/case-d03/results_true.dat b/tests/regression_tests/surface_source_write/case-d03/results_true.dat index 7fb415cb15..26b9e30a3b 100644 --- a/tests/regression_tests/surface_source_write/case-d03/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-d03/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.263843E-01 3.193920E-02 +9.288719E-01 6.877101E-03 diff --git a/tests/regression_tests/surface_source_write/case-d03/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-d03/surface_source_true.h5 index 8435e8f17f4284ea1916ca71e048265aea650f19..0af7160d4bb91e4efc535bbfa8bb2aa24851db7e 100644 GIT binary patch delta 15119 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 Dx83k^ delta 15115 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%0Aql-Vqu@~HIk$GDEq6hZIj&^OD zR6tdyUnf?+rxx}}G*kAvzHNKl91G%hs8uRBL==nGKJ-vINdn8@WVH6==20;JYem10(15FcnKXt5_inXHg+h||d|LxsRnBu%oGm!GV@TEomzTnqu zv1>wiUNmkS1ou06tgE=X!EYn|*Pglg@Ty|Z*3B96sN-Hfm!Gy)xZlzi$CZ|xl&n7q zP`;wvsPeu=0IBXOO1#m>uk3?sOIsX&8RO?L)xm->XJ&Pri4aA4PdwHawO7Xc$qtt) z1Z&}1L(xx1UyTCcP9#ak;u~l^8=PBthYPLl{h4qf<|>Y*EjJehp1m@>TNLxWx9$`C zL_m_APnk$|%45wnfjqU1!*JcK)p4(9jqvzodL!RgH6YQZ_u8c5X4FrF&$h8H49D)I znX&*6&To4@)PvK(bo&c_6ESm@*`mWQWw7Goo!+tu1@L06XWXZ_aTw`)-Gun@4b;0< zI|FYFAz!>UymQGqf@AS=Gfw}wjgIXJC6zm}5bn(QmJa!_Z}?sA)>%+_JWOO{_A2@^+lkF6!h9|hDUP}{IQIDF2Gs;0Lek(w!gYBci{vQK5Hzxo9 delta 18496 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 delta 17721 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 diff --git a/tests/regression_tests/surface_source_write/case-d07/results_true.dat b/tests/regression_tests/surface_source_write/case-d07/results_true.dat index 63ea1a64d4..5a4ea66898 100644 --- a/tests/regression_tests/surface_source_write/case-d07/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-d07/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.756086E-01 4.639209E-02 +9.947197E-01 3.711779E-02 diff --git a/tests/regression_tests/surface_source_write/case-d07/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-d07/surface_source_true.h5 index 0332f2dcfb100123fe3a4ee3a47f690be2af1bab..7ab2e2c807b2f2080745d6cd48db84e75f9a21b0 100644 GIT binary patch literal 33344 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 diff --git a/tests/regression_tests/surface_source_write/case-d08/results_true.dat b/tests/regression_tests/surface_source_write/case-d08/results_true.dat index 63ea1a64d4..5a4ea66898 100644 --- a/tests/regression_tests/surface_source_write/case-d08/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-d08/results_true.dat @@ -1,2 +1,2 @@ k-combined: -9.756086E-01 4.639209E-02 +9.947197E-01 3.711779E-02 diff --git a/tests/regression_tests/surface_source_write/case-d08/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-d08/surface_source_true.h5 index 2525592045ca7912138b0559d72d9d4eaeda6118..5da7564d1f4cd31322ff9a471a6dea175ba8fd0a 100644 GIT binary patch literal 33344 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 Bgy8@H literal 33344 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 diff --git a/tests/regression_tests/surface_source_write/case-e01/results_true.dat b/tests/regression_tests/surface_source_write/case-e01/results_true.dat index 8979eb5547..d4d1d1e5ad 100644 --- a/tests/regression_tests/surface_source_write/case-e01/results_true.dat +++ b/tests/regression_tests/surface_source_write/case-e01/results_true.dat @@ -1,2 +1,2 @@ k-combined: -5.169123E-02 9.144814E-03 +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/surface_source_write/case-e01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-e01/surface_source_true.h5 index 3047519e8c52b140a4756266192c9d81c7d204fb..0dda15ed2192739435e8f50e126831021d620f53 100644 GIT binary patch delta 16344 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 aVrYY7u{m!7cDBerf3wGbaon^L@c#gi>OkTE delta 16353 zcmb_@cRbbKAHQo|Bda7L**kla^M0FGilQh=lnQAm4Js*0i^kQ^q7;?NNF?f9*%{fJ z?7d|+{I0iq-#(A~`2K!>{rczhI`?><*FNXG&UsTpm?C080akwv^@juz(8*!KjX6^d?R1r6J2CCnvb+d zV$!lK{fyD<3^WG=&B;J>G0@x$^fGeWaw|eLIcqs>`qt&7MG~8C#nR6hEyzHxWT00u z&>{@9C<84*`!jz&y^|4iCi8bm33VF*K+OVT*NJQhK%)d4y$So)u8z@9IhcJ0; zjT&*8WN32Xe@%dhlZZvGyTa=K+xbeIM0iXd6Q@D)uO+buxPgfe1oC?kp+)9SuO$(V zkh9j(-HAHnh4AGydPC%4KH3nH1c|^(zAZr;k|;qUI_|dlLiCp)kMPkvKvQjynfy#f)L|ic88a>ZW23do#?l6wJG0>;$$@x=7q(eAjY7W5 zEn>bbnNS+p`}q0P0C@K>eQ^Dj7C3Z+%{6CE9UUnv)10bPAVZ}^&Pdd`tcc$<4&@E?H-WI?W6jm7`hEO^!s=|D3v)`;HW@I#+5M zUPW$|QzvAQ1>|W1)#XVRqU`9+=ybY^L-6xTej8s|LD^JC}c ztTVMN6w{j5Maln~VT0hI=c=pvAVyvRm@-X+{3;}3k6H1HPhH03Bb+qY(<&r_2sulIHl~$2rc%!@ zWZw^srKw5lNQ74M?RB&lR$OpPqu52 z2%+R>8lu?X<+Q;pI^k zf|4-CY2L}iOZL(NM8|A+oTtD7=afL!(6%BTlyJKI zquFTz2+IsSG-2tDpT*?x&*Dj-8-KUwvj`hyv7ZAmI4@fj^0xsV=HxU9jO&DbZr4pa z+&Y0a(^%ZI$ui{AhAZFiy>r1eZbk#-A#>^gqFUajS%n|HOXl>{ArbenhCD7C_)lUj zqjsu25|v87ud^hmzAlNVU>1b*&B!mgQ8cyFMpxy>e^W3A8P&HU-Z}&t#r~5!G56Ku zde+(Yg)$5T$)B{Oy8nTR*^%$-whV!f`=|8DNv{D1cj#%;*J#v zi=l;SNr0{%TKllGAgeKk8CfJb5Z>k-`&QF&@J;f*&_1Ddu%*c3PNQQ#xbZH7V!HY* z_~^T`W_yDIni2oOw`$Q@G4EN9c?Lyaow`_!=`R|5^+KOsY01ro;qXd$xM{P?XlxO5 zcqgLly1NG!ip%#N%;|z#Z9|K>UL*kKdqy_S$~>rV;w#^@1RdPkVq|{&#rqx~xG!er_r^exVw^m9$YhmoNx4FYj)s z4Z9E7G>;ZVJ2b)O;7WtSFiUj5bI~eoXQBTj+66m=xWu=8rp$mtrpq5(zEK8uq{e4& zuO5ckL7TjCS<69zvf<5cGGz`0HISyujr*sW~_c@>VCv#ftTST=(-|dv`);Ypr_3s-O!r1ix*#$!~@VPKRnt zJ~UmB5#!F9fxFGCGT81ncjDZ2J}nODx9@=-(kla9^fMvRwsMSqtrn*RS(*QZ)oC!+%c_h=4H1~%%2Bmlqd)Pt)76LZUKbMfgzxI8hw!W zpc1^7K2x02o(K9QNnhtSsH4S6zdqGF%i>z!%b*<_jYH)AJ(M2&+}c6Wxi825wfreD+Ck@bMHd;ZQT{RYr=l|67OS{+T8sqC%DS@Jb|awKX+ ze4w9_|3?E`k}(f-C3~4#5m)~>ubRKO5&oa+$!U&NdKCt3xNJkW=XeZG6A%ZrOOKZO z{DeEt6nSqx)C+W_Ox(O%8o=YUzV0guGH86m>+aFTOo`$0G03*{=H4DVeXm@j_bnZ^zj(-;qSym!Pxh$g)^>qMH{`xAi!? zwejq%&cL0O#CG4kZBtN*d2l6b*c@GY%FgGnekibI!2Bc9enGum@Uq9`VF|$=cxl~N zxl`sSx-)M}jKAbkY?xws!teD{efgGh7@YrL%NsQ!()x}ib@_v4aMdMzQ4S@Z^lM~VX zKwzLIX#-(52zh6oe5aa-@|Q7-6XQ&9{;7un>N?#2wp>&;^d~G%9^_s1dJ-n-iJh_+ zYzG>VXX3KD+5s@#u`%puJB;OHofONNLnb@D?aWT03n=yr#}oRQm2N7%3k@}PX>%|n z)$li8QwJWQjZ&z~dtxPwzAHz%v%UuQ#Gsp)PYeQu^)=oXPEH^aD-z#twj@90SUe^R zVa%BYor=Ag{s(+ba9HbFq&A#Y%umf}y=@@tPw}Mj2dCR81?Lb=m=uV;UV~AKA zQ{z{EbzDSk4CUZIB{8PiS)h5_iY?^aJXGF4CvW|80A!U3zwxZA0e=66pyb19c&Sn$ z^Xa?aNRi;25a$jB97UI0Zf8Y|`?=p(cU%^C&fRp0X>Hm|QP(Q1c^G|A#;!f@J6&)} z%gw}_dK+4yxD`P@H>wBnho5{BX5R#+D!6qZN3W#Fzhm-45P6vv5~r>7g8}LEFu%*d`AP z$&KV^o2`iUgGAtYel5Oa?jg5XS`m52?yh*Or-h$`nK8Yw*3N%C>yQRa98!2MPtQS@ z{ktPHHjIEO{(RdupESth^O-kmZ2@q+_)$7WKpyqGVi3qgm4v>1;bf3x(;qf>mXKc% z=|#071|x9|P0LtIe`GoYTM#*;KUbPy0P~fir!NNK#fF>JqF?mU;KbJ(1$&pmcg;c! z>7M2kx_A0)1FT89^gWzw4A|7wDy#4gK$0X(xHw)0S#3@gr@dUCDAj}1E~ zYJt~bq{&$tLi)&tBVRY@7_%Wvx9ztJQ{rI?&$1dXqaiAq?Xo6f9Vp+P*)YVN1K$2k zUOn%jfz~z}Po#gr>H?UxG#F(3C6{c}JGW#lZn=n^fox+CIcIyQrOXrBhUFiqmL35= zi(_rnsnryXJL64mJ2+9PHwBf`J_x>9*ha%;p|#@uVI>M&b3iQUd3556TDtC#@wLP- zEtf)=()G=vD!TyQC7v;O2ZzDs5k({6(sk&w>@luG8|CmVxgloRLnq$3%|D(2nmt<1 z5gJUCZ=ZZe<K>)Uajt;@9g*V$BnZOiuh6U;imDRSFii>4mH z{Jr9Jq_h$$eCg@xH&4uPp3TV@wh8O_7%CK(17PsiA(#q zoZ!4BtByXIy8Ekue<_dJVXIcD`aDw+4WqF1I#XEj^#M4UFj%c z!)*G}%a|xz^piikwpP)-mts3|LQDEa36$rYPbajb3l*2Owy=Y8##nSoXk>$$^069vs?|C>2WpP>#%B5BdmCbvbVZfKt zz%|J|FmdeX9!1ZeP{e9?lDv`*dc!*N!lndCoZsy;vWIR6Olo|(oVS9@MPNdjlIx*hmOgVlM%XMm%|w)Z42DREogZ3Mx15b zV!a4;+tL)6{O!?iT)*vd621NT9l$MvkI78C77`-F&z#-T4N&ghmCIw;QS{oWJBEwv zC6sYwjD2m5PN6?eAcxNmKW+xQL>D8>3~x%X17fBeiP z^4PLg_*b{ij=O^a_Y|nD2#x$h_bQ5=iF344CktiZ z!jlV5wmo2P^8@wu_AO94FjRGC!cTBz`T8e$6Pjodn|jnBRh#q*I0w0Jn-$SN&fi4N zc?;glg6TL~!?L~XTrn_r9@gVx?}r;M%x7l)?1k@EiIsFaw1ZQgdY|6BDg(!bcoRplj#3V8hM(0HcraEgw*>Cb;2$8}*jF}hARrpa9vo@aOuf&Q&I71KNnWSQ@KZM>$N4%3j4L|DEr8B zKvH@W_T*(P7|+kuA*Bw%)ho`efD+889a%(kAtTUtVvNOCak-`{wO#n37HPi~EXVbt z2bg7@+-Y?<6Y^^d|4UM72RA!x&>G=>up!FiPF>qKL|@R-%;Am|UM8`@wD~AD;P-&g zI4o4q7AFidQ8HZ`*%KW`V4*td#mt-s6x>2Yw8b;Q#@~%~9+N9j$A3nx{BZ{Og64uP zXsf&G1amL7z~Wnd8XCDQh{~T!hX%e3fs={mNWWzsIDeeE?MFowNG{)4P@JHPwpmCY zbydRlwwT`&X}V*lwYMkYPwam&2Yg_@&U!(1WU-rrl4=^b$M{((_`arcH2QiU$W@Tb zf0ED!XD*(3A9!5@_0)%g9*erejs;vaJo-&d@bTYjzu*kWy?Qr}hZnaAvVSCGr`Bi_ zkf&Tv-%PLr6^hv|U#<;;PhDT~oL*?5njKpQS+QdQ#;za@mfrNAZq7AXJ_i~i<+cSF zPvPz#=&tHome~i6X`chWX{pfSx?rYVNjp?&)pAwtScy8;wC?vBFvXV;ElimuVlS(N zzYKyq_Ql`8W)`HazU2(}^e`Cm`mpOhOD;6&d%?axqyVHlI;nBFiJ>!}yp+7(FDY|9 zjV-z|hjX?6Ipr77xkBc?Ew9j5XQOPp9<_|^emzi%&`Bf3mV+;4f&yP=1|V4Oc4PJm zCz{8uU?pB?fT#K`ba81d@>syt>8vk~`}GQo#p=Kgz@EOmf1}3`w7f?UTh>%seob@`119nxS}$ z=jy{Qo#5_(V`ThL2Y7MJro2*$g7`Q*mg@OyjpG_I;A+k7jQ%Y(gX2bC+vm9PqidDovEotpIpK2nuSu|>wWI?S%k^-n#`M6ic_aBBs~Zs8 z^|4#LE|TzcA zfB%=^~>aRSGYm?DR|6KpQD3WS`kG*n-^wXFri_>yY0`~Sh_it{Qj&l~BRc%o*6+djWn4m-mgStD&7t5{;?JmB9(lM2#PDjz z5Hi}J)VJiCEWJIRj8QwctrhCm zGF>crk`8z{?iWUh^+VqowxoKtI4G#HD@xqA9fXAJ`m3=@5sfB2in65M4ACp|%NVqo zS?zt$lz#^3JeTQ~H^M9Q6ieqnyT7pHz?&mXZI9>6!0xKj6iwe@=%WLJ_m|&7VpmP| z42*8aBi#w(EDMy7ZAK$ z9d;_V0k(ZGHqJ5V0CI8Kk*KE&a>UFpq*&w%UM-~Gr_$j!9uiVg4qx&VzfQpfPSGK7 zw@p?Qwlu)O=xec-sl9L=>`nq9EkHzmKKx|UFGR~~j4AUqz!zExIv}mx@cem%Qw=L+ zk>o&jNNKQ8APeGp;c50A=Wamh3wxN!N7X~E!^^>IE#UF$h+KZxIUv#<9dL6X4fk+H zJzNvK?eW%$oxg&7Y(TEC2+IMx+Go%MPt{!aM_NoE| zYM`l~Qa|G!F3!O3i*CIu*N$a@Egz+x>aD;}Rg}l)?yQsR>VZ9(bFm__jj(xtiLJ@L zR&ch8zv9@W0CKv))pO6~M>wt%11`%5r<}&_LOgOd+D!R=G#UgOx;GX~3g{ll6suiirm)L#Y<1&izzrO9P~|%~O_v|Be@;{jj3*!| zU2Uz8f7ionZx5a~if#kK_4)7nw)KFc{TakU@fz?|^2rph;UpfB+*sb^?w&PqdHV^j z|C=$>9@Pg;H`U6_Q%fDj7X*$PolFJ8ZkB#b-u0k~Ivb9yZ-suL284L07I<;ZlkQdQJwVxKzT;F{ zD~Rw($=^;W#l4DAn^%}RDs*bcprm*`r4LNvTIJHs{e03X3LJX;f?q1I8(uBxsR{bh z4I-bvK3Lx1hkSJ$s>t8sk4J$jjbHj|9P9YX(5QI~x_ro9nKDO2XnZ5Qoq;|p6Cc8i z))g=NcTsOW(}cgdy4J&r8*=f7jz@wzf%Jrdi+^!kMk}4jAW)J+mJVDEKZRTU(|VxO zl^@SLm$ifV%Ym}YiQOQ2VsJ;FP$M{dvD{)A`T+c$xt9jrx)$`Xb)k~Vs0Ze?|Mt5^ z{)SJ})gA^-F0INNzkS>F+oA_L$2KMUI6jBI0hcHl!(E_VSL2}e-iyHYZEWY?Gc14{ z%^~D5Wx)@(=9GC={19>#o%2h1jVv1nI9rUy2{ufzCcLa)qF%u_iC=(^;>E(&P7e?To zbmv_6lq{&?t!LlwkOB8Q@hcyQcnn_NOzC=7!V1Wve1iW|!-j_0!O%X99$ys6pO@~N zTxO!!S@#4<^3=c(8QXH7)E=O;i@)SBb*=IUvf(K|aSP}MrJhY$$^L%_mgj5U`z8Wk z`YBI6V(&`#u~4!{q_3Wf=>+V%?-h&s^}&Bt_2uKzpm zm-YJl493QBj>m=*9Z$rwP!c5*17a%&q4q@U^hc*UFvS19w!G*&F!pk{wHSR59F8B6 zI3D-^0RF}_pj?)`bfv=Tx`At}3JZlt)6aDL$`8n@rr95vJq*8z{Sj;Mf*?Izz)a2h z85rCt{9@+}H^wpMY>Zw!GFzj%(g(j=rg%;lOh2W}!lWAkpSgLu;FymM^J&&z$n@e< zYAk0W=s(S~*;J1my)#vJa|B`sUTjxEeeT00tgB|fsix*P2(XdW8e{4L0WH!W4^%aR zd-fSTKCAjbL>jB4q*D|8k`sP4t6U#d{3_4qc}sO6g<&9USR(v;O>0a+}%Axt;l!2SU30Pc`vvy%|E&8ZW)M)oD3j{=%NwJ+SjzU zE~S6Q^CrKMl$b`<3>Y+J@{^XvFFPsI5@qQI-K`+X@IdH&{!$n&GjdRHO+P&8795;DqfSwu$lqxM^=(d17K6@Ntxl z(95obu1$3uH66z2)8m%AK15)TQ82@f>DMLyotp-#G6|P6F@K z(0=A#X=!1FWBiUGYR*vXX2ZXse}AKqVv6``e0sO(Vv?UO>kPyw$EmtIcgf@npGB! zRVXoDq%o9t9umH%a=M}CQ{R>2sfhr|Cr%&M8-^b$cJ?P^=E0=g>XmOY%fa`XO+mvo z3aG4*8rRJU$lestLm?_Bjp}x7*^U&LAleyCOTF|xcb9{VH4-8}`39O81 zgW0S**IJ+7f@)r+-1)+Xm6|bL7VoaK%w5ytj}1W!cK)nGMRfq4iVr|2ouDq+Y>0hF zFASR1y-{@J0ZcOLLGQmOq0yJQtulqgaF53xr|M;g)OlIntphKULi)>!=D_2q)pAnS z!(flM`RJYHmGETBgt$%(1Q#Nw`Hs9%ML&_B{n#}iiF>>ugYA!fD4jRo`U@;}b5Qt2 zv~KZnOabjz2MppQU&9X;-UV6*`{4P)zCLxg4zSY4s@yEw5PiSR>f=2d^Mxf3lhFdx zcZ;~PC!0q<+_$ouO9DA=Z@zNlMVBVQSczx&se>x9vTHc>;E^?2Mt9g-n$bU0kZDH zm313*Q1>k+2ZS_K68T9+hoaPu^hln<7s44$= z3pDkcj^yd70xI86NVojy0|xQlqe*(Q=y_40q+XDNm-ZLFDOjbq`O#MP=T-l}(Vr(m zERs8+%XIIrtl?(RvBNGkZmtiYsy5kyuGH(+xL^Igu1e@Y9MR?0B6pYt7QQrCrT1XP z2aWd?fgp|ebg-R3-S}od-2Q8L7^s`oUjLc%3S=j<5p-6Sfm61fDl1M~q8tuFvbPME zWMn*|dW|Xg=d&%z_B}bzQrYt#4bIM3?8rwir<}BK?SpJ?zsHURH02n)U!O=V7PdeRY8AeIsd)_y`PFv`h~Z zEd&bE96Za`P@v22i+N8(Wzhbb6Llg~6#5Z$H3N5BTQ~%NCiK%SN)d_H6zz$bg50{R zECm#+fZGWNoj?AAkURWRLgSih@agRaQRiFhfOrw(K;H!|yk-=lyyT zaTjmBmYWBHEDjNu=Q`k{S8KKrcQt{SyEB*8y&D7q#ecZYoWBnx&uJxnIxT^^x-WbC z$y^(E-gOKjwgyF*jp_FQM=#R77k8I7I24v$sfiUGAaj}{!l14WvTj=8c)Pj_s(!lu z{(Jx%s=BLV#n}=={1mQ^1-|0@bgO?}WAGYr^v1~AUm%O^(xwo;VOXXt&mY`M0c!?} zx%kj3Fgo}*fX~eg?N-*@FY+Es`q+|0(=^T_Z%Wff6`7?v)5-d<@FzYa!0mQ-aK-I< zkg@4g%zmXl(4Z@KLsG5FZY1 zc6+wiMl1J~N(f1YM-do6m74H5r6xv#u>>C8Fh)vZwQt{#xIgnq`(+ygu!$!&)= z4S^Hpg+jTC2I!`H8bi9&hw}6{p9GA%^6H%0ugy%92`OqiS7b%@h998JO?QE5QM1sf zw_Q-I&j0d}!7}hn-^M+Tpo_YHJoNPhn=QkjpDh;S+3oq{AYrZM60S$Q z|D$bdS&-J$kKQ5f-(kU6^Xg`kHsI$LlTszs5B7?GZVn}HM7LM0tEpSW#nR{s@|JVL zy2o=Q-i>!cvmnU(ZW#eNpcf85BzM5S#xCwItX=R1J=P;@2aTqN80}YNc!x zPga7_->GyMw)G=RmRv7XFZ-GO^h+l^BRS)Nx+7?^T0)02SqG02>bF+Z4IxYL<X@HuQ+{L-|>rYAX3)Vmp&``Q49ZBa<(zw>;(ebRG$1zX@$N>fbU8Laa1Q- zQZeg@KE5O=GDz*@9MrO>><{Raj~mP;E_u>OO7qlPCCf;{CpD7R1&S(Q9lBA92Iv8ELTU@ zetUh}l$tf^-nx+im-Mgtl$t9GvO3)*#p5hHviLIx(ju>1`X?g`44EGryZ^cyIB_VF zl;yjD#7Fffo2xBR_UNE;3F;Pwp6{Hne5ZM%ZU2E30#X7~^=2;-kyyW-=YCzQ1kX7F z9(Q|pfNw70Cg0EWfTn@F64%#QqB}!V zFnQy)Cg3Z)+`B^8KmRPayP*xenoE^hrC#=-h!T2w)_3bFKW$uU`g;|+@J2#>r=ChM zBSu?ZH|9&>SFgxt-qh_;Qmw%M$~_NtwLWlCalg1Vr3O^}UMVg+r+`LK!hLSITjEwS zr32DhP1e(i+e6rqZ+dojnz`92i`^W^E+vFlsR_crXJ@AkmD-`$?j2{7xcY&~Y&4Iu ztuA_zTxj-#Y9+ch-Lcr`>3ZAM#aactXEUw}g-pN}>SpuJkzpA4@0V`vr%HGrVCMHS z?FgW3cR;}@Z3NLL*z$`nCQ>XLi(@u1rdUqy=OiE|JCm<+yq*O`L(_A0Llt0pdeCri zya#T&otY;!-wup+w6a!;XrdnKO6-S(v3KAYiZO=b=b7T-BR>f{HK&LiI3EH*-f#@M{Q*?@-JF7_L17ZiH*`N7MPG3)?{V0wwk6CeWl2ZRXbh7Us(&xLb^j0M{TJg|YCb z;6UuO{4&=`4#EQWbtPXit!qoKjEBBU{uGi zVrN1F;8UITA)M`lNVeA1*&0n0vB}gtO+5zD3w*@?75;}>~%n37_mTc7j$d>-Hac;D~Wb>E)X^Lou|9ZEPOC7dyZpSbKUsc6R=VPYtO>1Ku!`7Wyn z^Iz&eHL?_&6@isp$|kyOUM5SjkrqVk^_r#Em~2WXn=Q!;e@0}!^c^#c>ODC_VlQ+=G4s^03o$RzEFVHRFBoT(mVO$Gz8Of!bR{zLMbTSK_ zOjX-|e9uNFFQ=2)m*j=+xp_&1WO5GgLib!`9$u?|WIj5XpH3E_lZEJH5jt6PNnYsQ zUVudO<(&RpYCcBhVi&+nCPsD;u=@X6CH`xxAzqYRaudNFIwN;Vq zD`G`3BBLUU4(uaBS`e|}xGlZLWDh!dGo9>BC;KePiyk9NB7Qlau!WObf-J!$u+V6* zio_hMT6DLKe4kZlp(%D1iP%(5OfWpBfa{irY5-xfl$bg-!W_gF`R)}X5tm0^c>VPs zBZyP|RERtxra}Dr-TO-I!kYzLM4Uv(Bwr9;{Ojjb@gjMYCUQ%Vh^Hi8#9eUD$f}B1cIsev%?dBAQ8 zMp%kOe4g~Qc-~v^#!zab#CO-DZU1uYp*Gea9D!#nFuz*p!d{w0yqA}@I_BTTbZX

g`fA(nU`2k^cyvPnF!sJ$YbwUT3XZ1qw=9q;^t2KzBTMVoO*|?VwZ?B%uz^#iP z60i?L6*LGvwcuI~^UHm3Rl|)o?;uJ>8 zjF)^{SdBz1&pUcCF<)b;F_hYPt6+WJq^0aqg!NDxH8$?eucN9M4?BBxs&9Ap3e-Cy z^ZjB&MDZa;X#heIxm073z=#Hkctsh_W_|23KM-uhmgF2wE8^W}rWX>t%y9_rMF<9R zjyfQ`B@<{6l2nLG^7cK0KDzkFyo(<*ku|jdaYAgc+>Xa>NmG$pBw`~;J#Y0loB2Ok z)bl1yD`vkKmWw}e?=rxmk6T-VP)kO&7d)67Ya{7s5RZL^2RI5WaNY#6ueKF2>T~=i zVPiYoejMZ&9V=ppgzLEHjAY8R(G+H_2goi~5Y!BN5%rLXqC-)$=1;NC2$*B%<|GwI7Qa3>z-n zyj$r{`=1&L5B~+iq7R5|k^K$p6x3Ttx4J>(6T^2tDxKi0Gk?JMupE#aUEts)wHo~% z9bqH(PkLI8q3mONb>~9=1kgX^Oq%`s2kLGdvyAKP1*R$w$;VRL08gAnRmH<(&?XrB zuabIObKVzw3)o)QS-T!iTyKWVcKL{#YS0FKPzQD{Bv^P;~1>S_4T^GIUk%G-fO*e>kw2aI#nBLS^`%{en04$ zX^M^;I^R7Ptbr#yS#pTs{IoB}aKTmN$gPG}M9T>uX>~6poTnn$+Q^DPxuqb@A|MV?WR$I3M^frH6_r zk}G#es^AW-N*>)OtY>lhx3$j*SUJjYB(i=Id)B>~AZVi#{~oc&z+U|HeczJ<;M9f0BTtBpV6>+KG_O=cZHedk6HV3TqXNUVro&y$ z+|by2dk)9lpORni-&_Y)c3T`gceoSoFsrataq0#~HFIthoX7zt#=Tx4Uo6lqA#$}7 z0`hna+F=fserd&l)x(2O%5-Di=!Q`ca6cebGp!HiWHvI~a!H3aJR2pYJX*oHiuIPn z4_0X6nSwX&BXaY)ScoHvDT%l$u+YRNoo8MZn15{|D*`J5iM$UiMqnf$5kFPjZWF$Y zWq9l(Uo1@YTn_czxIGKr<}^~w%xB^C%ehYuax?++_2X-+qzAy+YsEJ5r{BURyN5Re z_sgI!C)!mM{s|Ly48^@gWVg_nY2dlhGh?6QPjJ`>xKEP%ft%}Qrrov8pgaG>%Qo>3 zQ1s{PDcf>=w3}mQ&7FTx_%W1-XWFmNv@sx``gZZ#>Xd-YidWVful9l*B=Fq!tvS#_ zuc*G_QyW~l(YxqYo;-RfaNyqb0t#j+0Xj=Ddfm}{_UjLBDF()p%CCZPu$f!X@0?8r zIKTOVNG5AH0N#5}Fi&^F%2T(m+FsN`i$sgEdqq)r}qyu_WMo$&Dw8J%Fx)}XAs7=*nQqO(@Rq# zPVqPKRy7XMhJ#$p7dmXkQ4D5Mpb;7A1L7HF6Ck+-^y+4Yik6zAo1bja-LHt16->#j z)f-g zIO>p{iu5+eVz6~brq1uS95|)&iDz0%a+s8`UdFx5 zJ*N)<`{ONJOwtIHX+fi$kimZ7>U6bW`>Sv8MNh)cO-v0?;i!!C#e-`@0$htn0N(x z6S{y$W!8^t8@k|d!$qU8QUlbeD>g5fD298mKY7zSD*_`qZruVUMl5l^d^7t#t(AbN z$@GqQ`*(ou5ZhSqy@T-lGL~)8tkuA6_1;avZJ%M8`DNXg!d9q#!s^&8sy9&+H^x?s zj_o+RtxQD45NvMO-LqjS-VnF18`8YU2{0=BG^%yG7|PTqNHMbxgM#I^#KTu?KuaV# z-Vc3KnpZ7`tFef?Z1I_}@yRRexH8<2a>I7Lb^SUGa<%ICCa5zQt9sY`;3qwRp%FeX z)@lXUqfB!h$^}uOk+cs5_J(*F)TG0`lgd)y!#M&Mnpr9LH+x;mYZ-*>`mUfoFif zcJtngwY~7R+1ixo?``nnBlKj}42s%%cFO3mY0l42Fuq!gxU|Q6zPs8fgbA4ITjQ=p zPN(svob6n`W8PAE!xpLf7QLaP z2{)J!!Hzht){$DxSZ!NOY760aEnGi!?U1%DD-8=15L(S7@JoRaP?FroZeq?B3sP? zm33k-x8Es?qnMCUM?nL`OgnV0>q#CJCJh-1A1y_K~ z$!9!^>}YxCd}P_!#ez|A=8(s=pH2j1;WaC=!gh=`^;#>iVPgarld8cdX@z~cv)$n2 zEhd+dD`x1;Ku?u>>6n$UqM%KU9qO8JHlMRb@()aNQTS{&@)t&Ze38xM*akc7U2-mE zm%zq7nbrpzd!Xk*2KO9N8}fNdUxWRgHJ)vy7TM7rlH|UNOt0H%wxFmYEzkC@>;|EQ z?T2_ibpRdPz@oDQrBKN)c{kV7E_i)ebkRhZB3j5u(!Xb5gl8{38sOq{@^o**t{-JI zT;!ItB=gnX)zE^!eh(9Dhw>|R5Z|~SKzvE8+c};K&15d81^bz!{*QNN6ZNrO49tf% z(BYop3VwW`uYrb3;eL|)BI(2wAf7ABhH_nSQlj*rgkU>l-FkDnm#GeT9(#DAD_6?EAr<3Xs6+} zV{kyc^3-5)53FJ4)05Qe0M9c^FAT;CpxbX=x*;8e?dxEcGbNAOSP?t=iD1Vm34EF6 zN7vgb6R8?4)q2{#%9oxt_+T#hy;*uaxP92VA|k&Np061a^X;4tK8}Q-#r+IY47ChpGsx=rdD}F@4cuJM{?&y${Q{)zuBkBbs~u zkJ= z1r)@y`L)B+9=Y>Md>>%&yXL_-^Il-#puFGDsRx;hJ^wVp9^exxY;#&atbvgsfukRo zZ~K1DYiBn^joX!qUk-t+U=_WW8%tqP*^%K*b!o6AnmwrKClfkTB9$O%ErS<;HRMz) zVRGtvb)xILK==D6wQ=5CXoMG^-ia!@Z;D#soYxH<<`)crs*B)9tMw!Ph&I zb#E>3tLV686WWM$1Q!1j3aIxuMQpkXo%0%)?u?=mu<`eU1K03 z_gf6pTodGCy6ln!`oV0Y?%f%IS^zxMbS_v|!JVRw-}g2}AqTX-KN48KbnGI6nS5JB z;juf(lfdi&3zzg1kur5tTV;PnEwG9rFoK>Ako4GLokm0l%+8K!NsW?0qr>^{ZV+EH zuR6#14I3cb_&|+n)+iIQt7~7+&(b}b>r8R@33kHi26l9 z3ao;+plI^7s9qTGOKMv+uK>CyIddvFzzm;}7?K@atcVAnhM3B`JK))Y3Bx|Sn)#eT zJ_BWEzk&a$OGL_@9;XoZksg3>_!rx~{Q)gkev{)2Y=cS@*?-xcz97n5uIh`{IpWw- z7|Q;jN^`q_TKH-9VXNlv-$3PgccYbgFO=A^e$7Z;8!W!_;z|N*KGaF|)-CUGM6dob z9`^`Xjc06?MfK6@iLcnz9f%*1B0EyC#^V?6dH*N7ivxe%%cGod50S!*YpNX)vMGNG z#)ST@3SuY)7tV-e?@I3gM5#g11C6avzxjBta!d<+WhHzm`Q#Lmb?9f5{&x}{7v^-v zT@YC*s{E#xt43y^%FSon{52SmQDpDlrk*A^5YJfI{Hz0-xMbU}7;XdMGHJo#vpT58 zZNiQlO~&}BWfpM>i_gn>$+q{uGE#PQN0(Xh;Z>CKf7v_zW5&y4BNq6m4d+k0^m;Os z_ztm94p**->y>7rJhW*$RoUDHG<~;pvQmpwkMzU78SZxYwaGOm#d{UHTW?sh&18Ny*FH80g$+Ij z2A>$B;UX@&feE4cJus_GNcJbC0p1P}5*7<@0HV*X8okQ#NBYlf5_GP=hEMP|((#>J z#mlUh$$~62vm%JqyEOghui-;3H@2{vW?(Nb?dt!f5A3!+Dj8(?9sa$ysgdclC0cW= zzI%SVnN}J_7jYT?1D_RnzPX=lxnkaJnH4S`_Oy(al zqqu(S9t?F{Rp|m-3cp*JPSrxkuOALX@U{ct*AH&Fs9!<)poINe&i#0?M6txQ>qO4f ziLe=HA$7&^_%bHsNtC}-`R{Icx~L>8F})oc=eQ2Fj1~j6!oO|a`NC*>GuKvh7&}qH z*cs8WOOiGtX@2_&TKaZ6-@kMjEWBn#f(u^iI9Rm-!e_@s`S|DXlUe7f5Q9F@6wKy! zXq^&zWA&d;J8oOz)^}LMrFj(%N5Z=6h7TWKvFU+YV2Z@{)c@HmgMhh%&KO`DWA_BTG| zT2m)NaY4^pu69GILl$wN>x*IXTaWFvd} zy2blyRL%VfFz8XVEN@^8TtxcZB!2aS5a%I&vvY-DTa7X6q-X;WF10<%HO7Ws(tX5w zwhzHa?MS1w_&if|;)0vUC>%dIY?CJX6KD64JKp^PQx&`tbaBRnSPEt0xxE@n24F!! zUjzRQW#rHFw!aPh_vYDQqgGhNqn-R6@tLV+4j6)joC3W7_c0t7vB=D{ecB5i+TFQP z^r8jo65{$(O3J{QWm_l0{w9FsNl7n`+T{FCT+S;y4)Z3C!sh}*f45U}(?YkbNN0hE z?dBDk@P}~KU!zAIKyA=QcDG>0^O+m$8-}bbE`(APD^TvAMRQRFX;;n}0@wL}3wmU6F`hWT)0|TqU zmqH!0rJeP6J(p^->N9|IY07Scf=W2xR5Dy3I0TS6a>DmZN8lIr))(x-E77^_=^ob> zChgb~feB;xX>-$!6Wf_6Bsr1#ZPl${^P@e*x4DJ^FaOb%F0Nmpte5dmBqRrDHYQhy zJXAwF6fFupl_zjpv(nkx?0fNc?iEX0Q!mIg3nfD0KXOWRrW2o$C8+|M2*d0IlK0oGi1X8 zP)P;l{V_K{Mymjq)SqFP{pH&pKHo^dE85IWv?rmTo^Ma7TwsTJBK>Jc!{rNptL92^ z4}5E!u4oqW8{Cz5P<2c#1B0n=H1?#lLBd|Oa2pfq67+1nhG?lAsy+HrQIpD-wjn1% z$9MmnN%@1z`82+WskOi5O%-ugbyFmeza+_LiUk$@5qveN2td7&2S zj=HECf7QmTkOUp>*;JN2Z_S!<+%JiKW=Hpr1Jf6=q|YLGK;W7Gjxl*`^zlrUq!xmW8nZtAoN1$5 zoS~F@BW`_)RZQ%mPh&8b@nzoJzFP3izh(cgUjy*P-Ah6;zdpghu1Y4J2?x|@>!{cq z!!YjiDp*7staDO$Zuk--Va*ij~>34>tjgy1#FnF`Pyc`qb_vlOf>G${F) zA&dUfeNp7aIE+W64o!`V&rgC1^)`V&;l02iVt~j9&XP|%QLsI)9C9-BqFHY`L6k3- zijzwxToL|!W#}~vbZe{dH&5y%Kw9?IrNiZ%+a&Sk`xMQGD3SL?0`h$(p`X=D<)02M z@ay9@j03@au@SDoZv`)H zEvBE8S^tB38W?j9>-t7Cf#b_A6XK0p;nlH0>jI-LP^9p>v%myJpFK$yJo69VHFUVI zc>}W}l15>V#IZ1W*Pl4w9?i+}WtNrj_)qbJcJK`x5G2}c;2(mAuhq2deQJSTetqJq z`~u&_Et~m6qjh!9g8~x4c`_; zjY7y{^_ioBy$OC>bs;>0WQtBW@o&Dk0oz2!hDajws0i!5k`wRXXF^(H_sN{UH3({C zVNBh-LHP0wBZ|DQ2B9u`@yOvjut=4Ioj(FWkHoKvG{3JgpDi$u`Ma}1`j^bThd=K7 z33wxxJ$ksh7qFH+n-jDf21$y4m_(KHLC~R>YitxU;9c7%kEX85qXQ0?nX@VX`*dw) zrlN6f%}+QznG8;FW`G4Fvr@hn*{dU=X>j28wS5*S1@zesF{RxfhAHC`ETdCA=w2D4 z_6-l$;!#4sd3f5XIkeKX2LybyU~0ZMK{EiN9+Ccof3_ZMPS`qHr`ZbolAdW%_`1P; zW4q|VWIMF!fK|ttA8Pnq!UY@knWJi`?5Te6_9iPsj7~E!QgoBF>>UOp+f&aD`rL&j zcN^Q{3sS+8pmE{qCI?i#)&ASLOul*dz;x$|p}47VPgWY$05z^>YYaN4;iS!px(i#n z!42CRrT!{;;BYvxMp(TQj$b(>+ahj(8nL9lyXY!~qj+E_A=i)TfGGxqBIehwS^f$> zYU4`~I6Vl`_;2+VY5V|oR_C+bjmsfXxY4XIejVDaHL?4pxh(FgK6G)Ue<9fYwmN>d zgYxvp=*-jL5!fDmv*Px-X6Si@O{VHwKQun_P*?n@BxBP*-D_#k$>FfiP5}iSQvu0o> z&t*75q-N2&k%Hn`IW(Pd#6sYotglMPPBCteOaAJ9m;eXO*1M(_2H5GozgonKl-pw02pwdli&cl+tXk|3doZ~-Ply+1~gC{il9oe<66vpkY z=IFB>!>z?cd6&_DJ`cXVGj-bbUJ0l~#lPC^9)dm-hqv?ZT!jXfla;n)89nW zbMQQ&`@J0JJ5yB0%b__5(`$bWU70F^*T`|bZq3gl=C$^yfj;IEebf3BN*ZtC@0sP zPrW6d0^4(q{j!)_AWzlwk@d0ET^FOHA~T7i=x?qweS!b@JpFC}<2&{rTidfB^Ou!l zjAxl~-jbJ>>v$Q*18+9V3>%X^@bW0vrV;Zt$RVh5cIQqMoi#Jg+(N~rc@_P24wa(o z%>wGJIA38KLWXD)ks_EKKEbP&2%E1>!eYG|7&INX_j%+X-0CTidX&!rO|S{=VOZdc zS!pF^rM1xpSigfYlV*v{@JY9S`PK^9^vIk=>g7N zZV@D*Dj2ojG0SgdD^S-b{>rJ6L?5h)R2ZO+k($G?TSzPm&Vv6}`n7g8axag@j#ASx zZR0K32iUKYi~P6Mf#PF%3IhZE@Fu&WMd*hT&{tYvc+4j-f9T!7FzKk$lnxQTj&=d zMkP$U6+v6B)8IFuiRE$vUAVEcs~HL!)(${E5ipUs<_o-&Jy(2eOCJo5s%AzETA{)+ z>!Ewh%Ta~TbIE)DF}5hC&iGeVfwtdAVM)W&zwukk!Bg?~6)pw+pkd9#PVcWZ5IM)C z?^ah1KB_WDI2^M^|L(u5d&n*lFJ?*@3Xe8SaQClgoMic!)Y*Q}wQHKm zU%dhrMLLZIMODMxBe^xXZ5C+rWF7CO1r#jpDANYF_^iCd!Ya_TbQamx3_6*w{Q=zf z%VcF5zJLO>@_bTvH;DIQ?Sm&eKyY}@&UL?5qX)8TwM?0Y@r4`x8Ry#yK|Kwm6AEv5 zWojmZpIuS5`ZkDs5-Eexm$r@&<37WlPFw!NwnH%b$1sQOhyZH$^N^z9KWQDI@y z&;=fB$o{5VLOoLu>sOcZXaR%cZ&?N2z|iQVzV(D3VDgUo?@JRyfVrJ>Q{MwQbj<9@Cae9}9bU}O zyyx2soc<>+H0f}!+i&GMd3h2( znEn1@uhJ}zTf*M$!6x1Y$A2^Mcpof-Ljg%)qwjj4bVfl^AaM7Qu{?WPrd zTzJVRW({qd29&nyBhoI^8y_n1Svm*$U`l7v{oj-2(9Z8?$eZ7d;QYNy>;J@zBfs7_ z=MA|nZJo%{@qPP6S&Wj|LF0+M4G~p(Zc3z>YGfK)QzxtB#@SJo3;jUScGIoipYh;w zv`Toy9XS+LeD)&5Y-wXh8Y`p+Bzr3>PfkLi>EwEr$`-EkdnYvR zEK>DQjRm9WyHoQ2Od*?%$jK|HhgP)hw`Fwf{DeB}dRfY8>?nhr!*8xOe*}XaJB5C` zzJZ)Ee7Z+(55wLSOf#_+IdGe?j&nV`F8cM3|H{S9LCmYz7IA5ZDvsHTE0iVrXt;g%cg)+Y`v_P=LcY)Uc=gxOg+|3eQA?*uo+(IEUt(yl0mQT5g634(!jH=1sz{m z=4L(FgI~cyGb_bRbtI`cjghkAgA(Q0SUcpC3*C{XQ3bnqMQ!xj)dd?|KOYzO*FeRO z$;aJXs8kqV`ddk+y9Kro{!GI|K0CgyR%StH_+M?(8Us#N08zENIYG`|a6k0#%NFid z=(1@F>}sRdqn0!)>CTJ4!7{v9aFEZOZS^i!g^2# z>z{DvGY?{tOE>iW}2B z6K_`lVtgK7+#JtrEfXDJwfSepD?2379ceGrzfg@t zb5<@oaw5Cy``1$UDHfVpDbM3HrS^<7B6UUEHcpqcgOaf8wTC)8VR2xU#FeKt;C3~~ zsvm#r5znMj$5m=eJK4h61f%!YoSEUNQ5ZR8?>TXx1q4Q|B$$l1L51XJ)t%*Wz*$)K z*1)G;*l}C=v|55J%74WaMLn@;3g$xeKMKj3m|DHJW+~zSzTMdE+1CLKP5q)0LP~7F|uLPwQUVK9Ip9EJPCkC#G$IogI zgt=Swv1cB<-_c_G(WeRSlxur`_E|r0K2`29UDJe^hijcWvkUw66vmhS45)AI;c|IS zX3B}$fc_wtCD$~1aXoz1o-XJqvu1?B{Ts+IeO$ISuM>u{+>G9tz5)Q4S(A2HfZj!QTWs# z9~yBh+Leu(`2W`~Vmnu#8~t%#v&0(l;Ky_OXt7hG@^^oVIHlB1fvFs{(3oeD-Pe4K(d!v-TGAg3I5K= zrd+P80wR0HmOl<31fo`l59yrHMm>ves#Z`73T>igNQc|Cdv;(|RvnEmrC8^9lvHRR zeA~X}{2kFk81>`KwHFt9;7{Q#;~zuXq2bX`;mp&z=r~83*X%#%E<`ecS-_AL@trO< zES@AFCC}E5@4D9qoU;VV&C7d$wuS0M&{QjE3$|w(+*Jm)DAauNE0IOh7)|b{N1*ub z4(&oXUBN>JGu4)TpKJx<-=rzYe&evUum8uEszLC|Zy?Ctvk+3qTI(Ab%Ar8v>Lb2c aVrYY7u{m!7cDBerf3wGbaon^L@c#hNxIp6o delta 16353 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 TJDVPnIAXpS-rknc>Fxgq)!}e; literal 33344 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

l11eivG9^A2FF@o(kK8lbM?n}(nd+t7C#e>`?H zC6C)gdGK=|xNVf6k)K$De&^fTD6DwFa;qE2&u7ybxseT<>-PJ~OtzUXh^T>XbIBxI74S-f2E^v>Q+dKd( z-#@rNdTB^j%8i$t=S}3$pUa_fFekOBW2V6=uy}!eJX0wPR=U(7 z-GrqAvaX#KlQAn0?px1zPh6=DK8ntz%zLklo>gGUN;pEc1HA7~%7f?O-XZe%u0Ozo*!suD$6BDRzI&-Os)jl?)epW= zAajWQhgQ*4brXM0B%Lphy-S|1Um@@I;ti|1A@|)`%!c%ldU<||3O|?Dx6d>(8*WqOWqHTV=3xy;CZ86jVurT+b7$HKF`5_`Nw|s zCnLDt5RY-ogE`f+u!SD1bE?i(0mBEu@)5VH!NR)jch+;&L*ETsZ=K&Ijb366otJAp zb3et;mrOSht=${GHkjXWR}q0>(fFnYN|~IQ2FaS-E9c_x}14*rw?z z_1rEB$ff2O)h%oXo<3{uJkAtEAAkAf(63CM{}BBFeofv_r(&0SeRb0`8L_nrx=$i| zi{LBIGqWl-cfcFT`Jh@L8Jz8i@!WGa8zu~T9*`UCN028cn+1oINp?V#ho7u4+8q@u zi7rN4EcyV0Yowc!Tou%aKSXt(h}%aSBCI7>rGYt>#|0UmPt5=8Uwkt9)`+BzTOMvS zA?J@0IrzU%f$Ob9HMHmZi3T90J;=TA(nS8|KQAgGAE_vFtM3g+IWAM#ZJ7#&+HWVu z?d$}WT8|d08uTK_je-4dT1`mu;JTW$H~f4FSu83N+s@z9HnINcka^L@?#mc>*_ib@ z+^G{BU1{I+=*bs&@`H#?^>`dG`D`|nsW=-ov*9{p`C#V!H$3kNkAXg9AK=U0HogCY z%<1VCe%Cn);+gElTQ}vwRK3W`+wyH7*3UF4+PVPTDhl8%PZmS>MO>C*yGV}Th~v+0 zvLF;@CU5F&CPqwkyPK#R7b7zDHWlfIF&8u@^8D|+RPs}BorJmj|~wGUAq`g5W9?{BFuj6gZNL9d#G^VNu9$kVCl znUv551WJRnm@Wl?TgJBTL#$;$&y;OVjVw?lj4xaTEwQ7Pa-G};$tU1xtWt+FkYLL%o5&bC6 z#O<1|`jN3jei4lPaNm*7@b@}}&%47F(Zc0$SZZC|ouLxom1ckZ7;iHaI(nINEWsaP z1)N^|ZYN24BXa1^N#J^06Y|wtazO(~q(q;UIm3cgItU!fJU4NUp!(y^c$2rl$vyL8 z0bdfB_h8)m!2A~omUr^Uu=P8|47r?AMd+3C+7vGp5-?N7n!YiZCu5S8N01^ z+PSU`AmV1ej`d}*)3x|03)e(`-0}?^xtuM?Xg@{MD2F`$5IMp$4qiCizU8~mb2@&* zGPjn#mv}!4mWfFK_7kxncbA*=tNv_Q&A_^X9}xQw-u}2ec)f#x0}F=@`r+ly^RdB;s^O*TOII%1wS%Z#2lMwb zyn+L_zDu7dErLud9+YH7uR)U^-@i5cEqR@fs5g8)jE;jjGOoN3S;>Ow$aZcOIMNMI z^hc*3C}@MthxXQnX6HkPeH8*#!r8F)e)oY+e}FD)LNa(Zk>}fZn@{Qu*B8!NaOwJm zScB>F=-5|?2DNql1krQ#mKR@3g=pAuYpPl&%*ruecKOr?sM+yqVPmcw>Ma%akohoq z9hTTW!~b=-c=JgcN z!aP`ZTCW_J2gCZp`^%LaL03V$$jjm{V8y9JjBdf5P;p}8r2m2(TDrw5?4<~KzCh%N z;{aNDCZaV0p;&S}6o$Tpo@z5LHUfGpNxulVi;;Mmynf?c2iyzKWiRID;V zZ&Me~MeG57{;! edE5?HrP?A#ixAW#=z`r^N%DD3qCE8bS^o!D&vB6e diff --git a/tests/regression_tests/surface_tally/results_true.dat b/tests/regression_tests/surface_tally/results_true.dat index 8b27fa1928..70d5cad2c6 100644 --- a/tests/regression_tests/surface_tally/results_true.dat +++ b/tests/regression_tests/surface_tally/results_true.dat @@ -1,52 +1,52 @@ mean,std. dev. -2.1200000e-02,1.8366636e-03 -7.4900000e-02,2.2083176e-03 -1.6220000e-01,2.8079253e-03 -6.4010000e-01,8.6838931e-03 -2.1000000e-03,3.7859389e-04 -5.6000000e-03,6.8637534e-04 -1.1700000e-02,1.4456832e-03 -4.1700000e-02,2.7041121e-03 -2.1200000e-02,1.8366636e-03 -7.4900000e-02,2.2083176e-03 -1.6220000e-01,2.8079253e-03 -6.4010000e-01,8.6838931e-03 -2.1000000e-03,3.7859389e-04 -5.6000000e-03,6.8637534e-04 -1.1700000e-02,1.4456832e-03 -4.1700000e-02,2.7041121e-03 -5.2000000e-03,5.9254629e-04 -3.9200000e-02,2.5508169e-03 -4.0200000e-02,1.9310331e-03 -4.1360000e-01,8.0072190e-03 -0.0000000e+00,0.0000000e+00 -1.9000000e-03,3.7859389e-04 +2.4100000e-02,2.1052844e-03 +6.7900000e-02,2.3211587e-03 +1.6860000e-01,4.4800794e-03 +6.4710000e-01,9.1826527e-03 +2.2000000e-03,3.8873013e-04 +5.5000000e-03,1.0979779e-03 +1.2500000e-02,1.5438048e-03 +4.4700000e-02,1.9035055e-03 +2.4100000e-02,2.1052844e-03 +6.7900000e-02,2.3211587e-03 +1.6860000e-01,4.4800794e-03 +6.4710000e-01,9.1826527e-03 +2.2000000e-03,3.8873013e-04 +5.5000000e-03,1.0979779e-03 +1.2500000e-02,1.5438048e-03 +4.4700000e-02,1.9035055e-03 +7.3000000e-03,9.8938814e-04 +3.6600000e-02,2.5086517e-03 +4.1600000e-02,2.4864075e-03 +4.2380000e-01,9.6087923e-03 1.0000000e-04,1.0000000e-04 -1.6400000e-02,1.2840907e-03 --5.2000000e-03,5.9254629e-04 --3.9200000e-02,2.5508169e-03 --4.0200000e-02,1.9310331e-03 --4.1360000e-01,8.0072190e-03 -0.0000000e+00,0.0000000e+00 --1.9000000e-03,3.7859389e-04 +1.5000000e-03,4.5338235e-04 +3.0000000e-04,1.5275252e-04 +1.7300000e-02,1.4609738e-03 +-7.3000000e-03,9.8938814e-04 +-3.6600000e-02,2.5086517e-03 +-4.1600000e-02,2.4864075e-03 +-4.2380000e-01,9.6087923e-03 -1.0000000e-04,1.0000000e-04 --1.6400000e-02,1.2840907e-03 -1.6000000e-02,2.1602469e-03 -3.5700000e-02,2.9441090e-03 -1.2200000e-01,3.5932035e-03 -2.2650000e-01,9.2463206e-03 +-1.5000000e-03,4.5338235e-04 +-3.0000000e-04,1.5275252e-04 +-1.7300000e-02,1.4609738e-03 +1.6800000e-02,1.5902481e-03 +3.1300000e-02,3.8094911e-03 +1.2700000e-01,5.0990195e-03 +2.2330000e-01,9.3631073e-03 2.1000000e-03,3.7859389e-04 -3.7000000e-03,8.1717671e-04 -1.1600000e-02,1.4772347e-03 -2.5300000e-02,1.9723083e-03 +4.0000000e-03,1.0540926e-03 +1.2200000e-02,1.6110728e-03 +2.7400000e-02,1.6613248e-03 0.0000000e+00,0.0000000e+00 --2.9700000e-02,2.4587711e-03 +-3.2000000e-02,1.5634719e-03 0.0000000e+00,0.0000000e+00 --3.5090000e-01,3.7161808e-03 +-3.5400000e-01,7.5938572e-03 0.0000000e+00,0.0000000e+00 --2.1000000e-03,4.8189441e-04 +-3.0000000e-03,6.4978629e-04 0.0000000e+00,0.0000000e+00 --2.1400000e-02,1.7397318e-03 +-2.1800000e-02,1.4892205e-03 0.0000000e+00,0.0000000e+00 0.0000000e+00,0.0000000e+00 0.0000000e+00,0.0000000e+00 diff --git a/tests/regression_tests/survival_biasing/results_true.dat b/tests/regression_tests/survival_biasing/results_true.dat index 7402722017..932414e98b 100644 --- a/tests/regression_tests/survival_biasing/results_true.dat +++ b/tests/regression_tests/survival_biasing/results_true.dat @@ -1,20 +1,20 @@ k-combined: -9.879232E-01 8.097582E-03 +9.517646E-01 1.303111E-02 tally 1: -4.295331E+01 -3.691096E+02 -1.802724E+01 -6.501934E+01 -2.193500E+00 -9.627609E-01 -1.893529E+00 -7.174104E-01 -4.902380E+00 -4.808570E+00 -3.418014E-02 -2.337353E-04 -3.667128E+08 -2.690758E+16 +4.164635E+01 +3.470110E+02 +1.724300E+01 +5.949580E+01 +2.124917E+00 +9.034789E-01 +1.844790E+00 +6.809026E-01 +4.784396E+00 +4.579552E+00 +3.348849E-02 +2.243613E-04 +3.573090E+08 +2.554338E+16 tally 2: -1.802724E+01 -6.501934E+01 +1.724300E+01 +5.949580E+01 diff --git a/tests/regression_tests/tallies/results_true.dat b/tests/regression_tests/tallies/results_true.dat index 3dda0f9b21..1d3aca4b07 100644 --- a/tests/regression_tests/tallies/results_true.dat +++ b/tests/regression_tests/tallies/results_true.dat @@ -1 +1 @@ -ddfbb0a6f5498eb8ff33bb10beb64e244b015861919eb4837bd82855e5fd87c3ff97dfa382d3d60afa81c48d9f857fba8e0b99263e7b35587f8adb75be1fc0ec \ No newline at end of file +d01c3accd5b4de2aa166a77df28cfe42f5738a44c2480752fcfae7564a507362fff006b6dffb7b1dfe248e14bacef0070cabacea5d75c5996653e5605f7c7384 \ No newline at end of file diff --git a/tests/regression_tests/tally_aggregation/results_true.dat b/tests/regression_tests/tally_aggregation/results_true.dat index 172adbfe13..ee6263373a 100644 --- a/tests/regression_tests/tally_aggregation/results_true.dat +++ b/tests/regression_tests/tally_aggregation/results_true.dat @@ -1,97 +1,97 @@ -[[1.6001087e-05 5.4190949e-04] - [3.2669968e-01 1.7730523e-01] - [1.8149266e-02 7.1525113e-01]], [[1.6239097e-05 5.7499676e-04] - [3.1268633e-01 1.7004165e-01] - [1.8873778e-02 7.0217885e-01]], [[1.6693071e-05 5.4106379e-04] - [3.3370208e-01 1.8051505e-01] - [1.9081306e-02 7.3647547e-01]], [[1.6725399e-05 5.1680146e-04] - [3.2854628e-01 1.7757185e-01] - [1.9529646e-02 7.1005198e-01]][[2.4751834e-07 4.3304565e-05] - [8.6840718e-03 4.3442535e-03] - [3.7054051e-04 6.5678133e-03]], [[4.0830852e-07 4.9612204e-05] - [1.2104241e-02 5.9708675e-03] - [7.1398189e-04 8.2408482e-03]], [[2.6546344e-07 2.5234256e-05] - [6.5083211e-03 3.2185071e-03] - [4.2935150e-04 5.1707774e-03]], [[2.7845203e-07 3.4453402e-05] - [3.3125427e-03 1.7749508e-03] - [6.0407731e-04 7.5353872e-03]][[1.0455251e-06 8.1938339e-04] - [1.1392765e+00 5.6434761e-01] - [1.4142831e-06 5.1213654e-01]], [[2.2009815e-06 1.0418935e-03] - [1.4422554e-01 1.0070647e-01] - [3.9488382e-05 7.9236390e-01]], [[1.4606612e-05 2.2374470e-04] - [1.2962842e-02 2.9268594e-02] - [3.1339824e-04 1.1056439e+00]], [[4.7805535e-05 8.9749934e-05] - [5.1694597e-03 1.1111105e-02] - [7.5279695e-02 4.5381305e-01]][[1.4955183e-08 1.1461548e-05] - [1.6454649e-02 8.1236707e-03] - [2.0028007e-08 6.8264819e-03]], [[1.6334486e-07 7.7617340e-05] - [2.1161584e-03 1.4078445e-03] - [1.4742097e-05 6.9350862e-03]], [[1.7444757e-07 1.9026095e-06] - [1.4084092e-04 2.0345990e-04] - [5.9546175e-06 8.6038812e-03]], [[5.6449127e-07 1.0110585e-06] - [5.9158873e-05 1.2485325e-04] - [1.0936497e-03 5.0836702e-03]][[0.2866239 0.2725595]], [[0.2729156 0.258831 ]], [[0.2920724 0.2755922]], [[0.287667 0.2703207]], [[0.035617 0.2232707]], [[0.0353082 0.2224423]], [[0.0370072 0.2288263]], [[0.0363348 0.219573 ]], [[0.0033013 0.2850034]], [[0.0032726 0.2771099]], [[0.0034234 0.2951295]], [[0.0032935 0.2778935]], [[0.0193227 0.1122647]], [[0.0200799 0.1144123]], [[0.0202971 0.1179836]], [[0.0207973 0.1203534]][[0.0086351 0.0061876]], [[0.0120688 0.0074831]], [[0.0064221 0.0035246]], [[0.0030483 0.0024267]], [[0.0009185 0.0033896]], [[0.0009223 0.0039584]], [[0.0010541 0.0038599]], [[0.0012934 0.0028331]], [[6.5126963e-05 2.8486593e-03]], [[7.1110242e-05 4.3424340e-03]], [[5.8911409e-05 2.4296178e-03]], [[8.4278765e-05 6.4182190e-03]], [[0.0003712 0.0020298]], [[0.0007152 0.0036115]], [[0.0004298 0.0019677]], [[0.0006046 0.0021965]][[2.0694650e-04] - [4.2868191e-01] - [1.3029457e-01]], [[1.9694048e-04] - [4.0809445e-01] - [1.2345525e-01]], [[2.1012645e-04] - [4.3670571e-01] - [1.3074883e-01]], [[2.0641548e-04] - [4.3014207e-01] - [1.2763930e-01]], [[0.0002584] - [0.0608867] - [0.1977426]], [[0.0003026] - [0.0602368] - [0.1972111]], [[0.0002509] - [0.0624699] - [0.2031126]], [[0.0002322] - [0.0613385] - [0.1943371]], [[5.9349736e-05] - [1.0506741e-02] - [2.7773865e-01]], [[5.7855564e-05] - [1.0389781e-02] - [2.6993483e-01]], [[6.1819700e-05] - [1.0910874e-02] - [2.8758020e-01]], [[5.9326317e-05] - [1.0424040e-02] - [2.7070367e-01]], [[3.3192167e-05] - [3.9295320e-03] - [1.2762462e-01]], [[3.3882691e-05] - [4.0069157e-03] - [1.3045143e-01]], [[3.4882103e-05] - [4.1306182e-03] - [1.3411514e-01]], [[3.5598508e-05] - [4.2134987e-03] - [1.3690156e-01]][[6.4505980e-06] - [9.6369034e-03] - [4.4700460e-03]], [[8.2880772e-06] - [1.3456171e-02] - [4.5368708e-03]], [[3.9384462e-06] - [7.1570638e-03] - [1.5629142e-03]], [[2.3565894e-06] - [3.4040401e-03] - [1.8956916e-03]], [[4.2806047e-05] - [1.1841015e-03] - [3.3058802e-03]], [[4.8905696e-05] - [1.0360139e-03] - [3.9298937e-03]], [[2.4911390e-05] - [1.2173305e-03] - [3.8114473e-03]], [[3.4347869e-05] - [1.5820360e-03] - [2.6824612e-03]], [[1.0809230e-06] - [1.0316180e-04] - [2.8475354e-03]], [[6.4150814e-07] - [1.1179425e-04] - [4.3415770e-03]], [[7.3848139e-07] - [9.3111666e-05] - [2.4285475e-03]], [[1.2349384e-06] - [1.7152843e-04] - [6.4164799e-03]], [[4.5871493e-07] - [5.4732075e-05] - [2.0627309e-03]], [[8.1649994e-07] - [9.7699188e-05] - [3.6803256e-03]], [[4.5174850e-07] - [5.3913784e-05] - [2.0133571e-03]], [[5.0962865e-07] - [6.0338032e-05] - [2.2773911e-03]] \ No newline at end of file +[[1.6242805e-05 6.2367673e-04] + [3.2895972e-01 1.7786452e-01] + [1.8044266e-02 7.0451122e-01]], [[1.6113947e-05 5.3572864e-04] + [3.1517504e-01 1.7132833e-01] + [1.8305682e-02 7.0072832e-01]], [[1.6472052e-05 5.5758006e-04] + [3.2362364e-01 1.7597163e-01] + [1.9107080e-02 7.2600440e-01]], [[1.6693277e-05 4.9204218e-04] + [3.2429262e-01 1.7600573e-01] + [1.9042489e-02 7.3053854e-01]][[2.9719061e-07 8.0925438e-05] + [8.9432259e-03 4.4057583e-03] + [5.2078407e-04 6.4387688e-03]], [[1.8572081e-07 2.5667235e-05] + [1.1641603e-02 5.7444311e-03] + [2.6983611e-04 6.9783224e-03]], [[2.4994113e-07 5.4993390e-05] + [6.0464041e-03 3.0764811e-03] + [2.6559118e-04 7.7279780e-03]], [[2.5965232e-07 3.9618775e-05] + [1.0409564e-02 5.1850104e-03] + [2.7831231e-04 7.4480576e-03]][[1.0329435e-06 8.0861229e-04] + [1.1265142e+00 5.5796079e-01] + [1.3965860e-06 5.0338828e-01]], [[2.2264172e-06 1.0828687e-03] + [1.4724979e-01 1.0226107e-01] + [2.2656045e-05 7.7618945e-01]], [[1.4789782e-05 2.2786630e-04] + [1.3149968e-02 2.9847169e-02] + [3.2638111e-04 1.1287326e+00]], [[4.7472938e-05 8.9680338e-05] + [5.1371041e-03 1.1101179e-02] + [7.4149084e-02 4.5347217e-01]][[1.7024771e-08 1.2878244e-05] + [1.8795566e-02 9.2705008e-03] + [2.2676749e-08 7.0878353e-03]], [[2.2018925e-07 1.0785388e-04] + [2.6715019e-03 1.6657928e-03] + [1.2479083e-05 8.6814018e-03]], [[2.0928485e-07 1.6600875e-06] + [1.1859535e-04 1.7969083e-04] + [1.5981387e-05 8.0489308e-03]], [[4.0016381e-07 7.6799157e-07] + [4.4157583e-05 9.4462925e-05] + [7.0115110e-04 3.8678806e-03]][[0.287433 0.2698042]], [[0.2751228 0.2598525]], [[0.280516 0.2648274]], [[0.2834448 0.2676736]], [[0.0370558 0.2148509]], [[0.0355217 0.2130189]], [[0.0385317 0.2292804]], [[0.0361655 0.2223832]], [[0.0033268 0.2855078]], [[0.0033498 0.2849403]], [[0.003359 0.2901157]], [[0.0034555 0.2982438]], [[0.0192046 0.1128364]], [[0.0195026 0.1147807]], [[0.0203405 0.1183102]], [[0.0202861 0.1187358]][[0.00889 0.0051934]], [[0.0115249 0.0072767]], [[0.0058841 0.0040289]], [[0.0103341 0.0063266]], [[0.0009734 0.0048865]], [[0.0016425 0.0038133]], [[0.0013902 0.0048875]], [[0.0012487 0.0039808]], [[1.8994140e-05 2.0410145e-03]], [[6.8277082e-05 3.4865782e-03]], [[6.1643568e-05 4.9220817e-03]], [[7.4147413e-05 4.9263295e-03]], [[0.0005213 0.0024208]], [[0.0002702 0.0014313]], [[0.0002665 0.0022006]], [[0.0002788 0.0014892]][[2.0601081e-04] + [4.2976789e-01] + [1.2726338e-01]], [[1.9802070e-04] + [4.1138025e-01] + [1.2339705e-01]], [[2.0174854e-04] + [4.1947542e-01] + [1.2566615e-01]], [[2.0386518e-04] + [4.2385140e-01] + [1.2706310e-01]], [[0.0003403] + [0.0624955] + [0.189071 ]], [[0.0002601] + [0.060449 ] + [0.1878314]], [[0.0002765] + [0.0652412] + [0.2022944]], [[0.0002082] + [0.0613252] + [0.1970153]], [[6.0336874e-05] + [1.0617692e-02] + [2.7815664e-01]], [[5.9823997e-05] + [1.0664059e-02] + [2.7756620e-01]], [[6.0873689e-05] + [1.0744209e-02] + [2.8266963e-01]], [[6.1621521e-05] + [1.0971177e-02] + [2.9066650e-01]], [[3.3297391e-05] + [3.9432037e-03] + [1.2806450e-01]], [[3.3863464e-05] + [4.0100180e-03] + [1.3023932e-01]], [[3.4930617e-05] + [4.1344613e-03] + [1.3448129e-01]], [[3.5061805e-05] + [4.1505999e-03] + [1.3483614e-01]][[5.8259835e-06] + [9.9096571e-03] + [2.7933778e-03]], [[8.0858909e-06] + [1.2843377e-02] + [4.5631248e-03]], [[4.3418585e-06] + [6.5638646e-03] + [2.7874612e-03]], [[6.9046376e-06] + [1.1531588e-02] + [3.7205377e-03]], [[8.0710599e-05] + [1.0889301e-03] + [4.8613465e-03]], [[2.4337121e-05] + [1.8861117e-03] + [3.6987509e-03]], [[5.4812439e-05] + [1.7085353e-03] + [4.7852139e-03]], [[3.9007791e-05] + [1.4998363e-03] + [3.8929646e-03]], [[7.5757577e-07] + [2.5845755e-05] + [2.0409391e-03]], [[1.0302346e-06] + [1.1907557e-04] + [3.4852130e-03]], [[9.1936614e-07] + [1.2974020e-04] + [4.9207575e-03]], [[5.6493555e-07] + [1.2113685e-04] + [4.9253980e-03]], [[5.4602210e-07] + [6.5233025e-05] + [2.4754550e-03]], [[3.2091909e-07] + [3.8472906e-05] + [1.4560974e-03]], [[4.8475651e-07] + [5.9108262e-05] + [2.2158781e-03]], [[3.3737822e-07] + [4.0544269e-05] + [1.5145628e-03]] \ No newline at end of file diff --git a/tests/regression_tests/tally_arithmetic/results_true.dat b/tests/regression_tests/tally_arithmetic/results_true.dat index 143930dd41..baa3805871 100644 --- a/tests/regression_tests/tally_arithmetic/results_true.dat +++ b/tests/regression_tests/tally_arithmetic/results_true.dat @@ -1,49 +1,49 @@ -[2.04229e-07 1.28343e-13 1.79333e-04 1.12698e-10 1.89952e-07 1.51210e-07 - 1.66796e-04 1.32777e-04 6.13215e-03 3.85362e-09 3.14746e-03 1.97795e-09 - 5.70345e-03 4.54021e-03 2.92742e-03 2.33037e-03 2.10575e-07 1.28419e-13 - 1.84905e-04 1.12764e-10 1.89188e-07 1.50221e-07 1.66125e-04 1.31908e-04 - 6.32269e-03 3.85587e-09 3.24526e-03 1.97911e-09 5.68054e-03 4.51051e-03 - 2.91566e-03 2.31512e-03 1.96696e-07 1.26388e-13 1.72718e-04 1.10981e-10 - 1.91283e-07 1.53449e-07 1.67964e-04 1.34743e-04 5.90596e-03 3.79491e-09 - 3.03136e-03 1.94782e-09 5.74342e-03 4.60742e-03 2.94794e-03 2.36486e-03 - 2.06016e-07 1.35264e-13 1.80901e-04 1.18775e-10 2.05873e-07 1.65814e-07 - 1.80776e-04 1.45600e-04 6.18579e-03 4.06142e-09 3.17499e-03 2.08461e-09 - 6.18150e-03 4.97869e-03 3.17279e-03 2.55542e-03 2.36089e-03 4.46651e-05 - 1.02263e-02 1.93469e-04 1.18179e-04 2.62375e-05 5.11897e-04 1.13649e-04 - 2.56040e-02 4.84394e-04 4.55595e-02 8.61927e-04 1.28165e-03 2.84546e-04 - 2.28056e-03 5.06320e-04 2.29877e-03 4.53056e-05 9.95724e-03 1.96244e-04 - 1.14803e-04 2.57898e-05 4.97276e-04 1.11710e-04 2.49302e-02 4.91340e-04 - 4.43606e-02 8.74289e-04 1.24504e-03 2.79691e-04 2.21542e-03 4.97680e-04 - 2.31940e-03 4.34238e-05 1.00466e-02 1.88093e-04 1.17620e-04 2.69280e-05 - 5.09479e-04 1.16640e-04 2.51540e-02 4.70932e-04 4.47588e-02 8.37974e-04 - 1.27560e-03 2.92034e-04 2.26979e-03 5.19644e-04 2.19212e-03 4.53914e-05 - 9.49530e-03 1.96615e-04 1.09609e-04 2.41615e-05 4.74778e-04 1.04657e-04 - 2.37736e-02 4.92271e-04 4.23026e-02 8.75944e-04 1.18871e-03 2.62032e-04 - 2.11519e-03 4.66257e-04][2.04229e-07 1.28343e-13 1.79333e-04 1.12698e-10 1.89952e-07 1.51210e-07 - 1.66796e-04 1.32777e-04 6.13215e-03 3.85362e-09 3.14746e-03 1.97795e-09 - 5.70345e-03 4.54021e-03 2.92742e-03 2.33037e-03 2.10575e-07 1.28419e-13 - 1.84905e-04 1.12764e-10 1.89188e-07 1.50221e-07 1.66125e-04 1.31908e-04 - 6.32269e-03 3.85587e-09 3.24526e-03 1.97911e-09 5.68054e-03 4.51051e-03 - 2.91566e-03 2.31512e-03 1.96696e-07 1.26388e-13 1.72718e-04 1.10981e-10 - 1.91283e-07 1.53449e-07 1.67964e-04 1.34743e-04 5.90596e-03 3.79491e-09 - 3.03136e-03 1.94782e-09 5.74342e-03 4.60742e-03 2.94794e-03 2.36486e-03 - 2.06016e-07 1.35264e-13 1.80901e-04 1.18775e-10 2.05873e-07 1.65814e-07 - 1.80776e-04 1.45600e-04 6.18579e-03 4.06142e-09 3.17499e-03 2.08461e-09 - 6.18150e-03 4.97869e-03 3.17279e-03 2.55542e-03 2.36089e-03 4.46651e-05 - 1.02263e-02 1.93469e-04 1.18179e-04 2.62375e-05 5.11897e-04 1.13649e-04 - 2.56040e-02 4.84394e-04 4.55595e-02 8.61927e-04 1.28165e-03 2.84546e-04 - 2.28056e-03 5.06320e-04 2.29877e-03 4.53056e-05 9.95724e-03 1.96244e-04 - 1.14803e-04 2.57898e-05 4.97276e-04 1.11710e-04 2.49302e-02 4.91340e-04 - 4.43606e-02 8.74289e-04 1.24504e-03 2.79691e-04 2.21542e-03 4.97680e-04 - 2.31940e-03 4.34238e-05 1.00466e-02 1.88093e-04 1.17620e-04 2.69280e-05 - 5.09479e-04 1.16640e-04 2.51540e-02 4.70932e-04 4.47588e-02 8.37974e-04 - 1.27560e-03 2.92034e-04 2.26979e-03 5.19644e-04 2.19212e-03 4.53914e-05 - 9.49530e-03 1.96615e-04 1.09609e-04 2.41615e-05 4.74778e-04 1.04657e-04 - 2.37736e-02 4.92271e-04 4.23026e-02 8.75944e-04 1.18871e-03 2.62032e-04 - 2.11519e-03 4.66257e-04][0.0057 0.00454 0.00293 0.00233 0.00568 0.00451 0.00292 0.00232 0.00574 - 0.00461 0.00295 0.00236 0.00618 0.00498 0.00317 0.00256 0.00128 0.00028 - 0.00228 0.00051 0.00125 0.00028 0.00222 0.0005 0.00128 0.00029 0.00227 - 0.00052 0.00119 0.00026 0.00212 0.00047][0.00018 0.00017 0.00315 0.00293 0.00018 0.00017 0.00325 0.00292 0.00017 - 0.00017 0.00303 0.00295 0.00018 0.00018 0.00317 0.00317 0.01023 0.00051 - 0.04556 0.00228 0.00996 0.0005 0.04436 0.00222 0.01005 0.00051 0.04476 - 0.00227 0.0095 0.00047 0.0423 0.00212][0.00293 0.00292 0.00295 0.00317 0.00228 0.00222 0.00227 0.00212] \ No newline at end of file +[2.29467e-07 1.47622e-13 2.02646e-04 1.30367e-10 2.20704e-07 1.76624e-07 + 1.94907e-04 1.55980e-04 6.32267e-03 4.06754e-09 3.26873e-03 2.10286e-09 + 6.08121e-03 4.86666e-03 3.14390e-03 2.51599e-03 1.89223e-07 1.06256e-13 + 1.67106e-04 9.38364e-11 1.53300e-07 1.20220e-07 1.35382e-04 1.06168e-04 + 5.21380e-03 2.92775e-09 2.69546e-03 1.51361e-09 4.22399e-03 3.31252e-03 + 2.18374e-03 1.71253e-03 2.21146e-07 1.41349e-13 1.95297e-04 1.24828e-10 + 2.11844e-07 1.69398e-07 1.87083e-04 1.49598e-04 6.09339e-03 3.89470e-09 + 3.15020e-03 2.01351e-09 5.83710e-03 4.66754e-03 3.01770e-03 2.41305e-03 + 1.92872e-07 1.05908e-13 1.70328e-04 9.35293e-11 1.59466e-07 1.25399e-07 + 1.40827e-04 1.10741e-04 5.31433e-03 2.91817e-09 2.74744e-03 1.50865e-09 + 4.39388e-03 3.45520e-03 2.27158e-03 1.78629e-03 2.44601e-03 4.71663e-05 + 1.09430e-02 2.11013e-04 1.23573e-04 2.76181e-05 5.52841e-04 1.23558e-04 + 2.71755e-02 5.24023e-04 4.76200e-02 9.18253e-04 1.37291e-03 3.06841e-04 + 2.40577e-03 5.37681e-04 2.29014e-03 4.44674e-05 1.02456e-02 1.98938e-04 + 1.12524e-04 2.48126e-05 5.03411e-04 1.11007e-04 2.54438e-02 4.94038e-04 + 4.45855e-02 8.65710e-04 1.25016e-03 2.75671e-04 2.19067e-03 4.83061e-04 + 2.38500e-03 4.58053e-05 1.06700e-02 2.04924e-04 1.22899e-04 2.95267e-05 + 5.49826e-04 1.32097e-04 2.64977e-02 5.08903e-04 4.64323e-02 8.91758e-04 + 1.36542e-03 3.28045e-04 2.39265e-03 5.74839e-04 2.17094e-03 4.21772e-05 + 9.71236e-03 1.88693e-04 1.09358e-04 2.46984e-05 4.89245e-04 1.10496e-04 + 2.41194e-02 4.68594e-04 4.22648e-02 8.21124e-04 1.21498e-03 2.74402e-04 + 2.12902e-03 4.80839e-04][2.29467e-07 1.47622e-13 2.02646e-04 1.30367e-10 2.20704e-07 1.76624e-07 + 1.94907e-04 1.55980e-04 6.32267e-03 4.06754e-09 3.26873e-03 2.10286e-09 + 6.08121e-03 4.86666e-03 3.14390e-03 2.51599e-03 1.89223e-07 1.06256e-13 + 1.67106e-04 9.38364e-11 1.53300e-07 1.20220e-07 1.35382e-04 1.06168e-04 + 5.21380e-03 2.92775e-09 2.69546e-03 1.51361e-09 4.22399e-03 3.31252e-03 + 2.18374e-03 1.71253e-03 2.21146e-07 1.41349e-13 1.95297e-04 1.24828e-10 + 2.11844e-07 1.69398e-07 1.87083e-04 1.49598e-04 6.09339e-03 3.89470e-09 + 3.15020e-03 2.01351e-09 5.83710e-03 4.66754e-03 3.01770e-03 2.41305e-03 + 1.92872e-07 1.05908e-13 1.70328e-04 9.35293e-11 1.59466e-07 1.25399e-07 + 1.40827e-04 1.10741e-04 5.31433e-03 2.91817e-09 2.74744e-03 1.50865e-09 + 4.39388e-03 3.45520e-03 2.27158e-03 1.78629e-03 2.44601e-03 4.71663e-05 + 1.09430e-02 2.11013e-04 1.23573e-04 2.76181e-05 5.52841e-04 1.23558e-04 + 2.71755e-02 5.24023e-04 4.76200e-02 9.18253e-04 1.37291e-03 3.06841e-04 + 2.40577e-03 5.37681e-04 2.29014e-03 4.44674e-05 1.02456e-02 1.98938e-04 + 1.12524e-04 2.48126e-05 5.03411e-04 1.11007e-04 2.54438e-02 4.94038e-04 + 4.45855e-02 8.65710e-04 1.25016e-03 2.75671e-04 2.19067e-03 4.83061e-04 + 2.38500e-03 4.58053e-05 1.06700e-02 2.04924e-04 1.22899e-04 2.95267e-05 + 5.49826e-04 1.32097e-04 2.64977e-02 5.08903e-04 4.64323e-02 8.91758e-04 + 1.36542e-03 3.28045e-04 2.39265e-03 5.74839e-04 2.17094e-03 4.21772e-05 + 9.71236e-03 1.88693e-04 1.09358e-04 2.46984e-05 4.89245e-04 1.10496e-04 + 2.41194e-02 4.68594e-04 4.22648e-02 8.21124e-04 1.21498e-03 2.74402e-04 + 2.12902e-03 4.80839e-04][0.00608 0.00487 0.00314 0.00252 0.00422 0.00331 0.00218 0.00171 0.00584 + 0.00467 0.00302 0.00241 0.00439 0.00346 0.00227 0.00179 0.00137 0.00031 + 0.00241 0.00054 0.00125 0.00028 0.00219 0.00048 0.00137 0.00033 0.00239 + 0.00057 0.00121 0.00027 0.00213 0.00048][0.0002 0.00019 0.00327 0.00314 0.00017 0.00014 0.0027 0.00218 0.0002 + 0.00019 0.00315 0.00302 0.00017 0.00014 0.00275 0.00227 0.01094 0.00055 + 0.04762 0.00241 0.01025 0.0005 0.04459 0.00219 0.01067 0.00055 0.04643 + 0.00239 0.00971 0.00049 0.04226 0.00213][0.00314 0.00218 0.00302 0.00227 0.00241 0.00219 0.00239 0.00213] \ No newline at end of file diff --git a/tests/regression_tests/tally_assumesep/results_true.dat b/tests/regression_tests/tally_assumesep/results_true.dat index 9d7cbf9c3d..c9ccf09282 100644 --- a/tests/regression_tests/tally_assumesep/results_true.dat +++ b/tests/regression_tests/tally_assumesep/results_true.dat @@ -1,11 +1,11 @@ k-combined: -5.683578E-01 1.129170E-02 +6.268465E-01 1.154810E-02 tally 1: -6.753950E+00 -9.188305E+00 +7.828708E+00 +1.230478E+01 tally 2: -2.278558E-01 -1.052944E-02 +2.582239E-01 +1.360117E-02 tally 3: -1.179091E+01 -2.795539E+01 +1.339335E+01 +3.663458E+01 diff --git a/tests/regression_tests/tally_nuclides/results_true.dat b/tests/regression_tests/tally_nuclides/results_true.dat index 7f9641fc8f..93a0e03fb5 100644 --- a/tests/regression_tests/tally_nuclides/results_true.dat +++ b/tests/regression_tests/tally_nuclides/results_true.dat @@ -1,28 +1,28 @@ k-combined: -1.132463E+00 5.721067E-02 +9.732610E-01 1.400780E-02 tally 1: -7.310528E+00 -1.080411E+01 -1.664215E+00 -5.567756E-01 -1.609340E+00 -5.205634E-01 -5.646313E+00 -6.459724E+00 -7.310528E+00 -1.080411E+01 -1.664215E+00 -5.567756E-01 -1.609340E+00 -5.205634E-01 -5.646313E+00 -6.459724E+00 +7.123025E+00 +1.021136E+01 +1.619905E+00 +5.258592E-01 +1.561322E+00 +4.881841E-01 +5.503120E+00 +6.105683E+00 +7.123025E+00 +1.021136E+01 +1.619905E+00 +5.258592E-01 +1.561322E+00 +4.881841E-01 +5.503120E+00 +6.105683E+00 tally 2: -7.310528E+00 -1.080411E+01 -1.664215E+00 -5.567756E-01 -1.609340E+00 -5.205634E-01 -5.646313E+00 -6.459724E+00 +7.123025E+00 +1.021136E+01 +1.619905E+00 +5.258592E-01 +1.561322E+00 +4.881841E-01 +5.503120E+00 +6.105683E+00 diff --git a/tests/regression_tests/tally_slice_merge/results_true.dat b/tests/regression_tests/tally_slice_merge/results_true.dat index 58b15fc18d..4b2cbdf1ad 100644 --- a/tests/regression_tests/tally_slice_merge/results_true.dat +++ b/tests/regression_tests/tally_slice_merge/results_true.dat @@ -1,45 +1,45 @@ cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 1.75e-01 1.20e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 nu-fission 4.26e-01 2.92e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 fission 2.41e-07 1.61e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U238 nu-fission 6.00e-07 4.01e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 fission 2.89e-02 2.07e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U235 nu-fission 7.07e-02 5.06e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 fission 1.41e-02 5.76e-04 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 6.25e-01 2.00e+07 U238 nu-fission 3.95e-02 1.90e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 fission 1.51e-01 1.17e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U235 nu-fission 3.69e-01 2.86e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 fission 2.07e-07 1.47e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 0.00e+00 6.25e-01 U238 nu-fission 5.17e-07 3.66e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 fission 2.57e-02 2.43e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U235 nu-fission 6.30e-02 5.92e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 fission 1.47e-02 1.41e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 27 6.25e-01 2.00e+07 U238 nu-fission 4.12e-02 4.02e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. -0 21 0.00e+00 6.25e-01 U235 fission 1.75e-01 1.20e-02 -1 21 0.00e+00 6.25e-01 U235 nu-fission 4.26e-01 2.92e-02 -2 21 0.00e+00 6.25e-01 U238 fission 2.41e-07 1.61e-08 -3 21 0.00e+00 6.25e-01 U238 nu-fission 6.00e-07 4.01e-08 -4 21 6.25e-01 2.00e+07 U235 fission 2.89e-02 2.07e-03 -5 21 6.25e-01 2.00e+07 U235 nu-fission 7.07e-02 5.06e-03 -6 21 6.25e-01 2.00e+07 U238 fission 1.41e-02 5.76e-04 -7 21 6.25e-01 2.00e+07 U238 nu-fission 3.95e-02 1.90e-03 -8 27 0.00e+00 6.25e-01 U235 fission 1.51e-01 1.17e-02 -9 27 0.00e+00 6.25e-01 U235 nu-fission 3.69e-01 2.86e-02 -10 27 0.00e+00 6.25e-01 U238 fission 2.07e-07 1.47e-08 -11 27 0.00e+00 6.25e-01 U238 nu-fission 5.17e-07 3.66e-08 -12 27 6.25e-01 2.00e+07 U235 fission 2.57e-02 2.43e-03 -13 27 6.25e-01 2.00e+07 U235 nu-fission 6.30e-02 5.92e-03 -14 27 6.25e-01 2.00e+07 U238 fission 1.47e-02 1.41e-03 -15 27 6.25e-01 2.00e+07 U238 nu-fission 4.12e-02 4.02e-03 +0 21 0.00e+00 6.25e-01 U235 fission 1.93e-01 1.92e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U235 nu-fission 4.70e-01 4.67e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U238 fission 2.65e-07 2.60e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U238 nu-fission 6.60e-07 6.47e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U235 fission 3.39e-02 1.53e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U235 nu-fission 8.30e-02 3.75e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U238 fission 1.70e-02 2.01e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 6.25e-01 2.00e+07 U238 nu-fission 4.76e-02 6.12e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U235 fission 7.61e-02 5.84e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U235 nu-fission 1.85e-01 1.42e-02 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U238 fission 1.06e-07 7.62e-09 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 0.00e+00 6.25e-01 U238 nu-fission 2.64e-07 1.90e-08 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U235 fission 1.69e-02 1.34e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U235 nu-fission 4.15e-02 3.29e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U238 fission 1.10e-02 1.69e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 27 6.25e-01 2.00e+07 U238 nu-fission 3.13e-02 5.35e-03 cell energy low [eV] energy high [eV] nuclide score mean std. dev. +0 21 0.00e+00 6.25e-01 U235 fission 1.93e-01 1.92e-02 +1 21 0.00e+00 6.25e-01 U235 nu-fission 4.70e-01 4.67e-02 +2 21 0.00e+00 6.25e-01 U238 fission 2.65e-07 2.60e-08 +3 21 0.00e+00 6.25e-01 U238 nu-fission 6.60e-07 6.47e-08 +4 21 6.25e-01 2.00e+07 U235 fission 3.39e-02 1.53e-03 +5 21 6.25e-01 2.00e+07 U235 nu-fission 8.30e-02 3.75e-03 +6 21 6.25e-01 2.00e+07 U238 fission 1.70e-02 2.01e-03 +7 21 6.25e-01 2.00e+07 U238 nu-fission 4.76e-02 6.12e-03 +8 27 0.00e+00 6.25e-01 U235 fission 7.61e-02 5.84e-03 +9 27 0.00e+00 6.25e-01 U235 nu-fission 1.85e-01 1.42e-02 +10 27 0.00e+00 6.25e-01 U238 fission 1.06e-07 7.62e-09 +11 27 0.00e+00 6.25e-01 U238 nu-fission 2.64e-07 1.90e-08 +12 27 6.25e-01 2.00e+07 U235 fission 1.69e-02 1.34e-03 +13 27 6.25e-01 2.00e+07 U235 nu-fission 4.15e-02 3.29e-03 +14 27 6.25e-01 2.00e+07 U238 fission 1.10e-02 1.69e-03 +15 27 6.25e-01 2.00e+07 U238 nu-fission 3.13e-02 5.35e-03 sum(distribcell) energy low [eV] energy high [eV] nuclide score mean std. dev. 0 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 1 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 2 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 3 (0, 100, 2000, 30000) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 -4 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 fission 9.53e-07 9.53e-07 -5 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 nu-fission 2.37e-06 2.37e-06 -6 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 fission 1.25e-08 1.25e-08 -7 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 nu-fission 3.15e-08 3.15e-08 +4 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 fission 0.00e+00 0.00e+00 +5 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U235 nu-fission 0.00e+00 0.00e+00 +6 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 +7 (0, 100, 2000, 30000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 8 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 9 (500, 5000, 50000) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 10 (500, 5000, 50000) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 @@ -49,19 +49,19 @@ 14 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 15 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 sum(mesh) energy low [eV] energy high [eV] nuclide score mean std. dev. -0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 6.73e-03 3.04e-03 -1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 1.64e-02 7.40e-03 -2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 8.80e-09 3.84e-09 -3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 2.19e-08 9.56e-09 -4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 9.89e-04 3.53e-04 -5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 2.42e-03 8.60e-04 -6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 5.01e-04 2.13e-04 -7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.36e-03 5.86e-04 -8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 1.63e-02 4.21e-03 -9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 3.98e-02 1.02e-02 -10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 2.28e-08 5.90e-09 -11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 5.67e-08 1.47e-08 -12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 1.79e-03 4.31e-04 -13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 4.37e-03 1.05e-03 -14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 7.51e-04 2.51e-04 -15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 2.02e-03 6.71e-04 +0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 1.94e-03 1.03e-03 +1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 4.74e-03 2.50e-03 +2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 2.74e-09 1.42e-09 +3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 6.83e-09 3.53e-09 +4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 9.02e-04 3.69e-04 +5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 2.24e-03 9.12e-04 +6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 1.44e-03 8.42e-04 +7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 4.37e-03 2.64e-03 +8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 1.27e-02 2.76e-03 +9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 3.09e-02 6.72e-03 +10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 1.70e-08 3.57e-09 +11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 4.25e-08 8.90e-09 +12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 1.43e-03 1.69e-04 +13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 3.52e-03 4.20e-04 +14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 1.37e-03 2.98e-04 +15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 4.16e-03 1.08e-03 diff --git a/tests/regression_tests/torus/results_true.dat b/tests/regression_tests/torus/results_true.dat index 42fb209cce..84cd3c7a44 100644 --- a/tests/regression_tests/torus/results_true.dat +++ b/tests/regression_tests/torus/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.667201E-01 1.136882E-02 +7.666453E-01 1.478848E-02 diff --git a/tests/regression_tests/trace/results_true.dat b/tests/regression_tests/trace/results_true.dat index bbf03de943..97b997ae6b 100644 --- a/tests/regression_tests/trace/results_true.dat +++ b/tests/regression_tests/trace/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 diff --git a/tests/regression_tests/track_output/results_true.dat b/tests/regression_tests/track_output/results_true.dat index 148b54a30b..205ac3eecb 100644 --- a/tests/regression_tests/track_output/results_true.dat +++ b/tests/regression_tests/track_output/results_true.dat @@ -143,76 +143,74 @@ neutron [((-9.469716e-01, -2.580266e-01, 1.414357e-01), (1.438873e-01, 2.365819e ((-3.920090e+00, -9.211794e-01, 2.908406e+00), (9.094673e-01, -3.659267e-01, -1.974002e-01), 9.547085e+00, 1.260840e-07, 1.000000e+00, 23, 2387, 1) ((-3.729948e+00, -9.976834e-01, 2.867135e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.750036e-07, 1.000000e+00, 23, 2387, 1) ((-3.744933e+00, -1.031047e+00, 2.831062e+00), (-2.916959e-01, -6.494657e-01, -7.022164e-01), 8.590591e+00, 1.876753e-07, 0.000000e+00, 23, 2387, 1)] -neutron [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450859e-05, 1.000000e+00, 21, 2367, 2) - ((6.037250e+00, -5.003484e+00, 5.468885e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450883e-05, 1.000000e+00, 22, 2367, 3) - ((5.942573e+00, -4.962444e+00, 5.480995e+00), (-9.112559e-01, 3.950037e-01, 1.165536e-01), 2.052226e+06, 4.450889e-05, 1.000000e+00, 23, 2367, 1) - ((5.861800e+00, -4.927431e+00, 5.491326e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450893e-05, 1.000000e+00, 23, 2367, 1) - ((5.725160e+00, -4.971424e+00, 5.491002e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450903e-05, 1.000000e+00, 23, 2366, 1) - ((5.494150e+00, -5.045802e+00, 5.490454e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450919e-05, 1.000000e+00, 22, 2366, 3) - ((5.392865e+00, -5.078412e+00, 5.490213e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450927e-05, 1.000000e+00, 21, 2366, 2) - ((4.612759e+00, -5.329579e+00, 5.488362e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450982e-05, 1.000000e+00, 22, 2366, 3) - ((4.511474e+00, -5.362189e+00, 5.488121e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.450989e-05, 1.000000e+00, 23, 2366, 1) - ((4.089400e+00, -5.498082e+00, 5.487119e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451019e-05, 1.000000e+00, 23, 2365, 1) - ((3.384113e+00, -5.725160e+00, 5.485445e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451069e-05, 1.000000e+00, 23, 2351, 1) - ((2.453640e+00, -6.024740e+00, 5.483237e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451136e-05, 1.000000e+00, 23, 2350, 1) - ((2.086813e+00, -6.142846e+00, 5.482366e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451162e-05, 1.000000e+00, 22, 2350, 3) - ((1.993594e+00, -6.172859e+00, 5.482145e+00), (-9.518772e-01, -3.064714e-01, -2.259335e-03), 1.141417e+06, 4.451168e-05, 1.000000e+00, 21, 2350, 2) - ((1.325704e+00, -6.387896e+00, 5.480560e+00), (8.986086e-01, -4.380574e-01, -2.466265e-02), 9.775839e+05, 4.451216e-05, 1.000000e+00, 21, 2350, 2) - ((2.061403e+00, -6.746538e+00, 5.460368e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451276e-05, 1.000000e+00, 21, 2350, 2) - ((1.122794e+00, -6.498940e+00, 4.743664e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451375e-05, 1.000000e+00, 22, 2350, 3) - ((1.036483e+00, -6.476172e+00, 4.677758e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451384e-05, 1.000000e+00, 23, 2350, 1) - ((8.178800e-01, -6.418507e+00, 4.510837e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451407e-05, 1.000000e+00, 23, 2349, 1) - ((5.725264e-01, -6.353784e+00, 4.323490e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451432e-05, 1.000000e+00, 22, 2349, 3) - ((4.668297e-01, -6.325902e+00, 4.242782e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451444e-05, 1.000000e+00, 21, 2349, 2) - ((-2.989816e-01, -6.123888e+00, 3.658023e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451524e-05, 1.000000e+00, 22, 2349, 3) - ((-4.046782e-01, -6.096006e+00, 3.577315e+00), (-7.778764e-01, 2.051975e-01, -5.939716e-01), 7.813219e+05, 4.451535e-05, 1.000000e+00, 23, 2349, 1) - ((-8.040445e-01, -5.990656e+00, 3.272367e+00), (-7.989001e-01, -1.890553e-01, -5.709787e-01), 6.637114e+05, 4.451577e-05, 1.000000e+00, 23, 2349, 1) - ((-8.178800e-01, -5.993930e+00, 3.262478e+00), (-7.989001e-01, -1.890553e-01, -5.709787e-01), 6.637114e+05, 4.451579e-05, 1.000000e+00, 23, 2348, 1) - ((-1.077910e+00, -6.055465e+00, 3.076633e+00), (-4.487118e-01, 1.670254e-01, -8.779295e-01), 4.550608e+05, 4.451608e-05, 1.000000e+00, 23, 2348, 1) - ((-1.215611e+00, -6.004208e+00, 2.807214e+00), (7.872329e-01, 4.481433e-01, -4.235941e-01), 3.544207e+03, 4.451641e-05, 1.000000e+00, 23, 2348, 1) - ((-1.100296e+00, -5.938564e+00, 2.745166e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.451819e-05, 1.000000e+00, 23, 2348, 1) - ((-8.178800e-01, -5.761448e+00, 2.754541e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.452273e-05, 1.000000e+00, 23, 2349, 1) - ((-7.600184e-01, -5.725160e+00, 2.756462e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.452366e-05, 1.000000e+00, 23, 2363, 1) - ((-2.947156e-01, -5.433347e+00, 2.771908e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.453115e-05, 1.000000e+00, 22, 2363, 3) - ((-2.073333e-01, -5.378546e+00, 2.774809e+00), (8.468456e-01, 5.310954e-01, 2.811230e-02), 2.812308e+03, 4.453256e-05, 1.000000e+00, 21, 2363, 2) - ((-1.746705e-01, -5.358062e+00, 2.775893e+00), (5.278774e-01, 5.459205e-01, 6.506276e-01), 2.806481e+03, 4.453309e-05, 1.000000e+00, 21, 2363, 2) - ((-8.681718e-02, -5.267205e+00, 2.884176e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.453536e-05, 1.000000e+00, 21, 2363, 2) - ((-3.684221e-01, -5.266924e+00, 2.745840e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.453967e-05, 1.000000e+00, 22, 2363, 3) - ((-4.840903e-01, -5.266809e+00, 2.689019e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.454144e-05, 1.000000e+00, 23, 2363, 1) - ((-8.178800e-01, -5.266475e+00, 2.525049e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.454656e-05, 1.000000e+00, 23, 2362, 1) - ((-1.151175e+00, -5.266142e+00, 2.361321e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.455166e-05, 1.000000e+00, 22, 2362, 3) - ((-1.266464e+00, -5.266027e+00, 2.304687e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.455343e-05, 1.000000e+00, 21, 2362, 2) - ((-2.005772e+00, -5.265288e+00, 1.941509e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.456475e-05, 1.000000e+00, 22, 2362, 3) - ((-2.121061e+00, -5.265173e+00, 1.884875e+00), (-8.975500e-01, 8.968076e-04, -4.409119e-01), 2.764929e+03, 4.456652e-05, 1.000000e+00, 23, 2362, 1) - ((-2.393759e+00, -5.264900e+00, 1.750915e+00), (-9.607392e-01, -1.749373e-01, 2.153533e-01), 1.619469e+03, 4.457070e-05, 1.000000e+00, 23, 2362, 1) - ((-2.453640e+00, -5.275804e+00, 1.764337e+00), (-9.607392e-01, -1.749373e-01, 2.153533e-01), 1.619469e+03, 4.457182e-05, 1.000000e+00, 23, 2361, 1) - ((-2.470658e+00, -5.278903e+00, 1.768152e+00), (-6.728606e-01, -2.916408e-01, -6.798561e-01), 4.873672e+02, 4.457214e-05, 1.000000e+00, 23, 2361, 1) - ((-3.463692e+00, -5.709318e+00, 7.647939e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.462047e-05, 1.000000e+00, 23, 2361, 1) - ((-3.467511e+00, -5.725160e+00, 7.600247e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.462139e-05, 1.000000e+00, 23, 2347, 1) - ((-3.533785e+00, -6.000066e+00, 6.772677e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.463730e-05, 1.000000e+00, 22, 2347, 3) - ((-3.562245e+00, -6.118119e+00, 6.417291e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.464414e-05, 1.000000e+00, 21, 2347, 2) - ((-3.723934e+00, -6.788806e+00, 4.398272e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.468297e-05, 1.000000e+00, 22, 2347, 3) - ((-3.752394e+00, -6.906859e+00, 4.042885e-01), (-2.249302e-01, -9.330150e-01, -2.808728e-01), 1.790901e+02, 4.468981e-05, 1.000000e+00, 23, 2347, 1) - ((-3.848515e+00, -7.305571e+00, 2.842613e-01), (6.498448e-01, -3.243413e-01, -6.873896e-01), 2.328979e+01, 4.471290e-05, 1.000000e+00, 23, 2347, 1) - ((-3.737619e+00, -7.360920e+00, 1.669579e-01), (6.498448e-01, -3.243413e-01, -6.873896e-01), 2.328979e+01, 4.473846e-05, 1.000000e+00, 11, 1750, 1) - ((-3.574308e+00, -7.442429e+00, -5.788041e-03), (6.794505e-01, 3.157106e-01, -6.623246e-01), 1.590416e+01, 4.477611e-05, 1.000000e+00, 11, 1750, 1) - ((-3.398889e+00, -7.360920e+00, -1.767852e-01), (6.794505e-01, 3.157106e-01, -6.623246e-01), 1.590416e+01, 4.482292e-05, 1.000000e+00, 23, 2347, 1) - ((-2.904712e+00, -7.131298e+00, -6.585068e-01), (-4.836985e-02, -2.819627e-01, -9.582053e-01), 2.610202e+00, 4.495477e-05, 1.000000e+00, 23, 2347, 1) - ((-2.923579e+00, -7.241285e+00, -1.032280e+00), (-6.089807e-01, -2.347428e-01, -7.576532e-01), 1.671268e+00, 4.512933e-05, 1.000000e+00, 23, 2347, 1) - ((-3.012516e+00, -7.275567e+00, -1.142930e+00), (3.221931e-01, -5.406104e-01, -7.771306e-01), 1.275709e-01, 4.521100e-05, 1.000000e+00, 23, 2347, 1) - ((-2.984032e+00, -7.323360e+00, -1.211633e+00), (-8.629564e-01, -1.719529e-01, -4.751195e-01), 1.897424e-02, 4.538995e-05, 1.000000e+00, 23, 2347, 1) - ((-3.172528e+00, -7.360920e+00, -1.315413e+00), (-8.629564e-01, -1.719529e-01, -4.751195e-01), 1.897424e-02, 4.653641e-05, 1.000000e+00, 11, 1750, 1) - ((-3.602328e+00, -7.446562e+00, -1.552049e+00), (-1.530190e-01, -7.092235e-01, 6.881767e-01), 1.306951e-02, 4.915052e-05, 1.000000e+00, 11, 1750, 1) - ((-3.625236e+00, -7.552741e+00, -1.449021e+00), (-1.976867e-01, 2.826475e-01, 9.386322e-01), 2.145548e-02, 5.009730e-05, 1.000000e+00, 11, 1750, 1) - ((-3.636290e+00, -7.536936e+00, -1.396537e+00), (1.266676e-01, 2.265353e-01, -9.657314e-01), 1.815564e-02, 5.037329e-05, 1.000000e+00, 11, 1750, 1) - ((-3.621792e+00, -7.511008e+00, -1.507069e+00), (-4.275550e-01, 8.441443e-01, 3.234457e-01), 1.848049e-02, 5.098741e-05, 1.000000e+00, 11, 1750, 1) - ((-3.697811e+00, -7.360920e+00, -1.449560e+00), (-4.275550e-01, 8.441443e-01, 3.234457e-01), 1.848049e-02, 5.193300e-05, 1.000000e+00, 23, 2347, 1) - ((-3.703436e+00, -7.349814e+00, -1.445305e+00), (-7.832167e-01, 5.713670e-01, 2.451762e-01), 1.861705e-02, 5.200297e-05, 1.000000e+00, 23, 2347, 1) - ((-3.823243e+00, -7.262414e+00, -1.407801e+00), (-9.917106e-01, 5.069164e-02, 1.180695e-01), 4.703334e-02, 5.281350e-05, 1.000000e+00, 23, 2347, 1) - ((-4.089400e+00, -7.248809e+00, -1.376113e+00), (-9.917106e-01, 5.069164e-02, 1.180695e-01), 4.703334e-02, 5.370820e-05, 1.000000e+00, 23, 2346, 1) - ((-4.131081e+00, -7.246679e+00, -1.371151e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.384831e-05, 1.000000e+00, 23, 2346, 1) - ((-4.089400e+00, -7.265067e+00, -1.366848e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.396486e-05, 1.000000e+00, 23, 2347, 1) - ((-3.872134e+00, -7.360920e+00, -1.344418e+00), (9.108632e-01, -4.018526e-01, 9.403556e-02), 8.057393e-02, 5.457240e-05, 1.000000e+00, 11, 1750, 1) - ((-3.673062e+00, -7.448746e+00, -1.323866e+00), (2.976906e-01, 8.174443e-01, -4.931178e-01), 5.538060e-02, 5.512905e-05, 1.000000e+00, 11, 1750, 1) - ((-3.658580e+00, -7.408978e+00, -1.347855e+00), (-5.409120e-01, 8.345378e-01, -1.046943e-01), 8.122576e-02, 5.527851e-05, 1.000000e+00, 11, 1750, 1) - ((-3.682981e+00, -7.371331e+00, -1.352578e+00), (-5.409120e-01, 8.345378e-01, -1.046943e-01), 8.122576e-02, 5.539295e-05, 0.000000e+00, 11, 1750, 1)] +neutron [((6.474155e+00, -5.192870e+00, 5.413003e+00), (-9.597810e-01, -1.081529e-01, -2.590820e-01), 9.900333e+05, 4.450859e-05, 1.000000e+00, 21, 2367, 2) + ((6.142109e+00, -5.230286e+00, 5.323371e+00), (-9.597810e-01, -1.081529e-01, -2.590820e-01), 9.900333e+05, 4.450884e-05, 1.000000e+00, 22, 2367, 3) + ((6.041244e+00, -5.241652e+00, 5.296144e+00), (-9.597810e-01, -1.081529e-01, -2.590820e-01), 9.900333e+05, 4.450892e-05, 1.000000e+00, 23, 2367, 1) + ((6.004037e+00, -5.245845e+00, 5.286100e+00), (-6.195407e-01, -7.332723e-01, -2.801446e-01), 5.512347e+05, 4.450895e-05, 1.000000e+00, 23, 2367, 1) + ((5.725160e+00, -5.575916e+00, 5.159997e+00), (-6.195407e-01, -7.332723e-01, -2.801446e-01), 5.512347e+05, 4.450939e-05, 1.000000e+00, 23, 2366, 1) + ((5.599064e+00, -5.725160e+00, 5.102979e+00), (-6.195407e-01, -7.332723e-01, -2.801446e-01), 5.512347e+05, 4.450958e-05, 1.000000e+00, 23, 2352, 1) + ((5.296886e+00, -6.082810e+00, 4.966340e+00), (-6.195407e-01, -7.332723e-01, -2.801446e-01), 5.512347e+05, 4.451006e-05, 1.000000e+00, 22, 2352, 3) + ((5.240003e+00, -6.150135e+00, 4.940619e+00), (-6.195407e-01, -7.332723e-01, -2.801446e-01), 5.512347e+05, 4.451015e-05, 1.000000e+00, 21, 2352, 2) + ((4.752072e+00, -6.727638e+00, 4.719986e+00), (3.721510e-02, -9.647240e-01, 2.606197e-01), 5.045933e+05, 4.451092e-05, 1.000000e+00, 21, 2352, 2) + ((4.764028e+00, -7.037568e+00, 4.803713e+00), (3.721510e-02, -9.647240e-01, 2.606197e-01), 5.045933e+05, 4.451124e-05, 1.000000e+00, 22, 2352, 3) + ((4.767580e+00, -7.129630e+00, 4.828584e+00), (3.721510e-02, -9.647240e-01, 2.606197e-01), 5.045933e+05, 4.451134e-05, 1.000000e+00, 23, 2352, 1) + ((4.776502e+00, -7.360920e+00, 4.891066e+00), (3.721510e-02, -9.647240e-01, 2.606197e-01), 5.045933e+05, 4.451158e-05, 1.000000e+00, 23, 2338, 1) + ((4.778286e+00, -7.407162e+00, 4.903559e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451163e-05, 1.000000e+00, 23, 2338, 1) + ((4.981926e+00, -7.580442e+00, 5.259893e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451239e-05, 1.000000e+00, 22, 2338, 3) + ((5.154144e+00, -7.726985e+00, 5.561246e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451303e-05, 1.000000e+00, 21, 2338, 2) + ((5.313757e+00, -7.862801e+00, 5.840540e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451362e-05, 1.000000e+00, 22, 2338, 3) + ((5.485976e+00, -8.009344e+00, 6.141893e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451426e-05, 1.000000e+00, 23, 2338, 1) + ((5.725160e+00, -8.212869e+00, 6.560424e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451515e-05, 1.000000e+00, 23, 2339, 1) + ((6.004950e+00, -8.450945e+00, 7.050007e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451618e-05, 1.000000e+00, 22, 2339, 3) + ((6.360530e+00, -8.753512e+00, 7.672210e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451750e-05, 1.000000e+00, 23, 2339, 1) + ((6.646303e+00, -8.996680e+00, 8.172263e+00), (4.571054e-01, -3.889563e-01, 7.998548e-01), 1.818775e+05, 4.451856e-05, 1.000000e+00, 23, 2326, 1) + ((6.702490e+00, -9.044491e+00, 8.270582e+00), (2.028534e-01, -9.607965e-01, -1.889990e-01), 1.805295e+04, 4.451877e-05, 1.000000e+00, 23, 2326, 1) + ((6.745127e+00, -9.246436e+00, 8.230857e+00), (2.028534e-01, -9.607965e-01, -1.889990e-01), 1.805295e+04, 4.451990e-05, 1.000000e+00, 22, 2326, 3) + ((6.767219e+00, -9.351070e+00, 8.210274e+00), (2.028534e-01, -9.607965e-01, -1.889990e-01), 1.805295e+04, 4.452049e-05, 1.000000e+00, 21, 2326, 2) + ((6.885344e+00, -9.910562e+00, 8.100216e+00), (-3.857824e-01, -3.006310e-01, -8.722344e-01), 1.795765e+04, 4.452362e-05, 1.000000e+00, 21, 2326, 2) + ((6.803615e+00, -9.974251e+00, 7.915431e+00), (-7.096135e-01, 6.778415e-01, 1.923009e-01), 1.779137e+04, 4.452476e-05, 1.000000e+00, 21, 2326, 2) + ((6.334815e+00, -9.526441e+00, 8.042473e+00), (-1.748210e-01, 9.821705e-01, -6.912779e-02), 1.729669e+04, 4.452835e-05, 1.000000e+00, 21, 2326, 2) + ((6.304853e+00, -9.358111e+00, 8.030625e+00), (-1.748210e-01, 9.821705e-01, -6.912779e-02), 1.729669e+04, 4.452929e-05, 1.000000e+00, 22, 2326, 3) + ((6.288777e+00, -9.267793e+00, 8.024268e+00), (-1.748210e-01, 9.821705e-01, -6.912779e-02), 1.729669e+04, 4.452979e-05, 1.000000e+00, 23, 2326, 1) + ((6.275105e+00, -9.190979e+00, 8.018862e+00), (-7.174952e-01, 5.897531e-01, -3.706642e-01), 9.207900e+03, 4.453022e-05, 1.000000e+00, 23, 2326, 1) + ((6.038719e+00, -8.996680e+00, 7.896743e+00), (-7.174952e-01, 5.897531e-01, -3.706642e-01), 9.207900e+03, 4.453271e-05, 1.000000e+00, 23, 2339, 1) + ((6.028805e+00, -8.988531e+00, 7.891621e+00), (-2.989803e-01, 4.300779e-01, -8.518473e-01), 5.653774e+03, 4.453281e-05, 1.000000e+00, 23, 2339, 1) + ((5.725160e+00, -8.551743e+00, 7.026484e+00), (-2.989803e-01, 4.300779e-01, -8.518473e-01), 5.653774e+03, 4.454257e-05, 1.000000e+00, 23, 2338, 1) + ((5.507324e+00, -8.238390e+00, 6.405832e+00), (-2.989803e-01, 4.300779e-01, -8.518473e-01), 5.653774e+03, 4.454958e-05, 1.000000e+00, 22, 2338, 3) + ((5.417387e+00, -8.109017e+00, 6.149584e+00), (-2.989803e-01, 4.300779e-01, -8.518473e-01), 5.653774e+03, 4.455247e-05, 1.000000e+00, 21, 2338, 2) + ((5.162017e+00, -7.741671e+00, 5.421991e+00), (7.522612e-01, -1.036919e-01, -6.506543e-01), 5.619608e+03, 4.456069e-05, 1.000000e+00, 21, 2338, 2) + ((5.184146e+00, -7.744722e+00, 5.402851e+00), (7.522612e-01, -1.036919e-01, -6.506543e-01), 5.619608e+03, 4.456097e-05, 1.000000e+00, 22, 2338, 3) + ((5.348057e+00, -7.767315e+00, 5.261079e+00), (7.522612e-01, -1.036919e-01, -6.506543e-01), 5.619608e+03, 4.456307e-05, 1.000000e+00, 23, 2338, 1) + ((5.581568e+00, -7.799502e+00, 5.059108e+00), (2.029690e-01, -4.131185e-01, -8.877706e-01), 3.359662e+03, 4.456606e-05, 1.000000e+00, 23, 2338, 1) + ((5.707007e+00, -8.054818e+00, 4.510447e+00), (3.894183e-01, -7.459178e-01, -5.403333e-01), 3.303714e+03, 4.457377e-05, 1.000000e+00, 23, 2338, 1) + ((5.725160e+00, -8.089590e+00, 4.485259e+00), (3.894183e-01, -7.459178e-01, -5.403333e-01), 3.303714e+03, 4.457436e-05, 1.000000e+00, 23, 2339, 1) + ((5.750893e+00, -8.138881e+00, 4.449554e+00), (-2.879829e-01, -5.545287e-01, -7.807456e-01), 1.744626e+03, 4.457519e-05, 1.000000e+00, 23, 2339, 1) + ((5.725160e+00, -8.188431e+00, 4.379790e+00), (-2.879829e-01, -5.545287e-01, -7.807456e-01), 1.744626e+03, 4.457674e-05, 1.000000e+00, 23, 2338, 1) + ((5.532143e+00, -8.560097e+00, 3.856504e+00), (-6.185172e-01, -7.766669e-01, -1.192687e-01), 8.559363e+02, 4.458834e-05, 1.000000e+00, 23, 2338, 1) + ((5.522333e+00, -8.572415e+00, 3.854613e+00), (-3.452053e-01, -2.657159e-02, -9.381510e-01), 9.272133e+01, 4.458873e-05, 1.000000e+00, 23, 2338, 1) + ((5.366948e+00, -8.584375e+00, 3.432328e+00), (4.761677e-01, -8.187551e-01, -3.207871e-01), 6.522002e+00, 4.462253e-05, 1.000000e+00, 23, 2338, 1) + ((5.516634e+00, -8.841755e+00, 3.331487e+00), (4.237115e-01, -6.022578e-01, 6.765752e-01), 9.968491e-01, 4.471152e-05, 1.000000e+00, 23, 2338, 1) + ((5.625629e+00, -8.996680e+00, 3.505530e+00), (4.237115e-01, -6.022578e-01, 6.765752e-01), 9.968491e-01, 4.489779e-05, 1.000000e+00, 23, 2325, 1) + ((5.723424e+00, -9.135684e+00, 3.661687e+00), (7.706137e-01, -6.358415e-01, 4.312932e-02), 5.695813e-01, 4.506493e-05, 1.000000e+00, 23, 2325, 1) + ((5.725160e+00, -9.137116e+00, 3.661784e+00), (7.706137e-01, -6.358415e-01, 4.312932e-02), 5.695813e-01, 4.506708e-05, 1.000000e+00, 23, 2326, 1) + ((6.079210e+00, -9.429247e+00, 3.681599e+00), (7.706137e-01, -6.358415e-01, 4.312932e-02), 5.695813e-01, 4.550721e-05, 1.000000e+00, 22, 2326, 3) + ((6.147194e+00, -9.485341e+00, 3.685404e+00), (7.706137e-01, -6.358415e-01, 4.312932e-02), 5.695813e-01, 4.559172e-05, 1.000000e+00, 21, 2326, 2) + ((6.864744e+00, -1.007740e+01, 3.725564e+00), (3.888690e-01, -8.895503e-01, -2.397522e-01), 5.691123e-01, 4.648372e-05, 1.000000e+00, 21, 2326, 2) + ((6.908415e+00, -1.017730e+01, 3.698639e+00), (3.888690e-01, -8.895503e-01, -2.397522e-01), 5.691123e-01, 4.659135e-05, 1.000000e+00, 22, 2326, 3) + ((6.945959e+00, -1.026318e+01, 3.675492e+00), (3.888690e-01, -8.895503e-01, -2.397522e-01), 5.691123e-01, 4.668388e-05, 1.000000e+00, 23, 2326, 1) + ((6.966122e+00, -1.030930e+01, 3.663060e+00), (7.493672e-01, -6.303754e-01, 2.026713e-01), 2.849108e-01, 4.673357e-05, 1.000000e+00, 23, 2326, 1) + ((7.350254e+00, -1.063244e+01, 3.766951e+00), (7.493672e-01, -6.303754e-01, 2.026713e-01), 2.849108e-01, 4.742789e-05, 1.000000e+00, 23, 2311, 1) + ((7.360920e+00, -1.064141e+01, 3.769836e+00), (7.493672e-01, -6.303754e-01, 2.026713e-01), 2.849108e-01, 4.744717e-05, 1.000000e+00, 23, 2312, 1) + ((7.449168e+00, -1.071565e+01, 3.793703e+00), (1.626881e-01, -1.480918e-01, 9.755006e-01), 2.025207e-01, 4.760667e-05, 1.000000e+00, 23, 2312, 1) + ((7.495754e+00, -1.075805e+01, 4.073039e+00), (-1.185723e-01, -6.787603e-01, 7.247241e-01), 2.121260e-01, 4.806671e-05, 1.000000e+00, 23, 2312, 1) + ((7.451135e+00, -1.101347e+01, 4.345753e+00), (-4.978877e-01, -3.750598e-02, 8.664301e-01), 2.609768e-02, 4.865741e-05, 1.000000e+00, 23, 2312, 1) + ((7.426401e+00, -1.101533e+01, 4.388795e+00), (9.221835e-01, -6.407530e-02, 3.814078e-01), 2.031765e-02, 4.887973e-05, 1.000000e+00, 23, 2312, 1) + ((7.438938e+00, -1.101621e+01, 4.393980e+00), (8.832139e-01, 3.563144e-01, 3.049151e-01), 2.038019e-02, 4.894869e-05, 1.000000e+00, 23, 2312, 1) + ((7.578355e+00, -1.095996e+01, 4.442112e+00), (5.564936e-01, 8.135970e-01, 1.684482e-01), 4.869241e-02, 4.974811e-05, 1.000000e+00, 23, 2312, 1) + ((7.802376e+00, -1.063244e+01, 4.509922e+00), (5.564936e-01, 8.135970e-01, 1.684482e-01), 4.869241e-02, 5.106705e-05, 1.000000e+00, 23, 2327, 1) + ((7.826035e+00, -1.059785e+01, 4.517083e+00), (-8.227572e-01, -5.662268e-01, 4.957651e-02), 8.202195e-02, 5.120634e-05, 1.000000e+00, 23, 2327, 1) + ((7.775776e+00, -1.063244e+01, 4.520112e+00), (-8.227572e-01, -5.662268e-01, 4.957651e-02), 8.202195e-02, 5.136055e-05, 1.000000e+00, 23, 2312, 1) + ((7.360920e+00, -1.091795e+01, 4.545109e+00), (-8.227572e-01, -5.662268e-01, 4.957651e-02), 8.202195e-02, 5.263343e-05, 1.000000e+00, 23, 2311, 1) + ((7.180267e+00, -1.104227e+01, 4.555995e+00), (5.568446e-01, -6.706436e-01, -4.900625e-01), 5.560680e-02, 5.318772e-05, 1.000000e+00, 23, 2311, 1) + ((7.207392e+00, -1.107494e+01, 4.532123e+00), (9.936512e-01, 4.529367e-02, -1.029847e-01), 8.142074e-02, 5.333706e-05, 1.000000e+00, 23, 2311, 1) + ((7.252245e+00, -1.107290e+01, 4.527474e+00), (9.936512e-01, 4.529367e-02, -1.029847e-01), 8.142074e-02, 5.345144e-05, 0.000000e+00, 23, 2311, 1)] diff --git a/tests/regression_tests/translation/results_true.dat b/tests/regression_tests/translation/results_true.dat index f832aa2964..6e03d2224f 100644 --- a/tests/regression_tests/translation/results_true.dat +++ b/tests/regression_tests/translation/results_true.dat @@ -1,2 +1,2 @@ k-combined: -4.087580E-01 4.466279E-03 +4.076610E-01 6.454244E-03 diff --git a/tests/regression_tests/trigger_batch_interval/results_true.dat b/tests/regression_tests/trigger_batch_interval/results_true.dat index 0571d6c4f9..92fa99d87a 100644 --- a/tests/regression_tests/trigger_batch_interval/results_true.dat +++ b/tests/regression_tests/trigger_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.767929E-01 5.327552E-03 +9.863217E-01 6.499354E-03 tally 1: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 tally 2: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 diff --git a/tests/regression_tests/trigger_no_batch_interval/results_true.dat b/tests/regression_tests/trigger_no_batch_interval/results_true.dat index 0571d6c4f9..92fa99d87a 100644 --- a/tests/regression_tests/trigger_no_batch_interval/results_true.dat +++ b/tests/regression_tests/trigger_no_batch_interval/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.767929E-01 5.327552E-03 +9.863217E-01 6.499354E-03 tally 1: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 tally 2: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 diff --git a/tests/regression_tests/trigger_no_status/results_true.dat b/tests/regression_tests/trigger_no_status/results_true.dat index fb6c0086ab..a62e1b3fe5 100644 --- a/tests/regression_tests/trigger_no_status/results_true.dat +++ b/tests/regression_tests/trigger_no_status/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.682315E-01 3.302924E-03 +9.858966E-01 1.500542E-02 tally 1: -7.046510E+00 -9.932168E+00 -1.591675E+00 -5.067777E-01 -1.541572E+00 -4.753743E-01 -5.454835E+00 -5.951990E+00 -7.046510E+00 -9.932168E+00 -1.591675E+00 -5.067777E-01 -1.541572E+00 -4.753743E-01 -5.454835E+00 -5.951990E+00 +7.081828E+00 +1.003709E+01 +1.607382E+00 +5.171386E-01 +1.559242E+00 +4.866413E-01 +5.474447E+00 +5.997737E+00 +7.081828E+00 +1.003709E+01 +1.607382E+00 +5.171386E-01 +1.559242E+00 +4.866413E-01 +5.474447E+00 +5.997737E+00 tally 2: -7.046510E+00 -9.932168E+00 -1.591675E+00 -5.067777E-01 -1.541572E+00 -4.753743E-01 -5.454835E+00 -5.951990E+00 +7.081828E+00 +1.003709E+01 +1.607382E+00 +5.171386E-01 +1.559242E+00 +4.866413E-01 +5.474447E+00 +5.997737E+00 diff --git a/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat b/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat index 01755ad8bc..59a8297009 100644 --- a/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat +++ b/tests/regression_tests/trigger_statepoint_restart/inputs_true.dat @@ -16,7 +16,7 @@ 15 10 - 0.003 + 0.002 std_dev diff --git a/tests/regression_tests/trigger_statepoint_restart/results_true.dat b/tests/regression_tests/trigger_statepoint_restart/results_true.dat index 3e6619d74d..3cb1e230dd 100644 --- a/tests/regression_tests/trigger_statepoint_restart/results_true.dat +++ b/tests/regression_tests/trigger_statepoint_restart/results_true.dat @@ -1,5 +1,5 @@ k-combined: -3.014717E-01 2.864764E-03 +2.948661E-01 1.949846E-03 tally 1: -8.946107E+01 -7.281263E+02 +5.515170E+01 +4.349007E+02 diff --git a/tests/regression_tests/trigger_statepoint_restart/test.py b/tests/regression_tests/trigger_statepoint_restart/test.py index 8144c1d0b0..b242f7f1cf 100644 --- a/tests/regression_tests/trigger_statepoint_restart/test.py +++ b/tests/regression_tests/trigger_statepoint_restart/test.py @@ -29,7 +29,7 @@ def model(): settings.inactive = 10 settings.particles = 400 # Choose a sufficiently low threshold to enable use of trigger - settings.keff_trigger = {'type': 'std_dev', 'threshold': 0.003} + settings.keff_trigger = {'type': 'std_dev', 'threshold': 0.002} settings.trigger_max_batches = 1000 settings.trigger_batch_interval = 1 settings.trigger_active = True @@ -41,10 +41,10 @@ def model(): tallies = openmc.Tallies([t]) # Put it all together - model = openmc.model.Model(materials=materials, - geometry=geometry, - settings=settings, - tallies=tallies) + model = openmc.Model(materials=materials, + geometry=geometry, + settings=settings, + tallies=tallies) return model diff --git a/tests/regression_tests/trigger_tallies/results_true.dat b/tests/regression_tests/trigger_tallies/results_true.dat index 0571d6c4f9..92fa99d87a 100644 --- a/tests/regression_tests/trigger_tallies/results_true.dat +++ b/tests/regression_tests/trigger_tallies/results_true.dat @@ -1,28 +1,28 @@ k-combined: -9.767929E-01 5.327552E-03 +9.863217E-01 6.499354E-03 tally 1: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 tally 2: -1.405471E+01 -1.976444E+01 -3.186139E+00 -1.015515E+00 -3.088643E+00 -9.542994E-01 -1.086857E+01 -1.182011E+01 +1.423436E+01 +2.027258E+01 +3.223740E+00 +1.039872E+00 +3.125016E+00 +9.771709E-01 +1.101062E+01 +1.212977E+01 diff --git a/tests/regression_tests/triso/results_true.dat b/tests/regression_tests/triso/results_true.dat index fa1842e547..d9850e410f 100644 --- a/tests/regression_tests/triso/results_true.dat +++ b/tests/regression_tests/triso/results_true.dat @@ -1,2 +1,2 @@ k-combined: -1.716873E+00 5.266107E-02 +1.604832E+00 2.031393E-03 diff --git a/tests/regression_tests/uniform_fs/results_true.dat b/tests/regression_tests/uniform_fs/results_true.dat index 46654b49b4..f7ceecfb73 100644 --- a/tests/regression_tests/uniform_fs/results_true.dat +++ b/tests/regression_tests/uniform_fs/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.685309E-01 1.861720E-03 +3.675645E-01 4.342970E-03 diff --git a/tests/regression_tests/universe/results_true.dat b/tests/regression_tests/universe/results_true.dat index bbf03de943..97b997ae6b 100644 --- a/tests/regression_tests/universe/results_true.dat +++ b/tests/regression_tests/universe/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.070134E-01 3.900396E-03 +2.940336E-01 7.338463E-04 diff --git a/tests/regression_tests/white_plane/results_true.dat b/tests/regression_tests/white_plane/results_true.dat index 6f1d064eb3..ffb19491dd 100644 --- a/tests/regression_tests/white_plane/results_true.dat +++ b/tests/regression_tests/white_plane/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.279719E+00 5.380792E-03 +2.274312E+00 4.223342E-03 diff --git a/tests/unit_tests/test_deplete_resultslist.py b/tests/unit_tests/test_deplete_resultslist.py index 308eccf7bb..9a4699a4fd 100644 --- a/tests/unit_tests/test_deplete_resultslist.py +++ b/tests/unit_tests/test_deplete_resultslist.py @@ -21,14 +21,14 @@ def test_get_activity(res): t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) a_ref = np.array( - [1.25167956e+06, 3.71938527e+11, 4.43264300e+11, 3.55547176e+11]) + [1.25167956e+06, 3.69842310e+11, 3.70099291e+11, 3.53629755e+11]) np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(a, a_ref) # Check by_nuclide a_xe135_ref = np.array( - [2.106574218e+05, 1.227519888e+11, 1.177491828e+11, 1.031986176e+11]) + [2.10657422e+05, 1.12825236e+11, 1.09055177e+11, 1.07491257e+11]) t_nuc, a_nuc = res.get_activity("1", by_nuclide=True) a_xe135 = np.array([a_nuc_i["Xe135"] for a_nuc_i in a_nuc]) @@ -43,7 +43,7 @@ def test_get_atoms(res): t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) n_ref = np.array( - [6.67473282e+08, 3.88942731e+14, 3.73091215e+14, 3.26987387e+14]) + [6.67473282e+08, 3.57489567e+14, 3.45544042e+14, 3.40588723e+14]) np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(n, n_ref) @@ -71,7 +71,7 @@ def test_get_decay_heat(res): t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) dh_ref = np.array( - [1.27933813e-09, 5.85347232e-03, 7.38773010e-03, 5.79954067e-03]) + [1.27933813e-09, 5.95370258e-03, 6.01335600e-03, 5.69831173e-03]) t, dh = res.get_decay_heat("1") @@ -80,7 +80,7 @@ def test_get_decay_heat(res): # Check by nuclide dh_xe135_ref = np.array( - [1.27933813e-09, 7.45481920e-04, 7.15099509e-04, 6.26732849e-04]) + [1.27933813e-09, 6.85196014e-04, 6.62300168e-04, 6.52802366e-04]) t_nuc, dh_nuc = res.get_decay_heat("1", by_nuclide=True) dh_nuc_xe135 = np.array([dh_nuc_i["Xe135"] for dh_nuc_i in dh_nuc]) @@ -95,7 +95,7 @@ def test_get_mass(res): t_ref = np.array([0.0, 1296000.0, 2592000.0, 3888000.0]) n_ref = np.array( - [6.67473282e+08, 3.88942731e+14, 3.73091215e+14, 3.26987387e+14]) + [6.67473282e+08, 3.57489567e+14, 3.45544042e+14, 3.40588723e+14]) # Get g n_ref *= openmc.data.atomic_mass('Xe135') / openmc.data.AVOGADRO @@ -123,8 +123,8 @@ def test_get_reaction_rate(res): t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)") t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - n_ref = [6.67473282e+08, 3.88942731e+14, 3.73091215e+14, 3.26987387e+14] - xs_ref = [2.53336104e-05, 4.21747011e-05, 3.48616127e-05, 3.61775563e-05] + n_ref = [6.67473282e+08, 3.57489567e+14, 3.45544042e+14, 3.40588723e+14] + xs_ref = [3.10220818e-05, 3.36754072e-05, 3.12740350e-05, 3.86717693e-05] np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(r, np.array(n_ref) * xs_ref) @@ -136,8 +136,8 @@ def test_get_keff(res): t_min, k = res.get_keff(time_units='min') t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0] - k_ref = [1.1596402556, 1.1914183335, 1.2292570871, 1.1797030302] - u_ref = [0.0270680649, 0.0219163444, 0.024268508 , 0.0221401194] + k_ref = [1.1773089172, 1.2231748584, 1.1611455694, 1.1714783649] + u_ref = [0.0384666252, 0.0311915665, 0.0226370102, 0.0315964732] np.testing.assert_allclose(t, t_ref) np.testing.assert_allclose(t_min * 60, t_ref) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 8080ce8948..43bc5a8f6f 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -161,16 +161,21 @@ def test_properties_temperature(lib_init): def test_cell_density(lib_init): cell = openmc.lib.cells[1] - cell.set_density(1.5, 0) - assert cell.get_density(0) == pytest.approx(1.5) - cell.set_density(2.0) - assert cell.get_density() == pytest.approx(2.0) + print('density', cell.get_density()) + orig_density = cell.get_density() + try: + cell.set_density(1.5, 0) + assert cell.get_density(0) == pytest.approx(1.5) + cell.set_density(2.0) + assert cell.get_density() == pytest.approx(2.0) + finally: + cell.set_density(orig_density) def test_properties_cell_density(lib_init): # Cell density should be 2.0 from above test cell = openmc.lib.cells[1] - assert cell.get_density() == pytest.approx(2.0) + orig_density = cell.get_density() # Export properties and change density openmc.lib.export_properties('properties.h5') @@ -179,7 +184,7 @@ def test_properties_cell_density(lib_init): # Import properties and check that density is restored openmc.lib.import_properties('properties.h5') - assert cell.get_density() == pytest.approx(2.0) + assert cell.get_density() == pytest.approx(orig_density) def test_new_cell(lib_init): diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 7f202bcdc7..6611e4227e 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -67,6 +67,7 @@ def test_export_to_xml(run_in_tmpdir): ) } s.max_particle_events = 100 + s.max_secondaries = 1_000_000 s.source_rejection_fraction = 0.01 # Make sure exporting XML works @@ -144,4 +145,5 @@ def test_export_to_xml(run_in_tmpdir): assert s.random_ray['distance_active'] == 100.0 assert s.random_ray['ray_source'].space.lower_left == [-1., -1., -1.] assert s.random_ray['ray_source'].space.upper_right == [1., 1., 1.] + assert s.max_secondaries == 1_000_000 assert s.source_rejection_fraction == 0.01 diff --git a/tests/unit_tests/test_statepoint_batches.py b/tests/unit_tests/test_statepoint_batches.py new file mode 100644 index 0000000000..bf54e18786 --- /dev/null +++ b/tests/unit_tests/test_statepoint_batches.py @@ -0,0 +1,26 @@ +from pathlib import Path + +import openmc + + +def test_statepoint_batches(run_in_tmpdir): + # Create a minimal model + mat = openmc.Material() + mat.add_nuclide('U235', 1.0) + mat.set_density('g/cm3', 4.5) + sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sphere) + model = openmc.Model() + model.geometry = openmc.Geometry([cell]) + model.settings.batches = 10 + model.settings.inactive = 5 + model.settings.particles = 100 + + # Specify when statepoints should be written + model.settings.statepoint = {'batches': [3, 6, 9]} + + # Run model and ensure that statepoints are created + model.run() + sp_files = ['statepoint.03.h5', 'statepoint.06.h5', 'statepoint.09.h5'] + for f in sp_files: + assert Path(f).is_file() From ca63da91b9b0fc0cd144766155b533318d4a71c3 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Fri, 19 Sep 2025 15:00:51 -0500 Subject: [PATCH 10/76] Ensure n_dimension_ attribute is set for unstructured meshes. (#3575) --- include/openmc/mesh.h | 3 +-- src/mesh.cpp | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index c15e256977..fbc6c46f50 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -666,9 +666,8 @@ class UnstructuredMesh : public Mesh { public: // Constructors - UnstructuredMesh() {}; + UnstructuredMesh() { n_dimension_ = 3; }; UnstructuredMesh(pugi::xml_node node); - UnstructuredMesh(const std::string& filename); static const std::string mesh_type; virtual std::string get_mesh_type() const override; diff --git a/src/mesh.cpp b/src/mesh.cpp index 3e4ff1a3ec..b7396a25ab 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -590,6 +590,8 @@ Position StructuredMesh::sample_element( UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) { + n_dimension_ = 3; + // check the mesh type if (check_for_node(node, "type")) { auto temp = get_node_value(node, "type", true, true); @@ -2519,7 +2521,9 @@ MOABMesh::MOABMesh(pugi::xml_node node) : UnstructuredMesh(node) } MOABMesh::MOABMesh(const std::string& filename, double length_multiplier) + : UnstructuredMesh() { + n_dimension_ = 3; filename_ = filename; set_length_multiplier(length_multiplier); initialize(); @@ -3242,6 +3246,7 @@ LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) LibMesh::LibMesh(const std::string& filename, double length_multiplier) : adaptive_(false) { + n_dimension_ = 3; set_mesh_pointer_from_filename(filename); set_length_multiplier(length_multiplier); initialize(); From 8f36ff2b3a5e2984254f7b21f1b92af7ad18140b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 23 Sep 2025 10:06:29 -0500 Subject: [PATCH 11/76] Update find_package calls in OpenMCConfig.cmake (#3572) --- cmake/OpenMCConfig.cmake.in | 11 +++++++---- openmc/deplete/transfer_rates.py | 2 +- tests/regression_tests/unstructured_mesh/test.py | 2 +- tests/unit_tests/dagmc/test_plot.py | 5 ++++- tests/unit_tests/test_model.py | 4 ++++ tests/unit_tests/test_region.py | 4 ++++ tests/unit_tests/test_universe.py | 4 ++++ tests/unit_tests/weightwindows/test_wwinp_reader.py | 2 +- tools/ci/gha-script.sh | 5 ++++- 9 files changed, 30 insertions(+), 9 deletions(-) diff --git a/cmake/OpenMCConfig.cmake.in b/cmake/OpenMCConfig.cmake.in index 3fe0c1bcd1..837a39c783 100644 --- a/cmake/OpenMCConfig.cmake.in +++ b/cmake/OpenMCConfig.cmake.in @@ -1,9 +1,12 @@ get_filename_component(OpenMC_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) -find_package(fmt REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../fmt) -find_package(pugixml REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../pugixml) -find_package(xtl REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtl) -find_package(xtensor REQUIRED HINTS ${OpenMC_CMAKE_DIR}/../xtensor) +# Compute the install prefix from this file's location +get_filename_component(_OPENMC_PREFIX "${OpenMC_CMAKE_DIR}/../../.." ABSOLUTE) + +find_package(fmt CONFIG REQUIRED HINTS ${_OPENMC_PREFIX}) +find_package(pugixml CONFIG REQUIRED HINTS ${_OPENMC_PREFIX}) +find_package(xtl CONFIG REQUIRED HINTS ${_OPENMC_PREFIX}) +find_package(xtensor CONFIG REQUIRED HINTS ${_OPENMC_PREFIX}) if(@OPENMC_USE_DAGMC@) find_package(DAGMC REQUIRED HINTS @DAGMC_DIR@) endif() diff --git a/openmc/deplete/transfer_rates.py b/openmc/deplete/transfer_rates.py index 4c28c7d150..4f2b9aba5f 100644 --- a/openmc/deplete/transfer_rates.py +++ b/openmc/deplete/transfer_rates.py @@ -366,7 +366,7 @@ class ExternalSourceRates(ExternalRates): rate : float External source rate in units of mass per time. A positive or negative value corresponds to a feed or removal rate, respectively. - units : {'g/s', 'g/min', 'g/h', 'g/d', 'g/a'} + rate_units : {'g/s', 'g/min', 'g/h', 'g/d', 'g/a'} Units for values specified in the `rate` argument. 's' for seconds, 'min' for minutes, 'h' for hours, 'a' for Julian years. timesteps : list of int, optional diff --git a/tests/regression_tests/unstructured_mesh/test.py b/tests/regression_tests/unstructured_mesh/test.py index 0082198dde..7607531d8b 100644 --- a/tests/regression_tests/unstructured_mesh/test.py +++ b/tests/regression_tests/unstructured_mesh/test.py @@ -256,7 +256,7 @@ for i, (lib, estimator, ext_geom, holes) in enumerate(product(*param_values)): def test_unstructured_mesh_tets(model, test_opts): # skip the test if the library is not enabled if test_opts['library'] == 'moab' and not openmc.lib._dagmc_enabled(): - pytest.skip("DAGMC (and MOAB) mesh not enbaled in this build.") + pytest.skip("DAGMC (and MOAB) mesh not enabled in this build.") if test_opts['library'] == 'libmesh' and not openmc.lib._libmesh_enabled(): pytest.skip("LibMesh is not enabled in this build.") diff --git a/tests/unit_tests/dagmc/test_plot.py b/tests/unit_tests/dagmc/test_plot.py index 62022b2583..6ce1d79a22 100644 --- a/tests/unit_tests/dagmc/test_plot.py +++ b/tests/unit_tests/dagmc/test_plot.py @@ -64,5 +64,8 @@ def test_plotting_geometry_filled_with_dagmc_universe(request): cell2 = openmc.Cell(fill=csg_material, region=+sphere1 & -sphere2) geometry = openmc.Geometry([cell1, cell2]) - geometry.plot() + + # Close plot to avoid warning + import matplotlib.pyplot as plt + plt.close() diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 12f0df6c9e..60f8b1a25a 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -654,6 +654,10 @@ def test_model_plot(): test_mask = (image_data == white) | (image_data == red) assert np.all(test_mask), "Colors other than white or red found in overlap plot image" + # Close plots to avoid warning + import matplotlib.pyplot as plt + plt.close('all') + def test_model_id_map_initialization(run_in_tmpdir): model = openmc.examples.pwr_assembly() diff --git a/tests/unit_tests/test_region.py b/tests/unit_tests/test_region.py index cbcd198312..cb9fa171bb 100644 --- a/tests/unit_tests/test_region.py +++ b/tests/unit_tests/test_region.py @@ -248,6 +248,10 @@ def test_plot(): c_before = openmc.Cell() region.plot() + # Close plot to avoid warning + import matplotlib.pyplot as plt + plt.close() + # Ensure that calling plot doesn't affect cell ID space c_after = openmc.Cell() assert c_after.id - 1 == c_before.id diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 46d4ec3f73..efe8552a64 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -99,6 +99,10 @@ def test_plot(run_in_tmpdir, sphere_model): pixels=100, ) + # Close plots to avoid warning + import matplotlib.pyplot as plt + plt.close('all') + def test_get_nuclides(uo2): c = openmc.Cell(fill=uo2) diff --git a/tests/unit_tests/weightwindows/test_wwinp_reader.py b/tests/unit_tests/weightwindows/test_wwinp_reader.py index 28548a4486..637463bb2e 100644 --- a/tests/unit_tests/weightwindows/test_wwinp_reader.py +++ b/tests/unit_tests/weightwindows/test_wwinp_reader.py @@ -140,4 +140,4 @@ def test_wwinp_reader_failures(wwinp_data, request): filename, expected_failure = wwinp_data with pytest.raises(expected_failure): - _ = openmc.wwinp_to_wws(request.node.path.parent / filename) + _ = openmc.WeightWindowsList.from_wwinp(request.node.path.parent / filename) diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index c0f754c32c..c1d2921377 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -15,4 +15,7 @@ if [[ $EVENT == 'y' ]]; then fi # Run unit tests and then regression tests -pytest --cov=openmc -v $args tests/unit_tests tests/regression_tests +pytest --cov=openmc -v $args \ + tests/test_matplotlib_import.py \ + tests/unit_tests \ + tests/regression_tests From ed433fe1cd9479e355cfe4ca6ec8fb99359f98cf Mon Sep 17 00:00:00 2001 From: Kevin Sawatzky <66632997+nuclearkevin@users.noreply.github.com> Date: Tue, 23 Sep 2025 11:31:14 -0500 Subject: [PATCH 12/76] Fix performance regression in libMesh unstructured mesh tallies (#3577) --- include/openmc/mesh.h | 49 ++++++++++++++----- src/mesh.cpp | 109 ++++++++++++++++++++++++------------------ 2 files changed, 101 insertions(+), 57 deletions(-) diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index fbc6c46f50..a56705c9ec 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -990,25 +990,26 @@ public: libMesh::MeshBase* mesh_ptr() const { return m_; }; +protected: + // Methods + + //! Translate a bin value to an element reference + virtual const libMesh::Elem& get_element_from_bin(int bin) const; + + //! Translate an element pointer to a bin index + virtual int get_bin_from_element(const libMesh::Elem* elem) const; + + libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set + //!< during intialization private: void initialize() override; void set_mesh_pointer_from_filename(const std::string& filename); void build_eqn_sys(); - // Methods - - //! Translate a bin value to an element reference - const libMesh::Elem& get_element_from_bin(int bin) const; - - //! Translate an element pointer to a bin index - int get_bin_from_element(const libMesh::Elem* elem) const; - // Data members unique_ptr unique_m_ = nullptr; //!< pointer to the libMesh MeshBase instance, only used if mesh is //!< created inside OpenMC - libMesh::MeshBase* m_; //!< pointer to libMesh MeshBase instance, always set - //!< during intialization vector> pl_; //!< per-thread point locators unique_ptr @@ -1022,8 +1023,34 @@ private: libMesh::BoundingBox bbox_; //!< bounding box of the mesh libMesh::dof_id_type first_element_id_; //!< id of the first element in the mesh +}; + +class AdaptiveLibMesh : public LibMesh { +public: + // Constructor + AdaptiveLibMesh( + libMesh::MeshBase& input_mesh, double length_multiplier = 1.0); + + // Overridden methods + int n_bins() const override; + + void add_score(const std::string& var_name) override; + + void set_score_data(const std::string& var_name, const vector& values, + const vector& std_dev) override; + + void write(const std::string& filename) const override; + +protected: + // Overridden methods + int get_bin_from_element(const libMesh::Elem* elem) const override; + + const libMesh::Elem& get_element_from_bin(int bin) const override; + +private: + // Data members + const libMesh::dof_id_type num_active_; //!< cached number of active elements - const bool adaptive_; //!< whether this mesh has adaptivity enabled or not std::vector bin_to_elem_map_; //!< mapping bin indices to dof indices for active //!< elements diff --git a/src/mesh.cpp b/src/mesh.cpp index b7396a25ab..58d218b9ca 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -3219,7 +3219,7 @@ void MOABMesh::write(const std::string& base_filename) const const std::string LibMesh::mesh_lib_type = "libmesh"; -LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node), adaptive_(false) +LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) { // filename_ and length_multiplier_ will already be set by the // UnstructuredMesh constructor @@ -3230,7 +3230,6 @@ LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node), adaptive_(false) // create the mesh from a pointer to a libMesh Mesh LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) - : adaptive_(input_mesh.n_active_elem() != input_mesh.n_elem()) { if (!dynamic_cast(&input_mesh)) { fatal_error("At present LibMesh tallies require a replicated mesh. Please " @@ -3244,7 +3243,6 @@ LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) // create the mesh from an input file LibMesh::LibMesh(const std::string& filename, double length_multiplier) - : adaptive_(false) { n_dimension_ = 3; set_mesh_pointer_from_filename(filename); @@ -3307,21 +3305,6 @@ void LibMesh::initialize() auto first_elem = *m_->elements_begin(); first_element_id_ = first_elem->id(); - // if the mesh is adaptive elements aren't guaranteed by libMesh to be - // contiguous in ID space, so we need to map from bin indices (defined over - // active elements) to global dof ids - if (adaptive_) { - bin_to_elem_map_.reserve(m_->n_active_elem()); - elem_to_bin_map_.resize(m_->n_elem(), -1); - for (auto it = m_->active_elements_begin(); it != m_->active_elements_end(); - it++) { - auto elem = *it; - - bin_to_elem_map_.push_back(elem->id()); - elem_to_bin_map_[elem->id()] = bin_to_elem_map_.size() - 1; - } - } - // bounding box for the mesh for quick rejection checks bbox_ = libMesh::MeshTools::create_bounding_box(*m_); libMesh::Point ll = bbox_.min(); @@ -3379,7 +3362,7 @@ std::string LibMesh::library() const int LibMesh::n_bins() const { - return m_->n_active_elem(); + return m_->n_elem(); } int LibMesh::n_surface_bins() const @@ -3402,14 +3385,6 @@ int LibMesh::n_surface_bins() const void LibMesh::add_score(const std::string& var_name) { - if (adaptive_) { - warning(fmt::format( - "Exodus output cannot be provided as unstructured mesh {} is adaptive.", - this->id_)); - - return; - } - if (!equation_systems_) { build_eqn_sys(); } @@ -3445,14 +3420,6 @@ void LibMesh::remove_scores() void LibMesh::set_score_data(const std::string& var_name, const vector& values, const vector& std_dev) { - if (adaptive_) { - warning(fmt::format( - "Exodus output cannot be provided as unstructured mesh {} is adaptive.", - this->id_)); - - return; - } - if (!equation_systems_) { build_eqn_sys(); } @@ -3496,14 +3463,6 @@ void LibMesh::set_score_data(const std::string& var_name, void LibMesh::write(const std::string& filename) const { - if (adaptive_) { - warning(fmt::format( - "Exodus output cannot be provided as unstructured mesh {} is adaptive.", - this->id_)); - - return; - } - write_message(fmt::format( "Writing file: {}.e for unstructured mesh {}", filename, this->id_)); libMesh::ExodusII_IO exo(*m_); @@ -3537,8 +3496,7 @@ int LibMesh::get_bin(Position r) const int LibMesh::get_bin_from_element(const libMesh::Elem* elem) const { - int bin = - adaptive_ ? elem_to_bin_map_[elem->id()] : elem->id() - first_element_id_; + int bin = elem->id() - first_element_id_; if (bin >= n_bins() || bin < 0) { fatal_error(fmt::format("Invalid bin: {}", bin)); } @@ -3553,7 +3511,7 @@ std::pair, vector> LibMesh::plot( const libMesh::Elem& LibMesh::get_element_from_bin(int bin) const { - return adaptive_ ? m_->elem_ref(bin_to_elem_map_.at(bin)) : m_->elem_ref(bin); + return m_->elem_ref(bin); } double LibMesh::volume(int bin) const @@ -3561,6 +3519,65 @@ double LibMesh::volume(int bin) const return this->get_element_from_bin(bin).volume(); } +AdaptiveLibMesh::AdaptiveLibMesh( + libMesh::MeshBase& input_mesh, double length_multiplier) + : LibMesh(input_mesh, length_multiplier), num_active_(m_->n_active_elem()) +{ + // if the mesh is adaptive elements aren't guaranteed by libMesh to be + // contiguous in ID space, so we need to map from bin indices (defined over + // active elements) to global dof ids + bin_to_elem_map_.reserve(num_active_); + elem_to_bin_map_.resize(m_->n_elem(), -1); + for (auto it = m_->active_elements_begin(); it != m_->active_elements_end(); + it++) { + auto elem = *it; + + bin_to_elem_map_.push_back(elem->id()); + elem_to_bin_map_[elem->id()] = bin_to_elem_map_.size() - 1; + } +} + +int AdaptiveLibMesh::n_bins() const +{ + return num_active_; +} + +void AdaptiveLibMesh::add_score(const std::string& var_name) +{ + warning(fmt::format( + "Exodus output cannot be provided as unstructured mesh {} is adaptive.", + this->id_)); +} + +void AdaptiveLibMesh::set_score_data(const std::string& var_name, + const vector& values, const vector& std_dev) +{ + warning(fmt::format( + "Exodus output cannot be provided as unstructured mesh {} is adaptive.", + this->id_)); +} + +void AdaptiveLibMesh::write(const std::string& filename) const +{ + warning(fmt::format( + "Exodus output cannot be provided as unstructured mesh {} is adaptive.", + this->id_)); +} + +int AdaptiveLibMesh::get_bin_from_element(const libMesh::Elem* elem) const +{ + int bin = elem_to_bin_map_[elem->id()]; + if (bin >= n_bins() || bin < 0) { + fatal_error(fmt::format("Invalid bin: {}", bin)); + } + return bin; +} + +const libMesh::Elem& AdaptiveLibMesh::get_element_from_bin(int bin) const +{ + return m_->elem_ref(bin_to_elem_map_.at(bin)); +} + #endif // OPENMC_LIBMESH_ENABLED //============================================================================== From 66e7d8634cbace480e3f6ccf58ca959ecfbf614e Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:02:19 +0200 Subject: [PATCH 13/76] Remove several TODOs related to C++17 support (#3574) Co-authored-by: Paul Romano --- src/bank.cpp | 13 +++---------- src/event.cpp | 13 +++++++------ src/hdf5_interface.cpp | 3 +-- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/bank.cpp b/src/bank.cpp index 9955939f6e..3e806b3c0b 100644 --- a/src/bank.cpp +++ b/src/bank.cpp @@ -79,16 +79,9 @@ void sort_fission_bank() // Perform exclusive scan summation to determine starting indices in fission // bank for each parent particle id - int64_t tmp = simulation::progeny_per_particle[0]; - simulation::progeny_per_particle[0] = 0; - for (int64_t i = 1; i < simulation::progeny_per_particle.size(); i++) { - int64_t value = simulation::progeny_per_particle[i - 1] + tmp; - tmp = simulation::progeny_per_particle[i]; - simulation::progeny_per_particle[i] = value; - } - - // TODO: C++17 introduces the exclusive_scan() function which could be - // used to replace everything above this point in this function. + std::exclusive_scan(simulation::progeny_per_particle.begin(), + simulation::progeny_per_particle.end(), + simulation::progeny_per_particle.begin(), 0); // We need a scratch vector to make permutation of the fission bank into // sorted order easy. Under normal usage conditions, the fission bank is diff --git a/src/event.cpp b/src/event.cpp index aa3987504b..f33e132d0a 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -1,4 +1,5 @@ #include "openmc/event.h" + #include "openmc/material.h" #include "openmc/simulation.h" #include "openmc/timer.h" @@ -73,17 +74,17 @@ void process_calculate_xs_events(SharedArray& queue) { simulation::time_event_calculate_xs.start(); - // TODO: If using C++17, perform a parallel sort of the queue - // by particle type, material type, and then energy, in order to - // improve cache locality and reduce thread divergence on GPU. Prior - // to C++17, std::sort is a serial only operation, which in this case - // makes it too slow to be practical for most test problems. + // TODO: If using C++17, we could perform a parallel sort of the queue by + // particle type, material type, and then energy, in order to improve cache + // locality and reduce thread divergence on GPU. However, the parallel + // algorithms typically require linking against an additional library (Intel + // TBB). Prior to C++17, std::sort is a serial only operation, which in this + // case makes it too slow to be practical for most test problems. // // std::sort(std::execution::par_unseq, queue.data(), queue.data() + // queue.size()); int64_t offset = simulation::advance_particle_queue.size(); - ; #pragma omp parallel for schedule(runtime) for (int64_t i = 0; i < queue.size(); i++) { diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index e90aa74901..bf1f79549e 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -225,8 +225,7 @@ void get_name(hid_t obj_id, std::string& name) { size_t size = 1 + H5Iget_name(obj_id, nullptr, 0); name.resize(size); - // TODO: switch to name.data() when using C++17 - H5Iget_name(obj_id, &name[0], size); + H5Iget_name(obj_id, name.data(), size); } int get_num_datasets(hid_t group_id) From 767db7e6a090b88a594be72b4971d71e3c2be243 Mon Sep 17 00:00:00 2001 From: Joffrey Dorville <54550047+JoffreyDorville@users.noreply.github.com> Date: Thu, 25 Sep 2025 14:58:29 -0500 Subject: [PATCH 14/76] Fix IFP implementation (#3580) --- include/openmc/ifp.h | 7 +++---- include/openmc/particle_data.h | 1 + src/ifp.cpp | 4 ++-- src/particle.cpp | 1 + src/physics.cpp | 9 +++------ tests/regression_tests/ifp/results_true.dat | 4 ++-- .../case-03/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-04/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-05/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-07/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-08/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-09/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-10/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-12/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-13/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-14/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-a01/surface_source_true.h5 | Bin 6720 -> 6720 bytes .../case-d07/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-d08/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e01/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e02/surface_source_true.h5 | Bin 33344 -> 33344 bytes .../case-e03/surface_source_true.h5 | Bin 33344 -> 33344 bytes 22 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/openmc/ifp.h b/include/openmc/ifp.h index 633a262d5f..01904d13c9 100644 --- a/include/openmc/ifp.h +++ b/include/openmc/ifp.h @@ -68,15 +68,14 @@ vector _ifp(const T& value, const vector& data) //! //! Add the IFP information in the IFP banks using the same index //! as the one used to append the fission site to the fission bank. +//! The information stored are the delayed group number and lifetime +//! of the neutron that created the fission event. //! Multithreading protection is guaranteed by the index returned by the //! thread_safe_append call in physics.cpp. //! -//! Needs to be done after the delayed group is found. -//! //! \param[in] p Particle -//! \param[in] site Fission site //! \param[in] idx Bank index from the thread_safe_append call in physics.cpp -void ifp(const Particle& p, const SourceSite& site, int64_t idx); +void ifp(const Particle& p, int64_t idx); //! Resize the IFP banks used in the simulation void resize_simulation_ifp_banks(); diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 1a22f58379..afcd564767 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -631,6 +631,7 @@ public: int& event_mt() { return event_mt_; } // MT number of collision const int& event_mt() const { return event_mt_; } int& delayed_group() { return delayed_group_; } // delayed group + const int& delayed_group() const { return delayed_group_; } const int& parent_nuclide() const { return parent_nuclide_; } int& parent_nuclide() { return parent_nuclide_; } // Parent nuclide diff --git a/src/ifp.cpp b/src/ifp.cpp index 1f81f26f6e..cc4a76538b 100644 --- a/src/ifp.cpp +++ b/src/ifp.cpp @@ -28,13 +28,13 @@ bool is_generation_time_or_both() return false; } -void ifp(const Particle& p, const SourceSite& site, int64_t idx) +void ifp(const Particle& p, int64_t idx) { if (is_beta_effective_or_both()) { const auto& delayed_groups = simulation::ifp_source_delayed_group_bank[p.current_work() - 1]; simulation::ifp_fission_delayed_group_bank[idx] = - _ifp(site.delayed_group, delayed_groups); + _ifp(p.delayed_group(), delayed_groups); } if (is_generation_time_or_both()) { const auto& lifetimes = diff --git a/src/particle.cpp b/src/particle.cpp index f5ad45d80f..402af2498a 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -144,6 +144,7 @@ void Particle::from_source(const SourceSite* src) time() = src->time; time_last() = src->time; parent_nuclide() = src->parent_nuclide; + delayed_group() = src->delayed_group; // Convert signed surface ID to signed index if (src->surf_id != SURFACE_NONE) { diff --git a/src/physics.cpp b/src/physics.cpp index f667fd586d..e947fecbb9 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -246,18 +246,15 @@ void create_fission_sites(Particle& p, int i_nuclide, const Reaction& rx) } // Iterated Fission Probability (IFP) method if (settings::ifp_on) { - ifp(p, site, idx); + ifp(p, idx); } } else { p.secondary_bank().push_back(site); } - // Set the delayed group on the particle as well - p.delayed_group() = site.delayed_group; - // Increment the number of neutrons born delayed - if (p.delayed_group() > 0) { - nu_d[p.delayed_group() - 1]++; + if (site.delayed_group > 0) { + nu_d[site.delayed_group - 1]++; } // Write fission particles to nuBank diff --git a/tests/regression_tests/ifp/results_true.dat b/tests/regression_tests/ifp/results_true.dat index 1d8f69e125..466ca1f015 100644 --- a/tests/regression_tests/ifp/results_true.dat +++ b/tests/regression_tests/ifp/results_true.dat @@ -3,7 +3,7 @@ k-combined: tally 1: 9.109384E-08 5.667165E-16 -6.500000E-02 -6.710000E-04 +5.200000E-02 +5.420000E-04 1.489000E+01 1.480036E+01 diff --git a/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 index 4dd5f821af92dd98395a8df31af2a81fab8a8ba4..228f5a7d0a462f38a1cb0b4274dd40d4307b5a12 100644 GIT binary patch delta 42 ycmX@m!gQd8X@dwmbDaH^&Eo8yDU2+W6SL1VvTZiZaTj7_nw%&gzj;R83T6N=*$u}4 delta 48 zcmX@m!gQd8X@dwm^EJ&=o5k5ZQzln%3QR7@J}|k1S75V4j)f42F}XlMVDpT+70dv* Csu83B diff --git a/tests/regression_tests/surface_source_write/case-04/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-04/surface_source_true.h5 index ee00af3895c349d60d786af1aedef39e05e24d20..c276af40f4302f4e0feff883bc3c472bc4df7ca1 100644 GIT binary patch delta 38 ucmX@m!gQd8X@dwmbDaH^&Eo8xzKkrB7lxc?WZPUAI-ie`X|rI8z8nArx(svx delta 44 xcmX@m!gQd8X@dwm^L5Qro5k5XeJ59N3QXP*a$vFtm%!$R&|0h5VN3AkPef$3?Q>mU+^N7 CA`&M6 diff --git a/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 index ca5eda8e2f347a1fc88b05db6690ad5b6d3a2a51..6c6925daba145c5db52a281023dd017f066e0732 100644 GIT binary patch delta 117 zcmX@m!gQd8X@dwmbAtVq&Eo8lQj<>z2yAXpOweRx+5FH;oYOG=2mfb3*B|@WHpD(y z^yT0FTL*$W*`i%Qt;HW$zbo>Udt8lS9X5&5&?bMwZEqk?BA) UUPkiE0XaX*)4?VeR9xT$0J0-9HUIzs delta 124 zcmV-?0E7R)gaW{X0a}p%0E$1%ExYoLO_SJDO6Vllc)#~laN_h elc)#~qxe}KlPD=5lYkHilOT9N0RppOc;5**VKsyR diff --git a/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 index ca5eda8e2f347a1fc88b05db6690ad5b6d3a2a51..6c6925daba145c5db52a281023dd017f066e0732 100644 GIT binary patch delta 117 zcmX@m!gQd8X@dwmbAtVq&Eo8lQj<>z2yAXpOweRx+5FH;oYOG=2mfb3*B|@WHpD(y z^yT0FTL*$W*`i%Qt;HW$zbo>Udt8lS9X5&5&?bMwZEqk?BA) UUPkiE0XaX*)4?VeR9xT$0J0-9HUIzs delta 124 zcmV-?0E7R)gaW{X0a}p%0E$1%ExYoLO_SJDO6Vllc)#~laN_h elc)#~qxe}KlPD=5lYkHilOT9N0RppOc;5**VKsyR diff --git a/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 index c9900bd9c0469d3b171f863f0518d6c94e966027..6c6925daba145c5db52a281023dd017f066e0732 100644 GIT binary patch delta 117 zcmX@m!gQd8X@dwmbAtVq&Eo8lQj<>z2yAXpOweRx+5FH;oYOG=2mfb3*B|@WHpD(y z^yT0FTL*$W*`i%Qt;HW$zbo>Udt8lS9X5&5&?bMwZEqk?BA) UUPkiE0XaX*)4?VeR9xT$0J0-9HUIzs delta 124 zcmV-?0E7R)gaW{X0a}p%0E$1%ExYoLO_SJDO6Vllc)#~laN_h elc)#~qxe}KlPD=5lYkHilOT9N0RppOc;5**(=~+v diff --git a/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 index 8dc148ee07eb33d6374387e557b35914f5fa2003..da36fc505eb67f3da0ce48511464b699a4fb16e3 100644 GIT binary patch delta 70 zcmX?La=>JR2s?9<{gut)?19XaFK}f{&fv<}Y{8wtJxM%c@(i(z$rph10tuivkhTEQ W1(F$)IV3$8StcLklb?J;G6MjFG#L5- delta 68 zcmX?La=>JR2s`s*%~PAj*#ns;U*O7^oWYf`*@8QPdy;s@X>K%LUYL4oBy*u_xg7`DD%%1Q6vVXpy?7Ij1?@Ya&Zg=K`&foCGUf}-ZSJHay^ESNO9MxAl*L;*XO>X>K%KZYL4oBy*u{Hg7`DD%%1Q6ynnu+?7Ij1?@Ya&ZgX>K%LUYL4oBy*u_xg7`DD%%1Q6vVXpy?7Ij1?@Ya&Zg=K`&foCGUf}-ZSJHay^ESNO9MxAl*L;*XO>X>K%KZYL4oBy*u{Hg7`DD%%1Q6ynnu+?7Ij1?@Ya&ZgLSiQX diff --git a/tests/regression_tests/surface_source_write/case-e01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-e01/surface_source_true.h5 index 0dda15ed2192739435e8f50e126831021d620f53..bbfbd152bc6543871750cb9bd4cc55fe0899754a 100644 GIT binary patch delta 39 vcmX@m!gQd8X@dwm^L6Jdo5k5Vtr*!hD>|xkF|us-^iEf2WZJy3sGlDI{ml#e delta 45 zcmV+|0Mh@!gaW{X0|xkF|us-^iEf2WZJy3sGlDI{ml#e delta 45 zcmV+|0Mh@!gaW{X0|fgu z`(V+RfBSD82<~KyeqpaT&*);s!pHXSSC}u~^zD?rU%;v3d2LP(9h)bH)H5-%Y!(bR wXPmsFL|}77#0D`CW3ohk#N->+5}P~ne=vh(CKPKhf^3?6!Bk-Ljgkyr09VyO4FCWD delta 148 zcmX@m!gQd8X@dwm^Bj*eo5k5BRTx<|8*2A+P4 Date: Fri, 26 Sep 2025 12:27:05 -0400 Subject: [PATCH 15/76] Multi-group capability for kinetics parameter calculations with Iterated Fission Probability (#3425) Co-authored-by: GuySten Co-authored-by: Paul Romano --- docs/source/usersguide/kinetics.rst | 25 +++++++- openmc/model/model.py | 41 +++++++++++-- openmc/statepoint.py | 58 +++++++++++++++++++ src/tallies/tally.cpp | 3 +- src/tallies/tally_scoring.cpp | 9 +++ .../ifp/groupwise/__init__.py | 0 .../ifp/groupwise/inputs_true.dat | 43 ++++++++++++++ .../ifp/groupwise/results_true.dat | 21 +++++++ tests/regression_tests/ifp/groupwise/test.py | 40 +++++++++++++ tests/regression_tests/ifp/total/__init__.py | 0 .../ifp/{ => total}/inputs_true.dat | 0 .../ifp/{ => total}/results_true.dat | 0 .../regression_tests/ifp/{ => total}/test.py | 1 - tests/unit_tests/test_ifp.py | 39 +++++++++++++ 14 files changed, 272 insertions(+), 8 deletions(-) create mode 100644 tests/regression_tests/ifp/groupwise/__init__.py create mode 100644 tests/regression_tests/ifp/groupwise/inputs_true.dat create mode 100644 tests/regression_tests/ifp/groupwise/results_true.dat create mode 100644 tests/regression_tests/ifp/groupwise/test.py create mode 100644 tests/regression_tests/ifp/total/__init__.py rename tests/regression_tests/ifp/{ => total}/inputs_true.dat (100%) rename tests/regression_tests/ifp/{ => total}/results_true.dat (100%) rename tests/regression_tests/ifp/{ => total}/test.py (99%) diff --git a/docs/source/usersguide/kinetics.rst b/docs/source/usersguide/kinetics.rst index bdf26d341b..9024ff8227 100644 --- a/docs/source/usersguide/kinetics.rst +++ b/docs/source/usersguide/kinetics.rst @@ -67,6 +67,23 @@ are needed to compute kinetics parameters in OpenMC: Obtaining kinetics parameters ----------------------------- +The ``Model`` class can be used to automatically generate all IFP tallies using +the Python API with :attr:`openmc.Settings.ifp_n_generation` greater than 0 and +the :meth:`openmc.Model.add_ifp_kinetics_tallies` method:: + + model = openmc.Model(geometry, settings=settings) + model.add_kinetics_parameters_tallies(num_groups=6) # Add 6 precursor groups + +Alternatively, each of the tallies can be manually defined using group-wise or +total :math:`\beta_{\text{eff}}` specified by providing a 6-group +:class:`openmc.DelayedGroupFilter`:: + + beta_tally = openmc.Tally(name="group-beta-score") + beta_tally.scores = ["ifp-beta-numerator"] + + # Add DelayedGroupFilter to enable group-wise tallies + beta_tally.filters = [openmc.DelayedGroupFilter(list(range(1, 7)))] + Here is an example showing how to declare the three available IFP scores in a single tally:: @@ -95,6 +112,12 @@ for ``ifp-denominator``: \beta_{\text{eff}} = \frac{S_{\text{ifp-beta-numerator}}}{S_{\text{ifp-denominator}}} +The kinetics parameters can be retrieved directly from a statepoint file using +the :meth:`openmc.StatePoint.ifp_results` method:: + + with openmc.StatePoint(output_path) as sp: + generation_time, beta_eff = sp.get_kinetics_parameters() + .. only:: html .. rubric:: References @@ -107,4 +130,4 @@ for ``ifp-denominator``: of the Iterated Fission Probability Method in OpenMC to Compute Adjoint-Weighted Kinetics Parameters", International Conference on Mathematics and Computational Methods Applied to Nuclear Science and Engineering (M&C 2025), Denver, April 27-30, - 2025 (to be presented). + 2025. diff --git a/openmc/model/model.py b/openmc/model/model.py index 59e6fa511e..c1ffafafd3 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections.abc import Iterable, Sequence import copy -from functools import lru_cache +from functools import cache from pathlib import Path import math from numbers import Integral, Real @@ -160,7 +160,7 @@ class Model: return False @property - @lru_cache(maxsize=None) + @cache def _materials_by_id(self) -> dict: """Dictionary mapping material ID --> material""" if self.materials: @@ -170,14 +170,14 @@ class Model: return {mat.id: mat for mat in mats} @property - @lru_cache(maxsize=None) + @cache def _cells_by_id(self) -> dict: """Dictionary mapping cell ID --> cell""" cells = self.geometry.get_all_cells() return {cell.id: cell for cell in cells.values()} @property - @lru_cache(maxsize=None) + @cache def _cells_by_name(self) -> dict[int, openmc.Cell]: # Get the names maps, but since names are not unique, store a set for # each name key. In this way when the user requests a change by a name, @@ -190,7 +190,7 @@ class Model: return result @property - @lru_cache(maxsize=None) + @cache def _materials_by_name(self) -> dict[int, openmc.Material]: if self.materials is None: mats = self.geometry.get_all_materials().values() @@ -203,6 +203,37 @@ class Model: result[mat.name].add(mat) return result + def add_kinetics_parameters_tallies(self, num_groups: int | None = None): + """Add tallies for calculating kinetics parameters using the IFP method. + + This method adds tallies to the model for calculating two kinetics + parameters, the generation time and the effective delayed neutron + fraction (beta effective). After a model is run, these parameters can be + determined through the :meth:`openmc.StatePoint.ifp_results` method. + + Parameters + ---------- + num_groups : int, optional + Number of precursor groups to filter the delayed neutron fraction. + If None, only the total effective delayed neutron fraction is + tallied. + + """ + if not any('ifp-time-numerator' in t.scores for t in self.tallies): + gen_time_tally = openmc.Tally(name='IFP time numerator') + gen_time_tally.scores = ['ifp-time-numerator'] + self.tallies.append(gen_time_tally) + if not any('ifp-beta-numerator' in t.scores for t in self.tallies): + beta_tally = openmc.Tally(name='IFP beta numerator') + beta_tally.scores = ['ifp-beta-numerator'] + if num_groups is not None: + beta_tally.filters = [openmc.DelayedGroupFilter(list(range(1, num_groups + 1)))] + self.tallies.append(beta_tally) + if not any('ifp-denominator' in t.scores for t in self.tallies): + denom_tally = openmc.Tally(name='IFP denominator') + denom_tally.scores = ['ifp-denominator'] + self.tallies.append(denom_tally) + @classmethod def from_xml( cls, diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 715becf488..29c11921cb 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,4 +1,5 @@ from datetime import datetime +from collections import namedtuple import glob import re import os @@ -8,6 +9,7 @@ import h5py import numpy as np from pathlib import Path from uncertainties import ufloat +from uncertainties.unumpy import uarray import openmc import openmc.checkvalue as cv @@ -15,6 +17,9 @@ import openmc.checkvalue as cv _VERSION_STATEPOINT = 18 +KineticsParameters = namedtuple("KineticsParameters", ["generation_time", "beta_effective"]) + + class StatePoint: """State information on a simulation at a certain point in time (at the end of a given batch). Statepoints can be used to analyze tally results as well @@ -710,3 +715,56 @@ class StatePoint: tally_filter.paths = cell.paths self._summary = summary + + def get_kinetics_parameters(self) -> KineticsParameters: + """Get kinetics parameters from IFP tallies. + + This method searches the tallies in the statepoint for the tallies + required to compute kinetics parameters using the Iterated Fission + Probability (IFP) method. + + Returns + ------- + KineticsParameters + A named tuple containing the generation time and effective delayed + neutron fraction. If the necessary tallies for one or both + parameters are not found, that parameter is returned as None. + + """ + + denom_tally = None + gen_time_tally = None + beta_tally = None + for tally in self.tallies.values(): + if 'ifp-denominator' in tally.scores: + denom_tally = self.get_tally(scores=['ifp-denominator']) + if 'ifp-time-numerator' in tally.scores: + gen_time_tally = self.get_tally(scores=['ifp-time-numerator']) + if 'ifp-beta-numerator' in tally.scores: + beta_tally = self.get_tally(scores=['ifp-beta-numerator']) + + if denom_tally is None: + return KineticsParameters(None, None) + + def get_ufloat(tally, score): + return uarray(tally.get_values(scores=[score]), + tally.get_values(scores=[score], value='std_dev')) + + denom_values = get_ufloat(denom_tally, 'ifp-denominator') + if gen_time_tally is None: + generation_time = None + else: + gen_time_values = get_ufloat(gen_time_tally, 'ifp-time-numerator') + gen_time_values /= denom_values*self.keff + generation_time = gen_time_values.flatten()[0] + + if beta_tally is None: + beta_effective = None + else: + beta_values = get_ufloat(beta_tally, 'ifp-beta-numerator') + beta_values /= denom_values + beta_effective = beta_values.flatten() + if beta_effective.size == 1: + beta_effective = beta_effective[0] + + return KineticsParameters(generation_time, beta_effective) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index ae0bffe6eb..b9c615ecb5 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -560,7 +560,8 @@ void Tally::set_scores(const vector& scores) // Make sure a delayed group filter wasn't used with an incompatible // score. if (delayedgroup_filter_ != C_NONE) { - if (score_str != "delayed-nu-fission" && score_str != "decay-rate") + if (score_str != "delayed-nu-fission" && score_str != "decay-rate" && + score_str != "ifp-beta-numerator") fatal_error("Cannot tally " + score_str + "with a delayedgroup filter"); } diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index 0df80a2398..67e851644a 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -964,6 +964,15 @@ void score_general_ce_nonanalog(Particle& p, int i_tally, int start_index, if (delayed_groups.size() == settings::ifp_n_generation) { if (delayed_groups[0] > 0) { score = p.wgt_last(); + if (tally.delayedgroup_filter_ != C_NONE) { + auto i_dg_filt = tally.filters()[tally.delayedgroup_filter_]; + const DelayedGroupFilter& filt { + *dynamic_cast( + model::tally_filters[i_dg_filt].get())}; + score_fission_delayed_dg(i_tally, delayed_groups[0] - 1, + score, score_index, p.filter_matches()); + continue; + } } } } diff --git a/tests/regression_tests/ifp/groupwise/__init__.py b/tests/regression_tests/ifp/groupwise/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/ifp/groupwise/inputs_true.dat b/tests/regression_tests/ifp/groupwise/inputs_true.dat new file mode 100644 index 0000000000..6d7e20717b --- /dev/null +++ b/tests/regression_tests/ifp/groupwise/inputs_true.dat @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + eigenvalue + 1000 + 20 + 5 + + + -10.0 -10.0 -10.0 10.0 10.0 10.0 + + + true + + + 5 + + + + 1 2 3 4 5 6 + + + ifp-time-numerator + + + 1 + ifp-beta-numerator + + + ifp-denominator + + + diff --git a/tests/regression_tests/ifp/groupwise/results_true.dat b/tests/regression_tests/ifp/groupwise/results_true.dat new file mode 100644 index 0000000000..ea66a8de3c --- /dev/null +++ b/tests/regression_tests/ifp/groupwise/results_true.dat @@ -0,0 +1,21 @@ +k-combined: +1.006559E+00 5.389391E-03 +tally 1: +9.109384E-08 +5.667165E-16 +tally 2: +3.000000E-03 +9.000000E-06 +0.000000E+00 +0.000000E+00 +2.100000E-02 +1.370000E-04 +2.800000E-02 +2.220000E-04 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +tally 3: +1.489000E+01 +1.480036E+01 diff --git a/tests/regression_tests/ifp/groupwise/test.py b/tests/regression_tests/ifp/groupwise/test.py new file mode 100644 index 0000000000..a1a0ebefb8 --- /dev/null +++ b/tests/regression_tests/ifp/groupwise/test.py @@ -0,0 +1,40 @@ +"""Test the Iterated Fission Probability (IFP) method to compute adjoint-weighted +kinetics parameters using dedicated tallies.""" + +import openmc +import pytest + +from tests.testing_harness import PyAPITestHarness + +@pytest.fixture() +def ifp_model(): + # Material + material = openmc.Material(name="core") + material.add_nuclide("U235", 1.0) + material.set_density('g/cm3', 16.0) + + # Geometry + radius = 10.0 + sphere = openmc.Sphere(r=radius, boundary_type="vacuum") + cell = openmc.Cell(region=-sphere, fill=material) + geometry = openmc.Geometry([cell]) + + # Settings + settings = openmc.Settings() + settings.particles = 1000 + settings.batches = 20 + settings.inactive = 5 + settings.ifp_n_generation = 5 + + model = openmc.Model(settings=settings, geometry=geometry) + + space = openmc.stats.Box(*cell.bounding_box) + model.settings.source = openmc.IndependentSource( + space=space, constraints={'fissionable': True}) + model.add_kinetics_parameters_tallies(num_groups=6) + return model + + +def test_iterated_fission_probability(ifp_model): + harness = PyAPITestHarness("statepoint.20.h5", model=ifp_model) + harness.main() diff --git a/tests/regression_tests/ifp/total/__init__.py b/tests/regression_tests/ifp/total/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/ifp/inputs_true.dat b/tests/regression_tests/ifp/total/inputs_true.dat similarity index 100% rename from tests/regression_tests/ifp/inputs_true.dat rename to tests/regression_tests/ifp/total/inputs_true.dat diff --git a/tests/regression_tests/ifp/results_true.dat b/tests/regression_tests/ifp/total/results_true.dat similarity index 100% rename from tests/regression_tests/ifp/results_true.dat rename to tests/regression_tests/ifp/total/results_true.dat diff --git a/tests/regression_tests/ifp/test.py b/tests/regression_tests/ifp/total/test.py similarity index 99% rename from tests/regression_tests/ifp/test.py rename to tests/regression_tests/ifp/total/test.py index 6969a54c49..18b89cfc0b 100644 --- a/tests/regression_tests/ifp/test.py +++ b/tests/regression_tests/ifp/total/test.py @@ -6,7 +6,6 @@ import pytest from tests.testing_harness import PyAPITestHarness - @pytest.fixture() def ifp_model(): model = openmc.Model() diff --git a/tests/unit_tests/test_ifp.py b/tests/unit_tests/test_ifp.py index 8d0fd98010..e527f16246 100644 --- a/tests/unit_tests/test_ifp.py +++ b/tests/unit_tests/test_ifp.py @@ -47,3 +47,42 @@ def test_exceptions(options, error, run_in_tmpdir, geometry): tallies = openmc.Tallies([tally]) model = openmc.Model(geometry=geometry, settings=settings, tallies=tallies) model.run() + + +@pytest.mark.parametrize( + "num_groups, use_auto_tallies", + [ + (None, True), + (None, False), + (6, True), + (6, False), + ], +) +def test_get_kinetics_parameters(run_in_tmpdir, geometry, num_groups, use_auto_tallies): + # Create basic model + model = openmc.Model(geometry=geometry) + model.settings.particles = 1000 + model.settings.batches = 20 + model.settings.inactive = 5 + model.settings.ifp_n_generation = 5 + + # Add IFP tallies either via the convenience method or manually + if use_auto_tallies: + model.add_kinetics_parameters_tallies(num_groups=num_groups) + else: + for score in ["ifp-time-numerator", "ifp-beta-numerator", "ifp-denominator"]: + tally = openmc.Tally() + tally.scores = [score] + if score == "ifp-beta-numerator" and num_groups is not None: + tally.filters = [openmc.DelayedGroupFilter(list(range(1, num_groups + 1)))] + model.tallies.append(tally) + + # Run and get kinetics parameters + sp_file = model.run() + with openmc.StatePoint(sp_file) as sp: + params = sp.get_kinetics_parameters() + assert isinstance(params, openmc.KineticsParameters) + assert params.generation_time is not None + assert params.beta_effective is not None + if num_groups is not None: + assert len(params.beta_effective) == num_groups From 4011b7a5515e4098f179d825313f574680d3a68f Mon Sep 17 00:00:00 2001 From: Perry <100789850+yrrepy@users.noreply.github.com> Date: Fri, 26 Sep 2025 09:46:23 -0700 Subject: [PATCH 16/76] Optional separation of mesh-material-volume calc from get_homogenized_materials (#3581) Co-authored-by: Paul Romano --- openmc/mesh.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 2e9abd1b65..9601207e91 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -287,6 +287,7 @@ class MeshBase(IDManagerMixin, ABC): model: openmc.Model, n_samples: int | tuple[int, int, int] = 10_000, include_void: bool = True, + material_volumes: MeshMaterialVolumes | None = None, **kwargs ) -> list[openmc.Material]: """Generate homogenized materials over each element in a mesh. @@ -305,8 +306,12 @@ class MeshBase(IDManagerMixin, ABC): the x, y, and z dimensions. include_void : bool, optional Whether homogenization should include voids. + material_volumes : MeshMaterialVolumes, optional + Previously computed mesh material volumes to use for homogenization. + If not provided, they will be computed by calling + :meth:`material_volumes`. **kwargs - Keyword-arguments passed to :meth:`MeshBase.material_volumes`. + Keyword-arguments passed to :meth:`material_volumes`. Returns ------- @@ -314,7 +319,10 @@ class MeshBase(IDManagerMixin, ABC): Homogenized material in each mesh element """ - vols = self.material_volumes(model, n_samples, **kwargs) + if material_volumes is None: + vols = self.material_volumes(model, n_samples, **kwargs) + else: + vols = material_volumes mat_volume_by_element = [vols.by_element(i) for i in range(vols.num_elements)] # Create homogenized material for each element @@ -424,7 +432,6 @@ class MeshBase(IDManagerMixin, ABC): # Restore original tallies model.tallies = original_tallies - return volumes From feefcc671307fc84e7357430f5f07343503919e5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Wed, 1 Oct 2025 00:09:15 +0200 Subject: [PATCH 17/76] Adding tally filter type option to statepoint get_tally (#3584) Co-authored-by: Jon Shimwell Co-authored-by: GuySten <62616591+GuySten@users.noreply.github.com> --- openmc/statepoint.py | 9 +++- tests/unit_tests/test_statepoint.py | 65 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/test_statepoint.py diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 29c11921cb..a763db3971 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -536,7 +536,7 @@ class StatePoint: def get_tally(self, scores=[], filters=[], nuclides=[], name=None, id=None, estimator=None, exact_filters=False, exact_nuclides=False, exact_scores=False, - multiply_density=None, derivative=None): + multiply_density=None, derivative=None, filter_type=None): """Finds and returns a Tally object with certain properties. This routine searches the list of Tallies and returns the first Tally @@ -580,6 +580,9 @@ class StatePoint: to the same value as this parameter. derivative : openmc.TallyDerivative, optional TallyDerivative object to match. + filter_type : type, optional + If not None, the Tally must have at least one Filter that is an + instance of this type. For example `openmc.MeshFilter`. Returns ------- @@ -653,6 +656,10 @@ class StatePoint: if not contains_filters: continue + if filter_type is not None: + if not any(isinstance(f, filter_type) for f in test_tally.filters): + continue + # Determine if Tally has the queried Nuclide(s) if nuclides: if not all(nuclide in test_tally.nuclides for nuclide in nuclides): diff --git a/tests/unit_tests/test_statepoint.py b/tests/unit_tests/test_statepoint.py new file mode 100644 index 0000000000..7ffaf7ec2c --- /dev/null +++ b/tests/unit_tests/test_statepoint.py @@ -0,0 +1,65 @@ +import openmc + + +def test_get_tally_filter_type(run_in_tmpdir): + """Test various ways of retrieving tallies from a StatePoint object.""" + + mat = openmc.Material() + mat.add_nuclide("H1", 1.0) + mat.set_density("g/cm3", 10.0) + + sphere = openmc.Sphere(r=10.0, boundary_type="vacuum") + cell = openmc.Cell(fill=mat, region=-sphere) + geometry = openmc.Geometry([cell]) + + settings = openmc.Settings() + settings.particles = 10 + settings.batches = 2 + settings.run_mode = "fixed source" + + reg_mesh = openmc.RegularMesh().from_domain(cell) + tally1 = openmc.Tally(tally_id=1) + mesh_filter = openmc.MeshFilter(reg_mesh) + tally1.filters = [mesh_filter] + tally1.scores = ["flux"] + + tally2 = openmc.Tally(tally_id=2, name="heating tally") + cell_filter = openmc.CellFilter(cell) + tally2.filters = [cell_filter] + tally2.scores = ["heating"] + + tallies = openmc.Tallies([tally1, tally2]) + model = openmc.Model( + geometry=geometry, materials=[mat], settings=settings, tallies=tallies + ) + + sp_filename = model.run() + + sp = openmc.StatePoint(sp_filename) + + tally_found = sp.get_tally(filter_type=openmc.MeshFilter) + assert tally_found.id == 1 + + tally_found = sp.get_tally(filter_type=openmc.CellFilter) + assert tally_found.id == 2 + + tally_found = sp.get_tally(filters=[mesh_filter]) + assert tally_found.id == 1 + + tally_found = sp.get_tally(filters=[cell_filter]) + assert tally_found.id == 2 + + tally_found = sp.get_tally(scores=["heating"]) + assert tally_found.id == 2 + + tally_found = sp.get_tally(name="heating tally") + assert tally_found.id == 2 + + tally_found = sp.get_tally(name=None) + assert tally_found.id == 1 + + tally_found = sp.get_tally(id=1) + assert tally_found.id == 1 + + tally_found = sp.get_tally(id=2) + assert tally_found.id == 2 From 3ac64d9a01d8d10ff126d62d8a9f618fbd803f4b Mon Sep 17 00:00:00 2001 From: John Tramm Date: Thu, 2 Oct 2025 11:02:43 -0500 Subject: [PATCH 18/76] Random Ray Base Source Region Refactor (#3576) --- include/openmc/constants.h | 5 + .../openmc/random_ray/flat_source_domain.h | 47 ++- .../openmc/random_ray/linear_source_domain.h | 2 +- include/openmc/random_ray/random_ray.h | 1 - .../openmc/random_ray/random_ray_simulation.h | 9 +- include/openmc/random_ray/source_region.h | 1 - src/random_ray/flat_source_domain.cpp | 373 ++++++++++-------- src/random_ray/linear_source_domain.cpp | 47 +-- src/random_ray/random_ray.cpp | 121 +++--- src/random_ray/random_ray_simulation.cpp | 190 ++++----- src/random_ray/source_region.cpp | 28 +- src/settings.cpp | 1 - .../random_ray_low_density/__init__.py | 0 .../random_ray_low_density/inputs_true.dat | 244 ++++++++++++ .../random_ray_low_density/results_true.dat | 9 + .../random_ray_low_density/test.py | 60 +++ .../results_true.dat | 8 +- 17 files changed, 700 insertions(+), 446 deletions(-) create mode 100644 tests/regression_tests/random_ray_low_density/__init__.py create mode 100644 tests/regression_tests/random_ray_low_density/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_low_density/results_true.dat create mode 100644 tests/regression_tests/random_ray_low_density/test.py diff --git a/include/openmc/constants.h b/include/openmc/constants.h index df13da3707..a0d1646131 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -68,6 +68,11 @@ constexpr double MIN_HITS_PER_BATCH {1.5}; // prevent extremely large adjoint source terms from being generated. constexpr double ZERO_FLUX_CUTOFF {1e-22}; +// The minimum macroscopic cross section value considered non-void for the +// random ray solver. Materials with any group with a cross section below this +// value will be converted to pure void. +constexpr double MINIMUM_MACRO_XS {1e-6}; + // ============================================================================ // MATH AND PHYSICAL CONSTANTS diff --git a/include/openmc/random_ray/flat_source_domain.h b/include/openmc/random_ray/flat_source_domain.h index 78351fcc5f..d4e8027346 100644 --- a/include/openmc/random_ray/flat_source_domain.h +++ b/include/openmc/random_ray/flat_source_domain.h @@ -27,8 +27,9 @@ public: //---------------------------------------------------------------------------- // Methods - virtual void update_neutron_source(double k_eff); - double compute_k_eff(double k_eff_old) const; + virtual void update_single_neutron_source(SourceRegionHandle& srh); + virtual void update_all_neutron_sources(); + void compute_k_eff(); virtual void normalize_scalar_flux_and_volumes( double total_active_distance_per_iteration); @@ -41,7 +42,7 @@ public: void output_to_vtk() const; void convert_external_sources(); void count_external_source_regions(); - void set_adjoint_sources(const vector& forward_flux); + void set_adjoint_sources(); void flux_swap(); virtual double evaluate_flux_at_point(Position r, int64_t sr, int g) const; double compute_fixed_source_normalization_factor() const; @@ -54,9 +55,8 @@ public: bool is_target_void); void apply_mesh_to_cell_and_children(int32_t i_cell, int32_t mesh_idx, int32_t target_material_id, bool is_target_void); - void prepare_base_source_regions(); SourceRegionHandle get_subdivided_source_region_handle( - int64_t sr, int mesh_bin, Position r, double dist, Direction u); + SourceRegionKey sr_key, Position r, Direction u); void finalize_discovered_source_regions(); void apply_transport_stabilization(); int64_t n_source_regions() const @@ -67,6 +67,10 @@ public: { return source_regions_.n_source_regions() * negroups_; } + int64_t lookup_base_source_region_idx(const GeometryState& p) const; + SourceRegionKey lookup_source_region_key(const GeometryState& p) const; + int64_t lookup_mesh_bin(int64_t sr, Position r) const; + int lookup_mesh_idx(int64_t sr) const; //---------------------------------------------------------------------------- // Static Data members @@ -86,6 +90,7 @@ public: //---------------------------------------------------------------------------- // Public Data members + double k_eff_ {1.0}; // Eigenvalue bool mapped_all_tallies_ {false}; // If all source regions have been visited int64_t n_external_source_regions_ {0}; // Total number of source regions with @@ -110,14 +115,6 @@ public: // The abstract container holding all source region-specific data SourceRegionContainer source_regions_; - // Base source region container. When source region subdivision via mesh - // is in use, this container holds the original (non-subdivided) material - // filled cell instance source regions. These are useful as they can be - // initialized with external source and mesh domain information ahead of time. - // Then, dynamically discovered source regions can be initialized by cloning - // their base region. - SourceRegionContainer base_source_regions_; - // Parallel hash map holding all source regions discovered during // a single iteration. This is a threadsafe data structure that is cleaned // out after each iteration and stored in the "source_regions_" container. @@ -134,8 +131,17 @@ public: // Map that relates a SourceRegionKey to the external source index. This map // is used to check if there are any point sources within a subdivided source // region at the time it is discovered. - std::unordered_map - point_source_map_; + std::unordered_map, SourceRegionKey::HashFunctor> + external_point_source_map_; + + // Map that relates a base source region index to the external source index. + // This map is used to check if there are any volumetric sources within a + // subdivided source region at the time it is discovered. + std::unordered_map> external_volumetric_source_map_; + + // Map that relates a base source region index to a mesh index. This map + // is used to check which subdivision mesh is present in a source region. + std::unordered_map mesh_map_; // If transport corrected MGXS data is being used, there may be negative // in-group scattering cross sections that can result in instability in MOC @@ -147,12 +153,11 @@ protected: //---------------------------------------------------------------------------- // Methods void apply_external_source_to_source_region( - Discrete* discrete, double strength_factor, SourceRegionHandle& srh); - void apply_external_source_to_cell_instances(int32_t i_cell, - Discrete* discrete, double strength_factor, int target_material_id, - const vector& instances); - void apply_external_source_to_cell_and_children(int32_t i_cell, - Discrete* discrete, double strength_factor, int32_t target_material_id); + int src_idx, SourceRegionHandle& srh); + void apply_external_source_to_cell_instances(int32_t i_cell, int src_idx, + int target_material_id, const vector& instances); + void apply_external_source_to_cell_and_children( + int32_t i_cell, int src_idx, int32_t target_material_id); virtual void set_flux_to_flux_plus_source(int64_t sr, double volume, int g); void set_flux_to_source(int64_t sr, int g); virtual void set_flux_to_old_flux(int64_t sr, int g); diff --git a/include/openmc/random_ray/linear_source_domain.h b/include/openmc/random_ray/linear_source_domain.h index 67fdd99f88..0098c78200 100644 --- a/include/openmc/random_ray/linear_source_domain.h +++ b/include/openmc/random_ray/linear_source_domain.h @@ -20,7 +20,7 @@ class LinearSourceDomain : public FlatSourceDomain { public: //---------------------------------------------------------------------------- // Methods - void update_neutron_source(double k_eff) override; + void update_single_neutron_source(SourceRegionHandle& srh) override; void normalize_scalar_flux_and_volumes( double total_active_distance_per_iteration) override; diff --git a/include/openmc/random_ray/random_ray.h b/include/openmc/random_ray/random_ray.h index abf2a26881..40c67ef954 100644 --- a/include/openmc/random_ray/random_ray.h +++ b/include/openmc/random_ray/random_ray.h @@ -48,7 +48,6 @@ public: static double distance_active_; // Active ray length static unique_ptr ray_source_; // Starting source for ray sampling static RandomRaySourceShape source_shape_; // Flag for linear source - static bool mesh_subdivision_enabled_; // Flag for mesh subdivision static RandomRaySampleMethod sample_method_; // Flag for sampling method //---------------------------------------------------------------------------- diff --git a/include/openmc/random_ray/random_ray_simulation.h b/include/openmc/random_ray/random_ray_simulation.h index b94e7401b3..3dec48bf26 100644 --- a/include/openmc/random_ray/random_ray_simulation.h +++ b/include/openmc/random_ray/random_ray_simulation.h @@ -21,11 +21,7 @@ public: // Methods void compute_segment_correction_factors(); void apply_fixed_sources_and_mesh_domains(); - void prepare_fixed_sources_adjoint(vector& forward_flux, - SourceRegionContainer& forward_source_regions, - SourceRegionContainer& forward_base_source_regions, - std::unordered_map& - forward_source_region_map); + void prepare_fixed_sources_adjoint(); void simulate(); void output_simulation_results() const; void instability_check( @@ -45,9 +41,6 @@ private: // Contains all flat source region data unique_ptr domain_; - // Random ray eigenvalue - double k_eff_ {1.0}; - // Tracks the average FSR miss rate for analysis and reporting double avg_miss_rate_ {0.0}; diff --git a/include/openmc/random_ray/source_region.h b/include/openmc/random_ray/source_region.h index 5c5b31f392..0f5a747fff 100644 --- a/include/openmc/random_ray/source_region.h +++ b/include/openmc/random_ray/source_region.h @@ -308,7 +308,6 @@ public: //---------------------------------------------------------------------------- // Constructors SourceRegion(int negroups, bool is_linear); - SourceRegion(const SourceRegionHandle& handle, int64_t parent_sr); SourceRegion() = default; //---------------------------------------------------------------------------- diff --git a/src/random_ray/flat_source_domain.cpp b/src/random_ray/flat_source_domain.cpp index 4092388308..1bf27e1eda 100644 --- a/src/random_ray/flat_source_domain.cpp +++ b/src/random_ray/flat_source_domain.cpp @@ -53,24 +53,6 @@ FlatSourceDomain::FlatSourceDomain() : negroups_(data::mg.num_energy_groups_) // Initialize source regions. bool is_linear = RandomRay::source_shape_ != RandomRaySourceShape::FLAT; source_regions_ = SourceRegionContainer(negroups_, is_linear); - source_regions_.assign( - base_source_regions, SourceRegion(negroups_, is_linear)); - - // Initialize materials - int64_t source_region_id = 0; - for (int i = 0; i < model::cells.size(); i++) { - Cell& cell = *model::cells[i]; - if (cell.type_ == Fill::MATERIAL) { - for (int j = 0; j < cell.n_instances(); j++) { - source_regions_.material(source_region_id++) = cell.material(j); - } - } - } - - // Sanity check - if (source_region_id != base_source_regions) { - fatal_error("Unexpected number of source regions"); - } // Initialize tally volumes if (volume_normalized_flux_tallies_) { @@ -118,34 +100,24 @@ void FlatSourceDomain::accumulate_iteration_flux() } } -// Compute new estimate of scattering + fission sources in each source region -// based on the flux estimate from the previous iteration. -void FlatSourceDomain::update_neutron_source(double k_eff) +void FlatSourceDomain::update_single_neutron_source(SourceRegionHandle& srh) { - simulation::time_update_src.start(); - - double inverse_k_eff = 1.0 / k_eff; - -// Reset all source regions to zero (important for void regions) -#pragma omp parallel for - for (int64_t se = 0; se < n_source_elements(); se++) { - source_regions_.source(se) = 0.0; + // Reset all source regions to zero (important for void regions) + for (int g = 0; g < negroups_; g++) { + srh.source(g) = 0.0; } // Add scattering + fission source -#pragma omp parallel for - for (int64_t sr = 0; sr < n_source_regions(); sr++) { - int material = source_regions_.material(sr); - if (material == MATERIAL_VOID) { - continue; - } + int material = srh.material(); + if (material != MATERIAL_VOID) { + double inverse_k_eff = 1.0 / k_eff_; for (int g_out = 0; g_out < negroups_; g_out++) { double sigma_t = sigma_t_[material * negroups_ + g_out]; double scatter_source = 0.0; double fission_source = 0.0; for (int g_in = 0; g_in < negroups_; g_in++) { - double scalar_flux = source_regions_.scalar_flux_old(sr, g_in); + double scalar_flux = srh.scalar_flux_old(g_in); double sigma_s = sigma_s_[material * negroups_ * negroups_ + g_out * negroups_ + g_in]; double nu_sigma_f = nu_sigma_f_[material * negroups_ + g_in]; @@ -154,18 +126,30 @@ void FlatSourceDomain::update_neutron_source(double k_eff) scatter_source += sigma_s * scalar_flux; fission_source += nu_sigma_f * scalar_flux * chi; } - source_regions_.source(sr, g_out) = + srh.source(g_out) = (scatter_source + fission_source * inverse_k_eff) / sigma_t; } } // Add external source if in fixed source mode if (settings::run_mode == RunMode::FIXED_SOURCE) { -#pragma omp parallel for - for (int64_t se = 0; se < n_source_elements(); se++) { - source_regions_.source(se) += source_regions_.external_source(se); + for (int g = 0; g < negroups_; g++) { + srh.source(g) += srh.external_source(g); } } +} + +// Compute new estimate of scattering + fission sources in each source region +// based on the flux estimate from the previous iteration. +void FlatSourceDomain::update_all_neutron_sources() +{ + simulation::time_update_src.start(); + +#pragma omp parallel for + for (int64_t sr = 0; sr < n_source_regions(); sr++) { + SourceRegionHandle srh = source_regions_.get_source_region_handle(sr); + update_single_neutron_source(srh); + } simulation::time_update_src.stop(); } @@ -320,7 +304,7 @@ int64_t FlatSourceDomain::add_source_to_scalar_flux() // Generates new estimate of k_eff based on the differences between this // iteration's estimate of the scalar flux and the last iteration's estimate. -double FlatSourceDomain::compute_k_eff(double k_eff_old) const +void FlatSourceDomain::compute_k_eff() { double fission_rate_old = 0; double fission_rate_new = 0; @@ -365,7 +349,7 @@ double FlatSourceDomain::compute_k_eff(double k_eff_old) const p[sr] = sr_fission_source_new; } - double k_eff_new = k_eff_old * (fission_rate_new / fission_rate_old); + double k_eff_new = k_eff_ * (fission_rate_new / fission_rate_old); double H = 0.0; // defining an inverse sum for better performance @@ -385,7 +369,7 @@ double FlatSourceDomain::compute_k_eff(double k_eff_old) const // Adds entropy value to shared entropy vector in openmc namespace. simulation::entropy.push_back(H); - return k_eff_new; + k_eff_ = k_eff_new; } // This function is responsible for generating a mapping between random @@ -652,7 +636,6 @@ void FlatSourceDomain::random_ray_tally() "random ray mode."); break; } - // Apply score to the appropriate tally bin Tally& tally {*model::tallies[task.tally_idx]}; #pragma omp atomic @@ -726,21 +709,21 @@ void FlatSourceDomain::output_to_vtk() const print_plot(); // Outer loop over plots - for (int p = 0; p < model::plots.size(); p++) { + for (int plt = 0; plt < model::plots.size(); plt++) { // Get handle to OpenMC plot object and extract params - Plot* openmc_plot = dynamic_cast(model::plots[p].get()); + Plot* openmc_plot = dynamic_cast(model::plots[plt].get()); // Random ray plots only support voxel plots if (!openmc_plot) { warning(fmt::format("Plot {} is invalid plot type -- only voxel plotting " "is allowed in random ray mode.", - p)); + plt)); continue; } else if (openmc_plot->type_ != Plot::PlotType::voxel) { warning(fmt::format("Plot {} is invalid plot type -- only voxel plotting " "is allowed in random ray mode.", - p)); + plt)); continue; } @@ -794,23 +777,11 @@ void FlatSourceDomain::output_to_vtk() const continue; } - int i_cell = p.lowest_coord().cell(); - int64_t sr = source_region_offsets_[i_cell] + p.cell_instance(); - if (RandomRay::mesh_subdivision_enabled_) { - int mesh_idx = base_source_regions_.mesh(sr); - int mesh_bin; - if (mesh_idx == C_NONE) { - mesh_bin = 0; - } else { - mesh_bin = model::meshes[mesh_idx]->get_bin(p.r()); - } - SourceRegionKey sr_key {sr, mesh_bin}; - auto it = source_region_map_.find(sr_key); - if (it != source_region_map_.end()) { - sr = it->second; - } else { - sr = -1; - } + SourceRegionKey sr_key = lookup_source_region_key(p); + int64_t sr = -1; + auto it = source_region_map_.find(sr_key); + if (it != source_region_map_.end()) { + sr = it->second; } voxel_indices[z * Ny * Nx + y * Nx + x] = sr; @@ -967,13 +938,17 @@ void FlatSourceDomain::output_to_vtk() const } void FlatSourceDomain::apply_external_source_to_source_region( - Discrete* discrete, double strength_factor, SourceRegionHandle& srh) + int src_idx, SourceRegionHandle& srh) { - srh.external_source_present() = 1; - + auto s = model::external_sources[src_idx].get(); + auto is = dynamic_cast(s); + auto discrete = dynamic_cast(is->energy()); + double strength_factor = is->strength(); const auto& discrete_energies = discrete->x(); const auto& discrete_probs = discrete->prob(); + srh.external_source_present() = 1; + for (int i = 0; i < discrete_energies.size(); i++) { int g = data::mg.get_group_index(discrete_energies[i]); srh.external_source(g) += discrete_probs[i] * strength_factor; @@ -981,8 +956,7 @@ void FlatSourceDomain::apply_external_source_to_source_region( } void FlatSourceDomain::apply_external_source_to_cell_instances(int32_t i_cell, - Discrete* discrete, double strength_factor, int target_material_id, - const vector& instances) + int src_idx, int target_material_id, const vector& instances) { Cell& cell = *model::cells[i_cell]; @@ -1000,16 +974,13 @@ void FlatSourceDomain::apply_external_source_to_cell_instances(int32_t i_cell, if (target_material_id == C_NONE || cell_material_id == target_material_id) { int64_t source_region = source_region_offsets_[i_cell] + j; - SourceRegionHandle srh = - source_regions_.get_source_region_handle(source_region); - apply_external_source_to_source_region(discrete, strength_factor, srh); + external_volumetric_source_map_[source_region].push_back(src_idx); } } } void FlatSourceDomain::apply_external_source_to_cell_and_children( - int32_t i_cell, Discrete* discrete, double strength_factor, - int32_t target_material_id) + int32_t i_cell, int src_idx, int32_t target_material_id) { Cell& cell = *model::cells[i_cell]; @@ -1017,14 +988,14 @@ void FlatSourceDomain::apply_external_source_to_cell_and_children( vector instances(cell.n_instances()); std::iota(instances.begin(), instances.end(), 0); apply_external_source_to_cell_instances( - i_cell, discrete, strength_factor, target_material_id, instances); + i_cell, src_idx, target_material_id, instances); } else if (target_material_id == C_NONE) { std::unordered_map> cell_instance_list = cell.get_contained_cells(0, nullptr); for (const auto& pair : cell_instance_list) { int32_t i_child_cell = pair.first; - apply_external_source_to_cell_instances(i_child_cell, discrete, - strength_factor, target_material_id, pair.second); + apply_external_source_to_cell_instances( + i_child_cell, src_idx, target_material_id, pair.second); } } } @@ -1070,36 +1041,17 @@ void FlatSourceDomain::convert_external_sources() "point source at {}", sp->r())); } - int i_cell = gs.lowest_coord().cell(); - int64_t sr = source_region_offsets_[i_cell] + gs.cell_instance(); + SourceRegionKey key = lookup_source_region_key(gs); - if (RandomRay::mesh_subdivision_enabled_) { - // If mesh subdivision is enabled, we need to determine which subdivided - // mesh bin the point source coordinate is in as well - int mesh_idx = source_regions_.mesh(sr); - int mesh_bin; - if (mesh_idx == C_NONE) { - mesh_bin = 0; - } else { - mesh_bin = model::meshes[mesh_idx]->get_bin(gs.r()); - } - // With the source region and mesh bin known, we can use the - // accompanying SourceRegionKey as a key into a map that stores the - // corresponding external source index for the point source. Notably, we - // do not actually apply the external source to any source regions here, - // as if mesh subdivision is enabled, they haven't actually been - // discovered & initilized yet. When discovered, they will read from the - // point_source_map to determine if there are any point source terms - // that should be applied. - SourceRegionKey key {sr, mesh_bin}; - point_source_map_[key] = es; - } else { - // If we are not using mesh subdivision, we can apply the external - // source directly to the source region as we do for volumetric domain - // constraint sources. - SourceRegionHandle srh = source_regions_.get_source_region_handle(sr); - apply_external_source_to_source_region(energy, strength_factor, srh); - } + // With the source region and mesh bin known, we can use the + // accompanying SourceRegionKey as a key into a map that stores the + // corresponding external source index for the point source. Notably, we + // do not actually apply the external source to any source regions here, + // as if mesh subdivision is enabled, they haven't actually been + // discovered & initilized yet. When discovered, they will read from the + // external_source_map to determine if there are any external source + // terms that should be applied. + external_point_source_map_[key].push_back(es); } else { // If not a point source, then use the volumetric domain constraints to @@ -1107,42 +1059,25 @@ void FlatSourceDomain::convert_external_sources() if (is->domain_type() == Source::DomainType::MATERIAL) { for (int32_t material_id : domain_ids) { for (int i_cell = 0; i_cell < model::cells.size(); i_cell++) { - apply_external_source_to_cell_and_children( - i_cell, energy, strength_factor, material_id); + apply_external_source_to_cell_and_children(i_cell, es, material_id); } } } else if (is->domain_type() == Source::DomainType::CELL) { for (int32_t cell_id : domain_ids) { int32_t i_cell = model::cell_map[cell_id]; - apply_external_source_to_cell_and_children( - i_cell, energy, strength_factor, C_NONE); + apply_external_source_to_cell_and_children(i_cell, es, C_NONE); } } else if (is->domain_type() == Source::DomainType::UNIVERSE) { for (int32_t universe_id : domain_ids) { int32_t i_universe = model::universe_map[universe_id]; Universe& universe = *model::universes[i_universe]; for (int32_t i_cell : universe.cells_) { - apply_external_source_to_cell_and_children( - i_cell, energy, strength_factor, C_NONE); + apply_external_source_to_cell_and_children(i_cell, es, C_NONE); } } } } } // End loop over external sources - -// Divide the fixed source term by sigma t (to save time when applying each -// iteration) -#pragma omp parallel for - for (int64_t sr = 0; sr < n_source_regions(); sr++) { - int material = source_regions_.material(sr); - if (material == MATERIAL_VOID) { - continue; - } - for (int g = 0; g < negroups_; g++) { - double sigma_t = sigma_t_[material * negroups_ + g]; - source_regions_.external_source(sr, g) /= sigma_t; - } - } } void FlatSourceDomain::flux_swap() @@ -1159,13 +1094,23 @@ void FlatSourceDomain::flatten_xs() const int a = 0; n_materials_ = data::mg.macro_xs_.size(); - for (auto& m : data::mg.macro_xs_) { + for (int i = 0; i < n_materials_; i++) { + auto& m = data::mg.macro_xs_[i]; for (int g_out = 0; g_out < negroups_; g_out++) { if (m.exists_in_model) { double sigma_t = m.get_xs(MgxsType::TOTAL, g_out, NULL, NULL, NULL, t, a); sigma_t_.push_back(sigma_t); + if (sigma_t < MINIMUM_MACRO_XS) { + Material* mat = model::materials[i].get(); + warning(fmt::format( + "Material \"{}\" (id: {}) has a group {} total cross section " + "({:.3e}) below the minimum threshold " + "({:.3e}). Material will be treated as pure void.", + mat->name(), mat->id(), g_out, sigma_t, MINIMUM_MACRO_XS)); + } + double nu_sigma_f = m.get_xs(MgxsType::NU_FISSION, g_out, NULL, NULL, NULL, t, a); nu_sigma_f_.push_back(nu_sigma_f); @@ -1206,7 +1151,7 @@ void FlatSourceDomain::flatten_xs() } } -void FlatSourceDomain::set_adjoint_sources(const vector& forward_flux) +void FlatSourceDomain::set_adjoint_sources() { // Set the adjoint external source to 1/forward_flux. If the forward flux is // negative, zero, or extremely close to zero, set the adjoint source to zero, @@ -1220,7 +1165,7 @@ void FlatSourceDomain::set_adjoint_sources(const vector& forward_flux) double max_flux = 0.0; #pragma omp parallel for reduction(max : max_flux) for (int64_t se = 0; se < n_source_elements(); se++) { - double flux = forward_flux[se]; + double flux = source_regions_.scalar_flux_final(se); if (flux > max_flux) { max_flux = flux; } @@ -1230,7 +1175,7 @@ void FlatSourceDomain::set_adjoint_sources(const vector& forward_flux) #pragma omp parallel for for (int64_t sr = 0; sr < n_source_regions(); sr++) { for (int g = 0; g < negroups_; g++) { - double flux = forward_flux[sr * negroups_ + g]; + double flux = source_regions_.scalar_flux_final(sr, g); if (flux <= ZERO_FLUX_CUTOFF * max_flux) { source_regions_.external_source(sr, g) = 0.0; } else { @@ -1239,6 +1184,7 @@ void FlatSourceDomain::set_adjoint_sources(const vector& forward_flux) if (flux > 0.0) { source_regions_.external_source_present(sr) = 1; } + source_regions_.scalar_flux_final(sr, g) = 0.0; } } @@ -1265,7 +1211,6 @@ void FlatSourceDomain::set_adjoint_sources(const vector& forward_flux) source_regions_.external_source_present(sr) = 0; } } - // Divide the fixed source term by sigma t (to save time when applying each // iteration) #pragma omp parallel for @@ -1326,13 +1271,14 @@ void FlatSourceDomain::apply_mesh_to_cell_instances(int32_t i_cell, if ((target_material_id == C_NONE && !is_target_void) || cell_material_id == target_material_id) { int64_t sr = source_region_offsets_[i_cell] + j; - if (source_regions_.mesh(sr) != C_NONE) { - // print out the source region that is broken: + // Check if the key is already present in the mesh_map_ + if (mesh_map_.find(sr) != mesh_map_.end()) { fatal_error(fmt::format("Source region {} already has mesh idx {} " "applied, but trying to apply mesh idx {}", - sr, source_regions_.mesh(sr), mesh_idx)); + sr, mesh_map_[sr], mesh_idx)); } - source_regions_.mesh(sr) = mesh_idx; + // If the SR has not already been assigned, then we can write to it + mesh_map_[sr] = mesh_idx; } } } @@ -1402,18 +1348,9 @@ void FlatSourceDomain::apply_meshes() } } -void FlatSourceDomain::prepare_base_source_regions() -{ - std::swap(source_regions_, base_source_regions_); - source_regions_.negroups() = base_source_regions_.negroups(); - source_regions_.is_linear() = base_source_regions_.is_linear(); -} - SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( - int64_t sr, int mesh_bin, Position r, double dist, Direction u) + SourceRegionKey sr_key, Position r, Direction u) { - SourceRegionKey sr_key {sr, mesh_bin}; - // Case 1: Check if the source region key is already present in the permanent // map. This is the most common condition, as any source region visited in a // previous power iteration will already be present in the permanent map. If @@ -1475,9 +1412,8 @@ SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( gs.r() = r + TINY_BIT * u; gs.u() = {1.0, 0.0, 0.0}; exhaustive_find_cell(gs); - int gs_i_cell = gs.lowest_coord().cell(); - int64_t sr_found = source_region_offsets_[gs_i_cell] + gs.cell_instance(); - if (sr_found != sr) { + int64_t sr_found = lookup_base_source_region_idx(gs); + if (sr_found != sr_key.base_source_region_id) { discovered_source_regions_.unlock(sr_key); SourceRegionHandle handle; handle.is_numerical_fp_artifact_ = true; @@ -1485,9 +1421,9 @@ SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( } // Sanity check on mesh bin - int mesh_idx = base_source_regions_.mesh(sr); + int mesh_idx = lookup_mesh_idx(sr_key.base_source_region_id); if (mesh_idx == C_NONE) { - if (mesh_bin != 0) { + if (sr_key.mesh_bin != 0) { discovered_source_regions_.unlock(sr_key); SourceRegionHandle handle; handle.is_numerical_fp_artifact_ = true; @@ -1496,7 +1432,7 @@ SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( } else { Mesh* mesh = model::meshes[mesh_idx].get(); int bin_found = mesh->get_bin(r + TINY_BIT * u); - if (bin_found != mesh_bin) { + if (bin_found != sr_key.mesh_bin) { discovered_source_regions_.unlock(sr_key); SourceRegionHandle handle; handle.is_numerical_fp_artifact_ = true; @@ -1508,26 +1444,60 @@ SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( // condition only occurs the first time the source region is discovered // (typically in the first power iteration). In this case, we need to handle // creation of the new source region and its storage into the parallel map. - // The new source region is created by copying the base source region, so as - // to inherit material, external source, and some flux properties etc. We - // also pass the base source region id to allow the new source region to - // know which base source region it is derived from. - SourceRegion* sr_ptr = discovered_source_regions_.emplace( - sr_key, {base_source_regions_.get_source_region_handle(sr), sr}); - discovered_source_regions_.unlock(sr_key); + // Additionally, we need to determine the source region's material, initialize + // the starting scalar flux guess, and apply any known external sources. + + // Call the basic constructor for the source region and store in the parallel + // map. + bool is_linear = RandomRay::source_shape_ != RandomRaySourceShape::FLAT; + SourceRegion* sr_ptr = + discovered_source_regions_.emplace(sr_key, {negroups_, is_linear}); SourceRegionHandle handle {*sr_ptr}; - // Check if the new source region contains a point source and apply it if so - auto it2 = point_source_map_.find(sr_key); - if (it2 != point_source_map_.end()) { - int es = it2->second; - auto s = model::external_sources[es].get(); - auto is = dynamic_cast(s); - auto energy = dynamic_cast(is->energy()); - double strength_factor = is->strength(); - apply_external_source_to_source_region(energy, strength_factor, handle); - int material = handle.material(); - if (material != MATERIAL_VOID) { + // Determine the material + int gs_i_cell = gs.lowest_coord().cell(); + Cell& cell = *model::cells[gs_i_cell]; + int material = cell.material(gs.cell_instance()); + + // If material total XS is extremely low, just set it to void to avoid + // problems with 1/Sigma_t + for (int g = 0; g < negroups_; g++) { + double sigma_t = sigma_t_[material * negroups_ + g]; + if (sigma_t < MINIMUM_MACRO_XS) { + material = MATERIAL_VOID; + break; + } + } + + handle.material() = material; + + // Store the mesh index (if any) assigned to this source region + handle.mesh() = mesh_idx; + + if (settings::run_mode == RunMode::FIXED_SOURCE) { + // Determine if there are any volumetric sources, and apply them. + // Volumetric sources are specifc only to the base SR idx. + auto it_vol = + external_volumetric_source_map_.find(sr_key.base_source_region_id); + if (it_vol != external_volumetric_source_map_.end()) { + const vector& vol_sources = it_vol->second; + for (int src_idx : vol_sources) { + apply_external_source_to_source_region(src_idx, handle); + } + } + + // Determine if there are any point sources, and apply them. + // Point sources are specific to the source region key. + auto it_point = external_point_source_map_.find(sr_key); + if (it_point != external_point_source_map_.end()) { + const vector& point_sources = it_point->second; + for (int src_idx : point_sources) { + apply_external_source_to_source_region(src_idx, handle); + } + } + + // Divide external source term by sigma_t + if (material != C_NONE) { for (int g = 0; g < negroups_; g++) { double sigma_t = sigma_t_[material * negroups_ + g]; handle.external_source(g) /= sigma_t; @@ -1535,6 +1505,21 @@ SourceRegionHandle FlatSourceDomain::get_subdivided_source_region_handle( } } + // Compute the combined source term + update_single_neutron_source(handle); + + // Unlock the parallel map. Note: we may be tempted to release + // this lock earlier, and then just use the source region's lock to protect + // the flux/source initialization stages above. However, the rest of the code + // only protects updates to the new flux and volume fields, and assumes that + // the source is constant for the duration of transport. Thus, using just the + // source region's lock by itself would result in other threads potentially + // reading from the source before it is computed, as they won't use the lock + // when only reading from the SR's source. It would be expensive to protect + // those operations, whereas generating the SR is only done once, so we just + // hold the map's bucket lock until the source region is fully initialized. + discovered_source_regions_.unlock(sr_key); + return handle; } @@ -1620,4 +1605,52 @@ void FlatSourceDomain::apply_transport_stabilization() } } +// Determines the base source region index (i.e., a material filled cell +// instance) that corresponds to a particular location in the geometry. Requires +// that the "gs" object passed in has already been initialized and has called +// find_cell etc. +int64_t FlatSourceDomain::lookup_base_source_region_idx( + const GeometryState& gs) const +{ + int i_cell = gs.lowest_coord().cell(); + int64_t sr = source_region_offsets_[i_cell] + gs.cell_instance(); + return sr; +} + +// Determines the index of the mesh (if any) that has been applied +// to a particular base source region index. +int FlatSourceDomain::lookup_mesh_idx(int64_t sr) const +{ + int mesh_idx = C_NONE; + auto mesh_it = mesh_map_.find(sr); + if (mesh_it != mesh_map_.end()) { + mesh_idx = mesh_it->second; + } + return mesh_idx; +} + +// Determines the source region key that corresponds to a particular location in +// the geometry. This takes into account both the base source region index as +// well as the mesh bin if a mesh is applied to this source region for +// subdivision. +SourceRegionKey FlatSourceDomain::lookup_source_region_key( + const GeometryState& gs) const +{ + int64_t sr = lookup_base_source_region_idx(gs); + int64_t mesh_bin = lookup_mesh_bin(sr, gs.r()); + return SourceRegionKey {sr, mesh_bin}; +} + +// Determines the mesh bin that corresponds to a particular base source region +// index and position. +int64_t FlatSourceDomain::lookup_mesh_bin(int64_t sr, Position r) const +{ + int mesh_idx = lookup_mesh_idx(sr); + int mesh_bin = 0; + if (mesh_idx != C_NONE) { + mesh_bin = model::meshes[mesh_idx]->get_bin(r); + } + return mesh_bin; +} + } // namespace openmc diff --git a/src/random_ray/linear_source_domain.cpp b/src/random_ray/linear_source_domain.cpp index 81412164ec..e1ad68e3d8 100644 --- a/src/random_ray/linear_source_domain.cpp +++ b/src/random_ray/linear_source_domain.cpp @@ -34,25 +34,18 @@ void LinearSourceDomain::batch_reset() } } -void LinearSourceDomain::update_neutron_source(double k_eff) +void LinearSourceDomain::update_single_neutron_source(SourceRegionHandle& srh) { - simulation::time_update_src.start(); - - double inverse_k_eff = 1.0 / k_eff; - -// Reset all source regions to zero (important for void regions) -#pragma omp parallel for - for (int64_t se = 0; se < n_source_elements(); se++) { - source_regions_.source(se) = 0.0; + // Reset all source regions to zero (important for void regions) + for (int g = 0; g < negroups_; g++) { + srh.source(g) = 0.0; } -#pragma omp parallel for - for (int64_t sr = 0; sr < n_source_regions(); sr++) { - int material = source_regions_.material(sr); - if (material == MATERIAL_VOID) { - continue; - } - MomentMatrix invM = source_regions_.mom_matrix(sr).inverse(); + // Add scattering + fission source + int material = srh.material(); + if (material != MATERIAL_VOID) { + double inverse_k_eff = 1.0 / k_eff_; + MomentMatrix invM = srh.mom_matrix().inverse(); for (int g_out = 0; g_out < negroups_; g_out++) { double sigma_t = sigma_t_[material * negroups_ + g_out]; @@ -64,8 +57,8 @@ void LinearSourceDomain::update_neutron_source(double k_eff) for (int g_in = 0; g_in < negroups_; g_in++) { // Handles for the flat and linear components of the flux - double flux_flat = source_regions_.scalar_flux_old(sr, g_in); - MomentArray flux_linear = source_regions_.flux_moments_old(sr, g_in); + double flux_flat = srh.scalar_flux_old(g_in); + MomentArray flux_linear = srh.flux_moments_old(g_in); // Handles for cross sections double sigma_s = @@ -81,7 +74,7 @@ void LinearSourceDomain::update_neutron_source(double k_eff) } // Compute the flat source term - source_regions_.source(sr, g_out) = + srh.source(g_out) = (scatter_flat + fission_flat * inverse_k_eff) / sigma_t; // Compute the linear source terms. In the first 10 iterations when the @@ -91,25 +84,21 @@ void LinearSourceDomain::update_neutron_source(double k_eff) // very small/noisy or have poorly developed spatial moments, so we zero // the source gradients (effectively making this a flat source region // temporarily), so as to improve stability. - if (simulation::current_batch > 10 && - source_regions_.source(sr, g_out) >= 0.0) { - source_regions_.source_gradients(sr, g_out) = + if (simulation::current_batch > 10 && srh.source(g_out) >= 0.0) { + srh.source_gradients(g_out) = invM * ((scatter_linear + fission_linear * inverse_k_eff) / sigma_t); } else { - source_regions_.source_gradients(sr, g_out) = {0.0, 0.0, 0.0}; + srh.source_gradients(g_out) = {0.0, 0.0, 0.0}; } } } + // Add external source if in fixed source mode if (settings::run_mode == RunMode::FIXED_SOURCE) { -// Add external source to flat source term if in fixed source mode -#pragma omp parallel for - for (int64_t se = 0; se < n_source_elements(); se++) { - source_regions_.source(se) += source_regions_.external_source(se); + for (int g = 0; g < negroups_; g++) { + srh.source(g) += srh.external_source(g); } } - - simulation::time_update_src.stop(); } void LinearSourceDomain::normalize_scalar_flux_and_volumes( diff --git a/src/random_ray/random_ray.cpp b/src/random_ray/random_ray.cpp index 27f674c427..89a91449df 100644 --- a/src/random_ray/random_ray.cpp +++ b/src/random_ray/random_ray.cpp @@ -237,7 +237,6 @@ double RandomRay::distance_inactive_; double RandomRay::distance_active_; unique_ptr RandomRay::ray_source_; RandomRaySourceShape RandomRay::source_shape_ {RandomRaySourceShape::FLAT}; -bool RandomRay::mesh_subdivision_enabled_ {false}; RandomRaySampleMethod RandomRay::sample_method_ {RandomRaySampleMethod::PRNG}; RandomRay::RandomRay() @@ -336,71 +335,60 @@ void RandomRay::event_advance_ray() void RandomRay::attenuate_flux(double distance, bool is_active, double offset) { - // Determine source region index etc. - int i_cell = lowest_coord().cell(); - - // The base source region is the spatial region index - int64_t sr = domain_->source_region_offsets_[i_cell] + cell_instance(); + // Lookup base source region index + int64_t sr = domain_->lookup_base_source_region_idx(*this); // Perform ray tracing across mesh - if (mesh_subdivision_enabled_) { - // Determine the mesh index for the base source region, if any - int mesh_idx = domain_->base_source_regions_.mesh(sr); + // Determine the mesh index for the base source region, if any + int mesh_idx = domain_->lookup_mesh_idx(sr); - if (mesh_idx == C_NONE) { - // If there's no mesh being applied to this cell, then - // we just attenuate the flux as normal, and set - // the mesh bin to 0 - attenuate_flux_inner(distance, is_active, sr, 0, r()); - } else { - // If there is a mesh being applied to this cell, then - // we loop over all the bin crossings and attenuate - // separately. - Mesh* mesh = model::meshes[mesh_idx].get(); - - // We adjust the start and end positions of the ray slightly - // to accomodate for floating point precision issues that tend - // to occur at mesh boundaries that overlap with geometry lattice - // boundaries. - Position start = r() + (offset + TINY_BIT) * u(); - Position end = start + (distance - 2.0 * TINY_BIT) * u(); - double reduced_distance = (end - start).norm(); - - // Ray trace through the mesh and record bins and lengths - mesh_bins_.resize(0); - mesh_fractional_lengths_.resize(0); - mesh->bins_crossed(start, end, u(), mesh_bins_, mesh_fractional_lengths_); - - // Loop over all mesh bins and attenuate flux - for (int b = 0; b < mesh_bins_.size(); b++) { - double physical_length = reduced_distance * mesh_fractional_lengths_[b]; - attenuate_flux_inner( - physical_length, is_active, sr, mesh_bins_[b], start); - start += physical_length * u(); - } - } + if (mesh_idx == C_NONE) { + // If there's no mesh being applied to this cell, then + // we just attenuate the flux as normal, and set + // the mesh bin to 0 + attenuate_flux_inner(distance, is_active, sr, 0, r()); } else { - attenuate_flux_inner(distance, is_active, sr, C_NONE, r()); + // If there is a mesh being applied to this cell, then + // we loop over all the bin crossings and attenuate + // separately. + Mesh* mesh = model::meshes[mesh_idx].get(); + + // We adjust the start and end positions of the ray slightly + // to accomodate for floating point precision issues that tend + // to occur at mesh boundaries that overlap with geometry lattice + // boundaries. + Position start = r() + (offset + TINY_BIT) * u(); + Position end = start + (distance - 2.0 * TINY_BIT) * u(); + double reduced_distance = (end - start).norm(); + + // Ray trace through the mesh and record bins and lengths + mesh_bins_.resize(0); + mesh_fractional_lengths_.resize(0); + mesh->bins_crossed(start, end, u(), mesh_bins_, mesh_fractional_lengths_); + + // Loop over all mesh bins and attenuate flux + for (int b = 0; b < mesh_bins_.size(); b++) { + double physical_length = reduced_distance * mesh_fractional_lengths_[b]; + attenuate_flux_inner( + physical_length, is_active, sr, mesh_bins_[b], start); + start += physical_length * u(); + } } } void RandomRay::attenuate_flux_inner( double distance, bool is_active, int64_t sr, int mesh_bin, Position r) { + SourceRegionKey sr_key {sr, mesh_bin}; SourceRegionHandle srh; - if (mesh_subdivision_enabled_) { - srh = domain_->get_subdivided_source_region_handle( - sr, mesh_bin, r, distance, u()); - if (srh.is_numerical_fp_artifact_) { - return; - } - } else { - srh = domain_->source_regions_.get_source_region_handle(sr); + srh = domain_->get_subdivided_source_region_handle(sr_key, r, u()); + if (srh.is_numerical_fp_artifact_) { + return; } switch (source_shape_) { case RandomRaySourceShape::FLAT: - if (this->material() == MATERIAL_VOID) { + if (srh.material() == MATERIAL_VOID) { attenuate_flux_flat_source_void(srh, distance, is_active, r); } else { attenuate_flux_flat_source(srh, distance, is_active, r); @@ -408,7 +396,7 @@ void RandomRay::attenuate_flux_inner( break; case RandomRaySourceShape::LINEAR: case RandomRaySourceShape::LINEAR_XY: - if (this->material() == MATERIAL_VOID) { + if (srh.material() == MATERIAL_VOID) { attenuate_flux_linear_source_void(srh, distance, is_active, r); } else { attenuate_flux_linear_source(srh, distance, is_active, r); @@ -439,7 +427,7 @@ void RandomRay::attenuate_flux_flat_source( n_event()++; // Get material - int material = this->material(); + int material = srh.material(); // MOC incoming flux attenuation + source contribution/attenuation equation for (int g = 0; g < negroups_; g++) { @@ -490,7 +478,7 @@ void RandomRay::attenuate_flux_flat_source_void( // The number of geometric intersections is counted for reporting purposes n_event()++; - int material = this->material(); + int material = srh.material(); // If ray is in the active phase (not in dead zone), make contributions to // source region bookkeeping @@ -537,7 +525,7 @@ void RandomRay::attenuate_flux_linear_source( // The number of geometric intersections is counted for reporting purposes n_event()++; - int material = this->material(); + int material = srh.material(); Position& centroid = srh.centroid(); Position midpoint = r + u() * (distance / 2.0); @@ -810,27 +798,12 @@ void RandomRay::initialize_ray(uint64_t ray_id, FlatSourceDomain* domain) cell_born() = lowest_coord().cell(); } + SourceRegionKey sr_key = domain_->lookup_source_region_key(*this); + SourceRegionHandle srh = + domain_->get_subdivided_source_region_handle(sr_key, r(), u()); + // Initialize ray's starting angular flux to starting location's isotropic // source - int i_cell = lowest_coord().cell(); - int64_t sr = domain_->source_region_offsets_[i_cell] + cell_instance(); - - SourceRegionHandle srh; - if (mesh_subdivision_enabled_) { - int mesh_idx = domain_->base_source_regions_.mesh(sr); - int mesh_bin; - if (mesh_idx == C_NONE) { - mesh_bin = 0; - } else { - Mesh* mesh = model::meshes[mesh_idx].get(); - mesh_bin = mesh->get_bin(r()); - } - srh = - domain_->get_subdivided_source_region_handle(sr, mesh_bin, r(), 0.0, u()); - } else { - srh = domain_->source_regions_.get_source_region_handle(sr); - } - if (!srh.is_numerical_fp_artifact_) { for (int g = 0; g < negroups_; g++) { angular_flux_[g] = srh.source(g); diff --git a/src/random_ray/random_ray_simulation.cpp b/src/random_ray/random_ray_simulation.cpp index 388a778b84..d475b2593e 100644 --- a/src/random_ray/random_ray_simulation.cpp +++ b/src/random_ray/random_ray_simulation.cpp @@ -47,97 +47,82 @@ void openmc_run_random_ray() if (mpi::master) validate_random_ray_inputs(); - // Declare forward flux so that it can be saved for later adjoint simulation - vector forward_flux; - SourceRegionContainer forward_source_regions; - SourceRegionContainer forward_base_source_regions; - std::unordered_map - forward_source_region_map; + // Initialize Random Ray Simulation Object + RandomRaySimulation sim; - { - // Initialize Random Ray Simulation Object - RandomRaySimulation sim; + // Initialize fixed sources, if present + sim.apply_fixed_sources_and_mesh_domains(); - // Initialize fixed sources, if present - sim.apply_fixed_sources_and_mesh_domains(); + // Begin main simulation timer + simulation::time_total.start(); - // Begin main simulation timer - simulation::time_total.start(); + // Execute random ray simulation + sim.simulate(); - // Execute random ray simulation - sim.simulate(); + // End main simulation timer + simulation::time_total.stop(); - // End main simulation timer - simulation::time_total.stop(); - - // Normalize and save the final forward flux - sim.domain()->serialize_final_fluxes(forward_flux); - - double source_normalization_factor = - sim.domain()->compute_fixed_source_normalization_factor() / - (settings::n_batches - settings::n_inactive); + // Normalize and save the final forward flux + double source_normalization_factor = + sim.domain()->compute_fixed_source_normalization_factor() / + (settings::n_batches - settings::n_inactive); #pragma omp parallel for - for (uint64_t i = 0; i < forward_flux.size(); i++) { - forward_flux[i] *= source_normalization_factor; - } - - forward_source_regions = sim.domain()->source_regions_; - forward_source_region_map = sim.domain()->source_region_map_; - forward_base_source_regions = sim.domain()->base_source_regions_; - - // Finalize OpenMC - openmc_simulation_finalize(); - - // Output all simulation results - sim.output_simulation_results(); + for (uint64_t se = 0; se < sim.domain()->n_source_elements(); se++) { + sim.domain()->source_regions_.scalar_flux_final(se) *= + source_normalization_factor; } + // Finalize OpenMC + openmc_simulation_finalize(); + + // Output all simulation results + sim.output_simulation_results(); + ////////////////////////////////////////////////////////// // Run adjoint simulation (if enabled) ////////////////////////////////////////////////////////// - if (adjoint_needed) { - reset_timers(); - - // Configure the domain for adjoint simulation - FlatSourceDomain::adjoint_ = true; - - if (mpi::master) - header("ADJOINT FLUX SOLVE", 3); - - // Initialize OpenMC general data structures - openmc_simulation_init(); - - // Initialize Random Ray Simulation Object - RandomRaySimulation adjoint_sim; - - // Initialize adjoint fixed sources, if present - adjoint_sim.prepare_fixed_sources_adjoint(forward_flux, - forward_source_regions, forward_base_source_regions, - forward_source_region_map); - - // Transpose scattering matrix - adjoint_sim.domain()->transpose_scattering_matrix(); - - // Swap nu_sigma_f and chi - adjoint_sim.domain()->nu_sigma_f_.swap(adjoint_sim.domain()->chi_); - - // Begin main simulation timer - simulation::time_total.start(); - - // Execute random ray simulation - adjoint_sim.simulate(); - - // End main simulation timer - simulation::time_total.stop(); - - // Finalize OpenMC - openmc_simulation_finalize(); - - // Output all simulation results - adjoint_sim.output_simulation_results(); + if (!adjoint_needed) { + return; } + + reset_timers(); + + // Configure the domain for adjoint simulation + FlatSourceDomain::adjoint_ = true; + + if (mpi::master) + header("ADJOINT FLUX SOLVE", 3); + + // Initialize OpenMC general data structures + openmc_simulation_init(); + + sim.domain()->k_eff_ = 1.0; + + // Initialize adjoint fixed sources, if present + sim.prepare_fixed_sources_adjoint(); + + // Transpose scattering matrix + sim.domain()->transpose_scattering_matrix(); + + // Swap nu_sigma_f and chi + sim.domain()->nu_sigma_f_.swap(sim.domain()->chi_); + + // Begin main simulation timer + simulation::time_total.start(); + + // Execute random ray simulation + sim.simulate(); + + // End main simulation timer + simulation::time_total.stop(); + + // Finalize OpenMC + openmc_simulation_finalize(); + + // Output all simulation results + sim.output_simulation_results(); } // Enforces restrictions on inputs in random ray mode. While there are @@ -348,7 +333,6 @@ void validate_random_ray_inputs() // when generating weight windows with FW-CADIS and an overlaid mesh. /////////////////////////////////////////////////////////////////// if (RandomRay::source_shape_ == RandomRaySourceShape::LINEAR && - RandomRay::mesh_subdivision_enabled_ && variance_reduction::weight_windows.size() > 0) { warning( "Linear sources may result in negative fluxes in small source regions " @@ -366,7 +350,6 @@ void openmc_reset_random_ray() FlatSourceDomain::mesh_domain_map_.clear(); RandomRay::ray_source_.reset(); RandomRay::source_shape_ = RandomRaySourceShape::FLAT; - RandomRay::mesh_subdivision_enabled_ = false; RandomRay::sample_method_ = RandomRaySampleMethod::PRNG; } @@ -412,20 +395,11 @@ void RandomRaySimulation::apply_fixed_sources_and_mesh_domains() } } -void RandomRaySimulation::prepare_fixed_sources_adjoint( - vector& forward_flux, SourceRegionContainer& forward_source_regions, - SourceRegionContainer& forward_base_source_regions, - std::unordered_map& - forward_source_region_map) +void RandomRaySimulation::prepare_fixed_sources_adjoint() { + domain_->source_regions_.adjoint_reset(); if (settings::run_mode == RunMode::FIXED_SOURCE) { - if (RandomRay::mesh_subdivision_enabled_) { - domain_->source_regions_ = forward_source_regions; - domain_->source_region_map_ = forward_source_region_map; - domain_->base_source_regions_ = forward_base_source_regions; - domain_->source_regions_.adjoint_reset(); - } - domain_->set_adjoint_sources(forward_flux); + domain_->set_adjoint_sources(); } } @@ -445,22 +419,18 @@ void RandomRaySimulation::simulate() simulation::total_weight = 1.0; // Update source term (scattering + fission) - domain_->update_neutron_source(k_eff_); + domain_->update_all_neutron_sources(); - // Reset scalar fluxes, iteration volume tallies, and region hit flags to - // zero + // Reset scalar fluxes, iteration volume tallies, and region hit flags + // to zero domain_->batch_reset(); - // At the beginning of the simulation, if mesh subvivision is in use, we + // At the beginning of the simulation, if mesh subdivision is in use, we // need to swap the main source region container into the base container, // as the main source region container will be used to hold the true // subdivided source regions. The base container will therefore only // contain the external source region information, the mesh indices, // material properties, and initial guess values for the flux/source. - if (RandomRay::mesh_subdivision_enabled_ && - simulation::current_batch == 1 && !FlatSourceDomain::adjoint_) { - domain_->prepare_base_source_regions(); - } // Start timer for transport simulation::time_transport.start(); @@ -476,11 +446,9 @@ void RandomRaySimulation::simulate() simulation::time_transport.stop(); - // If using mesh subdivision, add any newly discovered source regions - // to the main source region container. - if (RandomRay::mesh_subdivision_enabled_) { - domain_->finalize_discovered_source_regions(); - } + // Add any newly discovered source regions to the main source region + // container. + domain_->finalize_discovered_source_regions(); // Normalize scalar flux and update volumes domain_->normalize_scalar_flux_and_volumes( @@ -494,10 +462,10 @@ void RandomRaySimulation::simulate() if (settings::run_mode == RunMode::EIGENVALUE) { // Compute random ray k-eff - k_eff_ = domain_->compute_k_eff(k_eff_); + domain_->compute_k_eff(); // Store random ray k-eff into OpenMC's native k-eff variable - global_tally_tracklength = k_eff_; + global_tally_tracklength = domain_->k_eff_; } // Execute all tallying tasks, if this is an active batch @@ -507,12 +475,6 @@ void RandomRaySimulation::simulate() // estimate domain_->accumulate_iteration_flux(); - // Generate mapping between source regions and tallies - if (!domain_->mapped_all_tallies_ && - !RandomRay::mesh_subdivision_enabled_) { - domain_->convert_source_regions_to_tallies(0); - } - // Use above mapping to contribute FSR flux data to appropriate // tallies domain_->random_ray_tally(); @@ -522,7 +484,7 @@ void RandomRaySimulation::simulate() domain_->flux_swap(); // Check for any obvious insabilities/nans/infs - instability_check(n_hits, k_eff_, avg_miss_rate_); + instability_check(n_hits, domain_->k_eff_, avg_miss_rate_); } // End MPI master work // Finalize the current batch @@ -571,7 +533,7 @@ void RandomRaySimulation::instability_check( } if (k_eff > 10.0 || k_eff < 0.01 || !(std::isfinite(k_eff))) { - fatal_error("Instability detected"); + fatal_error(fmt::format("Instability detected: k-eff = {:.5f}", k_eff)); } } } diff --git a/src/random_ray/source_region.cpp b/src/random_ray/source_region.cpp index 1205b995a6..3b06f0ed09 100644 --- a/src/random_ray/source_region.cpp +++ b/src/random_ray/source_region.cpp @@ -48,7 +48,7 @@ SourceRegion::SourceRegion(int negroups, bool is_linear) } scalar_flux_new_.assign(negroups, 0.0); - source_.resize(negroups); + source_.assign(negroups, 0.0); scalar_flux_final_.assign(negroups, 0.0); tally_task_.resize(negroups); @@ -60,25 +60,6 @@ SourceRegion::SourceRegion(int negroups, bool is_linear) } } -SourceRegion::SourceRegion(const SourceRegionHandle& handle, int64_t parent_sr) - : SourceRegion(handle.negroups_, handle.is_linear_) -{ - material_ = handle.material(); - mesh_ = handle.mesh(); - parent_sr_ = parent_sr; - for (int g = 0; g < scalar_flux_new_.size(); g++) { - scalar_flux_old_[g] = handle.scalar_flux_old(g); - source_[g] = handle.source(g); - } - - if (settings::run_mode == RunMode::FIXED_SOURCE) { - external_source_present_ = handle.external_source_present(); - for (int g = 0; g < scalar_flux_new_.size(); g++) { - external_source_[g] = handle.external_source(g); - } - } -} - //============================================================================== // SourceRegionContainer implementation //============================================================================== @@ -259,9 +240,12 @@ void SourceRegionContainer::adjoint_reset() MomentMatrix {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); std::fill(mom_matrix_t_.begin(), mom_matrix_t_.end(), MomentMatrix {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); - std::fill(scalar_flux_old_.begin(), scalar_flux_old_.end(), 0.0); + if (settings::run_mode == RunMode::FIXED_SOURCE) { + std::fill(scalar_flux_old_.begin(), scalar_flux_old_.end(), 0.0); + } else { + std::fill(scalar_flux_old_.begin(), scalar_flux_old_.end(), 1.0); + } std::fill(scalar_flux_new_.begin(), scalar_flux_new_.end(), 0.0); - std::fill(scalar_flux_final_.begin(), scalar_flux_final_.end(), 0.0); std::fill(source_.begin(), source_.end(), 0.0f); std::fill(external_source_.begin(), external_source_.end(), 0.0f); std::fill(source_gradients_.begin(), source_gradients_.end(), diff --git a/src/settings.cpp b/src/settings.cpp index 03d42bb9da..f9a2469db9 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -346,7 +346,6 @@ void get_run_parameters(pugi::xml_node node_base) } FlatSourceDomain::mesh_domain_map_[mesh_id].emplace_back( type, domain_id); - RandomRay::mesh_subdivision_enabled_ = true; } } } diff --git a/tests/regression_tests/random_ray_low_density/__init__.py b/tests/regression_tests/random_ray_low_density/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/random_ray_low_density/inputs_true.dat b/tests/regression_tests/random_ray_low_density/inputs_true.dat new file mode 100644 index 0000000000..c4fd06f421 --- /dev/null +++ b/tests/regression_tests/random_ray_low_density/inputs_true.dat @@ -0,0 +1,244 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + 2.5 2.5 2.5 + 12 12 12 + 0.0 0.0 0.0 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +1 1 2 2 2 2 2 2 2 2 3 3 +1 1 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +1 1 2 2 2 2 2 2 2 2 3 3 +1 1 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 +2 2 2 2 2 2 2 2 2 2 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 + +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 + + + + + + + + + + fixed source + 90 + 10 + 5 + + + 100.0 1.0 + + + universe + 1 + + + multi-group + + 500.0 + 100.0 + + + 0.0 0.0 0.0 30.0 30.0 30.0 + + + True + + + + + 1 + + + 2 + + + 3 + + + 3 + flux + tracklength + + + 2 + flux + tracklength + + + 1 + flux + tracklength + + + diff --git a/tests/regression_tests/random_ray_low_density/results_true.dat b/tests/regression_tests/random_ray_low_density/results_true.dat new file mode 100644 index 0000000000..a4b3ee1bcd --- /dev/null +++ b/tests/regression_tests/random_ray_low_density/results_true.dat @@ -0,0 +1,9 @@ +tally 1: +5.973607E-01 +7.155477E-02 +tally 2: +3.206216E-02 +2.063375E-04 +tally 3: +2.096415E-03 +8.804963E-07 diff --git a/tests/regression_tests/random_ray_low_density/test.py b/tests/regression_tests/random_ray_low_density/test.py new file mode 100644 index 0000000000..1b4ffb7818 --- /dev/null +++ b/tests/regression_tests/random_ray_low_density/test.py @@ -0,0 +1,60 @@ +import os + +import numpy as np +import openmc +from openmc.examples import random_ray_three_region_cube + +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) + + +def test_random_ray_low_density(): + model = random_ray_three_region_cube() + + # Rebuild the MGXS library to have a material with very + # low macroscopic cross sections + ebins = [1e-5, 20.0e6] + groups = openmc.mgxs.EnergyGroups(group_edges=ebins) + + void_sigma_a = 4.0e-6 + void_sigma_s = 3.0e-4 + void_mat_data = openmc.XSdata('void', groups) + void_mat_data.order = 0 + void_mat_data.set_total([void_sigma_a + void_sigma_s]) + void_mat_data.set_absorption([void_sigma_a]) + void_mat_data.set_scatter_matrix( + np.rollaxis(np.array([[[void_sigma_s]]]), 0, 3)) + + absorber_sigma_a = 0.75 + absorber_sigma_s = 0.25 + absorber_mat_data = openmc.XSdata('absorber', groups) + absorber_mat_data.order = 0 + absorber_mat_data.set_total([absorber_sigma_a + absorber_sigma_s]) + absorber_mat_data.set_absorption([absorber_sigma_a]) + absorber_mat_data.set_scatter_matrix( + np.rollaxis(np.array([[[absorber_sigma_s]]]), 0, 3)) + + multiplier = 0.0000001 + source_sigma_a = void_sigma_a * multiplier + source_sigma_s = void_sigma_s * multiplier + source_mat_data = openmc.XSdata('source', groups) + source_mat_data.order = 0 + source_mat_data.set_total([source_sigma_a + source_sigma_s]) + source_mat_data.set_absorption([source_sigma_a]) + source_mat_data.set_scatter_matrix( + np.rollaxis(np.array([[[source_sigma_s]]]), 0, 3)) + + mg_cross_sections_file = openmc.MGXSLibrary(groups) + mg_cross_sections_file.add_xsdatas( + [source_mat_data, void_mat_data, absorber_mat_data]) + mg_cross_sections_file.export_to_hdf5() + + harness = MGXSTestHarness('statepoint.10.h5', model) + harness.main() diff --git a/tests/regression_tests/random_ray_point_source_locator/results_true.dat b/tests/regression_tests/random_ray_point_source_locator/results_true.dat index 1785dda574..8c6f358dd3 100644 --- a/tests/regression_tests/random_ray_point_source_locator/results_true.dat +++ b/tests/regression_tests/random_ray_point_source_locator/results_true.dat @@ -1,9 +1,9 @@ tally 1: -2.633900E+00 -2.948207E+00 +2.633923E+00 +2.948228E+00 tally 2: -1.440463E-01 -3.294032E-03 +1.440456E-01 +3.293984E-03 tally 3: 9.425207E-03 1.089748E-05 From 1dacf4fd2bba3582b575b6abf92b5d201eabab37 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 2 Oct 2025 11:48:02 -0500 Subject: [PATCH 19/76] Add missing documentation on in depletion chain file format (#3590) Co-authored-by: Paul Romano Co-authored-by: April Novak --- docs/source/io_formats/depletion_chain.rst | 21 +++++++++++++++++++++ openmc/data/decay.py | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/source/io_formats/depletion_chain.rst b/docs/source/io_formats/depletion_chain.rst index 89c76525f8..74413e7b61 100644 --- a/docs/source/io_formats/depletion_chain.rst +++ b/docs/source/io_formats/depletion_chain.rst @@ -56,6 +56,27 @@ attributes: .. _io_chain_reaction: +-------------------- +```` Element +-------------------- + +The ```` element represents photon and electron sources associated with +the decay of a nuclide and contains information to construct an +:class:`openmc.stats.Univariate` object that represents this emission as an +energy distribution. This element has the following attributes: + + :type: + The type of :class:`openmc.stats.Univariate` source term. + + :particle: + The type of particle emitted, e.g., 'photon' or 'electron' + + :parameters: + The parameters of the source term, e.g., for a + :class:`openmc.stats.Discrete` source, the energies (in [eV]) at which the + particles are emitted and their relative intensities in [Bq/atom] (in other + words, decay constants). + ---------------------- ```` Element ---------------------- diff --git a/openmc/data/decay.py b/openmc/data/decay.py index 1a11d3614f..c8a0bb5e7e 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -591,7 +591,7 @@ def decay_photon_energy(nuclide: str) -> Univariate | None: openmc.stats.Univariate or None Distribution of energies in [eV] of photons emitted from decay, or None if no photon source exists. Note that the probabilities represent - intensities, given as [Bq]. + intensities, given as [Bq/atom] (in other words, decay constants). """ if not _DECAY_PHOTON_ENERGY: chain_file = openmc.config.get('chain_file') From 91a19cf2201731017e02e445f2fc5995cfa51c46 Mon Sep 17 00:00:00 2001 From: Perry <100789850+yrrepy@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:50:42 -0700 Subject: [PATCH 20/76] Ensure weight_windows_file information is read from XML (#3587) Co-authored-by: Paul Romano --- openmc/settings.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/openmc/settings.py b/openmc/settings.py index 7bbc31c192..dc6fa99f9c 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1641,6 +1641,7 @@ class Settings: if mesh_memo is not None: mesh_memo.add(ww.mesh.id) + def _create_weight_windows_on_subelement(self, root): if self._weight_windows_on is not None: elem = ET.SubElement(root, "weight_windows_on") elem.text = str(self._weight_windows_on).lower() @@ -2074,10 +2075,16 @@ class Settings: ww = WeightWindows.from_xml_element(elem, meshes) self.weight_windows.append(ww) + def _weight_windows_on_from_xml_element(self, root): text = get_text(root, 'weight_windows_on') if text is not None: self.weight_windows_on = text in ('true', '1') + def _weight_windows_file_from_xml_element(self, root): + text = get_text(root, 'weight_windows_file') + if text is not None: + self.weight_windows_file = text + def _weight_window_checkpoints_from_xml_element(self, root): elem = root.find('weight_window_checkpoints') if elem is None: @@ -2214,6 +2221,7 @@ class Settings: self._create_log_grid_bins_subelement(element) self._create_write_initial_source_subelement(element) self._create_weight_windows_subelement(element, mesh_memo) + self._create_weight_windows_on_subelement(element) self._create_weight_window_generators_subelement(element, mesh_memo) self._create_weight_windows_file_element(element) self._create_weight_window_checkpoints_subelement(element) @@ -2324,6 +2332,8 @@ class Settings: settings._log_grid_bins_from_xml_element(elem) settings._write_initial_source_from_xml_element(elem) settings._weight_windows_from_xml_element(elem, meshes) + settings._weight_windows_on_from_xml_element(elem) + settings._weight_windows_file_from_xml_element(elem) settings._weight_window_generators_from_xml_element(elem, meshes) settings._weight_window_checkpoints_from_xml_element(elem) settings._max_history_splits_from_xml_element(elem) From 7806703c2614853be2d2ce49860e673e208145da Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Oct 2025 22:52:39 +0000 Subject: [PATCH 21/76] Fix random ray source region mesh export when using model.export_to_xml() (#3579) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jtramm <1009059+jtramm@users.noreply.github.com> Co-authored-by: Paul Romano --- openmc/settings.py | 20 +++++++++++---- .../inputs_true.dat | 4 +-- .../random_ray_adjoint_k_eff/inputs_true.dat | 4 +-- .../cell/inputs_true.dat | 2 +- .../material/inputs_true.dat | 2 +- .../universe/inputs_true.dat | 2 +- .../linear/inputs_true.dat | 2 +- .../linear_xy/inputs_true.dat | 2 +- .../flat/inputs_true.dat | 2 +- .../linear/inputs_true.dat | 2 +- .../False/inputs_true.dat | 2 +- .../True/inputs_true.dat | 2 +- .../flat/inputs_true.dat | 2 +- .../linear_xy/inputs_true.dat | 2 +- .../random_ray_halton_samples/inputs_true.dat | 2 +- .../random_ray_k_eff/inputs_true.dat | 2 +- .../random_ray_k_eff_mesh/inputs_true.dat | 2 +- .../random_ray_linear/linear/inputs_true.dat | 2 +- .../linear_xy/inputs_true.dat | 2 +- .../random_ray_low_density/inputs_true.dat | 2 +- .../inputs_true.dat | 2 +- .../random_ray_void/flat/inputs_true.dat | 2 +- .../random_ray_void/linear/inputs_true.dat | 2 +- .../hybrid/inputs_true.dat | 2 +- .../naive/inputs_true.dat | 2 +- .../simulation_averaged/inputs_true.dat | 2 +- .../hybrid/inputs_true.dat | 2 +- .../naive/inputs_true.dat | 2 +- .../simulation_averaged/inputs_true.dat | 2 +- .../weightwindows_fw_cadis/inputs_true.dat | 2 +- .../flat/inputs_true.dat | 2 +- .../linear/inputs_true.dat | 2 +- tests/unit_tests/test_settings.py | 25 ++++++++++++++++++- 33 files changed, 72 insertions(+), 39 deletions(-) diff --git a/openmc/settings.py b/openmc/settings.py index dc6fa99f9c..8f8aedc93e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1715,9 +1715,15 @@ class Settings: domain_elem = ET.SubElement(mesh_elem, 'domain') domain_elem.set('id', str(domain.id)) domain_elem.set('type', domain.__class__.__name__.lower()) - if mesh_memo is not None and mesh.id not in mesh_memo: + # See if a element already exists -- if not, add it + path = f"./mesh[@id='{mesh.id}']" + if root.find(path) is None: root.append(mesh.to_xml_element()) - mesh_memo.add(mesh.id) + if mesh_memo is not None: + mesh_memo.add(mesh.id) + elif isinstance(value, bool): + subelement = ET.SubElement(element, key) + subelement.text = str(value).lower() else: subelement = ET.SubElement(element, key) subelement.text = str(value) @@ -2110,7 +2116,7 @@ class Settings: if text is not None: self.max_tracks = int(text) - def _random_ray_from_xml_element(self, root): + def _random_ray_from_xml_element(self, root, meshes=None): elem = root.find('random_ray') if elem is not None: self.random_ray = {} @@ -2137,7 +2143,11 @@ class Settings: elif child.tag == 'source_region_meshes': self.random_ray['source_region_meshes'] = [] for mesh_elem in child.findall('mesh'): - mesh = MeshBase.from_xml_element(mesh_elem) + mesh_id = int(get_text(mesh_elem, 'id')) + if meshes and mesh_id in meshes: + mesh = meshes[mesh_id] + else: + mesh = MeshBase.from_xml_element(mesh_elem) domains = [] for domain_elem in mesh_elem.findall('domain'): domain_id = int(get_text(domain_elem, "id")) @@ -2339,7 +2349,7 @@ class Settings: settings._max_history_splits_from_xml_element(elem) settings._max_tracks_from_xml_element(elem) settings._max_secondaries_from_xml_element(elem) - settings._random_ray_from_xml_element(elem) + settings._random_ray_from_xml_element(elem, meshes) settings._use_decay_photons_from_xml_element(elem) settings._source_rejection_fraction_from_xml_element(elem) diff --git a/tests/regression_tests/random_ray_adjoint_fixed_source/inputs_true.dat b/tests/regression_tests/random_ray_adjoint_fixed_source/inputs_true.dat index 30e62a8853..0adfc54884 100644 --- a/tests/regression_tests/random_ray_adjoint_fixed_source/inputs_true.dat +++ b/tests/regression_tests/random_ray_adjoint_fixed_source/inputs_true.dat @@ -212,8 +212,8 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True - True + true + true naive diff --git a/tests/regression_tests/random_ray_adjoint_k_eff/inputs_true.dat b/tests/regression_tests/random_ray_adjoint_k_eff/inputs_true.dat index cd4e92aa1b..073348c41e 100644 --- a/tests/regression_tests/random_ray_adjoint_k_eff/inputs_true.dat +++ b/tests/regression_tests/random_ray_adjoint_k_eff/inputs_true.dat @@ -85,8 +85,8 @@ -1.26 -1.26 -1 1.26 1.26 1 - True - True + true + true diff --git a/tests/regression_tests/random_ray_fixed_source_domain/cell/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_domain/cell/inputs_true.dat index 4b8af76aaf..9f1987f3ac 100644 --- a/tests/regression_tests/random_ray_fixed_source_domain/cell/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_domain/cell/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_fixed_source_domain/material/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_domain/material/inputs_true.dat index 82fe48b614..b4f57dbfa8 100644 --- a/tests/regression_tests/random_ray_fixed_source_domain/material/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_domain/material/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_fixed_source_domain/universe/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_domain/universe/inputs_true.dat index c4fd06f421..ab91f74e50 100644 --- a/tests/regression_tests/random_ray_fixed_source_domain/universe/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_domain/universe/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_fixed_source_linear/linear/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_linear/linear/inputs_true.dat index 4085b0c7a1..220fa7db64 100644 --- a/tests/regression_tests/random_ray_fixed_source_linear/linear/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_linear/linear/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear diff --git a/tests/regression_tests/random_ray_fixed_source_linear/linear_xy/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_linear/linear_xy/inputs_true.dat index ff085d2fbb..f8c4430852 100644 --- a/tests/regression_tests/random_ray_fixed_source_linear/linear_xy/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_linear/linear_xy/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear_xy diff --git a/tests/regression_tests/random_ray_fixed_source_mesh/flat/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_mesh/flat/inputs_true.dat index 12c4d74edb..c84e544fcc 100644 --- a/tests/regression_tests/random_ray_fixed_source_mesh/flat/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_mesh/flat/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_fixed_source_mesh/linear/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_mesh/linear/inputs_true.dat index 07adb1ff55..05c4846e6b 100644 --- a/tests/regression_tests/random_ray_fixed_source_mesh/linear/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_mesh/linear/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_fixed_source_normalization/False/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_normalization/False/inputs_true.dat index ab077ae8aa..0c870e1006 100644 --- a/tests/regression_tests/random_ray_fixed_source_normalization/False/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_normalization/False/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - False + false diff --git a/tests/regression_tests/random_ray_fixed_source_normalization/True/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_normalization/True/inputs_true.dat index c4fd06f421..ab91f74e50 100644 --- a/tests/regression_tests/random_ray_fixed_source_normalization/True/inputs_true.dat +++ b/tests/regression_tests/random_ray_fixed_source_normalization/True/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true 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 index a124b5e3c4..0c05a71df3 100644 --- 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 @@ -115,7 +115,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - False + false flat 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 index cc557afb6e..a67495bf16 100644 --- 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 @@ -115,7 +115,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - False + false linear_xy diff --git a/tests/regression_tests/random_ray_halton_samples/inputs_true.dat b/tests/regression_tests/random_ray_halton_samples/inputs_true.dat index 3f058e45c2..36d5f6f227 100644 --- a/tests/regression_tests/random_ray_halton_samples/inputs_true.dat +++ b/tests/regression_tests/random_ray_halton_samples/inputs_true.dat @@ -85,7 +85,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - True + true halton diff --git a/tests/regression_tests/random_ray_k_eff/inputs_true.dat b/tests/regression_tests/random_ray_k_eff/inputs_true.dat index 33c9cac339..545bd1d457 100644 --- a/tests/regression_tests/random_ray_k_eff/inputs_true.dat +++ b/tests/regression_tests/random_ray_k_eff/inputs_true.dat @@ -85,7 +85,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - True + true diff --git a/tests/regression_tests/random_ray_k_eff_mesh/inputs_true.dat b/tests/regression_tests/random_ray_k_eff_mesh/inputs_true.dat index f0822d9f96..98badea18d 100644 --- a/tests/regression_tests/random_ray_k_eff_mesh/inputs_true.dat +++ b/tests/regression_tests/random_ray_k_eff_mesh/inputs_true.dat @@ -85,7 +85,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - True + true diff --git a/tests/regression_tests/random_ray_linear/linear/inputs_true.dat b/tests/regression_tests/random_ray_linear/linear/inputs_true.dat index 0069965572..a43a66e71c 100644 --- a/tests/regression_tests/random_ray_linear/linear/inputs_true.dat +++ b/tests/regression_tests/random_ray_linear/linear/inputs_true.dat @@ -85,7 +85,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - True + true linear diff --git a/tests/regression_tests/random_ray_linear/linear_xy/inputs_true.dat b/tests/regression_tests/random_ray_linear/linear_xy/inputs_true.dat index 81527c4793..7f76f2fd1c 100644 --- a/tests/regression_tests/random_ray_linear/linear_xy/inputs_true.dat +++ b/tests/regression_tests/random_ray_linear/linear_xy/inputs_true.dat @@ -85,7 +85,7 @@ -1.26 -1.26 -1 1.26 1.26 1 - True + true linear_xy diff --git a/tests/regression_tests/random_ray_low_density/inputs_true.dat b/tests/regression_tests/random_ray_low_density/inputs_true.dat index c4fd06f421..ab91f74e50 100644 --- a/tests/regression_tests/random_ray_low_density/inputs_true.dat +++ b/tests/regression_tests/random_ray_low_density/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_point_source_locator/inputs_true.dat b/tests/regression_tests/random_ray_point_source_locator/inputs_true.dat index 82ad979da8..088f803bfa 100644 --- a/tests/regression_tests/random_ray_point_source_locator/inputs_true.dat +++ b/tests/regression_tests/random_ray_point_source_locator/inputs_true.dat @@ -211,7 +211,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/random_ray_void/flat/inputs_true.dat b/tests/regression_tests/random_ray_void/flat/inputs_true.dat index ea8c22f0b5..aa28e7b68b 100644 --- a/tests/regression_tests/random_ray_void/flat/inputs_true.dat +++ b/tests/regression_tests/random_ray_void/flat/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true flat diff --git a/tests/regression_tests/random_ray_void/linear/inputs_true.dat b/tests/regression_tests/random_ray_void/linear/inputs_true.dat index a089604ef4..e4b2f22fa2 100644 --- a/tests/regression_tests/random_ray_void/linear/inputs_true.dat +++ b/tests/regression_tests/random_ray_void/linear/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear diff --git a/tests/regression_tests/random_ray_volume_estimator/hybrid/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator/hybrid/inputs_true.dat index 089534d744..8e8a8ed9b8 100644 --- a/tests/regression_tests/random_ray_volume_estimator/hybrid/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator/hybrid/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true hybrid diff --git a/tests/regression_tests/random_ray_volume_estimator/naive/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator/naive/inputs_true.dat index 56507df045..1e25b97da6 100644 --- a/tests/regression_tests/random_ray_volume_estimator/naive/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator/naive/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true naive diff --git a/tests/regression_tests/random_ray_volume_estimator/simulation_averaged/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator/simulation_averaged/inputs_true.dat index 0331b562cd..78c1626976 100644 --- a/tests/regression_tests/random_ray_volume_estimator/simulation_averaged/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator/simulation_averaged/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true simulation_averaged diff --git a/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/inputs_true.dat index 343833210e..47a8a71824 100644 --- a/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator_linear/hybrid/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear hybrid diff --git a/tests/regression_tests/random_ray_volume_estimator_linear/naive/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator_linear/naive/inputs_true.dat index 50be43eb38..80a9ada4d5 100644 --- a/tests/regression_tests/random_ray_volume_estimator_linear/naive/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator_linear/naive/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear naive diff --git a/tests/regression_tests/random_ray_volume_estimator_linear/simulation_averaged/inputs_true.dat b/tests/regression_tests/random_ray_volume_estimator_linear/simulation_averaged/inputs_true.dat index 3d64ab9783..4f032a62a8 100644 --- a/tests/regression_tests/random_ray_volume_estimator_linear/simulation_averaged/inputs_true.dat +++ b/tests/regression_tests/random_ray_volume_estimator_linear/simulation_averaged/inputs_true.dat @@ -212,7 +212,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true linear simulation_averaged diff --git a/tests/regression_tests/weightwindows_fw_cadis/inputs_true.dat b/tests/regression_tests/weightwindows_fw_cadis/inputs_true.dat index 448b4b145c..5fa6505ddf 100644 --- a/tests/regression_tests/weightwindows_fw_cadis/inputs_true.dat +++ b/tests/regression_tests/weightwindows_fw_cadis/inputs_true.dat @@ -227,7 +227,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true naive diff --git a/tests/regression_tests/weightwindows_fw_cadis_mesh/flat/inputs_true.dat b/tests/regression_tests/weightwindows_fw_cadis_mesh/flat/inputs_true.dat index d82aa6fae8..ceb89e6e34 100644 --- a/tests/regression_tests/weightwindows_fw_cadis_mesh/flat/inputs_true.dat +++ b/tests/regression_tests/weightwindows_fw_cadis_mesh/flat/inputs_true.dat @@ -227,7 +227,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/regression_tests/weightwindows_fw_cadis_mesh/linear/inputs_true.dat b/tests/regression_tests/weightwindows_fw_cadis_mesh/linear/inputs_true.dat index 9e4b21d27b..c7691e950c 100644 --- a/tests/regression_tests/weightwindows_fw_cadis_mesh/linear/inputs_true.dat +++ b/tests/regression_tests/weightwindows_fw_cadis_mesh/linear/inputs_true.dat @@ -227,7 +227,7 @@ 0.0 0.0 0.0 30.0 30.0 30.0 - True + true diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index 6611e4227e..a6abca41a0 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -59,12 +59,23 @@ def test_export_to_xml(run_in_tmpdir): s.electron_treatment = 'led' s.write_initial_source = True s.weight_window_checkpoints = {'surface': True, 'collision': False} + source_region_mesh = openmc.RegularMesh() + source_region_mesh.dimension = [2, 2, 2] + source_region_mesh.lower_left = [-2, -2, -2] + source_region_mesh.upper_right = [2, 2, 2] + root_universe = openmc.Universe() s.random_ray = { 'distance_inactive': 10.0, 'distance_active': 100.0, 'ray_source': openmc.IndependentSource( space=openmc.stats.Box((-1., -1., -1.), (1., 1., 1.)) - ) + ), + 'source_region_meshes': [(source_region_mesh, [root_universe])], + 'volume_estimator': 'hybrid', + 'source_shape': 'linear', + 'volume_normalized_flux_tallies': True, + 'adjoint': False, + 'sample_method': 'halton' } s.max_particle_events = 100 s.max_secondaries = 1_000_000 @@ -145,5 +156,17 @@ def test_export_to_xml(run_in_tmpdir): assert s.random_ray['distance_active'] == 100.0 assert s.random_ray['ray_source'].space.lower_left == [-1., -1., -1.] assert s.random_ray['ray_source'].space.upper_right == [1., 1., 1.] + assert 'source_region_meshes' in s.random_ray + assert len(s.random_ray['source_region_meshes']) == 1 + mesh_and_domains = s.random_ray['source_region_meshes'][0] + recovered_mesh = mesh_and_domains[0] + assert recovered_mesh.dimension == (2, 2, 2) + assert recovered_mesh.lower_left == [-2., -2., -2.] + assert recovered_mesh.upper_right == [2., 2., 2.] + assert s.random_ray['volume_estimator'] == 'hybrid' + assert s.random_ray['source_shape'] == 'linear' + assert s.random_ray['volume_normalized_flux_tallies'] + assert not s.random_ray['adjoint'] + assert s.random_ray['sample_method'] == 'halton' assert s.max_secondaries == 1_000_000 assert s.source_rejection_fraction == 0.01 From 8a62e7e3235f75810cf59fc80bd69951e0d99fda Mon Sep 17 00:00:00 2001 From: Thomas Kittelmann Date: Fri, 3 Oct 2025 01:27:36 +0200 Subject: [PATCH 22/76] Fix caching issue when using NCrystal materials (#3538) Co-authored-by: Jose Ignacio Marquez Damian <22483345+marquezj@users.noreply.github.com> Co-authored-by: Paul Romano --- include/openmc/particle_data.h | 7 ++++--- openmc/plotter.py | 2 +- src/particle.cpp | 4 +++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index afcd564767..5383487d4f 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -154,9 +154,10 @@ struct NuclideMicroXS { // Energy and temperature last used to evaluate these cross sections. If // these values have changed, then the cross sections must be re-evaluated. - double last_E {0.0}; //!< Last evaluated energy - double last_sqrtkT {0.0}; //!< Last temperature in sqrt(Boltzmann constant - //!< * temperature (eV)) + double last_E {0.0}; //!< Last evaluated energy + double last_sqrtkT {0.0}; //!< Last temperature in sqrt(Boltzmann constant + //!< * temperature (eV)) + double ncrystal_xs {-1.0}; //!< NCrystal cross section }; //============================================================================== diff --git a/openmc/plotter.py b/openmc/plotter.py index 693cdaca4e..abd8ab6dd4 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -501,7 +501,7 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, elif ncrystal_cfg: import NCrystal nc_scatter = NCrystal.createScatter(ncrystal_cfg) - nc_func = nc_scatter.crossSectionNonOriented + nc_func = nc_scatter.xsect nc_emax = 5 # eV # this should be obtained from NCRYSTAL_MAX_ENERGY energy_grid = np.union1d(np.geomspace(min(energy_grid), 1.1*nc_emax, diff --git a/src/particle.cpp b/src/particle.cpp index 402af2498a..06ccf462a1 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -855,10 +855,12 @@ void Particle::update_neutron_xs( // If the cache doesn't match, recalculate micro xs if (this->E() != micro.last_E || this->sqrtkT() != micro.last_sqrtkT || - i_sab != micro.index_sab || sab_frac != micro.sab_frac) { + i_sab != micro.index_sab || sab_frac != micro.sab_frac || + ncrystal_xs != micro.ncrystal_xs) { data::nuclides[i_nuclide]->calculate_xs(i_sab, i_grid, sab_frac, *this); // If NCrystal is being used, update micro cross section cache + micro.ncrystal_xs = ncrystal_xs; if (ncrystal_xs >= 0.0) { data::nuclides[i_nuclide]->calculate_elastic_xs(*this); ncrystal_update_micro(ncrystal_xs, micro); From 50071aa3bd29b78f28fe4c8efe211cb5f65778ee Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 3 Oct 2025 17:09:57 +0200 Subject: [PATCH 23/76] Speed up time correction factors (#3592) Co-authored-by: Jon Shimwell Co-authored-by: Paul Romano --- openmc/deplete/d1s.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openmc/deplete/d1s.py b/openmc/deplete/d1s.py index 311bc2d69c..f51dea4160 100644 --- a/openmc/deplete/d1s.py +++ b/openmc/deplete/d1s.py @@ -108,14 +108,15 @@ def time_correction_factors( # Create a 2D array for the time correction factors h = np.zeros((n_timesteps, n_nuclides)) - for i, (dt, rate) in enumerate(zip(timesteps, source_rates)): - # Precompute the exponential terms. Since (1 - exp(-x)) is susceptible to - # roundoff error, use expm1 instead (which computes exp(x) - 1) - g = np.exp(-decay_rate*dt) - one_minus_g = -np.expm1(-decay_rate*dt) + # Precompute all exponential terms with same shape as h + decay_dt = decay_rate[np.newaxis, :] * timesteps[:, np.newaxis] + g = np.exp(-decay_dt) + one_minus_g = -np.expm1(-decay_dt) + # Apply recurrence relation step by step + for i in range(len(timesteps)): # Eq. (4) in doi:10.1016/j.fusengdes.2019.111399 - h[i + 1] = rate*one_minus_g + h[i]*g + h[i + 1] = source_rates[i] * one_minus_g[i] + h[i] * g[i] return {nuclides[i]: h[:, i] for i in range(n_nuclides)} From 2c15480cc9f1f7407b2fecd8b47a56f976b7bd02 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Oct 2025 07:45:26 -0500 Subject: [PATCH 24/76] Add user setting for free gas threshold (#3593) --- docs/source/io_formats/settings.rst | 10 ++++++++++ include/openmc/physics.h | 7 ------- include/openmc/settings.h | 2 ++ openmc/settings.py | 28 ++++++++++++++++++++++++++++ src/finalize.cpp | 1 + src/physics.cpp | 2 +- src/settings.cpp | 5 +++++ tests/unit_tests/test_settings.py | 2 ++ 8 files changed, 49 insertions(+), 8 deletions(-) diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 26673faac2..720846c851 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -178,6 +178,16 @@ history-based parallelism. *Default*: false +-------------------------------- +```` Element +-------------------------------- + +The ```` element specifies the energy multiplier, expressed +in units of :math:`kT`, that determines when the free gas scattering approach is +used for elastic scattering. Values must be positive. + + *Default*: 400.0 + ----------------------------------- ```` Element ----------------------------------- diff --git a/include/openmc/physics.h b/include/openmc/physics.h index f62f43a02f..2472d97993 100644 --- a/include/openmc/physics.h +++ b/include/openmc/physics.h @@ -10,13 +10,6 @@ namespace openmc { -//============================================================================== -// Constants -//============================================================================== - -// Monoatomic ideal-gas scattering treatment threshold -constexpr double FREE_GAS_THRESHOLD {400.0}; - //============================================================================== // Non-member functions //============================================================================== diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 999b1b83f8..78bfa088e6 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -147,6 +147,8 @@ extern std::unordered_set source_write_surf_id; //!< Surface ids where sources will be written extern double source_rejection_fraction; //!< Minimum fraction of source sites //!< that must be accepted +extern double free_gas_threshold; //!< Threshold multiplier for free gas + //!< scattering treatment extern int max_history_splits; //!< maximum number of particle splits for weight windows diff --git a/openmc/settings.py b/openmc/settings.py index 8f8aedc93e..2f8a2b1248 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -84,6 +84,10 @@ class Settings: history-based parallelism. .. versionadded:: 0.12 + free_gas_threshold : float + Energy multiplier (in units of :math:`kT`) below which the free gas + scattering treatment is applied for elastic scattering. If not + specified, a value of 400.0 is used. generations_per_batch : int Number of generations per batch ifp_n_generation : int @@ -376,6 +380,7 @@ class Settings: self._seed = None self._stride = None self._survival_biasing = None + self._free_gas_threshold = None # Shannon entropy mesh self._entropy_mesh = None @@ -1255,6 +1260,17 @@ class Settings: cv.check_less_than('source_rejection_fraction', source_rejection_fraction, 1) self._source_rejection_fraction = source_rejection_fraction + @property + def free_gas_threshold(self) -> float | None: + return self._free_gas_threshold + + @free_gas_threshold.setter + def free_gas_threshold(self, free_gas_threshold: float | None): + if free_gas_threshold is not None: + cv.check_type('free gas threshold', free_gas_threshold, Real) + cv.check_greater_than('free gas threshold', free_gas_threshold, 0.0) + self._free_gas_threshold = free_gas_threshold + def _create_run_mode_subelement(self, root): elem = ET.SubElement(root, "run_mode") elem.text = self._run_mode.value @@ -1733,6 +1749,11 @@ class Settings: element = ET.SubElement(root, "source_rejection_fraction") element.text = str(self._source_rejection_fraction) + def _create_free_gas_threshold_subelement(self, root): + if self._free_gas_threshold is not None: + element = ET.SubElement(root, "free_gas_threshold") + element.text = str(self._free_gas_threshold) + def _eigenvalue_from_xml_element(self, root): elem = root.find('eigenvalue') if elem is not None: @@ -2171,6 +2192,11 @@ class Settings: if text is not None: self.source_rejection_fraction = float(text) + def _free_gas_threshold_from_xml_element(self, root): + text = get_text(root, 'free_gas_threshold') + if text is not None: + self.free_gas_threshold = float(text) + def to_xml_element(self, mesh_memo=None): """Create a 'settings' element to be written to an XML file. @@ -2241,6 +2267,7 @@ class Settings: self._create_random_ray_subelement(element, mesh_memo) self._create_use_decay_photons_subelement(element) self._create_source_rejection_fraction_subelement(element) + self._create_free_gas_threshold_subelement(element) # Clean the indentation in the file to be user-readable clean_indentation(element) @@ -2352,6 +2379,7 @@ class Settings: settings._random_ray_from_xml_element(elem, meshes) settings._use_decay_photons_from_xml_element(elem) settings._source_rejection_fraction_from_xml_element(elem) + settings._free_gas_threshold_from_xml_element(elem) return settings diff --git a/src/finalize.cpp b/src/finalize.cpp index 25b471a8bd..76babbb96c 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -85,6 +85,7 @@ int openmc_finalize() settings::time_cutoff = {INFTY, INFTY, INFTY, INFTY}; settings::entropy_on = false; settings::event_based = false; + settings::free_gas_threshold = 400.0; settings::gen_per_batch = 1; settings::legendre_to_tabular = true; settings::legendre_to_tabular_points = -1; diff --git a/src/physics.cpp b/src/physics.cpp index e947fecbb9..3a17077b36 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -851,7 +851,7 @@ Direction sample_target_velocity(const Nuclide& nuc, double E, Direction u, // otherwise, use free gas model } else { - if (E >= FREE_GAS_THRESHOLD * kT && nuc.awr_ > 1.0) { + if (E >= settings::free_gas_threshold * kT && nuc.awr_ > 1.0) { return {}; } else { sampling_method = ResScatMethod::cxs; diff --git a/src/settings.cpp b/src/settings.cpp index f9a2469db9..325256cdc5 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -126,6 +126,7 @@ SolverType solver_type {SolverType::MONTE_CARLO}; std::unordered_set sourcepoint_batch; std::unordered_set statepoint_batch; double source_rejection_fraction {0.05}; +double free_gas_threshold {400.0}; std::unordered_set source_write_surf_id; int64_t ssw_max_particles; int64_t ssw_max_files; @@ -651,6 +652,10 @@ void read_settings_xml(pugi::xml_node root) std::stod(get_node_value(root, "source_rejection_fraction")); } + if (check_for_node(root, "free_gas_threshold")) { + free_gas_threshold = std::stod(get_node_value(root, "free_gas_threshold")); + } + // Survival biasing if (check_for_node(root, "survival_biasing")) { survival_biasing = get_node_value_bool(root, "survival_biasing"); diff --git a/tests/unit_tests/test_settings.py b/tests/unit_tests/test_settings.py index a6abca41a0..fe618fd2d6 100644 --- a/tests/unit_tests/test_settings.py +++ b/tests/unit_tests/test_settings.py @@ -80,6 +80,7 @@ def test_export_to_xml(run_in_tmpdir): s.max_particle_events = 100 s.max_secondaries = 1_000_000 s.source_rejection_fraction = 0.01 + s.free_gas_threshold = 800.0 # Make sure exporting XML works s.export_to_xml() @@ -170,3 +171,4 @@ def test_export_to_xml(run_in_tmpdir): assert s.random_ray['sample_method'] == 'halton' assert s.max_secondaries == 1_000_000 assert s.source_rejection_fraction == 0.01 + assert s.free_gas_threshold == 800.0 From 3dfa34d2c6a239cad327baa5565cd71f158fc299 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 6 Oct 2025 21:14:37 -0500 Subject: [PATCH 25/76] Switch to using coveralls github action for reporting (#3594) --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++++++++++---- pyproject.toml | 4 ++-- tools/ci/gha-script.sh | 2 +- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38a49b6021..d75a64d662 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,6 +75,7 @@ jobs: LIBMESH: ${{ matrix.libmesh }} NPY_DISABLE_CPU_FEATURES: "AVX512F AVX512_SKX" OPENBLAS_NUM_THREADS: 1 + PYTEST_ADDOPTS: --cov=openmc --cov-report=lcov:coverage-python.lcov # libfabric complains about fork() as a result of using Python multiprocessing. # We can work around it with RDMAV_FORK_SAFE=1 in libfabric < 1.13 and with # FI_EFA_FORK_SAFE=1 in more recent versions. @@ -171,11 +172,37 @@ jobs: uses: mxschmitt/action-tmate@v3 timeout-minutes: 10 - - name: after_success + - name: Generate C++ coverage (gcovr) shell: bash run: | - cpp-coveralls -i src -i include -e src/external --exclude-pattern "/usr/*" --dump cpp_cov.json - coveralls --merge=cpp_cov.json --service=github + # Produce LCOV directly from gcov data in the build tree + gcovr \ + --root "$GITHUB_WORKSPACE" \ + --object-directory "$GITHUB_WORKSPACE/build" \ + --filter "$GITHUB_WORKSPACE/src" \ + --filter "$GITHUB_WORKSPACE/include" \ + --exclude "$GITHUB_WORKSPACE/src/external/.*" \ + --exclude "$GITHUB_WORKSPACE/src/include/openmc/external/.*" \ + --gcov-ignore-errors source_not_found \ + --gcov-ignore-errors output_error \ + --gcov-ignore-parse-errors suspicious_hits.warn \ + --print-summary \ + --lcov -o coverage-cpp.lcov || true + + - name: Merge C++ and Python coverage + shell: bash + run: | + # Merge C++ and Python LCOV into a single file for upload + cat coverage-cpp.lcov coverage-python.lcov > coverage.lcov + + - name: Upload coverage to Coveralls + if: ${{ hashFiles('coverage.lcov') != '' }} + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + parallel: true + flag-name: C++ and Python + path-to-lcov: coverage.lcov finish: needs: main @@ -184,5 +211,5 @@ jobs: - name: Coveralls Finished uses: coverallsapp/github-action@v2 with: - github-token: ${{ secrets.github_token }} + github-token: ${{ secrets.GITHUB_TOKEN }} parallel-finished: true diff --git a/pyproject.toml b/pyproject.toml index 7705de8dae..53d429d943 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,8 +48,8 @@ docs = [ "sphinxcontrib-svg2pdfconverter", "sphinx-rtd-theme" ] -test = ["packaging", "pytest", "pytest-cov", "colorama", "openpyxl"] -ci = ["cpp-coveralls", "coveralls"] +test = ["packaging", "pytest", "pytest-cov>=4.0", "colorama", "openpyxl"] +ci = ["coverage>=7.4", "gcovr>=7.2"] vtk = ["vtk"] [project.urls] diff --git a/tools/ci/gha-script.sh b/tools/ci/gha-script.sh index c1d2921377..b40238ffb5 100755 --- a/tools/ci/gha-script.sh +++ b/tools/ci/gha-script.sh @@ -15,7 +15,7 @@ if [[ $EVENT == 'y' ]]; then fi # Run unit tests and then regression tests -pytest --cov=openmc -v $args \ +pytest -v $args \ tests/test_matplotlib_import.py \ tests/unit_tests \ tests/regression_tests From 58c7fbeac67a3e6db0e26a9dc2db421da3abf933 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 14 Oct 2025 07:47:26 -0500 Subject: [PATCH 26/76] Re-run flaky tests when needed (#3604) --- pyproject.toml | 9 ++++++++- tests/unit_tests/test_deplete_activation.py | 1 + tests/unit_tests/test_stats.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 53d429d943..2d67e83401 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,14 @@ docs = [ "sphinxcontrib-svg2pdfconverter", "sphinx-rtd-theme" ] -test = ["packaging", "pytest", "pytest-cov>=4.0", "colorama", "openpyxl"] +test = [ + "packaging", + "pytest", + "pytest-cov>=4.0", + "pytest-rerunfailures", + "colorama", + "openpyxl", +] ci = ["coverage>=7.4", "gcovr>=7.2"] vtk = ["vtk"] diff --git a/tests/unit_tests/test_deplete_activation.py b/tests/unit_tests/test_deplete_activation.py index cbe00d680c..eace1976ef 100644 --- a/tests/unit_tests/test_deplete_activation.py +++ b/tests/unit_tests/test_deplete_activation.py @@ -49,6 +49,7 @@ ENERGIES = np.logspace(log10(1e-5), log10(2e7), 100) ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)']}, 1e-5), ("flux", {'energies': ENERGIES, 'reactions': ['(n,gamma)'], 'nuclides': ['W186', 'H3']}, 1e-2), ]) +@pytest.mark.flaky(reruns=1) def test_activation(run_in_tmpdir, model, reaction_rate_mode, reaction_rate_opts, tolerance): # Determine (n.gamma) reaction rate using initial run sp = model.run() diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index 386181f34d..abf143f12a 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -16,6 +16,7 @@ def assert_sample_mean(samples, expected_mean): assert np.abs(expected_mean - samples.mean()) < 4*std_dev +@pytest.mark.flaky(reruns=1) def test_discrete(): x = [0.0, 1.0, 10.0] p = [0.3, 0.2, 0.5] @@ -104,6 +105,7 @@ def test_clip_discrete(): d.clip(5) +@pytest.mark.flaky(reruns=1) def test_uniform(): a, b = 10.0, 20.0 d = openmc.stats.Uniform(a, b) @@ -127,6 +129,7 @@ def test_uniform(): assert_sample_mean(samples, exp_mean) +@pytest.mark.flaky(reruns=1) def test_powerlaw(): a, b, n = 10.0, 100.0, 2.0 d = openmc.stats.PowerLaw(a, b, n) @@ -148,6 +151,7 @@ def test_powerlaw(): assert_sample_mean(samples, exp_mean) +@pytest.mark.flaky(reruns=1) def test_maxwell(): theta = 1.2895e6 d = openmc.stats.Maxwell(theta) @@ -171,6 +175,7 @@ def test_maxwell(): assert samples_2.mean() != samples.mean() +@pytest.mark.flaky(reruns=1) def test_watt(): a, b = 0.965e6, 2.29e-6 d = openmc.stats.Watt(a, b) @@ -194,6 +199,7 @@ def test_watt(): assert_sample_mean(samples, exp_mean) +@pytest.mark.flaky(reruns=1) def test_tabular(): # test linear-linear sampling x = np.array([0.0, 5.0, 7.0, 10.0]) @@ -270,6 +276,7 @@ def test_legendre(): d.to_xml_element('distribution') +@pytest.mark.flaky(reruns=1) def test_mixture(): d1 = openmc.stats.Uniform(0, 5) d2 = openmc.stats.Uniform(3, 7) @@ -425,6 +432,7 @@ def test_point(): assert d.xyz == pytest.approx(p) +@pytest.mark.flaky(reruns=1) def test_normal(): mean = 10.0 std_dev = 2.0 @@ -444,6 +452,7 @@ def test_normal(): assert_sample_mean(samples, mean) +@pytest.mark.flaky(reruns=1) def test_muir(): mean = 10.0 mass = 5.0 @@ -463,6 +472,7 @@ def test_muir(): assert_sample_mean(samples, mean) +@pytest.mark.flaky(reruns=1) def test_combine_distributions(): # Combine two discrete (same data as in test_merge_discrete) x1 = [0.0, 1.0, 10.0] From e9077b1372fa1e3ee4adbcfcbfaeaf04a340c8dd Mon Sep 17 00:00:00 2001 From: jiankai-yu Date: Tue, 14 Oct 2025 16:21:11 -0400 Subject: [PATCH 27/76] Allow V0 in atomic_mass function (for ENDF/B-VII.0 data) (#3607) --- openmc/data/data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 2142a5dc90..5ecadd37be 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -324,7 +324,7 @@ def atomic_mass(isotope): # isotopes of their element (e.g. C0), calculate the atomic mass as # the sum of the atomic mass times the natural abundance of the isotopes # that make up the element. - for element in ['C', 'Zn', 'Pt', 'Os', 'Tl']: + for element in ['C', 'Zn', 'Pt', 'Os', 'Tl', 'V']: isotope_zero = element.lower() + '0' _ATOMIC_MASS[isotope_zero] = 0. for iso, abundance in isotopes(element): From b94b49611365a7eb9bd1a107861e5ae5c44b977d Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Thu, 16 Oct 2025 01:51:59 +0200 Subject: [PATCH 28/76] Ability to source electron/positrons directly (#3404) Co-authored-by: Paul Romano --- .../methods/charged_particles_physics.rst | 362 ++++++++++++++++++ docs/source/methods/index.rst | 3 +- docs/source/methods/photon_physics.rst | 338 ---------------- include/openmc/nuclide.h | 4 +- openmc/source.py | 7 +- src/finalize.cpp | 4 +- src/nuclide.cpp | 4 +- src/particle.cpp | 2 +- src/simulation.cpp | 21 +- src/source.cpp | 6 + .../electron_heating/__init__.py | 0 .../electron_heating/inputs_true.dat | 32 ++ .../electron_heating/results_true.dat | 3 + .../regression_tests/electron_heating/test.py | 40 ++ 14 files changed, 472 insertions(+), 354 deletions(-) create mode 100644 docs/source/methods/charged_particles_physics.rst create mode 100644 tests/regression_tests/electron_heating/__init__.py create mode 100644 tests/regression_tests/electron_heating/inputs_true.dat create mode 100644 tests/regression_tests/electron_heating/results_true.dat create mode 100644 tests/regression_tests/electron_heating/test.py diff --git a/docs/source/methods/charged_particles_physics.rst b/docs/source/methods/charged_particles_physics.rst new file mode 100644 index 0000000000..5d763074fd --- /dev/null +++ b/docs/source/methods/charged_particles_physics.rst @@ -0,0 +1,362 @@ +.. _methods_charged_particle_physics: + +======================== +Charged Particle Physics +======================== + +OpenMC neglects the spatial transport of charged particles (electrons and +positrons), assuming they deposit all their energy locally and produce +bremsstrahlung photons at their birth location. This approximation, called +thick-target bremsstrahlung (TTB) approximation is justified by the fact that +charged particles have much shorter stopping ranges compared to neutrons and +photons, especially in high-density materials. + +----------------------------- +Charged Particle Interactions +----------------------------- + +Bremsstrahlung +-------------- + +When a charged particle is decelerated in the field of an atom, some of its +kinetic energy is converted into electromagnetic radiation known as +bremsstrahlung, or 'braking radiation'. In each event, an electron or positron +with kinetic energy :math:`T` generates a photon with an energy :math:`E` +between :math:`0` and :math:`T`. Bremsstrahlung is described by a cross section +that is differential in photon energy, in the direction of the emitted photon, +and in the final direction of the charged particle. However, in Monte Carlo +simulations it is typical to integrate over the angular variables to obtain a +single differential cross section with respect to photon energy, which is often +expressed in the form + +.. math:: + :label: bremsstrahlung-dcs + + \frac{d\sigma_{\text{br}}}{dE} = \frac{Z^2}{\beta^2} \frac{1}{E} + \chi(Z, T, \kappa), + +where :math:`\kappa = E/T` is the reduced photon energy and :math:`\chi(Z, T, +\kappa)` is the scaled bremsstrahlung cross section, which is experimentally +measured. + +Because electrons are attracted to atomic nuclei whereas positrons are +repulsed, the cross section for positrons is smaller, though it approaches that +of electrons in the high energy limit. To obtain the positron cross section, we +multiply :eq:`bremsstrahlung-dcs` by the :math:`\kappa`-independent factor used +in Salvat_, + +.. math:: + :label: positron-factor + + \begin{aligned} + F_{\text{p}}(Z,T) = + & 1 - \text{exp}(-1.2359\times 10^{-1}t + 6.1274\times 10^{-2}t^2 - 3.1516\times 10^{-2}t^3 \\ + & + 7.7446\times 10^{-3}t^4 - 1.0595\times 10^{-3}t^5 + 7.0568\times 10^{-5}t^6 \\ + & - 1.8080\times 10^{-6}t^7), + \end{aligned} + +where + +.. math:: + :label: positron-factor-t + + t = \ln\left(1 + \frac{10^6}{Z^2}\frac{T}{\text{m}_\text{e}c^2} \right). + +:math:`F_{\text{p}}(Z,T)` is the ratio of the radiative stopping powers for +positrons and electrons. Stopping power describes the average energy loss per +unit path length of a charged particle as it passes through matter: + +.. math:: + :label: stopping-power + + -\frac{dT}{ds} = n \int E \frac{d\sigma}{dE} dE \equiv S(T), + +where :math:`n` is the number density of the material and :math:`d\sigma/dE` is +the cross section differential in energy loss. The total stopping power +:math:`S(T)` can be separated into two components: the radiative stopping +power :math:`S_{\text{rad}}(T)`, which refers to energy loss due to +bremsstrahlung, and the collision stopping power :math:`S_{\text{col}}(T)`, +which refers to the energy loss due to inelastic collisions with bound +electrons in the material that result in ionization and excitation. The +radiative stopping power for electrons is given by + +.. math:: + :label: radiative-stopping-power + + S_{\text{rad}}(T) = n \frac{Z^2}{\beta^2} T \int_0^1 \chi(Z,T,\kappa) + d\kappa. + + +To obtain the radiative stopping power for positrons, +:eq:`radiative-stopping-power` is multiplied by :eq:`positron-factor`. + +While the models for photon interactions with matter described above can safely +assume interactions occur with free atoms, sampling the target atom based on +the macroscopic cross sections, molecular effects cannot necessarily be +disregarded for charged particle treatment. For compounds and mixtures, the +bremsstrahlung cross section is calculated using Bragg's additivity rule as + +.. math:: + :label: material-bremsstrahlung-dcs + + \frac{d\sigma_{\text{br}}}{dE} = \frac{1}{\beta^2 E} \sum_i \gamma_i Z^2_i + \chi(Z_i, T, \kappa), + +where the sum is over the constituent elements and :math:`\gamma_i` is the +atomic fraction of the :math:`i`-th element. Similarly, the radiative stopping +power is calculated using Bragg's additivity rule as + +.. math:: + :label: material-radiative-stopping-power + + S_{\text{rad}}(T) = \sum_i w_i S_{\text{rad},i}(T), + +where :math:`w_i` is the mass fraction of the :math:`i`-th element and +:math:`S_{\text{rad},i}(T)` is found for element :math:`i` using +:eq:`radiative-stopping-power`. The collision stopping power, however, is a +function of certain quantities such as the mean excitation energy :math:`I` and +the density effect correction :math:`\delta_F` that depend on molecular +properties. These quantities cannot simply be summed over constituent elements +in a compound, but should instead be calculated for the material. The Bethe +formula can be used to find the collision stopping power of the material: + +.. math:: + :label: material-collision-stopping-power + + S_{\text{col}}(T) = \frac{2 \pi r_e^2 m_e c^2}{\beta^2} N_A \frac{Z}{A_M} + [\ln(T^2/I^2) + \ln(1 + \tau/2) + F(\tau) - \delta_F(T)], + +where :math:`N_A` is Avogadro's number, :math:`A_M` is the molar mass, +:math:`\tau = T/m_e`, and :math:`F(\tau)` depends on the particle type. For +electrons, + +.. math:: + :label: F-electron + + F_{-}(\tau) = (1 - \beta^2)[1 + \tau^2/8 - (2\tau + 1) \ln2], + +while for positrons + +.. math:: + :label: F-positron + + F_{+}(\tau) = 2\ln2 - (\beta^2/12)[23 + 14/(\tau + 2) + 10/(\tau + 2)^2 + + 4/(\tau + 2)^3]. + +The density effect correction :math:`\delta_F` takes into account the reduction +of the collision stopping power due to the polarization of the material the +charged particle is passing through by the electric field of the particle. +It can be evaluated using the method described by Sternheimer_, where the +equation for :math:`\delta_F` is + +.. math:: + :label: density-effect-correction + + \delta_F(\beta) = \sum_{i=1}^n f_i \ln[(l_i^2 + l^2)/l_i^2] - + l^2(1-\beta^2). + +Here, :math:`f_i` is the oscillator strength of the :math:`i`-th transition, +given by :math:`f_i = n_i/Z`, where :math:`n_i` is the number of electrons in +the :math:`i`-th subshell. The frequency :math:`l` is the solution of the +equation + +.. math:: + :label: density-effect-l + + \frac{1}{\beta^2} - 1 = \sum_{i=1}^{n} \frac{f_i}{\bar{\nu}_i^2 + l^2}, + +where :math:`\bar{v}_i` is defined as + +.. math:: + :label: density-effect-nubar + + \bar{\nu}_i = h\nu_i \rho / h\nu_p. + +The plasma energy :math:`h\nu_p` of the medium is given by + +.. math:: + :label: plasma-frequency + + h\nu_p = \sqrt{\frac{(hc)^2 r_e \rho_m N_A Z}{\pi A}}, + +where :math:`A` is the atomic weight and :math:`\rho_m` is the density of the +material. In :eq:`density-effect-nubar`, :math:`h\nu_i` is the oscillator +energy, and :math:`\rho` is an adjustment factor introduced to give agreement +between the experimental values of the oscillator energies and the mean +excitation energy. The :math:`l_i` in :eq:`density-effect-correction` are +defined as + +.. math:: + :label: density-effect-li + + \begin{aligned} + l_i &= (\bar{\nu}_i^2 + 2/3f_i)^{1/2} ~~~~&\text{for}~~ \bar{\nu}_i > 0 \\ + l_n &= f_n^{1/2} ~~~~&\text{for}~~ \bar{\nu}_n = 0, + \end{aligned} + +where the second case applies to conduction electrons. For a conductor, +:math:`f_n` is given by :math:`n_c/Z`, where :math:`n_c` is the effective +number of conduction electrons, and :math:`v_n = 0`. The adjustment factor +:math:`\rho` is determined using the equation for the mean excitation energy: + +.. math:: + :label: mean-excitation-energy + + \ln I = \sum_{i=1}^{n-1} f_i \ln[(h\nu_i\rho)^2 + 2/3f_i(h\nu_p)^2]^{1/2} + + f_n \ln (h\nu_pf_n^{1/2}). + +.. _ttb: + + +Thick-Target Bremsstrahlung Approximation ++++++++++++++++++++++++++++++++++++++++++ + +Since charged particles lose their energy on a much shorter distance scale than +neutral particles, not much error should be introduced by neglecting to +transport electrons. However, the bremsstrahlung emitted from high energy +electrons and positrons can travel far from the interaction site. Thus, even +without a full electron transport mode it is necessary to model bremsstrahlung. +We use a thick-target bremsstrahlung (TTB) approximation based on the models in +Salvat_ and Kaltiaisenaho_ for generating bremsstrahlung photons, which assumes +the charged particle loses all its energy in a single homogeneous material +region. + +To model bremsstrahlung using the TTB approximation, we need to know the number +of photons emitted by the charged particle and the energy distribution of the +photons. These quantities can be calculated using the continuous slowing down +approximation (CSDA). The CSDA assumes charged particles lose energy +continuously along their trajectory with a rate of energy loss equal to the +total stopping power, ignoring fluctuations in the energy loss. The +approximation is useful for expressing average quantities that describe how +charged particles slow down in matter. For example, the CSDA range approximates +the average path length a charged particle travels as it slows to rest: + +.. math:: + :label: csda-range + + R(T) = \int^T_0 \frac{dT'}{S(T')}. + +Actual path lengths will fluctuate around :math:`R(T)`. The average number of +photons emitted per unit path length is given by the inverse bremsstrahlung +mean free path: + +.. math:: + :label: inverse-bremsstrahlung-mfp + + \lambda_{\text{br}}^{-1}(T,E_{\text{cut}}) + = n\int_{E_{\text{cut}}}^T\frac{d\sigma_{\text{br}}}{dE}dE + = n\frac{Z^2}{\beta^2}\int_{\kappa_{\text{cut}}}^1\frac{1}{\kappa} + \chi(Z,T,\kappa)d\kappa. + +The lower limit of the integral in :eq:`inverse-bremsstrahlung-mfp` is non-zero +because the bremsstrahlung differential cross section diverges for small photon +energies but is finite for photon energies above some cutoff energy +:math:`E_{\text{cut}}`. The mean free path +:math:`\lambda_{\text{br}}^{-1}(T,E_{\text{cut}})` is used to calculate the +photon number yield, defined as the average number of photons emitted with +energy greater than :math:`E_{\text{cut}}` as the charged particle slows down +from energy :math:`T` to :math:`E_{\text{cut}}`. The photon number yield is +given by + +.. math:: + :label: photon-number-yield + + Y(T,E_{\text{cut}}) = \int^{R(T)}_{R(E_{\text{cut}})} + \lambda_{\text{br}}^{-1}(T',E_{\text{cut}})ds = \int_{E_{\text{cut}}}^T + \frac{\lambda_{\text{br}}^{-1}(T',E_{\text{cut}})}{S(T')}dT'. + +:math:`Y(T,E_{\text{cut}})` can be used to construct the energy spectrum of +bremsstrahlung photons: the number of photons created with energy between +:math:`E_1` and :math:`E_2` by a charged particle with initial kinetic energy +:math:`T` as it comes to rest is given by :math:`Y(T,E_1) - Y(T,E_2)`. + +To simulate the emission of bremsstrahlung photons, the total stopping power +and bremsstrahlung differential cross section for positrons and electrons must +be calculated for a given material using :eq:`material-bremsstrahlung-dcs` and +:eq:`material-radiative-stopping-power`. These quantities are used to build the +tabulated bremsstrahlung energy PDF and CDF for that material for each incident +energy :math:`T_k` on the energy grid. The following algorithm is then applied +to sample the photon energies: + +1. For an incident charged particle with energy :math:`T`, sample the number of + emitted photons as + + .. math:: + + N = \lfloor Y(T,E_{\text{cut}}) + \xi_1 \rfloor. + +2. Rather than interpolate the PDF between indices :math:`k` and :math:`k+1` + for which :math:`T_k < T < T_{k+1}`, which is computationally expensive, use + the composition method and sample from the PDF at either :math:`k` or + :math:`k+1`. Using linear interpolation on a logarithmic scale, the PDF can + be expressed as + + .. math:: + + p_{\text{br}}(T,E) = \pi_k p_{\text{br}}(T_k,E) + \pi_{k+1} + p_{\text{br}}(T_{k+1},E), + + where the interpolation weights are + + .. math:: + + \pi_k = \frac{\ln T_{k+1} - \ln T}{\ln T_{k+1} - \ln T_k},~~~ + \pi_{k+1} = \frac{\ln T - \ln T_k}{\ln T_{k+1} - \ln T_k}. + + Sample either the index :math:`i = k` or :math:`i = k+1` according to the + point probabilities :math:`\pi_{k}` and :math:`\pi_{k+1}`. + +3. Determine the maximum value of the CDF :math:`P_{\text{br,max}}`. + +3. Sample the photon energies using the inverse transform method with the + tabulated CDF :math:`P_{\text{br}}(T_i, E)` i.e., + + .. math:: + + E = E_j \left[ (1 + a_j) \frac{\xi_2 P_{\text{br,max}} - + P_{\text{br}}(T_i, E_j)} {E_j p_{\text{br}}(T_i, E_j)} + 1 + \right]^{\frac{1}{1 + a_j}} + + where the interpolation factor :math:`a_j` is given by + + .. math:: + + a_j = \frac{\ln p_{\text{br}}(T_i,E_{j+1}) - \ln p_{\text{br}}(T_i,E_j)} + {\ln E_{j+1} - \ln E_j} + + and :math:`P_{\text{br}}(T_i, E_j) \le \xi_2 P_{\text{br,max}} \le + P_{\text{br}}(T_i, E_{j+1})`. + +We ignore the range of the electron or positron, i.e., the bremsstrahlung +photons are produced in the same location that the charged particle was +created. The direction of the photons is assumed to be the same as the +direction of the incident charged particle, which is a reasonable approximation +at higher energies when the bremsstrahlung radiation is emitted at small +angles. + + +Electron-Positron Annihilation +------------------------------ + +When a positron collides with an electron, both particles are annihilated and +generally two photons with equal energy are created. If the kinetic energy of +the positron is high enough, the two photons can have different energies, and +the higher-energy photon is emitted preferentially in the direction of flight +of the positron. It is also possible to produce a single photon if the +interaction occurs with a bound electron, and in some cases three (or, rarely, +even more) photons can be emitted. However, the annihilation cross section is +largest for low-energy positrons, and as the positron energy decreases, the +angular distribution of the emitted photons becomes isotropic. + +In OpenMC, we assume the most likely case in which a low-energy positron (which +has already lost most of its energy to bremsstrahlung radiation) interacts with +an electron which is free and at rest. Two photons with energy equal to the +electron rest mass energy :math:`m_e c^2 = 0.511` MeV are emitted isotropically +in opposite directions. + + +.. _Kaltiaisenaho: https://aaltodoc.aalto.fi/bitstream/handle/123456789/21004/master_Kaltiaisenaho_Toni_2016.pdf + +.. _Salvat: https://doi.org/10.1787/32da5043-en + +.. _Sternheimer: https://doi.org/10.1103/PhysRevB.26.6067 diff --git a/docs/source/methods/index.rst b/docs/source/methods/index.rst index 75c421c877..121d04b1de 100644 --- a/docs/source/methods/index.rst +++ b/docs/source/methods/index.rst @@ -14,6 +14,7 @@ Theory and Methodology random_numbers neutron_physics photon_physics + charged_particles_physics tallies eigenvalue depletion @@ -21,4 +22,4 @@ Theory and Methodology parallelization cmfd variance_reduction - random_ray \ No newline at end of file + random_ray diff --git a/docs/source/methods/photon_physics.rst b/docs/source/methods/photon_physics.rst index 22d2c7f26a..d2bd3ac760 100644 --- a/docs/source/methods/photon_physics.rst +++ b/docs/source/methods/photon_physics.rst @@ -667,342 +667,6 @@ and Auger electrons: 5. Repeat from step 1 for vacancy left by the transition electron. -Electron-Positron Annihilation ------------------------------- - -When a positron collides with an electron, both particles are annihilated and -generally two photons with equal energy are created. If the kinetic energy of -the positron is high enough, the two photons can have different energies, and -the higher-energy photon is emitted preferentially in the direction of flight -of the positron. It is also possible to produce a single photon if the -interaction occurs with a bound electron, and in some cases three (or, rarely, -even more) photons can be emitted. However, the annihilation cross section is -largest for low-energy positrons, and as the positron energy decreases, the -angular distribution of the emitted photons becomes isotropic. - -In OpenMC, we assume the most likely case in which a low-energy positron (which -has already lost most of its energy to bremsstrahlung radiation) interacts with -an electron which is free and at rest. Two photons with energy equal to the -electron rest mass energy :math:`m_e c^2 = 0.511` MeV are emitted isotropically -in opposite directions. - -Bremsstrahlung --------------- - -When a charged particle is decelerated in the field of an atom, some of its -kinetic energy is converted into electromagnetic radiation known as -bremsstrahlung, or 'braking radiation'. In each event, an electron or positron -with kinetic energy :math:`T` generates a photon with an energy :math:`E` -between :math:`0` and :math:`T`. Bremsstrahlung is described by a cross section -that is differential in photon energy, in the direction of the emitted photon, -and in the final direction of the charged particle. However, in Monte Carlo -simulations it is typical to integrate over the angular variables to obtain a -single differential cross section with respect to photon energy, which is often -expressed in the form - -.. math:: - :label: bremsstrahlung-dcs - - \frac{d\sigma_{\text{br}}}{dE} = \frac{Z^2}{\beta^2} \frac{1}{E} - \chi(Z, T, \kappa), - -where :math:`\kappa = E/T` is the reduced photon energy and :math:`\chi(Z, T, -\kappa)` is the scaled bremsstrahlung cross section, which is experimentally -measured. - -Because electrons are attracted to atomic nuclei whereas positrons are -repulsed, the cross section for positrons is smaller, though it approaches that -of electrons in the high energy limit. To obtain the positron cross section, we -multiply :eq:`bremsstrahlung-dcs` by the :math:`\kappa`-independent factor used -in Salvat_, - -.. math:: - :label: positron-factor - - \begin{aligned} - F_{\text{p}}(Z,T) = - & 1 - \text{exp}(-1.2359\times 10^{-1}t + 6.1274\times 10^{-2}t^2 - 3.1516\times 10^{-2}t^3 \\ - & + 7.7446\times 10^{-3}t^4 - 1.0595\times 10^{-3}t^5 + 7.0568\times 10^{-5}t^6 \\ - & - 1.8080\times 10^{-6}t^7), - \end{aligned} - -where - -.. math:: - :label: positron-factor-t - - t = \ln\left(1 + \frac{10^6}{Z^2}\frac{T}{\text{m}_\text{e}c^2} \right). - -:math:`F_{\text{p}}(Z,T)` is the ratio of the radiative stopping powers for -positrons and electrons. Stopping power describes the average energy loss per -unit path length of a charged particle as it passes through matter: - -.. math:: - :label: stopping-power - - -\frac{dT}{ds} = n \int E \frac{d\sigma}{dE} dE \equiv S(T), - -where :math:`n` is the number density of the material and :math:`d\sigma/dE` is -the cross section differential in energy loss. The total stopping power -:math:`S(T)` can be separated into two components: the radiative stopping -power :math:`S_{\text{rad}}(T)`, which refers to energy loss due to -bremsstrahlung, and the collision stopping power :math:`S_{\text{col}}(T)`, -which refers to the energy loss due to inelastic collisions with bound -electrons in the material that result in ionization and excitation. The -radiative stopping power for electrons is given by - -.. math:: - :label: radiative-stopping-power - - S_{\text{rad}}(T) = n \frac{Z^2}{\beta^2} T \int_0^1 \chi(Z,T,\kappa) - d\kappa. - - -To obtain the radiative stopping power for positrons, -:eq:`radiative-stopping-power` is multiplied by :eq:`positron-factor`. - -While the models for photon interactions with matter described above can safely -assume interactions occur with free atoms, sampling the target atom based on -the macroscopic cross sections, molecular effects cannot necessarily be -disregarded for charged particle treatment. For compounds and mixtures, the -bremsstrahlung cross section is calculated using Bragg's additivity rule as - -.. math:: - :label: material-bremsstrahlung-dcs - - \frac{d\sigma_{\text{br}}}{dE} = \frac{1}{\beta^2 E} \sum_i \gamma_i Z^2_i - \chi(Z_i, T, \kappa), - -where the sum is over the constituent elements and :math:`\gamma_i` is the -atomic fraction of the :math:`i`-th element. Similarly, the radiative stopping -power is calculated using Bragg's additivity rule as - -.. math:: - :label: material-radiative-stopping-power - - S_{\text{rad}}(T) = \sum_i w_i S_{\text{rad},i}(T), - -where :math:`w_i` is the mass fraction of the :math:`i`-th element and -:math:`S_{\text{rad},i}(T)` is found for element :math:`i` using -:eq:`radiative-stopping-power`. The collision stopping power, however, is a -function of certain quantities such as the mean excitation energy :math:`I` and -the density effect correction :math:`\delta_F` that depend on molecular -properties. These quantities cannot simply be summed over constituent elements -in a compound, but should instead be calculated for the material. The Bethe -formula can be used to find the collision stopping power of the material: - -.. math:: - :label: material-collision-stopping-power - - S_{\text{col}}(T) = \frac{2 \pi r_e^2 m_e c^2}{\beta^2} N_A \frac{Z}{A_M} - [\ln(T^2/I^2) + \ln(1 + \tau/2) + F(\tau) - \delta_F(T)], - -where :math:`N_A` is Avogadro's number, :math:`A_M` is the molar mass, -:math:`\tau = T/m_e`, and :math:`F(\tau)` depends on the particle type. For -electrons, - -.. math:: - :label: F-electron - - F_{-}(\tau) = (1 - \beta^2)[1 + \tau^2/8 - (2\tau + 1) \ln2], - -while for positrons - -.. math:: - :label: F-positron - - F_{+}(\tau) = 2\ln2 - (\beta^2/12)[23 + 14/(\tau + 2) + 10/(\tau + 2)^2 + - 4/(\tau + 2)^3]. - -The density effect correction :math:`\delta_F` takes into account the reduction -of the collision stopping power due to the polarization of the material the -charged particle is passing through by the electric field of the particle. -It can be evaluated using the method described by Sternheimer_, where the -equation for :math:`\delta_F` is - -.. math:: - :label: density-effect-correction - - \delta_F(\beta) = \sum_{i=1}^n f_i \ln[(l_i^2 + l^2)/l_i^2] - - l^2(1-\beta^2). - -Here, :math:`f_i` is the oscillator strength of the :math:`i`-th transition, -given by :math:`f_i = n_i/Z`, where :math:`n_i` is the number of electrons in -the :math:`i`-th subshell. The frequency :math:`l` is the solution of the -equation - -.. math:: - :label: density-effect-l - - \frac{1}{\beta^2} - 1 = \sum_{i=1}^{n} \frac{f_i}{\bar{\nu}_i^2 + l^2}, - -where :math:`\bar{v}_i` is defined as - -.. math:: - :label: density-effect-nubar - - \bar{\nu}_i = h\nu_i \rho / h\nu_p. - -The plasma energy :math:`h\nu_p` of the medium is given by - -.. math:: - :label: plasma-frequency - - h\nu_p = \sqrt{\frac{(hc)^2 r_e \rho_m N_A Z}{\pi A}}, - -where :math:`A` is the atomic weight and :math:`\rho_m` is the density of the -material. In :eq:`density-effect-nubar`, :math:`h\nu_i` is the oscillator -energy, and :math:`\rho` is an adjustment factor introduced to give agreement -between the experimental values of the oscillator energies and the mean -excitation energy. The :math:`l_i` in :eq:`density-effect-correction` are -defined as - -.. math:: - :label: density-effect-li - - \begin{aligned} - l_i &= (\bar{\nu}_i^2 + 2/3f_i)^{1/2} ~~~~&\text{for}~~ \bar{\nu}_i > 0 \\ - l_n &= f_n^{1/2} ~~~~&\text{for}~~ \bar{\nu}_n = 0, - \end{aligned} - -where the second case applies to conduction electrons. For a conductor, -:math:`f_n` is given by :math:`n_c/Z`, where :math:`n_c` is the effective -number of conduction electrons, and :math:`v_n = 0`. The adjustment factor -:math:`\rho` is determined using the equation for the mean excitation energy: - -.. math:: - :label: mean-excitation-energy - - \ln I = \sum_{i=1}^{n-1} f_i \ln[(h\nu_i\rho)^2 + 2/3f_i(h\nu_p)^2]^{1/2} + - f_n \ln (h\nu_pf_n^{1/2}). - -.. _ttb: - -Thick-Target Bremsstrahlung Approximation -+++++++++++++++++++++++++++++++++++++++++ - -Since charged particles lose their energy on a much shorter distance scale than -neutral particles, not much error should be introduced by neglecting to -transport electrons. However, the bremsstrahlung emitted from high energy -electrons and positrons can travel far from the interaction site. Thus, even -without a full electron transport mode it is necessary to model bremsstrahlung. -We use a thick-target bremsstrahlung (TTB) approximation based on the models in -Salvat_ and Kaltiaisenaho_ for generating bremsstrahlung photons, which assumes -the charged particle loses all its energy in a single homogeneous material -region. - -To model bremsstrahlung using the TTB approximation, we need to know the number -of photons emitted by the charged particle and the energy distribution of the -photons. These quantities can be calculated using the continuous slowing down -approximation (CSDA). The CSDA assumes charged particles lose energy -continuously along their trajectory with a rate of energy loss equal to the -total stopping power, ignoring fluctuations in the energy loss. The -approximation is useful for expressing average quantities that describe how -charged particles slow down in matter. For example, the CSDA range approximates -the average path length a charged particle travels as it slows to rest: - -.. math:: - :label: csda-range - - R(T) = \int^T_0 \frac{dT'}{S(T')}. - -Actual path lengths will fluctuate around :math:`R(T)`. The average number of -photons emitted per unit path length is given by the inverse bremsstrahlung -mean free path: - -.. math:: - :label: inverse-bremsstrahlung-mfp - - \lambda_{\text{br}}^{-1}(T,E_{\text{cut}}) - = n\int_{E_{\text{cut}}}^T\frac{d\sigma_{\text{br}}}{dE}dE - = n\frac{Z^2}{\beta^2}\int_{\kappa_{\text{cut}}}^1\frac{1}{\kappa} - \chi(Z,T,\kappa)d\kappa. - -The lower limit of the integral in :eq:`inverse-bremsstrahlung-mfp` is non-zero -because the bremsstrahlung differential cross section diverges for small photon -energies but is finite for photon energies above some cutoff energy -:math:`E_{\text{cut}}`. The mean free path -:math:`\lambda_{\text{br}}^{-1}(T,E_{\text{cut}})` is used to calculate the -photon number yield, defined as the average number of photons emitted with -energy greater than :math:`E_{\text{cut}}` as the charged particle slows down -from energy :math:`T` to :math:`E_{\text{cut}}`. The photon number yield is -given by - -.. math:: - :label: photon-number-yield - - Y(T,E_{\text{cut}}) = \int^{R(T)}_{R(E_{\text{cut}})} - \lambda_{\text{br}}^{-1}(T',E_{\text{cut}})ds = \int_{E_{\text{cut}}}^T - \frac{\lambda_{\text{br}}^{-1}(T',E_{\text{cut}})}{S(T')}dT'. - -:math:`Y(T,E_{\text{cut}})` can be used to construct the energy spectrum of -bremsstrahlung photons: the number of photons created with energy between -:math:`E_1` and :math:`E_2` by a charged particle with initial kinetic energy -:math:`T` as it comes to rest is given by :math:`Y(T,E_1) - Y(T,E_2)`. - -To simulate the emission of bremsstrahlung photons, the total stopping power -and bremsstrahlung differential cross section for positrons and electrons must -be calculated for a given material using :eq:`material-bremsstrahlung-dcs` and -:eq:`material-radiative-stopping-power`. These quantities are used to build the -tabulated bremsstrahlung energy PDF and CDF for that material for each incident -energy :math:`T_k` on the energy grid. The following algorithm is then applied -to sample the photon energies: - -1. For an incident charged particle with energy :math:`T`, sample the number of - emitted photons as - - .. math:: - - N = \lfloor Y(T,E_{\text{cut}}) + \xi_1 \rfloor. - -2. Rather than interpolate the PDF between indices :math:`k` and :math:`k+1` - for which :math:`T_k < T < T_{k+1}`, which is computationally expensive, use - the composition method and sample from the PDF at either :math:`k` or - :math:`k+1`. Using linear interpolation on a logarithmic scale, the PDF can - be expressed as - - .. math:: - - p_{\text{br}}(T,E) = \pi_k p_{\text{br}}(T_k,E) + \pi_{k+1} - p_{\text{br}}(T_{k+1},E), - - where the interpolation weights are - - .. math:: - - \pi_k = \frac{\ln T_{k+1} - \ln T}{\ln T_{k+1} - \ln T_k},~~~ - \pi_{k+1} = \frac{\ln T - \ln T_k}{\ln T_{k+1} - \ln T_k}. - - Sample either the index :math:`i = k` or :math:`i = k+1` according to the - point probabilities :math:`\pi_{k}` and :math:`\pi_{k+1}`. - -3. Determine the maximum value of the CDF :math:`P_{\text{br,max}}`. - -3. Sample the photon energies using the inverse transform method with the - tabulated CDF :math:`P_{\text{br}}(T_i, E)` i.e., - - .. math:: - - E = E_j \left[ (1 + a_j) \frac{\xi_2 P_{\text{br,max}} - - P_{\text{br}}(T_i, E_j)} {E_j p_{\text{br}}(T_i, E_j)} + 1 - \right]^{\frac{1}{1 + a_j}} - - where the interpolation factor :math:`a_j` is given by - - .. math:: - - a_j = \frac{\ln p_{\text{br}}(T_i,E_{j+1}) - \ln p_{\text{br}}(T_i,E_j)} - {\ln E_{j+1} - \ln E_j} - - and :math:`P_{\text{br}}(T_i, E_j) \le \xi_2 P_{\text{br,max}} \le - P_{\text{br}}(T_i, E_{j+1})`. - -We ignore the range of the electron or positron, i.e., the bremsstrahlung -photons are produced in the same location that the charged particle was -created. The direction of the photons is assumed to be the same as the -direction of the incident charged particle, which is a reasonable approximation -at higher energies when the bremsstrahlung radiation is emitted at small -angles. .. _photon_production: @@ -1070,5 +734,3 @@ emitted photon. .. _Kaltiaisenaho: https://aaltodoc.aalto.fi/bitstream/handle/123456789/21004/master_Kaltiaisenaho_Toni_2016.pdf .. _Salvat: https://doi.org/10.1787/32da5043-en - -.. _Sternheimer: https://doi.org/10.1103/PhysRevB.26.6067 diff --git a/include/openmc/nuclide.h b/include/openmc/nuclide.h index 329c776d03..60b88a153b 100644 --- a/include/openmc/nuclide.h +++ b/include/openmc/nuclide.h @@ -164,8 +164,8 @@ namespace data { // Minimum/maximum transport energy for each particle type. Order corresponds to // that of the ParticleType enum -extern array energy_min; -extern array energy_max; +extern array energy_min; +extern array energy_max; //! Minimum temperature in [K] that nuclide data is available at extern double temperature_min; diff --git a/openmc/source.py b/openmc/source.py index c463ccb275..9b730cf1de 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -260,7 +260,7 @@ class IndependentSource(SourceBase): time distribution of source sites strength : float Strength of the source - particle : {'neutron', 'photon'} + particle : {'neutron', 'photon', 'electron', 'positron'} Source particle type domains : iterable of openmc.Cell, openmc.Material, or openmc.Universe Domains to reject based on, i.e., if a sampled spatial location is not @@ -299,7 +299,7 @@ class IndependentSource(SourceBase): .. versionadded:: 0.14.0 - particle : {'neutron', 'photon'} + particle : {'neutron', 'photon', 'electron', 'positron'} Source particle type constraints : dict Constraints on sampled source particles. Valid keys include @@ -404,7 +404,8 @@ class IndependentSource(SourceBase): @particle.setter def particle(self, particle): - cv.check_value('source particle', particle, ['neutron', 'photon']) + cv.check_value('source particle', particle, + ['neutron', 'photon', 'electron', 'positron']) self._particle = particle def populate_xml_element(self, element): diff --git a/src/finalize.cpp b/src/finalize.cpp index 76babbb96c..659f390b39 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -156,8 +156,8 @@ int openmc_finalize() simulation::entropy_mesh = nullptr; simulation::ufs_mesh = nullptr; - data::energy_max = {INFTY, INFTY}; - data::energy_min = {0.0, 0.0}; + data::energy_max = {INFTY, INFTY, INFTY, INFTY}; + data::energy_min = {0.0, 0.0, 0.0, 0.0}; data::temperature_min = 0.0; data::temperature_max = INFTY; model::root_universe = -1; diff --git a/src/nuclide.cpp b/src/nuclide.cpp index 7cb84640d6..5ae6e30ee2 100644 --- a/src/nuclide.cpp +++ b/src/nuclide.cpp @@ -31,8 +31,8 @@ namespace openmc { //============================================================================== namespace data { -array energy_min {0.0, 0.0}; -array energy_max {INFTY, INFTY}; +array energy_min {0.0, 0.0, 0.0, 0.0}; +array energy_max {INFTY, INFTY, INFTY, INFTY}; double temperature_min {INFTY}; double temperature_max {0.0}; std::unordered_map nuclide_map; diff --git a/src/particle.cpp b/src/particle.cpp index 06ccf462a1..6b4c332a8b 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -232,7 +232,7 @@ void Particle::event_advance() // Sample a distance to collision if (type() == ParticleType::electron || type() == ParticleType::positron) { - collision_distance() = 0.0; + collision_distance() = material() == MATERIAL_VOID ? INFINITY : 0.0; } else if (macro_xs().total == 0.0) { collision_distance() = INFINITY; } else { diff --git a/src/simulation.cpp b/src/simulation.cpp index b9986f4737..f55546c4ce 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -674,8 +674,9 @@ void calculate_work() void initialize_data() { // Determine minimum/maximum energy for incident neutron/photon data - data::energy_max = {INFTY, INFTY}; - data::energy_min = {0.0, 0.0}; + data::energy_max = {INFTY, INFTY, INFTY, INFTY}; + data::energy_min = {0.0, 0.0, 0.0, 0.0}; + for (const auto& nuc : data::nuclides) { if (nuc->grid_.size() >= 1) { int neutron = static_cast(ParticleType::neutron); @@ -703,11 +704,21 @@ void initialize_data() // than the current minimum/maximum if (data::ttb_e_grid.size() >= 1) { int photon = static_cast(ParticleType::photon); + int electron = static_cast(ParticleType::electron); + int positron = static_cast(ParticleType::positron); int n_e = data::ttb_e_grid.size(); + + const std::vector charged = {electron, positron}; + for (auto t : charged) { + data::energy_min[t] = std::exp(data::ttb_e_grid(1)); + data::energy_max[t] = std::exp(data::ttb_e_grid(n_e - 1)); + } + data::energy_min[photon] = - std::max(data::energy_min[photon], std::exp(data::ttb_e_grid(1))); - data::energy_max[photon] = std::min( - data::energy_max[photon], std::exp(data::ttb_e_grid(n_e - 1))); + std::max(data::energy_min[photon], data::energy_min[electron]); + + data::energy_max[photon] = + std::min(data::energy_max[photon], data::energy_max[electron]); } } } diff --git a/src/source.cpp b/src/source.cpp index 12323f7bd7..f6aa665ebd 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -290,6 +290,12 @@ IndependentSource::IndependentSource(pugi::xml_node node) : Source(node) } else if (temp_str == "photon") { particle_ = ParticleType::photon; settings::photon_transport = true; + } else if (temp_str == "electron") { + particle_ = ParticleType::electron; + settings::photon_transport = true; + } else if (temp_str == "positron") { + particle_ = ParticleType::positron; + settings::photon_transport = true; } else { fatal_error(std::string("Unknown source particle type: ") + temp_str); } diff --git a/tests/regression_tests/electron_heating/__init__.py b/tests/regression_tests/electron_heating/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/electron_heating/inputs_true.dat b/tests/regression_tests/electron_heating/inputs_true.dat new file mode 100644 index 0000000000..ec8e5a8376 --- /dev/null +++ b/tests/regression_tests/electron_heating/inputs_true.dat @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + fixed source + 10000 + 1 + + + 10000000.0 1.0 + + + + 1000.0 + + + + + heating + + + diff --git a/tests/regression_tests/electron_heating/results_true.dat b/tests/regression_tests/electron_heating/results_true.dat new file mode 100644 index 0000000000..4f54ceaa4d --- /dev/null +++ b/tests/regression_tests/electron_heating/results_true.dat @@ -0,0 +1,3 @@ +tally 1: +1.000000E+07 +1.000000E+14 diff --git a/tests/regression_tests/electron_heating/test.py b/tests/regression_tests/electron_heating/test.py new file mode 100644 index 0000000000..e7a58560c4 --- /dev/null +++ b/tests/regression_tests/electron_heating/test.py @@ -0,0 +1,40 @@ +import pytest +import openmc + +from tests.testing_harness import PyAPITestHarness + + +@pytest.fixture +def water_model(): + # Define materals and geometry + water = openmc.Material() + water.add_nuclide("H1", 2.0) + water.add_nuclide("O16", 1.0) + water.set_density("g/cc", 1.0) + sphere = openmc.Sphere(r=1.0, boundary_type="reflective") + sph = openmc.Cell(fill=water, region=-sphere) + geometry = openmc.Geometry([sph]) + source = openmc.IndependentSource( + energy=openmc.stats.delta_function(10.0e6), + particle="electron" + ) + + # Define settings + settings = openmc.Settings() + settings.particles = 10000 + settings.batches = 1 + settings.cutoff = {"energy_photon": 1000.0} + settings.run_mode = "fixed source" + settings.source = source + + # Define tallies + tally = openmc.Tally() + tally.scores = ["heating"] + tallies = openmc.Tallies([tally]) + + return openmc.Model(geometry=geometry, settings=settings, tallies=tallies) + + +def test_electron_heating_calc(water_model): + harness = PyAPITestHarness("statepoint.1.h5", water_model) + harness.main() From 055ea15a2ddf40f6fff4eef52990e79b37652f64 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 17 Oct 2025 18:09:37 -0500 Subject: [PATCH 29/76] Clip mixture distributions based on mean times integral (#3603) --- openmc/stats/univariate.py | 76 ++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/openmc/stats/univariate.py b/openmc/stats/univariate.py index d6cf19f2b8..c48cc00757 100644 --- a/openmc/stats/univariate.py +++ b/openmc/stats/univariate.py @@ -295,6 +295,20 @@ class Discrete(Univariate): """ return np.sum(self.p) + def mean(self) -> float: + """Return mean of the discrete distribution + + The mean is the weighted average of the discrete values. + + .. versionadded:: 0.15.3 + + Returns + ------- + float + Mean of discrete distribution + """ + return np.sum(self.x * self.p) / np.sum(self.p) + def clip(self, tolerance: float = 1e-6, inplace: bool = False) -> Discrete: r"""Remove low-importance points from discrete distribution. @@ -413,6 +427,18 @@ class Uniform(Univariate): rng = np.random.RandomState(seed) return rng.uniform(self.a, self.b, n_samples) + def mean(self) -> float: + """Return mean of the uniform distribution + + .. versionadded:: 0.15.3 + + Returns + ------- + float + Mean of uniform distribution + """ + return 0.5 * (self.a + self.b) + def to_xml_element(self, element_name: str): """Return XML representation of the uniform distribution @@ -1123,7 +1149,7 @@ class Tabular(Univariate): """ interpolation = get_text(elem, 'interpolation') - params = get_elem_list(elem, "parameters", float) + params = get_elem_list(elem, "parameters", float) m = (len(params) + 1)//2 # +1 for when len(params) is odd x = params[:m] p = params[m:] @@ -1347,6 +1373,30 @@ class Mixture(Univariate): for p, dist in zip(self.probability, self.distribution) ]) + def mean(self) -> float: + """Return mean of the mixture distribution + + The mean is the weighted average of the means of the component + distributions, weighted by probability * integral. + + .. versionadded:: 0.15.3 + + Returns + ------- + float + Mean of the mixture distribution + """ + # Weight each component by its probability and integral + weights = [p*dist.integral() for p, dist in + zip(self.probability, self.distribution)] + total_weight = sum(weights) + + if total_weight == 0: + return 0.0 + + return sum([w*dist.mean() for w, dist in + zip(weights, self.distribution)]) / total_weight + def clip(self, tolerance: float = 1e-6, inplace: bool = False) -> Mixture: r"""Remove low-importance points / distributions @@ -1369,14 +1419,14 @@ class Mixture(Univariate): Distribution with low-importance points / distributions removed """ - # Determine integral of original distribution to compare later - original_integral = self.integral() + # Calculate mean * integral for original distribution to compare later. + original_mean_integral = self.mean() * self.integral() # Determine indices for any distributions that contribute non-negligibly - # to overall intensity - intensities = [prob*dist.integral() for prob, dist in - zip(self.probability, self.distribution)] - indices = _intensity_clip(intensities, tolerance=tolerance) + # to overall mean * integral + mean_integrals = [prob*dist.mean()*dist.integral() for prob, dist in + zip(self.probability, self.distribution)] + indices = _intensity_clip(mean_integrals, tolerance=tolerance) # Clip mixture of distributions probability = self.probability[indices] @@ -1397,12 +1447,14 @@ class Mixture(Univariate): # Create new distribution new_dist = type(self)(probability, distribution) - # Show warning if integral of new distribution is not within - # tolerance of original - diff = (original_integral - new_dist.integral())/original_integral + # Show warning if mean * integral of new distribution is not within + # tolerance of original. For energy distributions, mean * integral + # represents total energy. + new_mean_integral = new_dist.mean() * new_dist.integral() + diff = (original_mean_integral - new_mean_integral)/original_mean_integral if diff > tolerance: - warn("Clipping mixture distribution resulted in an integral that is " - f"lower by a fraction of {diff} when tolerance={tolerance}.") + warn("Clipping mixture distribution resulted in a mean*integral " + f"that is lower by a fraction of {diff} when tolerance={tolerance}.") return new_dist From 3ac5d6f8f540a0bfbe53b8264ae1d691093853ec Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 20 Oct 2025 18:45:14 +0200 Subject: [PATCH 30/76] Allow Path objects in MGXSLibrary.export_to_hdf5 (#3608) Co-authored-by: Paul Romano --- openmc/mgxs_library.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index b840563cff..ce86f97dfb 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -11,7 +11,7 @@ import openmc import openmc.mgxs from openmc.mgxs import SCATTER_TABULAR, SCATTER_LEGENDRE, SCATTER_HISTOGRAM from .checkvalue import check_type, check_value, check_greater_than, \ - check_iterable_type, check_less_than, check_filetype_version + check_iterable_type, check_less_than, check_filetype_version, PathLike ROOM_TEMPERATURE_KELVIN = 294.0 @@ -2506,7 +2506,7 @@ class MGXSLibrary: Parameters ---------- - filename : str + filename : str or PathLike Filename of file, default is mgxs.h5. libver : {'earliest', 'latest'} Compatibility mode for the HDF5 file. 'latest' will produce files @@ -2514,7 +2514,7 @@ class MGXSLibrary: """ - check_type('filename', filename, str) + check_type('filename', filename, PathLike) # Create and write to the HDF5 file file = h5py.File(filename, "w", libver=libver) From c31032cf25f5a8c839c20fdb1017cbbf6de88278 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Wed, 22 Oct 2025 02:03:27 +0300 Subject: [PATCH 31/76] load mesh objects from weight_windows.h5 file (#3598) Co-authored-by: Patrick Shriwise --- include/openmc/mesh.h | 22 ++ src/mesh.cpp | 369 ++++++++++++++++++++++------ src/weight_windows.cpp | 4 + tests/cpp_unit_tests/CMakeLists.txt | 1 + tests/cpp_unit_tests/test_mesh.cpp | 257 +++++++++++++++++++ 5 files changed, 579 insertions(+), 74 deletions(-) create mode 100644 tests/cpp_unit_tests/test_mesh.cpp diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index a56705c9ec..5c9272e93b 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -132,8 +132,14 @@ public: // Constructors and destructor Mesh() = default; Mesh(pugi::xml_node node); + Mesh(hid_t group); virtual ~Mesh() = default; + // Factory method for creating meshes from either an XML node or HDF5 group + template + static const std::unique_ptr& create( + T dataset, const std::string& mesh_type, const std::string& mesh_library); + // Methods //! Perform any preparation needed to support point location within the mesh virtual void prepare_for_point_location() {}; @@ -258,6 +264,7 @@ class StructuredMesh : public Mesh { public: StructuredMesh() = default; StructuredMesh(pugi::xml_node node) : Mesh {node} {}; + StructuredMesh(hid_t group) : Mesh {group} {}; virtual ~StructuredMesh() = default; using MeshIndex = std::array; @@ -423,6 +430,7 @@ class PeriodicStructuredMesh : public StructuredMesh { public: PeriodicStructuredMesh() = default; PeriodicStructuredMesh(pugi::xml_node node) : StructuredMesh {node} {}; + PeriodicStructuredMesh(hid_t group) : StructuredMesh {group} {}; Position local_coords(const Position& r) const override { @@ -442,6 +450,7 @@ public: // Constructors RegularMesh() = default; RegularMesh(pugi::xml_node node); + RegularMesh(hid_t group); // Overridden methods int get_index_in_direction(double r, int i) const override; @@ -481,6 +490,8 @@ public: //! Return the volume for a given mesh index double volume(const MeshIndex& ijk) const override; + int set_grid(); + // Data members double volume_frac_; //!< Volume fraction of each mesh element double element_volume_; //!< Volume of each mesh element @@ -492,6 +503,7 @@ public: // Constructors RectilinearMesh() = default; RectilinearMesh(pugi::xml_node node); + RectilinearMesh(hid_t group); // Overridden methods int get_index_in_direction(double r, int i) const override; @@ -534,6 +546,7 @@ public: // Constructors CylindricalMesh() = default; CylindricalMesh(pugi::xml_node node); + CylindricalMesh(hid_t group); // Overridden methods virtual MeshIndex get_indices(Position r, bool& in_mesh) const override; @@ -598,6 +611,7 @@ public: // Constructors SphericalMesh() = default; SphericalMesh(pugi::xml_node node); + SphericalMesh(hid_t group); // Overridden methods virtual MeshIndex get_indices(Position r, bool& in_mesh) const override; @@ -668,6 +682,7 @@ public: // Constructors UnstructuredMesh() { n_dimension_ = 3; }; UnstructuredMesh(pugi::xml_node node); + UnstructuredMesh(hid_t group); static const std::string mesh_type; virtual std::string get_mesh_type() const override; @@ -774,6 +789,7 @@ public: // Constructors MOABMesh() = default; MOABMesh(pugi::xml_node); + MOABMesh(hid_t group); MOABMesh(const std::string& filename, double length_multiplier = 1.0); MOABMesh(std::shared_ptr external_mbi); @@ -943,6 +959,7 @@ class LibMesh : public UnstructuredMesh { public: // Constructors LibMesh(pugi::xml_node node); + LibMesh(hid_t group); LibMesh(const std::string& filename, double length_multiplier = 1.0); LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier = 1.0); @@ -1069,6 +1086,11 @@ private: //! \param[in] root XML node void read_meshes(pugi::xml_node root); +//! Read meshes from an HDF5 file +// +//! \param[in] group HDF5 group ("meshes" group) +void read_meshes(hid_t group); + //! Write mesh data to an HDF5 group // //! \param[in] group HDF5 group diff --git a/src/mesh.cpp b/src/mesh.cpp index 58d218b9ca..610d057cf0 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -230,6 +230,42 @@ void MaterialVolumes::add_volume_unsafe( // Mesh implementation //============================================================================== +template +const std::unique_ptr& Mesh::create( + T dataset, const std::string& mesh_type, const std::string& mesh_library) +{ + // Determine mesh type. Add to model vector and map + if (mesh_type == RegularMesh::mesh_type) { + model::meshes.push_back(make_unique(dataset)); + } else if (mesh_type == RectilinearMesh::mesh_type) { + model::meshes.push_back(make_unique(dataset)); + } else if (mesh_type == CylindricalMesh::mesh_type) { + model::meshes.push_back(make_unique(dataset)); + } else if (mesh_type == SphericalMesh::mesh_type) { + model::meshes.push_back(make_unique(dataset)); +#ifdef OPENMC_DAGMC_ENABLED + } else if (mesh_type == UnstructuredMesh::mesh_type && + mesh_library == MOABMesh::mesh_lib_type) { + model::meshes.push_back(make_unique(dataset)); +#endif +#ifdef OPENMC_LIBMESH_ENABLED + } else if (mesh_type == UnstructuredMesh::mesh_type && + mesh_library == LibMesh::mesh_lib_type) { + model::meshes.push_back(make_unique(dataset)); +#endif + } else if (mesh_type == UnstructuredMesh::mesh_type) { + fatal_error("Unstructured mesh support is not enabled or the mesh " + "library is invalid."); + } else { + fatal_error(fmt::format("Invalid mesh type: {}", mesh_type)); + } + + // Map ID to position in vector + model::mesh_map[model::meshes.back()->id_] = model::meshes.size() - 1; + + return model::meshes.back(); +} + Mesh::Mesh(pugi::xml_node node) { // Read mesh id @@ -238,6 +274,17 @@ Mesh::Mesh(pugi::xml_node node) name_ = get_node_value(node, "name"); } +Mesh::Mesh(hid_t group) +{ + // Read mesh ID + read_attribute(group, "id", id_); + + // Read mesh name + if (object_exists(group, "name")) { + read_dataset(group, "name", name_); + } +} + void Mesh::set_id(int32_t id) { assert(id >= 0 || id == C_NONE); @@ -265,7 +312,13 @@ void Mesh::set_id(int32_t id) // Update ID and entry in the mesh map id_ = id; - model::mesh_map[id] = model::meshes.size() - 1; + + // find the index of this mesh in the model::meshes vector + // (search in reverse because this mesh was likely just added to the vector) + auto it = std::find_if(model::meshes.rbegin(), model::meshes.rend(), + [this](const std::unique_ptr& mesh) { return mesh.get() == this; }); + + model::mesh_map[id] = std::distance(model::meshes.begin(), it.base()) - 1; } vector Mesh::volumes() const @@ -627,6 +680,46 @@ UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node) } } +UnstructuredMesh::UnstructuredMesh(hid_t group) : Mesh(group) +{ + n_dimension_ = 3; + + // check the mesh type + if (object_exists(group, "type")) { + std::string temp; + read_dataset(group, "type", temp); + if (temp != mesh_type) { + fatal_error(fmt::format("Invalid mesh type: {}", temp)); + } + } + + // check if a length unit multiplier was specified + if (object_exists(group, "length_multiplier")) { + read_dataset(group, "length_multiplier", length_multiplier_); + } + + // get the filename of the unstructured mesh to load + if (object_exists(group, "filename")) { + read_dataset(group, "filename", filename_); + if (!file_exists(filename_)) { + fatal_error("Mesh file '" + filename_ + "' does not exist!"); + } + } else { + fatal_error(fmt::format( + "No filename supplied for unstructured mesh with ID: {}", id_)); + } + + if (attribute_exists(group, "options")) { + read_attribute(group, "options", options_); + } + + // check if mesh tally data should be written with + // statepoint files + if (attribute_exists(group, "output")) { + read_attribute(group, "output", output_); + } +} + void UnstructuredMesh::determine_bounds() { double xmin = INFTY; @@ -1086,6 +1179,72 @@ void StructuredMesh::surface_bins_crossed( // RegularMesh implementation //============================================================================== +int RegularMesh::set_grid() +{ + auto shape = xt::adapt(shape_, {n_dimension_}); + + // Check that dimensions are all greater than zero + if (xt::any(shape <= 0)) { + set_errmsg("All entries for a regular mesh dimensions " + "must be positive."); + return OPENMC_E_INVALID_ARGUMENT; + } + + // Make sure lower_left and dimension match + if (lower_left_.size() != n_dimension_) { + set_errmsg("Number of entries in lower_left must be the same " + "as the regular mesh dimensions."); + return OPENMC_E_INVALID_ARGUMENT; + } + if (width_.size() > 0) { + + // Check to ensure width has same dimensions + if (width_.size() != n_dimension_) { + set_errmsg("Number of entries on width must be the same as " + "the regular mesh dimensions."); + return OPENMC_E_INVALID_ARGUMENT; + } + + // Check for negative widths + if (xt::any(width_ < 0.0)) { + set_errmsg("Cannot have a negative width on a regular mesh."); + return OPENMC_E_INVALID_ARGUMENT; + } + + // Set width and upper right coordinate + upper_right_ = xt::eval(lower_left_ + shape * width_); + + } else if (upper_right_.size() > 0) { + + // Check to ensure upper_right_ has same dimensions + if (upper_right_.size() != n_dimension_) { + set_errmsg("Number of entries on upper_right must be the " + "same as the regular mesh dimensions."); + return OPENMC_E_INVALID_ARGUMENT; + } + + // Check that upper-right is above lower-left + if (xt::any(upper_right_ < lower_left_)) { + set_errmsg( + "The upper_right coordinates of a regular mesh must be greater than " + "the lower_left coordinates."); + return OPENMC_E_INVALID_ARGUMENT; + } + + // Set width + width_ = xt::eval((upper_right_ - lower_left_) / shape); + } + + // Set material volumes + volume_frac_ = 1.0 / xt::prod(shape)(); + + element_volume_ = 1.0; + for (int i = 0; i < n_dimension_; i++) { + element_volume_ *= width_[i]; + } + return 0; +} + RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node} { // Determine number of dimensions for mesh @@ -1100,12 +1259,6 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node} } std::copy(shape.begin(), shape.end(), shape_.begin()); - // Check that dimensions are all greater than zero - if (xt::any(shape <= 0)) { - fatal_error("All entries on the element for a tally " - "mesh must be positive."); - } - // Check for lower-left coordinates if (check_for_node(node, "lower_left")) { // Read mesh lower-left corner location @@ -1114,12 +1267,6 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node} fatal_error("Must specify on a mesh."); } - // Make sure lower_left and dimension match - if (shape.size() != lower_left_.size()) { - fatal_error("Number of entries on must be the same " - "as the number of entries on ."); - } - if (check_for_node(node, "width")) { // Make sure one of upper-right or width were specified if (check_for_node(node, "upper_right")) { @@ -1128,49 +1275,52 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node} width_ = get_node_xarray(node, "width"); - // Check to ensure width has same dimensions - auto n = width_.size(); - if (n != lower_left_.size()) { - fatal_error("Number of entries on must be the same as " - "the number of entries on ."); - } - - // Check for negative widths - if (xt::any(width_ < 0.0)) { - fatal_error("Cannot have a negative on a tally mesh."); - } - - // Set width and upper right coordinate - upper_right_ = xt::eval(lower_left_ + shape * width_); - } else if (check_for_node(node, "upper_right")) { + upper_right_ = get_node_xarray(node, "upper_right"); - // Check to ensure width has same dimensions - auto n = upper_right_.size(); - if (n != lower_left_.size()) { - fatal_error("Number of entries on must be the " - "same as the number of entries on ."); - } - - // Check that upper-right is above lower-left - if (xt::any(upper_right_ < lower_left_)) { - fatal_error("The coordinates must be greater than " - "the coordinates on a tally mesh."); - } - - // Set width - width_ = xt::eval((upper_right_ - lower_left_) / shape); } else { fatal_error("Must specify either or on a mesh."); } - // Set material volumes - volume_frac_ = 1.0 / xt::prod(shape)(); + if (int err = set_grid()) { + fatal_error(openmc_err_msg); + } +} - element_volume_ = 1.0; - for (int i = 0; i < n_dimension_; i++) { - element_volume_ *= width_[i]; +RegularMesh::RegularMesh(hid_t group) : StructuredMesh {group} +{ + // Determine number of dimensions for mesh + if (!object_exists(group, "dimension")) { + fatal_error("Must specify on a regular mesh."); + } + + xt::xtensor shape; + read_dataset(group, "dimension", shape); + int n = n_dimension_ = shape.size(); + if (n != 1 && n != 2 && n != 3) { + fatal_error("Mesh must be one, two, or three dimensions."); + } + std::copy(shape.begin(), shape.end(), shape_.begin()); + + // Check for lower-left coordinates + if (object_exists(group, "lower_left")) { + // Read mesh lower-left corner location + read_dataset(group, "lower_left", lower_left_); + } else { + fatal_error("Must specify lower_left dataset on a mesh."); + } + + if (object_exists(group, "upper_right")) { + + read_dataset(group, "upper_right", upper_right_); + + } else { + fatal_error("Must specify either upper_right dataset on a mesh."); + } + + if (int err = set_grid()) { + fatal_error(openmc_err_msg); } } @@ -1343,6 +1493,19 @@ RectilinearMesh::RectilinearMesh(pugi::xml_node node) : StructuredMesh {node} } } +RectilinearMesh::RectilinearMesh(hid_t group) : StructuredMesh {group} +{ + n_dimension_ = 3; + + read_dataset(group, "x_grid", grid_[0]); + read_dataset(group, "y_grid", grid_[1]); + read_dataset(group, "z_grid", grid_[2]); + + if (int err = set_grid()) { + fatal_error(openmc_err_msg); + } +} + const std::string RectilinearMesh::mesh_type = "rectilinear"; std::string RectilinearMesh::get_mesh_type() const @@ -1478,6 +1641,19 @@ CylindricalMesh::CylindricalMesh(pugi::xml_node node) } } +CylindricalMesh::CylindricalMesh(hid_t group) : PeriodicStructuredMesh {group} +{ + n_dimension_ = 3; + read_dataset(group, "r_grid", grid_[0]); + read_dataset(group, "phi_grid", grid_[1]); + read_dataset(group, "z_grid", grid_[2]); + read_dataset(group, "origin", origin_); + + if (int err = set_grid()) { + fatal_error(openmc_err_msg); + } +} + const std::string CylindricalMesh::mesh_type = "cylindrical"; std::string CylindricalMesh::get_mesh_type() const @@ -1756,6 +1932,20 @@ SphericalMesh::SphericalMesh(pugi::xml_node node) } } +SphericalMesh::SphericalMesh(hid_t group) : PeriodicStructuredMesh {group} +{ + n_dimension_ = 3; + + read_dataset(group, "r_grid", grid_[0]); + read_dataset(group, "theta_grid", grid_[1]); + read_dataset(group, "phi_grid", grid_[2]); + read_dataset(group, "origin", origin_); + + if (int err = set_grid()) { + fatal_error(openmc_err_msg); + } +} + const std::string SphericalMesh::mesh_type = "spherical"; std::string SphericalMesh::get_mesh_type() const @@ -2520,6 +2710,11 @@ MOABMesh::MOABMesh(pugi::xml_node node) : UnstructuredMesh(node) initialize(); } +MOABMesh::MOABMesh(hid_t group) : UnstructuredMesh(group) +{ + initialize(); +} + MOABMesh::MOABMesh(const std::string& filename, double length_multiplier) : UnstructuredMesh() { @@ -3228,6 +3423,15 @@ LibMesh::LibMesh(pugi::xml_node node) : UnstructuredMesh(node) initialize(); } +LibMesh::LibMesh(hid_t group) : UnstructuredMesh(group) +{ + // filename_ and length_multiplier_ will already be set by the + // UnstructuredMesh constructor + set_mesh_pointer_from_filename(filename_); + set_length_multiplier(length_multiplier_); + initialize(); +} + // create the mesh from a pointer to a libMesh Mesh LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) { @@ -3618,34 +3822,51 @@ void read_meshes(pugi::xml_node root) mesh_lib = get_node_value(node, "library", true, true); } - // Read mesh and add to vector - if (mesh_type == RegularMesh::mesh_type) { - model::meshes.push_back(make_unique(node)); - } else if (mesh_type == RectilinearMesh::mesh_type) { - model::meshes.push_back(make_unique(node)); - } else if (mesh_type == CylindricalMesh::mesh_type) { - model::meshes.push_back(make_unique(node)); - } else if (mesh_type == SphericalMesh::mesh_type) { - model::meshes.push_back(make_unique(node)); -#ifdef OPENMC_DAGMC_ENABLED - } else if (mesh_type == UnstructuredMesh::mesh_type && - mesh_lib == MOABMesh::mesh_lib_type) { - model::meshes.push_back(make_unique(node)); -#endif -#ifdef OPENMC_LIBMESH_ENABLED - } else if (mesh_type == UnstructuredMesh::mesh_type && - mesh_lib == LibMesh::mesh_lib_type) { - model::meshes.push_back(make_unique(node)); -#endif - } else if (mesh_type == UnstructuredMesh::mesh_type) { - fatal_error("Unstructured mesh support is not enabled or the mesh " - "library is invalid."); - } else { - fatal_error("Invalid mesh type: " + mesh_type); + Mesh::create(node, mesh_type, mesh_lib); + } +} + +void read_meshes(hid_t group) +{ + std::unordered_set mesh_ids; + + std::vector ids; + read_attribute(group, "ids", ids); + + for (auto id : ids) { + + // Check to make sure multiple meshes in the same file don't share IDs + if (contains(mesh_ids, id)) { + fatal_error(fmt::format("Two or more meshes use the same unique ID " + "'{}' in the same HDF5 input file", + id)); + } + mesh_ids.insert(id); + + // If we've already read a mesh with the same ID in a *different* file, + // assume it is the same here + if (model::mesh_map.find(id) != model::mesh_map.end()) { + warning(fmt::format("Mesh with ID={} appears in multiple files.", id)); + continue; } - // Map ID to position in vector - model::mesh_map[model::meshes.back()->id_] = model::meshes.size() - 1; + std::string name = fmt::format("mesh {}", id); + hid_t mesh_group = open_group(group, name.c_str()); + + std::string mesh_type; + if (object_exists(mesh_group, "type")) { + read_dataset(mesh_group, "type", mesh_type); + } else { + mesh_type = "regular"; + } + + // determine the mesh library to use + std::string mesh_lib; + if (object_exists(mesh_group, "library")) { + read_dataset(mesh_group, "library", mesh_lib); + } + + Mesh::create(mesh_group, mesh_type, mesh_lib); } } diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index 26762ad18a..0d648d3335 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -1328,6 +1328,10 @@ extern "C" int openmc_weight_windows_import(const char* filename) hid_t weight_windows_group = open_group(ww_file, "weight_windows"); + hid_t mesh_group = open_group(ww_file, "meshes"); + + read_meshes(mesh_group); + std::vector names = group_names(weight_windows_group); for (const auto& name : names) { diff --git a/tests/cpp_unit_tests/CMakeLists.txt b/tests/cpp_unit_tests/CMakeLists.txt index 8fedc2daa5..5f87db9eac 100644 --- a/tests/cpp_unit_tests/CMakeLists.txt +++ b/tests/cpp_unit_tests/CMakeLists.txt @@ -5,6 +5,7 @@ set(TEST_NAMES test_interpolate test_math test_mcpl_stat_sum + test_mesh # Add additional unit test files here ) diff --git a/tests/cpp_unit_tests/test_mesh.cpp b/tests/cpp_unit_tests/test_mesh.cpp new file mode 100644 index 0000000000..24c4f77373 --- /dev/null +++ b/tests/cpp_unit_tests/test_mesh.cpp @@ -0,0 +1,257 @@ +#include +#include +#include + +#include +#include + +#include "openmc/hdf5_interface.h" +#include "openmc/mesh.h" + +using namespace openmc; + +TEST_CASE("Test mesh hdf5 roundtrip - regular") +{ + // The XML data as a string + std::string xml_string = R"( + + 3 4 5 + -2 -3 -5 + 2 3 5 + + )"; + + // Create a pugixml document object + pugi::xml_document doc; + + // Load the XML from the string + pugi::xml_parse_result result = doc.load_string(xml_string.c_str()); + + pugi::xml_node root = doc.child("mesh"); + + auto mesh = RegularMesh(root); + + hid_t file_id = file_open("mesh.h5", 'w'); + + mesh.to_hdf5(file_id); + + file_close(file_id); + + hid_t file_id2 = file_open("mesh.h5", 'r'); + + hid_t group = open_group(file_id2, "mesh 1"); + + auto mesh2 = RegularMesh(group); + + file_close(file_id2); + + remove("mesh.h5"); + + REQUIRE(mesh2.shape_ == mesh.shape_); + + REQUIRE(mesh2.lower_left() == mesh.lower_left()); + + REQUIRE(mesh2.upper_right() == mesh.upper_right()); +} + +TEST_CASE("Test mesh hdf5 roundtrip - rectilinear") +{ + // The XML data as a string + std::string xml_string = R"( + + 0.0 1.0 5.0 10.0 + -10.0 -5.0 0.0 + -100.0 0.0 100.0 + + )"; + + // Create a pugixml document object + pugi::xml_document doc; + + // Load the XML from the string + pugi::xml_parse_result result = doc.load_string(xml_string.c_str()); + + pugi::xml_node root = doc.child("mesh"); + + auto mesh = RectilinearMesh(root); + + hid_t file_id = file_open("mesh.h5", 'w'); + + mesh.to_hdf5(file_id); + + file_close(file_id); + + hid_t file_id2 = file_open("mesh.h5", 'r'); + + hid_t group = open_group(file_id2, "mesh 1"); + + auto mesh2 = RectilinearMesh(group); + + file_close(file_id2); + + remove("mesh.h5"); + + REQUIRE(mesh2.shape_ == mesh.shape_); + + REQUIRE(mesh2.grid_ == mesh.grid_); +} + +TEST_CASE("Test mesh hdf5 roundtrip - cylindrical") +{ + // The XML data as a string + std::string xml_string = R"( + + 0.1 0.2 0.5 1.0 + 0.0 6.283185307179586 + 0.1 0.2 0.4 0.6 1.0 + 0 0 0 + + )"; + + // Create a pugixml document object + pugi::xml_document doc; + + // Load the XML from the string + pugi::xml_parse_result result = doc.load_string(xml_string.c_str()); + + pugi::xml_node root = doc.child("mesh"); + + auto mesh = CylindricalMesh(root); + + hid_t file_id = file_open("mesh.h5", 'w'); + + mesh.to_hdf5(file_id); + + file_close(file_id); + + hid_t file_id2 = file_open("mesh.h5", 'r'); + + hid_t group = open_group(file_id2, "mesh 1"); + + auto mesh2 = CylindricalMesh(group); + + file_close(file_id2); + + remove("mesh.h5"); + + REQUIRE(mesh2.shape_ == mesh.shape_); + + REQUIRE(mesh2.grid_ == mesh.grid_); +} + +TEST_CASE("Test mesh hdf5 roundtrip - spherical") +{ + // The XML data as a string + std::string xml_string = R"( + + 0.1 0.2 0.5 1.0 + 0.0 3.141592653589793 + 0.0 6.283185307179586 + 0.0 0.0 0.0 + ' + )"; + + // Create a pugixml document object + pugi::xml_document doc; + + // Load the XML from the string + pugi::xml_parse_result result = doc.load_string(xml_string.c_str()); + + pugi::xml_node root = doc.child("mesh"); + + auto mesh = SphericalMesh(root); + + hid_t file_id = file_open("mesh.h5", 'w'); + + mesh.to_hdf5(file_id); + + file_close(file_id); + + hid_t file_id2 = file_open("mesh.h5", 'r'); + + hid_t group = open_group(file_id2, "mesh 1"); + + auto mesh2 = SphericalMesh(group); + + file_close(file_id2); + + remove("mesh.h5"); + + REQUIRE(mesh2.shape_ == mesh.shape_); + + REQUIRE(mesh2.grid_ == mesh.grid_); +} + +TEST_CASE("Test multiple meshes HDF5 roundtrip - spherical") +{ + // The XML data as a string + std::string xml_string = R"( + + + 0.1 0.2 0.5 1.0 + 0.0 3.141592653589793 + 0.0 6.283185307179586 + 0.0 0.0 0.0 + + + 3 4 5 + -2 -3 -5 + 2 3 5 + + + )"; + + // Create a pugixml document object + pugi::xml_document doc; + + // Load the XML from the string + pugi::xml_parse_result result = doc.load_string(xml_string.c_str()); + + pugi::xml_node root = doc.child("meshes"); + + read_meshes(root); + + const auto spherical_mesh_xml = + dynamic_cast(model::meshes[0].get()); + const auto regular_mesh_xml = + dynamic_cast(model::meshes[1].get()); + + hid_t file_id = file_open("meshes.h5", 'w'); + + hid_t root_group = create_group(file_id, "root"); + + open_group(file_id, "root"); + + meshes_to_hdf5(root_group); + + close_group(root_group); + + file_close(file_id); + + hid_t file_id2 = file_open("meshes.h5", 'r'); + + hid_t root_group_read = open_group(file_id2, "root"); + + hid_t mesh_group_read = open_group(root_group_read, "meshes"); + + read_meshes(mesh_group_read); + + // increment mesh IDs to avoid collision during read + for (auto& mesh : model::meshes) { + mesh->set_id(mesh->id() + 10); + } + + const auto spherical_mesh_hdf5 = dynamic_cast( + model::meshes[model::mesh_map[spherical_mesh_xml->id_]].get()); + const auto regular_mesh_hdf5 = dynamic_cast( + model::meshes[model::mesh_map[regular_mesh_xml->id_]].get()); + + remove("meshes.h5"); + + REQUIRE(spherical_mesh_hdf5->shape_ == spherical_mesh_xml->shape_); + REQUIRE(spherical_mesh_hdf5->grid_ == spherical_mesh_xml->grid_); + + REQUIRE(regular_mesh_hdf5->shape_ == regular_mesh_xml->shape_); + REQUIRE(regular_mesh_hdf5->lower_left() == regular_mesh_xml->lower_left()); + REQUIRE(regular_mesh_hdf5->upper_right() == regular_mesh_xml->upper_right()); +} From 70b52546624cb3a654189856d8c9e012624c7672 Mon Sep 17 00:00:00 2001 From: John Tramm Date: Mon, 27 Oct 2025 03:30:54 -0500 Subject: [PATCH 32/76] Random Ray Geometry Debug Mode Fix (#3615) --- src/random_ray/random_ray.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/random_ray/random_ray.cpp b/src/random_ray/random_ray.cpp index 89a91449df..c19d136a4a 100644 --- a/src/random_ray/random_ray.cpp +++ b/src/random_ray/random_ray.cpp @@ -278,6 +278,10 @@ uint64_t RandomRay::transport_history_based_single_ray() // Transports ray across a single source region void RandomRay::event_advance_ray() { + // If geometry debug mode is on, check for cell overlaps + if (settings::check_overlaps) + check_cell_overlap(*this); + // Find the distance to the nearest boundary boundary() = distance_to_boundary(*this); double distance = boundary().distance(); From 230db28d39ae1e3011e3ad85cb8b5090693fe862 Mon Sep 17 00:00:00 2001 From: John Tramm Date: Tue, 28 Oct 2025 03:22:37 -0500 Subject: [PATCH 33/76] FW-CADIS Disregard Max Realizations Setting (#3616) --- docs/source/usersguide/variance_reduction.rst | 3 +-- src/simulation.cpp | 7 ++----- src/weight_windows.cpp | 15 +++++++++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/source/usersguide/variance_reduction.rst b/docs/source/usersguide/variance_reduction.rst index 369e33e2d8..5c24851585 100644 --- a/docs/source/usersguide/variance_reduction.rst +++ b/docs/source/usersguide/variance_reduction.rst @@ -133,8 +133,7 @@ random ray mode can be found in the :ref:`Random Ray User Guide `. # we used for source region decomposition wwg = openmc.WeightWindowGenerator( method='fw_cadis', - mesh=mesh, - max_realizations=settings.batches + mesh=mesh ) # Add generator to openmc.settings object diff --git a/src/simulation.cpp b/src/simulation.cpp index f55546c4ce..05d5545260 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -400,11 +400,8 @@ void finalize_batch() simulation::time_tallies.stop(); // update weight windows if needed - if (settings::solver_type != SolverType::RANDOM_RAY || - simulation::current_batch == settings::n_batches) { - for (const auto& wwg : variance_reduction::weight_windows_generators) { - wwg->update(); - } + for (const auto& wwg : variance_reduction::weight_windows_generators) { + wwg->update(); } // Reset global tally results diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index 0d648d3335..674fae49c3 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -26,6 +26,7 @@ #include "openmc/random_ray/flat_source_domain.h" #include "openmc/search.h" #include "openmc/settings.h" +#include "openmc/simulation.h" #include "openmc/tallies/filter_energy.h" #include "openmc/tallies/filter_mesh.h" #include "openmc/tallies/filter_particle.h" @@ -966,11 +967,17 @@ void WeightWindowsGenerator::update() const Tally* tally = model::tallies[tally_idx_].get(); - // if we're beyond the number of max realizations or not at the corrrect - // update interval, skip the update - if (max_realizations_ < tally->n_realizations_ || - tally->n_realizations_ % update_interval_ != 0) + // If in random ray mode, only update on the last batch + if (settings::solver_type == SolverType::RANDOM_RAY) { + if (simulation::current_batch != settings::n_batches) { + return; + } + // If in Monte Carlo mode and beyond the number of max realizations or + // not at the correct update interval, skip the update + } else if (max_realizations_ < tally->n_realizations_ || + tally->n_realizations_ % update_interval_ != 0) { return; + } wws->update_weights(tally, tally_value_, threshold_, ratio_, method_); From f10d7d9f67375acb088d01e82bab957617f18e39 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 28 Oct 2025 03:23:16 -0500 Subject: [PATCH 34/76] Speed up `apply_time_correction` by reducing file I/O and deepcopies (#3617) --- openmc/deplete/d1s.py | 27 ++++++++++++++++----------- tests/unit_tests/test_d1s.py | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/openmc/deplete/d1s.py b/openmc/deplete/d1s.py index f51dea4160..bc99fc42db 100644 --- a/openmc/deplete/d1s.py +++ b/openmc/deplete/d1s.py @@ -5,7 +5,7 @@ shutdown dose rate calculations. """ -from copy import deepcopy +from copy import copy from typing import Sequence from math import log, prod @@ -164,8 +164,12 @@ def apply_time_correction( radionuclides = [str(x) for x in tally.filters[i_filter].bins] tcf = np.array([time_correction_factors[x][index] for x in radionuclides]) - # Create copy of tally - new_tally = deepcopy(tally) + # Force tally results to be read and std_dev to be computed + tally.std_dev + + # Create shallow copy of tally + new_tally = copy(tally) + new_tally._filters = copy(tally._filters) # Determine number of bins in other filters n_bins_before = prod([f.num_bins for f in tally.filters[:i_filter]]) @@ -177,32 +181,33 @@ def apply_time_correction( shape = (n_bins_before, n_radionuclides, n_bins_after, n_nuclides, n_scores) tally_sum = new_tally.sum.reshape(shape) tally_sum_sq = new_tally.sum_sq.reshape(shape) + tally_mean = new_tally.mean.reshape(shape) + tally_std_dev = new_tally.std_dev.reshape(shape) # Apply TCF, broadcasting to the correct dimensions tcf.shape = (1, -1, 1, 1, 1) new_tally._sum = tally_sum * tcf new_tally._sum_sq = tally_sum_sq * (tcf*tcf) - new_tally._mean = None - new_tally._std_dev = None + new_tally._mean = tally_mean * tcf + new_tally._std_dev = tally_std_dev * tcf shape = (-1, n_nuclides, n_scores) if sum_nuclides: - # Query the mean and standard deviation - mean = new_tally.mean - std_dev = new_tally.std_dev - # Sum over parent nuclides (note that when combining different bins for # parent nuclide, we can't work directly on sum_sq) - new_tally._mean = mean.sum(axis=1).reshape(shape) - new_tally._std_dev = np.linalg.norm(std_dev, axis=1).reshape(shape) + new_tally._mean = new_tally.mean.sum(axis=1).reshape(shape) + new_tally._std_dev = np.linalg.norm(new_tally.std_dev, axis=1).reshape(shape) new_tally._derived = True # Remove ParentNuclideFilter new_tally.filters.pop(i_filter) else: + # Change shape back to (filter combinations, nuclides, scores) new_tally._sum.shape = shape new_tally._sum_sq.shape = shape + new_tally._mean.shape = shape + new_tally._std_dev.shape = shape return new_tally diff --git a/tests/unit_tests/test_d1s.py b/tests/unit_tests/test_d1s.py index 9410f2da2e..8f3b62f400 100644 --- a/tests/unit_tests/test_d1s.py +++ b/tests/unit_tests/test_d1s.py @@ -120,6 +120,13 @@ def test_apply_time_correction(run_in_tmpdir): tally = sp.tallies[tally.id] flux = tally.mean.flatten() + # Copy attributes from original tally + tally_filters = list(tally.filters) + tally_sum = tally.sum.copy() + tally_sum_sq = tally.sum_sq.copy() + tally_mean = tally.mean.copy() + tally_std_dev = tally.std_dev.copy() + # Apply TCF and make sure results are consistent result = d1s.apply_time_correction(tally, factors, sum_nuclides=False) tcf = np.array([factors[nuc][-1] for nuc in nuclides]) @@ -129,6 +136,13 @@ def test_apply_time_correction(run_in_tmpdir): result_summed = d1s.apply_time_correction(tally, factors) assert result_summed.mean.flatten()[0] == pytest.approx(result.mean.sum()) + # Make sure original tally is unchanged + assert tally.filters == tally_filters + assert np.all(tally.sum == tally_sum) + assert np.all(tally.sum_sq == tally_sum_sq) + assert np.all(tally.mean == tally_mean) + assert np.all(tally.std_dev == tally_std_dev) + # Make sure various tally methods work result.get_values() result_summed.get_values() From a74c1424a8a883066b2c0afe4b23f20c84cbb815 Mon Sep 17 00:00:00 2001 From: Makarand More <40858007+Jarvis2001@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:20:11 +0530 Subject: [PATCH 35/76] Update `check_type` calls to accept both `str` and `os.PathLike` objects. (#3618) Co-authored-by: Paul Romano --- openmc/checkvalue.py | 2 +- openmc/mgxs/library.py | 7 ++-- openmc/mgxs/mdgxs.py | 3 +- openmc/mgxs/mgxs.py | 3 +- openmc/mgxs_library.py | 5 ++- openmc/plots.py | 2 +- tests/unit_tests/test_pathlike_simple.py | 46 ++++++++++++++++++++++++ 7 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 tests/unit_tests/test_pathlike_simple.py diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index 4fa205b14f..5ff2cf9ac5 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -37,7 +37,7 @@ def check_type(name, value, expected_type, expected_iter_type=None, *, none_ok=F [t.__name__ for t in expected_type])) else: msg = (f'Unable to set "{name}" to "{value}" which is not of type "' - f'{expected_type.__name__}"') + f'{expected_type}"') raise TypeError(msg) if expected_iter_type: diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 12a4630bdc..f782cbe9e5 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -10,6 +10,7 @@ import numpy as np import openmc import openmc.mgxs import openmc.checkvalue as cv +from openmc.checkvalue import PathLike from ..tallies import ESTIMATOR_TYPES @@ -851,7 +852,7 @@ class Library: 'since a statepoint has not yet been loaded' raise ValueError(msg) - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) cv.check_type('directory', directory, str) import h5py @@ -894,7 +895,7 @@ class Library: """ - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) cv.check_type('directory', directory, str) # Make directory if it does not exist @@ -930,7 +931,7 @@ class Library: """ - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) cv.check_type('directory', directory, str) # Make directory if it does not exist diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index b95a4fbc0e..c12c1a9abe 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -7,6 +7,7 @@ import numpy as np import openmc import openmc.checkvalue as cv +from openmc.checkvalue import PathLike from openmc.mgxs import MGXS from .mgxs import _DOMAIN_TO_FILTER @@ -722,7 +723,7 @@ class MDGXS(MGXS): """ - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) cv.check_type('directory', directory, str) cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) cv.check_value('xs_type', xs_type, ['macro', 'micro']) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index b8f2b8d3fb..533ab0ad32 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -10,6 +10,7 @@ import numpy as np import openmc from openmc.data import REACTION_MT, REACTION_NAME, FISSION_MTS import openmc.checkvalue as cv +from openmc.checkvalue import PathLike from ..tallies import ESTIMATOR_TYPES from . import EnergyGroups @@ -1982,7 +1983,7 @@ class MGXS: """ - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) cv.check_type('directory', directory, str) cv.check_value('format', format, ['csv', 'excel', 'pickle', 'latex']) cv.check_value('xs_type', xs_type, ['macro', 'micro']) diff --git a/openmc/mgxs_library.py b/openmc/mgxs_library.py index ce86f97dfb..4bc2d4a5a7 100644 --- a/openmc/mgxs_library.py +++ b/openmc/mgxs_library.py @@ -2514,8 +2514,7 @@ class MGXSLibrary: """ - check_type('filename', filename, PathLike) - + check_type('filename', filename, (str, PathLike)) # Create and write to the HDF5 file file = h5py.File(filename, "w", libver=libver) file.attrs['filetype'] = np.bytes_(_FILETYPE_MGXS_LIBRARY) @@ -2554,7 +2553,7 @@ class MGXSLibrary: raise ValueError("Either path or openmc.config['mg_cross_sections']" "must be set") - check_type('filename', filename, str) + check_type('filename', filename, (str, PathLike)) file = h5py.File(filename, 'r') # Check filetype and version diff --git a/openmc/plots.py b/openmc/plots.py index e9130f0bea..a0bde3f007 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -439,7 +439,7 @@ class PlotBase(IDManagerMixin): @filename.setter def filename(self, filename): - cv.check_type('filename', filename, str) + cv.check_type('filename', filename, (str, PathLike)) self._filename = filename @property diff --git a/tests/unit_tests/test_pathlike_simple.py b/tests/unit_tests/test_pathlike_simple.py new file mode 100644 index 0000000000..e0116bf01c --- /dev/null +++ b/tests/unit_tests/test_pathlike_simple.py @@ -0,0 +1,46 @@ +"""Simple test for PathLike filename support""" + +from pathlib import Path + +import pytest +import openmc +from openmc.checkvalue import check_type, PathLike + + +def test_pathlike_type_checking(): + """Test that PathLike type checking works correctly""" + + # Test with string (should work) + check_type('filename', 'test.txt', PathLike) + + # Test with Path object (should work) + path_obj = Path('test.txt') + check_type('filename', path_obj, PathLike) + + # Test with Path object containing subdirectories (should work) + path_with_subdir = Path('subdir') / 'test.txt' + check_type('filename', path_with_subdir, PathLike) + + # Test with invalid type (should raise TypeError) + with pytest.raises(TypeError): + check_type('filename', 123, PathLike) + + +def test_plot_filename_pathlike(): + """Test that plot filename accepts Path objects""" + + plot = openmc.Plot() + + # Test with string (should still work) + plot.filename = "test_plot" + assert plot.filename == "test_plot" + + # Test with Path object + path_obj = Path("test_plot_path") + plot.filename = path_obj + assert plot.filename == path_obj + + # Test with Path object containing subdirectories + path_with_subdir = Path("subdir") / "test_plot" + plot.filename = path_with_subdir + assert plot.filename == path_with_subdir From 4c4176661124fe92f5304d20d1b6e7675c44d455 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 28 Oct 2025 11:36:03 -0500 Subject: [PATCH 36/76] Criticality search method on the Model class (#3569) --- openmc/model/model.py | 270 ++++++++++++++++++++++++++++++++- src/settings.cpp | 5 - tests/unit_tests/test_lib.py | 3 - tests/unit_tests/test_model.py | 57 +++++++ 4 files changed, 326 insertions(+), 9 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index c1ffafafd3..7963751d56 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1,6 +1,7 @@ from __future__ import annotations -from collections.abc import Iterable, Sequence +from collections.abc import Callable, Iterable, Sequence import copy +from dataclasses import dataclass, field from functools import cache from pathlib import Path import math @@ -8,11 +9,13 @@ from numbers import Integral, Real import random import re from tempfile import NamedTemporaryFile, TemporaryDirectory +from typing import Any, Protocol import warnings import h5py import lxml.etree as ET import numpy as np +from scipy.optimize import curve_fit import openmc import openmc._xml as xml @@ -24,6 +27,12 @@ from openmc.plots import add_plot_params, _BASIS_INDICES from openmc.utility_funcs import change_directory +# Protocol for a function that is passed to search_keff +class ModelModifier(Protocol): + def __call__(self, val: float, **kwargs: Any) -> None: + ... + + class Model: """Model container. @@ -2196,3 +2205,262 @@ class Model: # Take a wild guess as to how many rays are needed self.settings.particles = 2 * int(max_length) + + def keff_search( + self, + func: ModelModifier, + x0: float, + x1: float, + target: float = 1.0, + k_tol: float = 1e-4, + sigma_final: float = 3e-4, + p: float = 0.5, + q: float = 0.95, + memory: int = 4, + x_min: float | None = None, + x_max: float | None = None, + b0: int | None = None, + b_min: int = 20, + b_max: int | None = None, + maxiter: int = 50, + output: bool = False, + func_kwargs: dict[str, Any] | None = None, + run_kwargs: dict[str, Any] | None = None, + ) -> SearchResult: + r"""Perform a keff search on a model parametrized by a single variable. + + This method uses the GRsecant method described in a paper by `Price and + Roskoff `_. The GRsecant + method is a modification of the secant method that accounts for + uncertainties in the function evaluations. The method uses a weighted + linear fit of the most recent function evaluations to predict the next + point to evaluate. It also adaptively changes the number of batches to + meet the target uncertainty value at each iteration. + + The target uncertainty for iteration :math:`n+1` is determined by the + following equation (following Eq. (8) in the paper): + + .. math:: + \sigma_{i+1} = q \sigma_\text{final} \left ( \frac{ \min \left \{ + \left\lvert k_i - k_\text{target} \right\rvert : k=0,1,\dots,n + \right \} }{k_\text{tol}} \right )^p + + where :math:`q` is a multiplicative factor less than 1, given as the + ``sigma_factor`` parameter below. + + Parameters + ---------- + func : ModelModifier + Function that takes the parameter to be searched and makes a + modification to the model. + x0 : float + First guess for the parameter passed to `func` + x1 : float + Second guess for the parameter passed to `func` + target : float, optional + keff value to search for + k_tol : float, optional + Stopping criterion on the function value; the absolute value must be + within ``k_tol`` of zero to be accepted. + sigma_final : float, optional + Maximum accepted k-effective uncertainty for the stopping criterion. + p : float, optional + Exponent used in the stopping criterion. + q : float, optional + Multiplicative factor used in the stopping criterion. + memory : int, optional + Number of most-recent points used in the weighted linear fit of + ``f(x) = a + b x`` to predict the next point. + x_min : float, optional + Minimum allowed value for the parameter ``x``. + x_max : float, optional + Maximum allowed value for the parameter ``x``. + b0 : int, optional + Number of active batches to use for the initial function + evaluations. If None, uses the model's current setting. + b_min : int, optional + Minimum number of active batches to use in a function evaluation. + b_max : int, optional + Maximum number of active batches to use in a function evaluation. + maxiter : int, optional + Maximum number of iterations to perform. + output : bool, optional + Whether or not to display output showing iteration progress. + func_kwargs : dict, optional + Keyword-based arguments to pass to the `func` function. + run_kwargs : dict, optional + Keyword arguments to pass to :meth:`openmc.Model.run` or + :meth:`openmc.lib.run`. + + Returns + ------- + SearchResult + Result object containing the estimated root (parameter value) and + evaluation history (parameters, means, standard deviations, and + batches), plus convergence status and termination reason. + + """ + import openmc.lib + + check_type('model modifier', func, Callable) + check_type('target', target, Real) + if memory < 2: + raise ValueError("memory must be ≥ 2") + func_kwargs = {} if func_kwargs is None else dict(func_kwargs) + run_kwargs = {} if run_kwargs is None else dict(run_kwargs) + run_kwargs.setdefault('output', False) + + # Create lists to store the history of evaluations + xs: list[float] = [] + fs: list[float] = [] + ss: list[float] = [] + gs: list[int] = [] + count = 0 + + # Helper function to evaluate f and store results + def eval_at(x: float, batches: int) -> tuple[float, float]: + # Modify the model with the current guess + func(x, **func_kwargs) + + # Change the number of batches and run the model + batches += self.settings.inactive + if openmc.lib.is_initialized: + openmc.lib.settings.set_batches(batches) + openmc.lib.reset() + openmc.lib.run(**run_kwargs) + sp_filepath = f'statepoint.{batches}.h5' + else: + self.settings.batches = batches + sp_filepath = self.run(**run_kwargs) + + # Extract keff and its uncertainty + with openmc.StatePoint(sp_filepath) as sp: + keff = sp.keff + + if output: + nonlocal count + count += 1 + print(f'Iteration {count}: {batches=}, {x=:.6g}, {keff=:.5f}') + + xs.append(float(x)) + fs.append(float(keff.n - target)) + ss.append(float(keff.s)) + gs.append(int(batches)) + return fs[-1], ss[-1] + + # Default b0 to current model settings if not explicitly provided + if b0 is None: + b0 = self.settings.batches - self.settings.inactive + + # Perform the search (inlined GRsecant) in a temporary directory + with TemporaryDirectory() as tmpdir: + if not openmc.lib.is_initialized: + run_kwargs.setdefault('cwd', tmpdir) + + # ---- Seed with two evaluations + f0, s0 = eval_at(x0, b0) + if abs(f0) <= k_tol and s0 <= sigma_final: + return SearchResult(x0, xs, fs, ss, gs, True, "converged") + f1, s1 = eval_at(x1, b0) + if abs(f1) <= k_tol and s1 <= sigma_final: + return SearchResult(x1, xs, fs, ss, gs, True, "converged") + + for _ in range(maxiter - 2): + # ------ Step 1: propose next x via GRsecant + m = min(memory, len(xs)) + + # Perform a curve fit on f(x) = a + bx accounting for + # uncertainties. This is equivalent to minimizing the function + # in Equation (A.14) + (a, b), _ = curve_fit( + lambda x, a, b: a + b*x, + xs[-m:], fs[-m:], sigma=ss[-m:], absolute_sigma=True + ) + x_new = float(-a / b) + + # Clamp x_new to the bounds if provided + if x_min is not None: + x_new = max(x_new, x_min) + if x_max is not None: + x_new = min(x_new, x_max) + + # ------ Step 2: choose target σ for next run (Eq. 8 + clamp) + + min_abs_f = float(np.min(np.abs(fs))) + base = q * sigma_final + ratio = min_abs_f / k_tol if k_tol > 0 else 1.0 + sig = base * (ratio ** p) + sig_target = max(sig, base) + + # ------ Step 3: choose generations to hit σ_target (Appendix C) + + # Use at least two past points for regression + if len(gs) >= 2 and np.var(np.log(gs)) > 0.0: + # Perform a curve fit based on Eq. (C.3) to solve for ln(k). + # Note that unlike in the paper, we do not leave r as an + # undetermined parameter and choose r=0.5. + (ln_k,), _ = curve_fit( + lambda ln_b, ln_k: ln_k - 0.5*ln_b, + np.log(gs[-4:]), np.log(ss[-4:]), + ) + k = float(np.exp(ln_k)) + else: + k = float(ss[-1] * math.sqrt(gs[-1])) + + b_new = (k / sig_target) ** 2 + + # Clamp and round up to integer + b_new = max(b_min, math.ceil(b_new)) + if b_max is not None: + b_new = min(b_new, b_max) + + # Evaluate at proposed x with batches determined above + f_new, s_new = eval_at(x_new, b_new) + + # Termination based on both criteria (|f| and σ) + if abs(f_new) <= k_tol and s_new <= sigma_final: + return SearchResult(x_new, xs, fs, ss, gs, True, "converged") + + return SearchResult(xs[-1], xs, fs, ss, gs, False, "maxiter") + + +@dataclass +class SearchResult: + """Result of a GRsecant keff search. + + Attributes + ---------- + root : float + Estimated parameter value where f(x) = 0 at termination. + parameters : list[float] + Parameter values (x) evaluated during the search, in order. + keffs : list[float] + Estimated keff values for each evaluation. + stdevs : list[float] + One-sigma uncertainties of keff for each evaluation. + batches : list[int] + Number of active batches used for each evaluation. + converged : bool + Whether both |f| <= k_tol and sigma <= sigma_final were met. + flag : str + Reason for termination (e.g., "converged", "maxiter"). + """ + root: float + parameters: list[float] = field(repr=False) + means: list[float] = field(repr=False) + stdevs: list[float] = field(repr=False) + batches: list[int] = field(repr=False) + converged: bool + flag: str + + @property + def function_calls(self) -> int: + """Number of function evaluations performed.""" + return len(self.parameters) + + @property + def total_batches(self) -> int: + """Total number of active batches used across all evaluations.""" + return sum(self.batches) + + diff --git a/src/settings.cpp b/src/settings.cpp index 325256cdc5..13b91b0e4f 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1220,11 +1220,6 @@ extern "C" int openmc_set_n_batches( return OPENMC_E_INVALID_ARGUMENT; } - if (simulation::current_batch >= n_batches) { - set_errmsg("Number of batches must be greater than current batch."); - return OPENMC_E_INVALID_ARGUMENT; - } - if (!settings::trigger_on) { // Set n_batches and n_max_batches to same value settings::n_batches = n_batches; diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index 43bc5a8f6f..eb4dc3dce6 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -496,9 +496,6 @@ def test_set_n_batches(lib_run): for i in range(7): openmc.lib.next_batch() - # Setting n_batches less than current_batch should raise error - with pytest.raises(exc.InvalidArgumentError): - settings.set_batches(6) # n_batches should stay the same assert settings.get_batches() == 10 diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 60f8b1a25a..f4f94a47ca 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -901,6 +901,7 @@ def test_id_map_aligned_model(): assert tr_instance == 3, f"Expected cell instance 3 at top-right corner, got {tr_instance}" assert tr_material == 5, f"Expected material ID 5 at top-right corner, got {tr_material}" + def test_setter_from_list(): mat = openmc.Material() model = openmc.Model(materials=[mat]) @@ -913,3 +914,59 @@ def test_setter_from_list(): plot = openmc.Plot() model = openmc.Model(plots=[plot]) assert isinstance(model.plots, openmc.Plots) + + +def test_keff_search(run_in_tmpdir): + """Test the Model.keff_search method""" + + # Create model of a sphere of U235 + mat = openmc.Material() + mat.set_density('g/cm3', 18.9) + mat.add_nuclide('U235', 1.0) + sphere = openmc.Sphere(r=10.0, boundary_type='vacuum') + cell = openmc.Cell(fill=mat, region=-sphere) + geometry = openmc.Geometry([cell]) + settings = openmc.Settings(particles=1000, inactive=10, batches=30) + model = openmc.Model(geometry=geometry, settings=settings) + + # Define function to modify sphere radius + def modify_radius(radius): + sphere.r = radius + + # Perform keff search + k_tol = 4e-3 + sigma_final = 2e-3 + result = model.keff_search( + func=modify_radius, + x0=6.0, + x1=9.0, + k_tol=k_tol, + sigma_final=sigma_final, + output=True, + ) + + final_keff = result.means[-1] + 1.0 # Add back target since means are (keff - target) + final_sigma = result.stdevs[-1] + + # Check for convergence and that tolerances are met + assert result.converged, "keff_search did not converge" + assert abs(final_keff - 1.0) <= k_tol, \ + f"Final keff {final_keff:.5f} not within k_tol {k_tol}" + assert final_sigma <= sigma_final, \ + f"Final uncertainty {final_sigma:.5f} exceeds sigma_final {sigma_final}" + + # Check type of result + assert isinstance(result, openmc.model.SearchResult) + + # Check that we have function evaluation history + assert len(result.parameters) >= 2 + assert len(result.means) == len(result.parameters) + assert len(result.stdevs) == len(result.parameters) + assert len(result.batches) == len(result.parameters) + + # Check that function_calls property works + assert result.function_calls == len(result.parameters) + + # Check that total_batches property works + assert result.total_batches == sum(result.batches) + assert result.total_batches > 0 From 5fc289b99d6ace24d6bcf736a77cfef4c59f6a82 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 31 Oct 2025 19:15:25 -0500 Subject: [PATCH 37/76] Automate workflow for mesh- or cell-based R2S calculations (#3508) Co-authored-by: Ethan Peterson Co-authored-by: Jonathan Shimwell --- docs/source/pythonapi/deplete.rst | 10 + docs/source/usersguide/decay_sources.rst | 205 ++++++- openmc/deplete/__init__.py | 1 + openmc/deplete/microxs.py | 113 +++- openmc/deplete/r2s.py | 680 +++++++++++++++++++++++ openmc/mesh.py | 18 +- openmc/model/model.py | 23 + openmc/utility_funcs.py | 19 + tests/unit_tests/test_r2s.py | 152 +++++ 9 files changed, 1173 insertions(+), 48 deletions(-) create mode 100644 openmc/deplete/r2s.py create mode 100644 tests/unit_tests/test_r2s.py diff --git a/docs/source/pythonapi/deplete.rst b/docs/source/pythonapi/deplete.rst index f112cf8ccf..25fcd898f4 100644 --- a/docs/source/pythonapi/deplete.rst +++ b/docs/source/pythonapi/deplete.rst @@ -287,6 +287,16 @@ the following abstract base classes: abc.SIIntegrator abc.DepSystemSolver +R2S Automation +-------------- + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: myclass.rst + + R2SManager + D1S Functions ------------- diff --git a/docs/source/usersguide/decay_sources.rst b/docs/source/usersguide/decay_sources.rst index d5a078135b..398680e746 100644 --- a/docs/source/usersguide/decay_sources.rst +++ b/docs/source/usersguide/decay_sources.rst @@ -6,42 +6,189 @@ Decay Sources Through the :ref:`depletion ` capabilities in OpenMC, it is possible to simulate radiation emitted from the decay of activated materials. -For fusion energy systems, this is commonly done using what is known as the -`rigorous 2-step `_ (R2S) method. -In this method, a neutron transport calculation is used to determine the neutron -flux and reaction rates over a cell- or mesh-based spatial discretization of the -model. Then, the neutron flux in each discrete region is used to predict the -activated material composition using a depletion solver. Finally, a photon -transport calculation with a source based on the activity and energy spectrum of -the activated materials is used to determine a desired physical response (e.g., -a dose rate) at one or more locations of interest. +For fusion energy systems, this is commonly done using either the `rigorous +2-step `_ (R2S) method or the +`direct 1-step `_ (D1S) method. +In the R2S method, a neutron transport calculation is used to determine the +neutron flux and reaction rates over a cell- or mesh-based spatial +discretization of the model. Then, the neutron flux in each discrete region is +used to predict the activated material composition using a depletion solver. +Finally, a photon transport calculation with a source based on the activity and +energy spectrum of the activated materials is used to determine a desired +physical response (e.g., a dose rate) at one or more locations of interest. +OpenMC includes automation for both the R2S and D1S methods as described in the +following sections. -Once a depletion simulation has been completed in OpenMC, the intrinsic decay -source can be determined as follows. First the activated material composition -can be determined using the :class:`openmc.deplete.Results` object. Indexing an -instance of this class with the timestep index returns a -:class:`~openmc.deplete.StepResult` object, which itself has a -:meth:`~openmc.deplete.StepResult.get_material` method. Once the activated -:class:`~openmc.Material` has been obtained, the -:meth:`~openmc.Material.get_decay_photon_energy` method will give the energy -spectrum of the decay photon source. The integral of the spectrum also indicates -the intensity of the source in units of [Bq]. Altogether, the workflow looks as -follows:: +Rigorous 2-Step (R2S) Calculations +================================== +OpenMC includes an :class:`openmc.deplete.R2SManager` class that fully automates +cell- and mesh-based R2S calculations. Before we describe this class, it is +useful to understand the basic mechanics of how an R2S calculation works. +Generally, it involves the following steps: + +1. The :meth:`openmc.deplete.get_microxs_and_flux` function is called to run a + neutron transport calculation that determines fluxes and microscopic cross + sections in each activation region. +2. The :class:`openmc.deplete.IndependentOperator` and + :class:`openmc.deplete.PredictorIntegrator` classes are used to carry out a + depletion (activation) calculation in order to determine predicted material + compositions based on a set of timesteps and source rates. +3. The activated material composition is determined using the + :class:`openmc.deplete.Results` class. Indexing an instance of this class + with the timestep index returns a :class:`~openmc.deplete.StepResult` object, + which itself has a :meth:`~openmc.deplete.StepResult.get_material` method + returning an activated material. +4. The :meth:`openmc.Material.get_decay_photon_energy` method is used to obtain + the energy spectrum of the decay photon source. The integral of the spectrum + also indicates the intensity of the source in units of [Bq]. +5. A new photon source is defined using one of OpenMC's source classes with the + energy distribution set equal to the object returned by the + :meth:`openmc.Material.get_decay_photon_energy` method. The source is then + assigned to a photon :class:`~openmc.Model`. +6. A photon transport calculation is run with ``model.run()``. + +Altogether, the workflow looks as follows:: + + # Run neutron transport calculation + fluxes, micros = openmc.deplete.get_microxs_and_flux(model, domains) + + # Run activation calculation + op = openmc.deplete.IndependentOperator(mats, fluxes, micros) + timesteps = ... + source_rates = ... + integrator = openmc.deplete.Integrator(op, timesteps, source_rates) + integrator.integrate() + + # Get decay photon source at last timestep results = openmc.deplete.Results("depletion_results.h5") - - # Get results at last timestep step = results[-1] - - # Get activated material composition for ID=1 activated_mat = step.get_material('1') - - # Determine photon source photon_energy = activated_mat.get_decay_photon_energy() + photon_source = openmc.IndependentSource( + space=..., + energy=photon_energy, + particle='photon', + strength=photon_energy.integral() + ) -By default, the :meth:`~openmc.Material.get_decay_photon_energy` method will -eliminate spectral lines with very low intensity, but this behavior can be -configured with the ``clip_tolerance`` argument. + # Run photon transport calculation + model.settings.source = photon_source + model.run() + +Note that by default, the :meth:`~openmc.Material.get_decay_photon_energy` +method will eliminate spectral lines with very low intensity, but this behavior +can be configured with the ``clip_tolerance`` argument. + +Cell-based R2S +-------------- + +In practice, users do not need to manually go through each of the steps in an R2S +calculation described above. The :class:`~openmc.deplete.R2SManager` fully +automates the execution of neutron transport, depletion, decay source +generation, and photon transport. For a cell-based R2S calculation, once you +have a :class:`~openmc.Model` that has been defined, simply create an instance +of :class:`~openmc.deplete.R2SManager` by passing the model and a list of cells +to activate:: + + r2s = openmc.deplete.R2SManager(model, [cell1, cell2, cell3]) + +Note that the ``volume`` attribute must be set for any cell that is to be +activated. The :class:`~openmc.deplete.R2SManager` class allows you to +optionally specify a separate photon model; if not given as an argument, it will +create a shallow copy of the original neutron model (available as the +``neutron_model`` attribute) and store it in the ``photon_model`` attribute. We +can use this to define tallies specific to the photon model:: + + dose_tally = openmc.Tally() + ... + r2s.photon_model.tallies = [dose_tally] + +Next, define the timesteps and source rates for the activation calculation:: + + timesteps = [(3.0, 'd'), (5.0, 'h')] + source_rates = [1e12, 0.0] + +In this case, the model is irradiated for 3 days with a source rate of +:math:`10^{12}` neutron/sec and then the source is turned off and the activated +materials are allowed to decay for 5 hours. These parameters should be passed to +the :meth:`~openmc.deplete.R2SManager.run` method to execute the full R2S +calculation. Before we can do that though, for a cell-based calculation, the one +other piece of information that is needed is bounding boxes of the activated +cells:: + + bounding_boxes = { + cell1.id: cell1.bounding_box, + cell2.id: cell2.bounding_box, + cell3.id: cell3.bounding_box + } + +Note that calling the ``bounding_box`` attribute may not work for all +constructive solid geometry regions (for example, a cell that uses a +non-axis-aligned plane). In these cases, the bounding box will need to be +specified manually. Once you have a set of bounding boxes, the R2S calculation +can be run:: + + r2s.run(timesteps, source_rates, bounding_boxes=bounding_boxes) + +If not specified otherwise, a photon transport calculation is run at each time +in the depletion schedule. That means in the case above, we would see three +photon transport calculations. To specify specific times at which photon +transport calculations should be run, pass the ``photon_time_indices`` argument. +For example, if we wanted to run a photon transport calculation only on the last +time (after the 5 hour decay), we would run:: + + r2s.run(timesteps, source_rates, bounding_boxes=bounding_boxes, + photon_time_indices=[2]) + +After an R2S calculation has been run, the :class:`~openmc.deplete.R2SManager` +instance will have a ``results`` dictionary that allows you to directly access +results from each of the steps. It will also write out all the output files into +a directory that is named "r2s_/". The ``output_dir`` argument to the +:meth:`~openmc.deplete.R2SManager.run` method enables you to override the +default output directory name if desired. + +The :meth:`~openmc.deplete.R2SManager.run` method actually runs three +lower-level methods under the hood:: + + r2s.step1_neutron_transport(...) + r2s.step2_activation(...) + r2s.step3_photon_transport(...) + +For users looking for more control over the calculation, these lower-level +methods can be used in lieu of the :meth:`openmc.deplete.R2SManager.run` method. + +Mesh-based R2S +-------------- + +Executing a mesh-based R2S calculation looks nearly identical to the cell-based +R2S workflow described above. The only difference is that instead of passing a +list of cells to the ``domains`` argument of +:class:`~openmc.deplete.R2SManager`, you need to define a mesh object and pass +that instead. This might look like the following:: + + # Define a regular Cartesian mesh + mesh = openmc.RegularMesh() + mesh.lower_left = (-50., -50., 0.) + mesh.upper_right = (50., 50., 75.) + mesh.dimension = (10, 10, 5) + + r2s = openmc.deplete.R2SManager(model, mesh) + +Executing the R2S calculation is then performed by adding photon tallies and +calling the :meth:`~openmc.deplete.R2SManager.run` method with the appropriate +timesteps and source rates. Note that in this case we do not need to define cell +volumes or bounding boxes as is required for a cell-based R2S calculation. +Instead, during the neutron transport step, OpenMC will run a raytracing +calculation to determine material volume fractions within each mesh element +using the :meth:`openmc.MeshBase.material_volumes` method. Arguments to this +method can be customized via the ``mat_vol_kwargs`` argument to the +:meth:`~openmc.deplete.R2SManager.run` method. Most often, this would involve +customizing the number of rays traced to obtain better estimates of volumes. As +an example, if we wanted to run the raytracing calculation with 10 million rays, +we would run:: + + r2s.run(timesteps, source_rates, mat_vol_kwargs={'n_samples': 10_000_000}) Direct 1-Step (D1S) Calculations ================================ diff --git a/openmc/deplete/__init__.py b/openmc/deplete/__init__.py index 8a9509e900..052e224596 100644 --- a/openmc/deplete/__init__.py +++ b/openmc/deplete/__init__.py @@ -17,6 +17,7 @@ from .stepresult import * from .results import * from .integrators import * from .transfer_rates import * +from .r2s import * from . import abc from . import cram from . import helpers diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index 4ce199f0cc..e351c923df 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -8,8 +8,9 @@ from __future__ import annotations from collections.abc import Sequence import shutil from tempfile import TemporaryDirectory -from typing import Union, TypeAlias +from typing import Union, TypeAlias, Self +import h5py import pandas as pd import numpy as np @@ -20,6 +21,7 @@ from openmc.data import REACTION_MT import openmc from .chain import Chain, REACTIONS, _get_chain from .coupled_operator import _find_cross_sections, _get_nuclides_with_data +from ..utility_funcs import h5py_file_or_group import openmc.lib from openmc.mpi import comm @@ -47,6 +49,7 @@ def get_microxs_and_flux( reaction_rate_mode: str = 'direct', chain_file: PathLike | Chain | None = None, path_statepoint: PathLike | None = None, + path_input: PathLike | None = None, run_kwargs=None ) -> tuple[list[np.ndarray], list[MicroXS]]: """Generate microscopic cross sections and fluxes for multiple domains. @@ -59,7 +62,7 @@ def get_microxs_and_flux( .. versionadded:: 0.14.0 .. versionchanged:: 0.15.3 - Added `reaction_rate_mode` and `path_statepoint` arguments. + Added `reaction_rate_mode`, `path_statepoint`, `path_input` arguments. Parameters ---------- @@ -90,6 +93,10 @@ def get_microxs_and_flux( Path to write the statepoint file from the neutron transport solve to. By default, The statepoint file is written to a temporary directory and is not kept. + path_input : path-like, optional + Path to write the model XML file from the neutron transport solve to. + By default, the model XML file is written to a temporary directory and + not kept. run_kwargs : dict, optional Keyword arguments passed to :meth:`openmc.Model.run` @@ -108,7 +115,7 @@ def get_microxs_and_flux( check_value('reaction_rate_mode', reaction_rate_mode, {'direct', 'flux'}) # Save any original tallies on the model - original_tallies = model.tallies + original_tallies = list(model.tallies) # Determine what reactions and nuclides are available in chain chain = _get_chain(chain_file) @@ -178,6 +185,10 @@ def get_microxs_and_flux( shutil.move(statepoint_path, path_statepoint) statepoint_path = path_statepoint + # Export the model to path_input if provided + if path_input is not None: + model.export_to_model_xml(path_input) + with StatePoint(statepoint_path) as sp: if reaction_rate_mode == 'direct': rr_tally = sp.tallies[rr_tally.id] @@ -383,8 +394,7 @@ class MicroXS: MicroXS """ - if 'float_precision' not in kwargs: - kwargs['float_precision'] = 'round_trip' + kwargs.setdefault('float_precision', 'round_trip') df = pd.read_csv(csv_file, **kwargs) df.set_index(['nuclides', 'reactions', 'groups'], inplace=True) @@ -419,3 +429,96 @@ class MicroXS: ) df = pd.DataFrame({'xs': self.data.flatten()}, index=multi_index) df.to_csv(*args, **kwargs) + + def to_hdf5(self, group_or_filename: h5py.Group | PathLike, **kwargs): + """Export microscopic cross section data to HDF5 format + + Parameters + ---------- + group_or_filename : h5py.Group or path-like + HDF5 group or filename to write to + kwargs : dict, optional + Keyword arguments to pass to :meth:`h5py.Group.create_dataset`. + Defaults to {'compression': 'lzf'}. + + """ + kwargs.setdefault('compression', 'lzf') + + with h5py_file_or_group(group_or_filename, 'w') as group: + # Store cross section data as 3D dataset + group.create_dataset('data', data=self.data, **kwargs) + + # Store metadata as datasets using string encoding + group.create_dataset('nuclides', data=np.array(self.nuclides, dtype='S')) + group.create_dataset('reactions', data=np.array(self.reactions, dtype='S')) + + @classmethod + def from_hdf5(cls, group_or_filename: h5py.Group | PathLike) -> Self: + """Load data from an HDF5 file + + Parameters + ---------- + group_or_filename : h5py.Group or str or PathLike + HDF5 group or path to HDF5 file. If given as an h5py.Group, the + data is read from that group. If given as a string, it is assumed + to be the filename for the HDF5 file. + + Returns + ------- + MicroXS + """ + + with h5py_file_or_group(group_or_filename, 'r') as group: + # Read data from HDF5 group + data = group['data'][:] + nuclides = [nuc.decode('utf-8') for nuc in group['nuclides'][:]] + reactions = [rxn.decode('utf-8') for rxn in group['reactions'][:]] + + return cls(data, nuclides, reactions) + + +def write_microxs_hdf5( + micros: Sequence[MicroXS], + filename: PathLike, + names: Sequence[str] | None = None, + **kwargs +): + """Write multiple MicroXS objects to an HDF5 file + + Parameters + ---------- + micros : list of MicroXS + List of MicroXS objects + filename : PathLike + Output HDF5 filename + names : list of str, optional + Names for each MicroXS object. If None, uses 'domain_0', 'domain_1', + etc. + **kwargs + Additional keyword arguments passed to :meth:`h5py.Group.create_dataset` + """ + if names is None: + names = [f'domain_{i}' for i in range(len(micros))] + + # Open file once and write all domains using group interface + with h5py.File(filename, 'w') as f: + for microxs, name in zip(micros, names): + group = f.create_group(name) + microxs.to_hdf5(group, **kwargs) + + +def read_microxs_hdf5(filename: PathLike) -> dict[str, MicroXS]: + """Read multiple MicroXS objects from an HDF5 file + + Parameters + ---------- + filename : path-like + HDF5 filename + + Returns + ------- + dict + Dictionary mapping domain names to MicroXS objects + """ + with h5py.File(filename, 'r') as f: + return {name: MicroXS.from_hdf5(group) for name, group in f.items()} diff --git a/openmc/deplete/r2s.py b/openmc/deplete/r2s.py new file mode 100644 index 0000000000..7b5deddc23 --- /dev/null +++ b/openmc/deplete/r2s.py @@ -0,0 +1,680 @@ +from __future__ import annotations +from collections.abc import Sequence +import copy +from datetime import datetime +import json +from pathlib import Path + +import numpy as np +import openmc +from . import IndependentOperator, PredictorIntegrator +from .microxs import get_microxs_and_flux, write_microxs_hdf5, read_microxs_hdf5 +from .results import Results +from ..checkvalue import PathLike + + +def get_activation_materials( + model: openmc.Model, mmv: openmc.MeshMaterialVolumes +) -> openmc.Materials: + """Get a list of activation materials for each mesh element/material. + + When performing a mesh-based R2S calculation, a unique material is needed + for each activation region, which is a combination of a mesh element and a + material within that mesh element. This function generates a list of such + materials, each with a unique name and volume corresponding to the mesh + element and material. + + Parameters + ---------- + model : openmc.Model + The full model containing the geometry and materials. + mmv : openmc.MeshMaterialVolumes + The mesh material volumes object containing the materials and their + volumes for each mesh element. + + Returns + ------- + openmc.Materials + A list of materials, each corresponding to a unique mesh element and + material combination. + + """ + # Get the material ID, volume, and element index for each element-material + # combination + mat_ids = mmv._materials[mmv._materials > -1] + volumes = mmv._volumes[mmv._materials > -1] + elems, _ = np.where(mmv._materials > -1) + + # Get all materials in the model + material_dict = model._get_all_materials() + + # Create a new activation material for each element-material combination + materials = openmc.Materials() + for elem, mat_id, vol in zip(elems, mat_ids, volumes): + mat = material_dict[mat_id] + new_mat = mat.clone() + new_mat.depletable = True + new_mat.name = f'Element {elem}, Material {mat_id}' + new_mat.volume = vol + materials.append(new_mat) + + return materials + + +class R2SManager: + """Manager for Rigorous 2-Step (R2S) method calculations. + + This class is responsible for managing the materials and sources needed for + mesh-based or cell-based R2S calculations. It provides methods to get + activation materials and decay photon sources based on the mesh/cells and + materials in the OpenMC model. + + This class supports the use of a different models for the neutron and photon + transport calculation. However, for cell-based calculations, it assumes that + the only changes in the model are material assignments. For mesh-based + calculations, it checks material assignments in the photon model and any + element--material combinations that don't appear in the photon model are + skipped. + + Parameters + ---------- + neutron_model : openmc.Model + The OpenMC model to use for neutron transport. + domains : openmc.MeshBase or Sequence[openmc.Cell] + The mesh or a sequence of cells that represent the spatial units over + which the R2S calculation will be performed. + photon_model : openmc.Model, optional + The OpenMC model to use for photon transport calculations. If None, a + shallow copy of the neutron_model will be created and used. + + Attributes + ---------- + domains : openmc.MeshBase or Sequence[openmc.Cell] + The mesh or a sequence of cells that represent the spatial units over + which the R2S calculation will be performed. + neutron_model : openmc.Model + The OpenMC model used for neutron transport. + photon_model : openmc.Model + The OpenMC model used for photon transport calculations. + method : {'mesh-based', 'cell-based'} + Indicates whether the R2S calculation uses mesh elements ('mesh-based') + as the spatial discetization or a list of a cells ('cell-based'). + results : dict + A dictionary that stores results from the R2S calculation. + + """ + def __init__( + self, + neutron_model: openmc.Model, + domains: openmc.MeshBase | Sequence[openmc.Cell], + photon_model: openmc.Model | None = None, + ): + self.neutron_model = neutron_model + if photon_model is None: + # Create a shallow copy of the neutron model for photon transport + self.photon_model = openmc.Model( + geometry=copy.copy(neutron_model.geometry), + materials=copy.copy(neutron_model.materials), + settings=copy.copy(neutron_model.settings), + tallies=copy.copy(neutron_model.tallies), + plots=copy.copy(neutron_model.plots), + ) + else: + self.photon_model = photon_model + if isinstance(domains, openmc.MeshBase): + self.method = 'mesh-based' + else: + self.method = 'cell-based' + self.domains = domains + self.results = {} + + def run( + self, + timesteps: Sequence[float] | Sequence[tuple[float, str]], + source_rates: float | Sequence[float], + timestep_units: str = 's', + photon_time_indices: Sequence[int] | None = None, + output_dir: PathLike | None = None, + bounding_boxes: dict[int, openmc.BoundingBox] | None = None, + chain_file: PathLike | None = None, + micro_kwargs: dict | None = None, + mat_vol_kwargs: dict | None = None, + run_kwargs: dict | None = None, + operator_kwargs: dict | None = None, + ): + """Run the R2S calculation. + + Parameters + ---------- + timesteps : Sequence[float] or Sequence[tuple[float, str]] + Sequence of timesteps. Note that values are not cumulative. The + units are specified by the `timestep_units` argument when + `timesteps` is an iterable of float. Alternatively, units can be + specified for each step by passing an iterable of (value, unit) + tuples. + source_rates : float or Sequence[float] + Source rate in [neutron/sec] for each interval in `timesteps`. + timestep_units : {'s', 'min', 'h', 'd', 'a'}, optional + Units for values specified in the `timesteps` argument when passing + float values. 's' means seconds, 'min' means minutes, 'h' means + hours, 'd' means days, and 'a' means years (Julian). + photon_time_indices : Sequence[int], optional + Sequence of time indices at which photon transport should be run; + represented as indices into the array of times formed by the + timesteps. For example, if two timesteps are specified, the array of + times would contain three entries, and [2] would indicate computing + photon results at the last time. A value of None indicates to run + photon transport for each time. + output_dir : PathLike, optional + Path to directory where R2S calculation outputs will be saved. If + not provided, a timestamped directory 'r2s_YYYY-MM-DDTHH-MM-SS' is + created. Subdirectories will be created for the neutron transport, + activation, and photon transport steps. + bounding_boxes : dict[int, openmc.BoundingBox], optional + Dictionary mapping cell IDs to bounding boxes used for spatial + source sampling in cell-based R2S calculations. Required if method + is 'cell-based'. + chain_file : PathLike, optional + Path to the depletion chain XML file to use during activation. If + not provided, the default configured chain file will be used. + micro_kwargs : dict, optional + Additional keyword arguments passed to + :func:`openmc.deplete.get_microxs_and_flux` during the neutron + transport step. + mat_vol_kwargs : dict, optional + Additional keyword arguments passed to + :meth:`openmc.MeshBase.material_volumes`. + run_kwargs : dict, optional + Additional keyword arguments passed to :meth:`openmc.Model.run` + during the neutron and photon transport step. By default, output is + disabled. + operator_kwargs : dict, optional + Additional keyword arguments passed to + :class:`openmc.deplete.IndependentOperator`. + + Returns + ------- + Path + Path to the output directory containing all calculation results + """ + + if output_dir is None: + stamp = datetime.now().strftime('%Y-%m-%dT%H-%M-%S') + output_dir = Path(f'r2s_{stamp}') + + # Set run_kwargs for the neutron transport step + if micro_kwargs is None: + micro_kwargs = {} + if run_kwargs is None: + run_kwargs = {} + if operator_kwargs is None: + operator_kwargs = {} + run_kwargs.setdefault('output', False) + micro_kwargs.setdefault('run_kwargs', run_kwargs) + # If a chain file is provided, prefer it for steps 1 and 2 + if chain_file is not None: + micro_kwargs.setdefault('chain_file', chain_file) + operator_kwargs.setdefault('chain_file', chain_file) + + self.step1_neutron_transport( + output_dir / 'neutron_transport', mat_vol_kwargs, micro_kwargs + ) + self.step2_activation( + timesteps, source_rates, timestep_units, output_dir / 'activation', + operator_kwargs=operator_kwargs + ) + self.step3_photon_transport( + photon_time_indices, bounding_boxes, output_dir / 'photon_transport', + mat_vol_kwargs=mat_vol_kwargs, run_kwargs=run_kwargs + ) + + return output_dir + + def step1_neutron_transport( + self, + output_dir: PathLike = "neutron_transport", + mat_vol_kwargs: dict | None = None, + micro_kwargs: dict | None = None + ): + """Run the neutron transport step. + + This step computes the material volume fractions on the mesh, creates a + mesh-material filter, and retrieves the fluxes and microscopic cross + sections for each mesh/material combination. This step will populate the + 'fluxes' and 'micros' keys in the results dictionary. For a mesh-based + calculation, it will also populate the 'mesh_material_volumes' key. + + Parameters + ---------- + output_dir : PathLike, optional + The directory where the results will be saved. + mat_vol_kwargs : dict, optional + Additional keyword arguments based to + :meth:`openmc.MeshBase.material_volumes`. + micro_kwargs : dict, optional + Additional keyword arguments passed to + :func:`openmc.deplete.get_microxs_and_flux`. + + """ + + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + if self.method == 'mesh-based': + # Compute material volume fractions on the mesh + if mat_vol_kwargs is None: + mat_vol_kwargs = {} + self.results['mesh_material_volumes'] = mmv = \ + self.domains.material_volumes(self.neutron_model, **mat_vol_kwargs) + + # Save results to file + mmv.save(output_dir / 'mesh_material_volumes.npz') + + # Create mesh-material filter based on what combos were found + domains = openmc.MeshMaterialFilter.from_volumes(self.domains, mmv) + else: + domains: Sequence[openmc.Cell] = self.domains + + # Check to make sure that each cell is filled with a material and + # that the volume has been set + + # TODO: If volumes are not set, run volume calculation for cells + for cell in domains: + if cell.fill is None: + raise ValueError( + f"Cell {cell.id} is not filled with a materials. " + "Please set the fill material for each cell before " + "running the R2S calculation." + ) + if cell.volume is None: + raise ValueError( + f"Cell {cell.id} does not have a volume set. " + "Please set the volume for each cell before running " + "the R2S calculation." + ) + + # Set default keyword arguments for microxs and flux calculation + if micro_kwargs is None: + micro_kwargs = {} + micro_kwargs.setdefault('path_statepoint', output_dir / 'statepoint.h5') + micro_kwargs.setdefault('path_input', output_dir / 'model.xml') + + # Run neutron transport and get fluxes and micros + self.results['fluxes'], self.results['micros'] = get_microxs_and_flux( + self.neutron_model, domains, **micro_kwargs) + + # Save flux and micros to file + np.save(output_dir / 'fluxes.npy', self.results['fluxes']) + write_microxs_hdf5(self.results['micros'], output_dir / 'micros.h5') + + def step2_activation( + self, + timesteps: Sequence[float] | Sequence[tuple[float, str]], + source_rates: float | Sequence[float], + timestep_units: str = 's', + output_dir: PathLike = 'activation', + operator_kwargs: dict | None = None, + ): + """Run the activation step. + + This step creates a unique copy of each activation material based on the + mesh elements or cells, then solves the depletion equations for each + material using the fluxes and microscopic cross sections obtained in the + neutron transport step. This step will populate the 'depletion_results' + and 'activation_materials' keys in the results dictionary. + + Parameters + ---------- + timesteps : Sequence[float] or Sequence[tuple[float, str]] + Sequence of timesteps. Note that values are not cumulative. The + units are specified by the `timestep_units` argument when + `timesteps` is an iterable of float. Alternatively, units can be + specified for each step by passing an iterable of (value, unit) + tuples. + source_rates : float | Sequence[float] + Source rate in [neutron/sec] for each interval in `timesteps`. + timestep_units : {'s', 'min', 'h', 'd', 'a'}, optional + Units for values specified in the `timesteps` argument when passing + float values. 's' means seconds, 'min' means minutes, 'h' means + hours, 'd' means days, and 'a' means years (Julian). + output_dir : PathLike, optional + Path to directory where activation calculation outputs will be + saved. + operator_kwargs : dict, optional + Additional keyword arguments passed to + :class:`openmc.deplete.IndependentOperator`. + """ + + if self.method == 'mesh-based': + # Get unique material for each (mesh, material) combination + mmv = self.results['mesh_material_volumes'] + self.results['activation_materials'] = get_activation_materials(self.neutron_model, mmv) + else: + # Create unique material for each cell + activation_mats = openmc.Materials() + for cell in self.domains: + mat = cell.fill.clone() + mat.name = f'Cell {cell.id}' + mat.depletable = True + mat.volume = cell.volume + activation_mats.append(mat) + self.results['activation_materials'] = activation_mats + + # Save activation materials to file + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + self.results['activation_materials'].export_to_xml( + output_dir / 'materials.xml') + + # Create depletion operator for the activation materials + if operator_kwargs is None: + operator_kwargs = {} + operator_kwargs.setdefault('normalization_mode', 'source-rate') + op = IndependentOperator( + self.results['activation_materials'], + self.results['fluxes'], + self.results['micros'], + **operator_kwargs + ) + + # Create time integrator and solve depletion equations + integrator = PredictorIntegrator( + op, timesteps, source_rates=source_rates, timestep_units=timestep_units + ) + output_path = output_dir / 'depletion_results.h5' + integrator.integrate(final_step=False, path=output_path) + + # Get depletion results + self.results['depletion_results'] = Results(output_path) + + def step3_photon_transport( + self, + time_indices: Sequence[int] | None = None, + bounding_boxes: dict[int, openmc.BoundingBox] | None = None, + output_dir: PathLike = 'photon_transport', + mat_vol_kwargs: dict | None = None, + run_kwargs: dict | None = None, + ): + """Run the photon transport step. + + This step performs photon transport calculations using decay photon + sources created from the activated materials. For each specified time, + it creates appropriate photon sources and runs a transport calculation. + In mesh-based mode, the sources are created using the mesh material + volumes, while in cell-based mode, they are created using bounding boxes + for each cell. This step will populate the 'photon_tallies' key in the + results dictionary. + + Parameters + ---------- + time_indices : Sequence[int], optional + Sequence of time indices at which photon transport should be run; + represented as indices into the array of times formed by the + timesteps. For example, if two timesteps are specified, the array of + times would contain three entries, and [2] would indicate computing + photon results at the last time. A value of None indicates to run + photon transport for each time. + bounding_boxes : dict[int, openmc.BoundingBox], optional + Dictionary mapping cell IDs to bounding boxes used for spatial + source sampling in cell-based R2S calculations. Required if method + is 'cell-based'. + output_dir : PathLike, optional + Path to directory where photon transport outputs will be saved. + mat_vol_kwargs : dict, optional + Additional keyword arguments passed to + :meth:`openmc.MeshBase.material_volumes`. + run_kwargs : dict, optional + Additional keyword arguments passed to :meth:`openmc.Model.run` + during the photon transport step. By default, output is disabled. + """ + + # TODO: Automatically determine bounding box for each cell + if bounding_boxes is None and self.method == 'cell-based': + raise ValueError("bounding_boxes must be provided for cell-based " + "R2S calculations.") + + # Set default run arguments if not provided + if run_kwargs is None: + run_kwargs = {} + run_kwargs.setdefault('output', False) + + # Write out JSON file with tally IDs that can be used for loading + # results + output_dir = Path(output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + # Get default time indices if not provided + if time_indices is None: + n_steps = len(self.results['depletion_results']) + time_indices = list(range(n_steps)) + + # Check whether the photon model is different + neutron_univ = self.neutron_model.geometry.root_universe + photon_univ = self.photon_model.geometry.root_universe + different_photon_model = (neutron_univ != photon_univ) + + # For mesh-based calculations, compute material volume fractions for the + # photon model if it is different from the neutron model to account for + # potential material changes + if self.method == 'mesh-based' and different_photon_model: + self.results['mesh_material_volumes_photon'] = photon_mmv = \ + self.domains.material_volumes(self.photon_model, **mat_vol_kwargs) + + # Save photon MMV results to file + photon_mmv.save(output_dir / 'mesh_material_volumes.npz') + + tally_ids = [tally.id for tally in self.photon_model.tallies] + with open(output_dir / 'tally_ids.json', 'w') as f: + json.dump(tally_ids, f) + + self.results['photon_tallies'] = {} + + # Get dictionary of cells in the photon model + if different_photon_model: + photon_cells = self.photon_model.geometry.get_all_cells() + + for time_index in time_indices: + # Create decay photon source + if self.method == 'mesh-based': + self.photon_model.settings.source = \ + self.get_decay_photon_source_mesh(time_index) + else: + sources = [] + results = self.results['depletion_results'] + for cell, original_mat in zip(self.domains, self.results['activation_materials']): + # Skip if the cell is not in the photon model or the + # material has changed + if different_photon_model: + if cell.id not in photon_cells or \ + cell.fill.id != photon_cells[cell.id].fill.id: + continue + + # Get bounding box for the cell + bounding_box = bounding_boxes[cell.id] + + # Get activated material composition + activated_mat = results[time_index].get_material(str(original_mat.id)) + + # Create decay photon source source + space = openmc.stats.Box(*bounding_box) + energy = activated_mat.get_decay_photon_energy() + strength = energy.integral() if energy is not None else 0.0 + source = openmc.IndependentSource( + space=space, + energy=energy, + particle='photon', + strength=strength, + constraints={'domains': [cell]} + ) + sources.append(source) + self.photon_model.settings.source = sources + + # Convert time_index (which may be negative) to a normal index + if time_index < 0: + time_index = len(self.results['depletion_results']) + time_index + + # Run photon transport calculation + run_kwargs['cwd'] = Path(output_dir) / f'time_{time_index}' + statepoint_path = self.photon_model.run(**run_kwargs) + + # Store tally results + with openmc.StatePoint(statepoint_path) as sp: + self.results['photon_tallies'][time_index] = [ + sp.tallies[tally.id] for tally in self.photon_model.tallies + ] + + def get_decay_photon_source_mesh( + self, + time_index: int = -1 + ) -> list[openmc.MeshSource]: + """Create decay photon source for a mesh-based calculation. + + This function creates N :class:`MeshSource` objects where N is the + maximum number of unique materials that appears in a single mesh + element. For each mesh element-material combination, and + IndependentSource instance is created with a spatial constraint limited + the sampled decay photons to the correct region. + + When the photon transport model is different from the neutron model, the + photon MeshMaterialVolumes is used to determine whether an (element, + material) combination exists in the photon model. + + Parameters + ---------- + time_index : int, optional + Time index for the decay photon source. Default is -1 (last time). + + Returns + ------- + list of openmc.MeshSource + A list of MeshSource objects, each containing IndependentSource + instances for the decay photons in the corresponding mesh element. + + """ + mat_dict = self.neutron_model._get_all_materials() + + # Some MeshSource objects will have empty positions; create a "null source" + # that is used for this case + null_source = openmc.IndependentSource(particle='photon', strength=0.0) + + # List to hold sources for each MeshSource (length = N) + source_lists = [] + + # Index in the overall list of activated materials + index_mat = 0 + + # Get various results from previous steps + mat_vols = self.results['mesh_material_volumes'] + materials = self.results['activation_materials'] + results = self.results['depletion_results'] + photon_mat_vols = self.results.get('mesh_material_volumes_photon') + + # Total number of mesh elements + n_elements = mat_vols.num_elements + + for index_elem in range(n_elements): + # Determine which materials exist in the photon model for this element + if photon_mat_vols is not None: + photon_materials = { + mat_id + for mat_id, _ in photon_mat_vols.by_element(index_elem) + if mat_id is not None + } + + for j, (mat_id, _) in enumerate(mat_vols.by_element(index_elem)): + # Skip void volume + if mat_id is None: + continue + + # Skip if this material doesn't exist in photon model + if photon_mat_vols is not None and mat_id not in photon_materials: + index_mat += 1 + continue + + # Check whether a new MeshSource object is needed + if j >= len(source_lists): + source_lists.append([null_source]*n_elements) + + # Get activated material composition + original_mat = materials[index_mat] + activated_mat = results[time_index].get_material(str(original_mat.id)) + + # Create decay photon source source + energy = activated_mat.get_decay_photon_energy() + if energy is not None: + strength = energy.integral() + source_lists[j][index_elem] = openmc.IndependentSource( + energy=energy, + particle='photon', + strength=strength, + constraints={'domains': [mat_dict[mat_id]]} + ) + + # Increment index of activated material + index_mat += 1 + + # Return list of mesh sources + return [openmc.MeshSource(self.domains, sources) for sources in source_lists] + + def load_results(self, path: PathLike): + """Load results from a previous R2S calculation. + + Parameters + ---------- + path : PathLike + Path to the directory containing the R2S calculation results. + + """ + path = Path(path) + + # Load neutron transport results + neutron_dir = path / 'neutron_transport' + if self.method == 'mesh-based': + mmv_file = neutron_dir / 'mesh_material_volumes.npz' + if mmv_file.exists(): + self.results['mesh_material_volumes'] = \ + openmc.MeshMaterialVolumes.from_npz(mmv_file) + fluxes_file = neutron_dir / 'fluxes.npy' + if fluxes_file.exists(): + self.results['fluxes'] = list(np.load(fluxes_file, allow_pickle=True)) + micros_dict = read_microxs_hdf5(neutron_dir / 'micros.h5') + self.results['micros'] = [ + micros_dict[f'domain_{i}'] for i in range(len(micros_dict)) + ] + + # Load activation results + activation_dir = path / 'activation' + activation_results = activation_dir / 'depletion_results.h5' + if activation_results.exists(): + self.results['depletion_results'] = Results(activation_results) + activation_mats_file = activation_dir / 'materials.xml' + if activation_mats_file.exists(): + self.results['activation_materials'] = \ + openmc.Materials.from_xml(activation_mats_file) + + # Load photon transport results + photon_dir = path / 'photon_transport' + + # Load photon mesh material volumes if they exist (for mesh-based calculations) + if self.method == 'mesh-based': + photon_mmv_file = photon_dir / 'mesh_material_volumes.npz' + if photon_mmv_file.exists(): + self.results['mesh_material_volumes_photon'] = \ + openmc.MeshMaterialVolumes.from_npz(photon_mmv_file) + + # Load tally IDs from JSON file + tally_ids_path = photon_dir / 'tally_ids.json' + if tally_ids_path.exists(): + with tally_ids_path.open('r') as f: + tally_ids = json.load(f) + self.results['photon_tallies'] = {} + + # For each photon transport calc, load the statepoint and get the + # tally results based on tally_ids + for time_dir in photon_dir.glob('time_*'): + time_index = int(time_dir.name.split('_')[1]) + for sp_path in time_dir.glob('statepoint.*.h5'): + with openmc.StatePoint(sp_path) as sp: + self.results['photon_tallies'][time_index] = [ + sp.tallies[tally_id] for tally_id in tally_ids + ] diff --git a/openmc/mesh.py b/openmc/mesh.py index 9601207e91..3d93d87a1b 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -325,20 +325,10 @@ class MeshBase(IDManagerMixin, ABC): vols = material_volumes mat_volume_by_element = [vols.by_element(i) for i in range(vols.num_elements)] + # Get dictionary of all materials + materials = model._get_all_materials() + # Create homogenized material for each element - materials = model.geometry.get_all_materials() - - # Account for materials in DAGMC universes - # TODO: This should really get incorporated in lower-level calls to - # get_all_materials, but right now it requires information from the - # Model object - for cell in model.geometry.get_all_cells().values(): - if isinstance(cell.fill, openmc.DAGMCUniverse): - names = cell.fill.material_names - materials.update({ - mat.id: mat for mat in model.materials if mat.name in names - }) - homogenized_materials = [] for mat_volume_list in mat_volume_by_element: material_ids, volumes = [list(x) for x in zip(*mat_volume_list)] @@ -410,7 +400,7 @@ class MeshBase(IDManagerMixin, ABC): # In order to get mesh into model, we temporarily replace the # tallies with a single mesh tally using the current mesh - original_tallies = model.tallies + original_tallies = list(model.tallies) new_tally = openmc.Tally() new_tally.filters = [openmc.MeshFilter(self)] new_tally.scores = ['flux'] diff --git a/openmc/model/model.py b/openmc/model/model.py index 7963751d56..64294c23cb 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -212,6 +212,29 @@ class Model: result[mat.name].add(mat) return result + # TODO: This should really get incorporated in lower-level calls to + # get_all_materials, but right now it requires information from the Model object + def _get_all_materials(self) -> dict[int, openmc.Material]: + """Get all materials including those in DAGMC universes + + Returns + ------- + dict + Dictionary mapping material ID to material instances + """ + # Get all materials from the Geometry object + materials = self.geometry.get_all_materials() + + # Account for materials in DAGMC universes + for cell in self.geometry.get_all_cells().values(): + if isinstance(cell.fill, openmc.DAGMCUniverse): + names = cell.fill.material_names + materials.update({ + mat.id: mat for mat in self.materials if mat.name in names + }) + + return materials + def add_kinetics_parameters_tallies(self, num_groups: int | None = None): """Add tallies for calculating kinetics parameters using the IFP method. diff --git a/openmc/utility_funcs.py b/openmc/utility_funcs.py index da9f73b165..935a589853 100644 --- a/openmc/utility_funcs.py +++ b/openmc/utility_funcs.py @@ -3,6 +3,8 @@ import os from pathlib import Path from tempfile import TemporaryDirectory +import h5py + import openmc from .checkvalue import PathLike @@ -57,3 +59,20 @@ def input_path(filename: PathLike) -> Path: return Path(filename).resolve() else: return Path(filename) + + +@contextmanager +def h5py_file_or_group(group_or_filename: PathLike | h5py.Group, *args, **kwargs): + """Context manager for opening an HDF5 file or using an existing group + + Parameters + ---------- + group_or_filename : path-like or h5py.Group + Path to HDF5 file, or group from an existing HDF5 file + + """ + if isinstance(group_or_filename, h5py.Group): + yield group_or_filename + else: + with h5py.File(group_or_filename, *args, **kwargs) as f: + yield f diff --git a/tests/unit_tests/test_r2s.py b/tests/unit_tests/test_r2s.py new file mode 100644 index 0000000000..a94f85c8c0 --- /dev/null +++ b/tests/unit_tests/test_r2s.py @@ -0,0 +1,152 @@ +from pathlib import Path + +import pytest +import openmc +from openmc.deplete import Chain, R2SManager + + +@pytest.fixture +def simple_model_and_mesh(tmp_path): + # Define two materials: water and Ni + h2o = openmc.Material() + h2o.add_nuclide("H1", 2.0) + h2o.add_nuclide("O16", 1.0) + h2o.set_density("g/cm3", 1.0) + nickel = openmc.Material() + nickel.add_element("Ni", 1.0) + nickel.set_density("g/cm3", 4.0) + + # Geometry: two half-spaces split by x=0 plane + left = openmc.XPlane(0.0) + x_min = openmc.XPlane(-10.0, boundary_type='vacuum') + x_max = openmc.XPlane(10.0, boundary_type='vacuum') + y_min = openmc.YPlane(-10.0, boundary_type='vacuum') + y_max = openmc.YPlane(10.0, boundary_type='vacuum') + z_min = openmc.ZPlane(-10.0, boundary_type='vacuum') + z_max = openmc.ZPlane(10.0, boundary_type='vacuum') + + c1 = openmc.Cell(fill=h2o, region=+x_min & -left & +y_min & -y_max & +z_min & -z_max) + c2 = openmc.Cell(fill=nickel, region=+left & -x_max & +y_min & -y_max & +z_min & -z_max) + c1.volume = 4000.0 + c2.volume = 4000.0 + geometry = openmc.Geometry([c1, c2]) + + # Simple settings with a point source + settings = openmc.Settings() + settings.batches = 10 + settings.particles = 1000 + settings.run_mode = 'fixed source' + settings.source = openmc.IndependentSource() + model = openmc.Model(geometry, settings=settings) + + mesh = openmc.RegularMesh() + mesh.lower_left = (-10.0, -10.0, -10.0) + mesh.upper_right = (10.0, 10.0, 10.0) + mesh.dimension = (1, 1, 1) + return model, (c1, c2), mesh + + +def test_r2s_mesh_expected_output(simple_model_and_mesh, tmp_path): + model, (c1, c2), mesh = simple_model_and_mesh + + # Use mesh-based domains + r2s = R2SManager(model, mesh) + + # Use custom reduced chain file for Ni + chain = Chain.from_xml(Path(__file__).parents[1] / "chain_ni.xml") + + # Run R2S calculation + outdir = r2s.run( + timesteps=[(1.0, 'd')], + source_rates=[1.0], + photon_time_indices=[1], + output_dir=tmp_path, + chain_file=chain, + ) + + # Check directories and files exist + nt = Path(outdir) / 'neutron_transport' + assert (nt / 'fluxes.npy').exists() + assert (nt / 'micros.h5').exists() + assert (nt / 'mesh_material_volumes.npz').exists() + act = Path(outdir) / 'activation' + assert (act / 'depletion_results.h5').exists() + pt = Path(outdir) / 'photon_transport' + assert (pt / 'tally_ids.json').exists() + assert (pt / 'time_1' / 'statepoint.10.h5').exists() + + # Basic results structure checks + assert len(r2s.results['fluxes']) == 2 + assert len(r2s.results['micros']) == 2 + assert len(r2s.results['mesh_material_volumes']) == 2 + assert len(r2s.results['activation_materials']) == 2 + assert len(r2s.results['depletion_results']) == 2 + + # Check activation materials + amats = r2s.results['activation_materials'] + assert all(m.depletable for m in amats) + # Volumes preserved + assert {m.volume for m in amats} == {c1.volume, c2.volume} + + # Check loading results + r2s_loaded = R2SManager(model, mesh) + r2s_loaded.load_results(outdir) + assert len(r2s_loaded.results['fluxes']) == 2 + assert len(r2s_loaded.results['micros']) == 2 + assert len(r2s_loaded.results['mesh_material_volumes']) == 2 + assert len(r2s_loaded.results['activation_materials']) == 2 + assert len(r2s_loaded.results['depletion_results']) == 2 + + +def test_r2s_cell_expected_output(simple_model_and_mesh, tmp_path): + model, (c1, c2), _ = simple_model_and_mesh + + # Use cell-based domains + r2s = R2SManager(model, [c1, c2]) + + # Use custom reduced chain file for Ni + chain = Chain.from_xml(Path(__file__).parents[1] / "chain_ni.xml") + + # Run R2S calculation + bounding_boxes = {c1.id: c1.bounding_box, c2.id: c2.bounding_box} + outdir = r2s.run( + timesteps=[(1.0, 'd')], + source_rates=[1.0], + photon_time_indices=[1], + output_dir=tmp_path, + bounding_boxes=bounding_boxes, + chain_file=chain + ) + + # Check directories and files exist + nt = Path(outdir) / 'neutron_transport' + assert (nt / 'fluxes.npy').exists() + assert (nt / 'micros.h5').exists() + act = Path(outdir) / 'activation' + assert (act / 'depletion_results.h5').exists() + pt = Path(outdir) / 'photon_transport' + assert (pt / 'tally_ids.json').exists() + assert (pt / 'time_1' / 'statepoint.10.h5').exists() + + # Basic results structure checks + assert len(r2s.results['fluxes']) == 2 + assert len(r2s.results['micros']) == 2 + assert len(r2s.results['activation_materials']) == 2 + assert len(r2s.results['depletion_results']) == 2 + + # Check activation materials + amats = r2s.results['activation_materials'] + assert all(m.depletable for m in amats) + # Names include cell IDs + assert any(f"Cell {c1.id}" in m.name for m in amats) + assert any(f"Cell {c2.id}" in m.name for m in amats) + # Volumes preserved + assert {m.volume for m in amats} == {c1.volume, c2.volume} + + # Check loading results + r2s_loaded = R2SManager(model, [c1, c2]) + r2s_loaded.load_results(outdir) + assert len(r2s_loaded.results['fluxes']) == 2 + assert len(r2s_loaded.results['micros']) == 2 + assert len(r2s_loaded.results['activation_materials']) == 2 + assert len(r2s_loaded.results['depletion_results']) == 2 From fd964bc9b04dcf2090b212b8307551b32fea810b Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Mon, 3 Nov 2025 09:42:59 +0200 Subject: [PATCH 38/76] Enable specifying reference direction for azimuthal angle in PolarAzimuthal distribution (#3582) Co-authored-by: shimwell --- include/openmc/distribution_multi.h | 2 ++ openmc/stats/multivariate.py | 25 +++++++++++++++- src/distribution_multi.cpp | 15 +++++++++- tests/regression_tests/source/inputs_true.dat | 2 +- .../regression_tests/source/results_true.dat | 2 +- tests/unit_tests/test_stats.py | 30 +++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-) diff --git a/include/openmc/distribution_multi.h b/include/openmc/distribution_multi.h index 9e84d03d57..75126593f7 100644 --- a/include/openmc/distribution_multi.h +++ b/include/openmc/distribution_multi.h @@ -51,6 +51,8 @@ public: Distribution* phi() const { return phi_.get(); } private: + Direction v_ref_ {1.0, 0.0, 0.0}; //!< reference direction + Direction w_ref_; UPtrDist mu_; //!< Distribution of polar angle UPtrDist phi_; //!< Distribution of azimuthal angle }; diff --git a/openmc/stats/multivariate.py b/openmc/stats/multivariate.py index 222d2d18a5..1ce998758a 100644 --- a/openmc/stats/multivariate.py +++ b/openmc/stats/multivariate.py @@ -79,6 +79,9 @@ class PolarAzimuthal(UnitSphere): reference_uvw : Iterable of float Direction from which polar angle is measured. Defaults to the positive z-direction. + reference_vwu : Iterable of float + Direction from which azimuthal angle is measured. Defaults to the positive + x-direction. Attributes ---------- @@ -89,8 +92,9 @@ class PolarAzimuthal(UnitSphere): """ - def __init__(self, mu=None, phi=None, reference_uvw=(0., 0., 1.)): + def __init__(self, mu=None, phi=None, reference_uvw=(0., 0., 1.), reference_vwu=(1., 0., 0.)): super().__init__(reference_uvw) + self.reference_vwu = reference_vwu if mu is not None: self.mu = mu else: @@ -100,6 +104,20 @@ class PolarAzimuthal(UnitSphere): self.phi = phi else: self.phi = Uniform(0., 2*pi) + + @property + def reference_vwu(self): + return self._reference_vwu + + @reference_vwu.setter + def reference_vwu(self, vwu): + cv.check_type('reference v direction', vwu, Iterable, Real) + vwu = np.asarray(vwu) + uvw = self.reference_uvw + cv.check_greater_than('reference v direction must not be parallel to reference u direction', np.linalg.norm(np.cross(vwu,uvw)), 1e-6*np.linalg.norm(vwu)) + vwu -= vwu.dot(uvw)*uvw + cv.check_less_than('reference v direction must be orthogonal to reference u direction', np.abs(vwu.dot(uvw)), 1e-6) + self._reference_vwu = vwu/np.linalg.norm(vwu) @property def mu(self): @@ -132,6 +150,8 @@ class PolarAzimuthal(UnitSphere): element.set("type", "mu-phi") if self.reference_uvw is not None: element.set("reference_uvw", ' '.join(map(str, self.reference_uvw))) + if self.reference_vwu is not None: + element.set("reference_vwu", ' '.join(map(str, self.reference_vwu))) element.append(self.mu.to_xml_element('mu')) element.append(self.phi.to_xml_element('phi')) return element @@ -155,6 +175,9 @@ class PolarAzimuthal(UnitSphere): uvw = get_elem_list(elem, "reference_uvw", float) if uvw is not None: mu_phi.reference_uvw = uvw + vwu = get_elem_list(elem, "reference_vwu", float) + if vwu is not None: + mu_phi.reference_vwu = vwu mu_phi.mu = Univariate.from_xml_element(elem.find('mu')) mu_phi.phi = Univariate.from_xml_element(elem.find('phi')) return mu_phi diff --git a/src/distribution_multi.cpp b/src/distribution_multi.cpp index b7b3efe526..cdb33adc2a 100644 --- a/src/distribution_multi.cpp +++ b/src/distribution_multi.cpp @@ -58,6 +58,15 @@ PolarAzimuthal::PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi) PolarAzimuthal::PolarAzimuthal(pugi::xml_node node) : UnitSphereDistribution {node} { + // Read reference directional unit vector + if (check_for_node(node, "reference_vwu")) { + auto v_ref = get_node_array(node, "reference_vwu"); + if (v_ref.size() != 3) + fatal_error("Angular distribution reference v direction must have " + "three parameters specified."); + v_ref_ = Direction(v_ref.data()); + } + w_ref_ = u_ref_.cross(v_ref_); if (check_for_node(node, "mu")) { pugi::xml_node node_dist = node.child("mu"); mu_ = distribution_from_xml(node_dist); @@ -79,11 +88,15 @@ Direction PolarAzimuthal::sample(uint64_t* seed) const double mu = mu_->sample(seed); if (mu == 1.0) return u_ref_; + if (mu == -1.0) + return -u_ref_; // Sample azimuthal angle double phi = phi_->sample(seed); - return rotate_angle(u_ref_, mu, &phi, seed); + double f = std::sqrt(1 - mu * mu); + + return mu * u_ref_ + f * std::cos(phi) * v_ref_ + f * std::sin(phi) * w_ref_; } //============================================================================== diff --git a/tests/regression_tests/source/inputs_true.dat b/tests/regression_tests/source/inputs_true.dat index 9f10b79d6b..0c3764ba6f 100644 --- a/tests/regression_tests/source/inputs_true.dat +++ b/tests/regression_tests/source/inputs_true.dat @@ -25,7 +25,7 @@ -2.0 0.0 2.0 0.2 0.3 0.2 - + -1.0 0.0 1.0 0.5 0.25 0.25 diff --git a/tests/regression_tests/source/results_true.dat b/tests/regression_tests/source/results_true.dat index 951075bbb9..7d03c696d3 100644 --- a/tests/regression_tests/source/results_true.dat +++ b/tests/regression_tests/source/results_true.dat @@ -1,2 +1,2 @@ k-combined: -3.034717E-01 2.799386E-03 +3.080655E-01 4.837707E-03 diff --git a/tests/unit_tests/test_stats.py b/tests/unit_tests/test_stats.py index abf143f12a..998d4b984c 100644 --- a/tests/unit_tests/test_stats.py +++ b/tests/unit_tests/test_stats.py @@ -516,3 +516,33 @@ def test_combine_distributions(): # uncertainty of the expected value samples = combined.sample(10_000) assert_sample_mean(samples, 0.25) + +def test_reference_vwu_projection(): + """When a non-orthogonal vector is provided, the setter should project out + any component along reference_uvw so the stored vector is orthogonal. + """ + pa = openmc.stats.PolarAzimuthal() # default reference_uvw == (0, 0, 1) + + # Provide a vector that is not orthogonal to (0,0,1) + pa.reference_vwu = (2.0, 0.5, 0.3) + + reference_v = np.asarray(pa.reference_vwu) + reference_u = np.asarray(pa.reference_uvw) + + # reference_v should be orthogonal to reference_u + assert abs(np.dot(reference_v, reference_u)) < 1e-6 + + +def test_reference_vwu_normalization(): + """When a non-normalized vector is provided, the setter should normalize + the projected vector to unit length. + """ + pa = openmc.stats.PolarAzimuthal() # default reference_uvw == (0, 0, 1) + + # Provide a vector that is neither orthogonal to (0,0,1) nor unit-length + pa.reference_vwu = (2.0, 0.5, 0.3) + + reference_v = np.asarray(pa.reference_vwu) + + # reference_v should be unit length + assert np.isclose(np.linalg.norm(reference_v), 1.0, atol=1e-12) From 2d8e006c3de9c8fbc0b010357ebf5a870909c8bc Mon Sep 17 00:00:00 2001 From: Perry <100789850+yrrepy@users.noreply.github.com> Date: Mon, 3 Nov 2025 09:10:30 -0800 Subject: [PATCH 39/76] Enable nuclide filters with get_decay_photon_energy (#3614) Co-authored-by: Paul Romano --- openmc/material.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index c7b954b666..1609da05a3 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -290,11 +290,13 @@ class Material(IDManagerMixin): return self.get_decay_photon_energy(0.0) def get_decay_photon_energy( - self, - clip_tolerance: float = 1e-6, - units: str = 'Bq', - volume: float | None = None - ) -> Univariate | None: + self, + clip_tolerance: float = 1e-6, + units: str = 'Bq', + volume: float | None = None, + exclude_nuclides: list[str] | None = None, + include_nuclides: list[str] | None = None + ) -> Univariate | None: r"""Return energy distribution of decay photons from unstable nuclides. .. versionadded:: 0.14.0 @@ -302,22 +304,31 @@ class Material(IDManagerMixin): Parameters ---------- clip_tolerance : float - Maximum fraction of :math:`\sum_i x_i p_i` for discrete - distributions that will be discarded. + Maximum fraction of :math:`\sum_i x_i p_i` for discrete distributions + that will be discarded. units : {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'} Specifies the units on the integral of the distribution. volume : float, optional Volume of the material. If not passed, defaults to using the :attr:`Material.volume` attribute. + exclude_nuclides : list of str, optional + Nuclides to exclude from the photon source calculation. + include_nuclides : list of str, optional + Nuclides to include in the photon source calculation. If specified, + only these nuclides are used. Returns ------- Univariate or None - Decay photon energy distribution. The integral of this distribution - is the total intensity of the photon source in the requested units. + Decay photon energy distribution. The integral of this distribution is + the total intensity of the photon source in the requested units. """ cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'}) + + if exclude_nuclides is not None and include_nuclides is not None: + raise ValueError("Cannot specify both exclude_nuclides and include_nuclides") + if units == 'Bq': multiplier = volume if volume is not None else self.volume if multiplier is None: @@ -332,6 +343,11 @@ class Material(IDManagerMixin): dists = [] probs = [] for nuc, atoms_per_bcm in self.get_nuclide_atom_densities().items(): + if exclude_nuclides is not None and nuc in exclude_nuclides: + continue + if include_nuclides is not None and nuc not in include_nuclides: + continue + source_per_atom = openmc.data.decay_photon_energy(nuc) if source_per_atom is not None and atoms_per_bcm > 0.0: dists.append(source_per_atom) From bd76fc056651e33d138d18dbee061c0a7bc83823 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 3 Nov 2025 11:11:57 -0600 Subject: [PATCH 40/76] Fix bug in normalization of tally results with no_reduce (#3619) --- src/tallies/tally.cpp | 7 +++++- tests/unit_tests/test_no_reduce.py | 40 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/test_no_reduce.py diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index b9c615ecb5..12ee3427eb 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -825,9 +825,14 @@ void Tally::accumulate() total_source = 1.0; } + // Determine number of particles contributing to tally + double contributing_particles = settings::reduce_tallies + ? settings::n_particles + : simulation::work_per_rank; + // Account for number of source particles in normalization double norm = - total_source / (settings::n_particles * settings::gen_per_batch); + total_source / (contributing_particles * settings::gen_per_batch); if (settings::solver_type == SolverType::RANDOM_RAY) { norm = 1.0; diff --git a/tests/unit_tests/test_no_reduce.py b/tests/unit_tests/test_no_reduce.py new file mode 100644 index 0000000000..00ddb5a959 --- /dev/null +++ b/tests/unit_tests/test_no_reduce.py @@ -0,0 +1,40 @@ +"""Test the settings.no_reduce feature to ensure tallies are correctly +reduced across MPI processes.""" + +import openmc +import pytest + +from tests.testing_harness import config + + +@pytest.mark.parametrize('no_reduce', [True, False]) +def test_no_reduce(no_reduce, run_in_tmpdir): + """Test that tally results are correct with and without no_reduce.""" + + # Create simple sphere model with vacuum + model = openmc.Model() + sphere = openmc.Sphere(r=1.0, boundary_type='vacuum') + cell = openmc.Cell(region=-sphere) + model.geometry = openmc.Geometry([cell]) + model.settings.run_mode = 'fixed source' + model.settings.batches = 10 + model.settings.particles = 100 + model.settings.source = openmc.IndependentSource(space=openmc.stats.Point()) + model.settings.no_reduce = no_reduce + + # Tally: surface current on vacuum boundary + surf_filter = openmc.SurfaceFilter(sphere) + tally = openmc.Tally() + tally.filters = [surf_filter] + tally.scores = ['current'] + model.tallies = [tally] + + # Run OpenMC with proper MPI arguments if needed + kwargs = {'apply_tally_results': True, 'openmc_exec': config['exe']} + if config['mpi']: + kwargs['mpi_args'] = [config['mpiexec'], '-n', config['mpi_np']] + model.run(**kwargs) + + # The tally should be ~1.0 (every particle crosses the surface once) + tally_mean = tally.mean.flatten()[0] + assert tally_mean == pytest.approx(1.0) From e5c7d0ca88983cdd37bb9870cd1fccc8e4301736 Mon Sep 17 00:00:00 2001 From: Jon Shimwell Date: Wed, 5 Nov 2025 17:03:20 +0100 Subject: [PATCH 41/76] Adding vtkhdf option to write vtk data (#3252) Co-authored-by: shimwell Co-authored-by: Jonathan Shimwell Co-authored-by: rherrero-pf <156206440+rherrero-pf@users.noreply.github.com> Co-authored-by: Patrick Shriwise Co-authored-by: Paul Romano --- openmc/mesh.py | 166 ++++++++++++++++-- .../test_mesh_dagmc_tets.vtk | 159 +++++++++++++++++ tests/unit_tests/test_mesh.py | 69 ++++++++ tests/unit_tests/test_mesh_dagmc_tets.vtk | 1 + 4 files changed, 377 insertions(+), 18 deletions(-) create mode 100644 tests/regression_tests/unstructured_mesh/test_mesh_dagmc_tets.vtk create mode 120000 tests/unit_tests/test_mesh_dagmc_tets.vtk diff --git a/openmc/mesh.py b/openmc/mesh.py index 3d93d87a1b..ce5218b5e9 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -5,6 +5,7 @@ from collections.abc import Iterable, Sequence, Mapping from functools import wraps from math import pi, sqrt, atan2 from numbers import Integral, Real +from pathlib import Path from typing import Protocol import h5py @@ -2443,6 +2444,7 @@ class UnstructuredMesh(MeshBase): _UNSUPPORTED_ELEM = -1 _LINEAR_TET = 0 _LINEAR_HEX = 1 + _VTK_TETRA = 10 def __init__(self, filename: PathLike, library: str, mesh_id: int | None = None, name: str = '', length_multiplier: float = 1.0, @@ -2652,7 +2654,8 @@ class UnstructuredMesh(MeshBase): warnings.warn( "The 'UnstructuredMesh.write_vtk_mesh' method has been renamed " "to 'write_data_to_vtk' and will be removed in a future version " - " of OpenMC.", FutureWarning + " of OpenMC.", + FutureWarning, ) self.write_data_to_vtk(**kwargs) @@ -2670,9 +2673,10 @@ class UnstructuredMesh(MeshBase): Parameters ---------- filename : str or pathlib.Path - Name of the VTK file to write. If the filename ends in '.vtu' then a - binary VTU format file will be written, if the filename ends in - '.vtk' then a legacy VTK file will be written. + Name of the VTK file to write. If the filename ends in '.vtkhdf' + then a VTKHDF format file will be written. If the filename ends in + '.vtu' then a binary VTU format file will be written. If the + filename ends in '.vtk' then a legacy VTK file will be written. datasets : dict Dictionary whose keys are the data labels and values are numpy appropriately sized arrays of the data @@ -2680,6 +2684,35 @@ class UnstructuredMesh(MeshBase): Whether or not to normalize the data by the volume of the mesh elements """ + + if Path(filename).suffix == ".vtkhdf": + + self._write_data_to_vtk_hdf5_format( + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization, + ) + + elif Path(filename).suffix == ".vtk" or Path(filename).suffix == ".vtu": + + self._write_data_to_vtk_ascii_format( + filename=filename, + datasets=datasets, + volume_normalization=volume_normalization, + ) + + else: + raise ValueError( + "Unsupported file extension, The filename must end with " + "'.vtkhdf', '.vtu' or '.vtk'" + ) + + def _write_data_to_vtk_ascii_format( + self, + filename: PathLike | None = None, + datasets: dict | None = None, + volume_normalization: bool = True, + ): from vtkmodules.util import numpy_support from vtkmodules import vtkCommonCore from vtkmodules import vtkCommonDataModel @@ -2687,9 +2720,7 @@ class UnstructuredMesh(MeshBase): from vtkmodules import vtkIOXML if self.connectivity is None or self.vertices is None: - raise RuntimeError( - "This mesh has not been loaded from a statepoint file." - ) + raise RuntimeError("This mesh has not been loaded from a statepoint file.") if filename is None: filename = f"mesh_{self.id}.vtk" @@ -2771,29 +2802,128 @@ class UnstructuredMesh(MeshBase): writer.Write() + def _write_data_to_vtk_hdf5_format( + self, + filename: PathLike | None = None, + datasets: dict | None = None, + volume_normalization: bool = True, + ): + def append_dataset(dset, array): + """Convenience function to append data to an HDF5 dataset""" + origLen = dset.shape[0] + dset.resize(origLen + array.shape[0], axis=0) + dset[origLen:] = array + + if self.library != "moab": + raise NotImplementedError("VTKHDF output is only supported for MOAB meshes") + + # the self.connectivity contains arrays of length 8 to support hex + # elements as well, in the case of tetrahedra mesh elements, the + # last 4 values are -1 and are removed + trimmed_connectivity = [] + for cell in self.connectivity: + # Find the index of the first -1 value, if any + first_negative_index = np.where(cell == -1)[0] + if first_negative_index.size > 0: + # Slice the array up to the first -1 value + trimmed_connectivity.append(cell[: first_negative_index[0]]) + else: + # No -1 values, append the whole cell + trimmed_connectivity.append(cell) + trimmed_connectivity = np.array(trimmed_connectivity, dtype="int32").flatten() + + # MOAB meshes supports tet elements only so we know it has 4 points per cell + points_per_cell = 4 + + # offsets are the indices of the first point of each cell in the array of points + offsets = np.arange(0, self.n_elements * points_per_cell + 1, points_per_cell) + + for name, data in datasets.items(): + if data.shape != self.dimension: + raise ValueError( + f'Cannot apply dataset "{name}" with ' + f"shape {data.shape} to mesh {self.id} " + f"with dimensions {self.dimension}" + ) + + with h5py.File(filename, "w") as f: + + root = f.create_group("VTKHDF") + vtk_file_format_version = (2, 1) + root.attrs["Version"] = vtk_file_format_version + ascii_type = "UnstructuredGrid".encode("ascii") + root.attrs.create( + "Type", + ascii_type, + dtype=h5py.string_dtype("ascii", len(ascii_type)), + ) + + # create hdf5 file structure + root.create_dataset("NumberOfPoints", (0,), maxshape=(None,), dtype="i8") + root.create_dataset("Types", (0,), maxshape=(None,), dtype="uint8") + root.create_dataset("Points", (0, 3), maxshape=(None, 3), dtype="f") + root.create_dataset( + "NumberOfConnectivityIds", (0,), maxshape=(None,), dtype="i8" + ) + root.create_dataset("NumberOfCells", (0,), maxshape=(None,), dtype="i8") + root.create_dataset("Offsets", (0,), maxshape=(None,), dtype="i8") + root.create_dataset("Connectivity", (0,), maxshape=(None,), dtype="i8") + + append_dataset(root["NumberOfPoints"], np.array([len(self.vertices)])) + append_dataset(root["Points"], self.vertices) + append_dataset( + root["NumberOfConnectivityIds"], + np.array([len(trimmed_connectivity)]), + ) + append_dataset(root["Connectivity"], trimmed_connectivity) + append_dataset(root["NumberOfCells"], np.array([self.n_elements])) + append_dataset(root["Offsets"], offsets) + + append_dataset( + root["Types"], np.full(self.n_elements, self._VTK_TETRA, dtype="uint8") + ) + + cell_data_group = root.create_group("CellData") + + for name, data in datasets.items(): + + cell_data_group.create_dataset( + name, (0,), maxshape=(None,), dtype="float64", chunks=True + ) + + if volume_normalization: + data /= self.volumes + append_dataset(cell_data_group[name], data) + @classmethod def from_hdf5(cls, group: h5py.Group, mesh_id: int, name: str): - filename = group['filename'][()].decode() - library = group['library'][()].decode() - if 'options' in group.attrs: + filename = group["filename"][()].decode() + library = group["library"][()].decode() + if "options" in group.attrs: options = group.attrs['options'].decode() else: options = None - mesh = cls(filename=filename, library=library, mesh_id=mesh_id, name=name, options=options) + mesh = cls( + filename=filename, + library=library, + mesh_id=mesh_id, + name=name, + options=options, + ) mesh._has_statepoint_data = True - vol_data = group['volumes'][()] + vol_data = group["volumes"][()] mesh.volumes = np.reshape(vol_data, (vol_data.shape[0],)) mesh.n_elements = mesh.volumes.size - vertices = group['vertices'][()] + vertices = group["vertices"][()] mesh._vertices = vertices.reshape((-1, 3)) - connectivity = group['connectivity'][()] + connectivity = group["connectivity"][()] mesh._connectivity = connectivity.reshape((-1, 8)) - mesh._element_types = group['element_types'][()] + mesh._element_types = group["element_types"][()] - if 'length_multiplier' in group: - mesh.length_multiplier = group['length_multiplier'][()] + if "length_multiplier" in group: + mesh.length_multiplier = group["length_multiplier"][()] return mesh @@ -2812,7 +2942,7 @@ class UnstructuredMesh(MeshBase): element.set("library", self._library) if self.options is not None: - element.set('options', self.options) + element.set("options", self.options) subelement = ET.SubElement(element, "filename") subelement.text = str(self.filename) diff --git a/tests/regression_tests/unstructured_mesh/test_mesh_dagmc_tets.vtk b/tests/regression_tests/unstructured_mesh/test_mesh_dagmc_tets.vtk new file mode 100644 index 0000000000..2ddd228cf1 --- /dev/null +++ b/tests/regression_tests/unstructured_mesh/test_mesh_dagmc_tets.vtk @@ -0,0 +1,159 @@ +# vtk DataFile Version 2.0 +made_with_cad_to_dagmc_package, Created by Gmsh 4.12.1 +ASCII +DATASET UNSTRUCTURED_GRID +POINTS 14 double +-0.5 -0.5 0.5 +-0.5 -0.5 -0.5 +-0.5 0.5 0.5 +-0.5 0.5 -0.5 +0.5 -0.5 0.5 +0.5 -0.5 -0.5 +0.5 0.5 0.5 +0.5 0.5 -0.5 +-0.5 0 0 +0.5 0 0 +0 -0.5 0 +0 0.5 0 +0 0 -0.5 +0 0 0.5 + +CELLS 68 268 +1 0 +1 1 +1 2 +1 3 +1 4 +1 5 +1 6 +1 7 +2 1 0 +2 0 2 +2 3 2 +2 1 3 +2 5 4 +2 4 6 +2 7 6 +2 5 7 +2 1 5 +2 0 4 +2 3 7 +2 2 6 +3 1 0 8 +3 0 2 8 +3 3 1 8 +3 2 3 8 +3 5 9 4 +3 4 9 6 +3 7 9 5 +3 6 9 7 +3 0 1 10 +3 4 0 10 +3 1 5 10 +3 5 4 10 +3 2 11 3 +3 6 11 2 +3 3 11 7 +3 7 11 6 +3 1 3 12 +3 5 1 12 +3 3 7 12 +3 7 5 12 +3 0 13 2 +3 4 13 0 +3 2 13 6 +3 6 13 4 +4 13 8 12 10 +4 11 8 12 13 +4 12 11 13 9 +4 10 12 13 9 +4 12 3 11 7 +4 13 2 8 0 +4 8 12 1 3 +4 11 3 8 2 +4 10 8 1 0 +4 0 10 13 4 +4 1 12 10 5 +4 11 2 13 6 +4 4 9 13 6 +4 6 9 11 7 +4 10 9 4 5 +4 7 9 12 5 +4 3 8 12 11 +4 1 12 8 10 +4 8 11 2 13 +4 10 13 8 0 +4 13 10 9 4 +4 11 13 9 6 +4 12 11 9 7 +4 9 10 12 5 + +CELL_TYPES 68 +1 +1 +1 +1 +1 +1 +1 +1 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +3 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 diff --git a/tests/unit_tests/test_mesh.py b/tests/unit_tests/test_mesh.py index f0f289408a..9aca8b5965 100644 --- a/tests/unit_tests/test_mesh.py +++ b/tests/unit_tests/test_mesh.py @@ -2,6 +2,7 @@ from math import pi from tempfile import TemporaryDirectory from pathlib import Path +import h5py import numpy as np from scipy.stats import chi2 import pytest @@ -486,6 +487,74 @@ def test_umesh(run_in_tmpdir, simple_umesh, export_type): with pytest.raises(ValueError, match='Cannot apply dataset "mean"'): simple_umesh.write_data_to_vtk(datasets={'mean': ref_data[:-2]}, filename=filename) + +@pytest.mark.skipif(not openmc.lib._dagmc_enabled(), reason="DAGMC not enabled.") +def test_write_vtkhdf(request, run_in_tmpdir): + """Performs a minimal UnstructuredMesh simulation, reads in the resulting + statepoint file and writes the mesh data to vtk and vtkhdf files. It is + necessary to read in the unstructured mesh from a statepoint file to ensure + it has all the required attributes + """ + model = openmc.Model() + + surf1 = openmc.Sphere(r=1000.0, boundary_type="vacuum") + cell1 = openmc.Cell(region=-surf1) + model.geometry = openmc.Geometry([cell1]) + + umesh = openmc.UnstructuredMesh( + request.path.parent / "test_mesh_dagmc_tets.vtk", + "moab", + mesh_id = 1 + ) + mesh_filter = openmc.MeshFilter(umesh) + + # Create flux mesh tally to score alpha production + mesh_tally = openmc.Tally(name="test_tally") + mesh_tally.filters = [mesh_filter] + mesh_tally.scores = ["flux"] + + model.tallies = [mesh_tally] + + model.settings.run_mode = "fixed source" + model.settings.batches = 2 + model.settings.particles = 10 + + statepoint_file = model.run() + + with openmc.StatePoint(statepoint_file) as statepoint: + my_tally = statepoint.get_tally(name="test_tally") + + umesh_from_sp = statepoint.meshes[umesh.id] + + datasets={ + "mean": my_tally.mean.flatten(), + "std_dev": my_tally.std_dev.flatten() + } + + umesh_from_sp.write_data_to_vtk(datasets=datasets, filename="test_mesh.vtkhdf") + umesh_from_sp.write_data_to_vtk(datasets=datasets, filename="test_mesh.vtk") + + with pytest.raises(ValueError, match="Unsupported file extension"): + # Supported file extensions are vtk or vtkhdf, not hdf5, so this should raise an error + umesh_from_sp.write_data_to_vtk( + datasets=datasets, + filename="test_mesh.hdf5", + ) + with pytest.raises(ValueError, match="Cannot apply dataset"): + # The shape of the data should match the shape of the mesh, so this should raise an error + umesh_from_sp.write_data_to_vtk( + datasets={'incorrectly_shaped_data': np.array(([1,2,3]))}, + filename="test_mesh_incorrect_shape.vtkhdf", + ) + + assert Path("test_mesh.vtk").exists() + assert Path("test_mesh.vtkhdf").exists() + + # just ensure we can open the file without error + with h5py.File("test_mesh.vtkhdf", "r"): + ... + + def test_mesh_get_homogenized_materials(): """Test the get_homogenized_materials method""" # Simple model with 1 cm of Fe56 next to 1 cm of H1 diff --git a/tests/unit_tests/test_mesh_dagmc_tets.vtk b/tests/unit_tests/test_mesh_dagmc_tets.vtk new file mode 120000 index 0000000000..9f7000175d --- /dev/null +++ b/tests/unit_tests/test_mesh_dagmc_tets.vtk @@ -0,0 +1 @@ +../regression_tests/unstructured_mesh/test_mesh_dagmc_tets.vtk \ No newline at end of file From c0f302db6845e2d303625317430b6ee26ff2cec7 Mon Sep 17 00:00:00 2001 From: Perry <100789850+yrrepy@users.noreply.github.com> Date: Fri, 7 Nov 2025 08:58:40 -0800 Subject: [PATCH 42/76] Add energy group structure: SCALE-999 (#3564) --- openmc/mgxs/__init__.py | 208 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 3 deletions(-) diff --git a/openmc/mgxs/__init__.py b/openmc/mgxs/__init__.py index 5de85afb0e..682b5d5507 100644 --- a/openmc/mgxs/__init__.py +++ b/openmc/mgxs/__init__.py @@ -13,8 +13,8 @@ GROUP_STRUCTURES = {} - "XMAS-172_" designed for LWR analysis ([SAR1990]_, [SAN2004]_) - "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_) -- "SCALE-X" (where X is 44 which is designed for criticality analysis - and 252 is designed for thermal reactors) for the SCALE code suite +- "SCALE-X" (where X is 44 which is designed for criticality analysis, 252 is designed + for thermal reactors and 999 for multipurpose activation) for the SCALE code suite ([ZAL1999]_ and [REARDEN2013]_) - "MPACT-X" (where X is 51 (PWR), 60 (BWR), 69 (Magnox)) from the MPACT_ reactor physics code ([KIM2019]_ and [KIM2020]_) @@ -29,6 +29,7 @@ GROUP_STRUCTURES = {} .. _SCALE44: https://www-nds.iaea.org/publications/indc/indc-czr-0001.pdf .. _ECCO-33: https://serpent.vtt.fi/mediawiki/index.php/ECCO_33-group_structure .. _SCALE252: https://oecd-nea.org/science/wpncs/amct/workingarea/meeting2013/EGAMCT2013_08.pdf +.. _SCALE999: https://info.ornl.gov/sites/publications/Files/Pub67728.pdf, https://www.nrc.gov/docs/ML1218/ML12184A002.pdf .. _MPACT: https://vera.ornl.gov/mpact/ .. _XMAS-172: https://www-nds.iaea.org/wimsd/energy.htm .. _SHEM-361: http://merlin.polymtl.ca/downloads/FP214.pdf @@ -593,7 +594,208 @@ GROUP_STRUCTURES['CCFE-709'] = np.array([ 2.4000e8, 2.8000e8, 3.2000e8, 3.6000e8, 4.0000e8, 4.4000e8, 4.8000e8, 5.2000e8, 5.6000e8, 6.0000e8, 6.4000e8, 6.8000e8, 7.2000e8, 7.6000e8, 8.0000e8, - 8.4000e8, 8.8000e8, 9.2000e8, 9.6000e8, 1.0000e9,]) + 8.4000e8, 8.8000e8, 9.2000e8, 9.6000e8, 1.0000e9]) +GROUP_STRUCTURES['SCALE-999'] = np.array([ + 1.000e-5, 1.000e-4, 5.000e-4, 7.500e-4, 1.000e-3, + 1.200e-3, 1.500e-3, 2.000e-3, 2.500e-3, 3.000e-3, + 4.000e-3, 5.000e-3, 7.500e-3, 1.000e-2, 1.450e-2, + 1.850e-2, 2.100e-2, 2.530e-2, 3.000e-2, 4.000e-2, + 5.000e-2, 6.000e-2, 7.000e-2, 8.000e-2, 9.000e-2, + 1.000e-1, 1.250e-1, 1.500e-1, 1.750e-1, 1.840e-1, + 2.000e-1, 2.250e-1, 2.500e-1, 2.750e-1, 3.000e-1, + 3.250e-1, 3.500e-1, 3.668e-1, 3.750e-1, 4.000e-1, + 4.140e-1, 4.500e-1, 5.000e-1, 5.316e-1, 5.500e-1, + 6.000e-1, 6.250e-1, 6.500e-1, 6.826e-1, 7.000e-1, + 7.500e-1, 8.000e-1, 8.500e-1, 8.764e-1, 9.000e-1, + 9.250e-1, 9.500e-1, 9.750e-1, 1.000e+0, 1.010e+0, + 1.020e+0, 1.030e+0, 1.040e+0, 1.050e+0, 1.060e+0, + 1.070e+0, 1.080e+0, 1.090e+0, 1.100e+0, 1.110e+0, + 1.120e+0, 1.130e+0, 1.140e+0, 1.150e+0, 1.175e+0, + 1.200e+0, 1.225e+0, 1.250e+0, 1.300e+0, 1.350e+0, + 1.400e+0, 1.450e+0, 1.500e+0, 1.545e+0, 1.590e+0, + 1.635e+0, 1.680e+0, 1.725e+0, 1.770e+0, 1.815e+0, + 1.860e+0, 1.900e+0, 1.940e+0, 1.970e+0, 2.000e+0, + 2.060e+0, 2.120e+0, 2.165e+0, 2.210e+0, 2.255e+0, + 2.300e+0, 2.340e+0, 2.380e+0, 2.425e+0, 2.470e+0, + 2.520e+0, 2.570e+0, 2.620e+0, 2.670e+0, 2.720e+0, + 2.770e+0, 2.820e+0, 2.870e+0, 2.920e+0, 2.970e+0, + 3.000e+0, 3.100e+0, 3.200e+0, 3.300e+0, 3.500e+0, + 3.620e+0, 3.730e+0, 3.830e+0, 3.928e+0, 4.000e+0, + 4.100e+0, 4.300e+0, 4.500e+0, 4.750e+0, 4.875e+0, + 5.000e+0, 5.044e+0, 5.250e+0, 5.400e+0, 5.550e+0, + 5.700e+0, 5.850e+0, 6.000e+0, 6.250e+0, 6.375e+0, + 6.500e+0, 6.625e+0, 6.750e+0, 6.875e+0, 7.000e+0, + 7.075e+0, 7.150e+0, 7.625e+0, 8.100e+0, 8.208e+0, + 8.315e+0, 8.708e+0, 9.100e+0, 9.550e+0, 1.000e+1, + 1.034e+1, 1.068e+1, 1.109e+1, 1.150e+1, 1.170e+1, + 1.190e+1, 1.240e+1, 1.290e+1, 1.333e+1, 1.375e+1, + 1.408e+1, 1.440e+1, 1.475e+1, 1.510e+1, 1.555e+1, + 1.600e+1, 1.650e+1, 1.700e+1, 1.730e+1, 1.760e+1, + 1.805e+1, 1.850e+1, 1.875e+1, 1.900e+1, 1.940e+1, + 2.000e+1, 2.050e+1, 2.100e+1, 2.175e+1, 2.250e+1, + 2.375e+1, 2.500e+1, 2.625e+1, 2.750e+1, 2.826e+1, + 2.902e+1, 2.951e+1, 3.000e+1, 3.063e+1, 3.125e+1, + 3.150e+1, 3.175e+1, 3.250e+1, 3.325e+1, 3.350e+1, + 3.375e+1, 3.418e+1, 3.460e+1, 3.500e+1, 3.550e+1, + 3.600e+1, 3.700e+1, 3.713e+1, 3.727e+1, 3.763e+1, + 3.800e+1, 3.855e+1, 3.910e+1, 3.935e+1, 3.960e+1, + 4.030e+1, 4.100e+1, 4.170e+1, 4.240e+1, 4.320e+1, + 4.400e+1, 4.460e+1, 4.520e+1, 4.610e+1, 4.700e+1, + 4.743e+1, 4.785e+1, 4.808e+1, 4.830e+1, 4.875e+1, + 4.920e+1, 4.990e+1, 5.060e+1, 5.130e+1, 5.200e+1, + 5.270e+1, 5.340e+1, 5.620e+1, 5.800e+1, 6.000e+1, + 6.100e+1, 6.122e+1, 6.144e+1, 6.300e+1, 6.500e+1, + 6.625e+1, 6.750e+1, 6.975e+1, 7.200e+1, 7.400e+1, + 7.600e+1, 7.745e+1, 7.889e+1, 7.945e+1, 8.000e+1, + 8.170e+1, 8.200e+1, 8.400e+1, 8.600e+1, 8.800e+1, + 9.000e+1, 9.250e+1, 9.500e+1, 9.700e+1, 1.000e+2, + 1.012e+2, 1.038e+2, 1.050e+2, 1.080e+2, 1.105e+2, + 1.130e+2, 1.160e+2, 1.175e+2, 1.190e+2, 1.205e+2, + 1.220e+2, 1.240e+2, 1.260e+2, 1.280e+2, 1.301e+2, + 1.325e+2, 1.350e+2, 1.375e+2, 1.400e+2, 1.430e+2, + 1.450e+2, 1.475e+2, 1.500e+2, 1.525e+2, 1.550e+2, + 1.575e+2, 1.600e+2, 1.625e+2, 1.650e+2, 1.670e+2, + 1.700e+2, 1.716e+2, 1.739e+2, 1.763e+2, 1.786e+2, + 1.800e+2, 1.877e+2, 1.885e+2, 1.915e+2, 1.930e+2, + 1.962e+2, 1.999e+2, 2.020e+2, 2.074e+2, 2.088e+2, + 2.095e+2, 2.122e+2, 2.145e+2, 2.175e+2, 2.200e+2, + 2.237e+2, 2.269e+2, 2.301e+2, 2.333e+2, 2.367e+2, + 2.400e+2, 2.442e+2, 2.484e+2, 2.527e+2, 2.571e+2, + 2.615e+2, 2.661e+2, 2.707e+2, 2.754e+2, 2.801e+2, + 2.850e+2, 2.899e+2, 2.948e+2, 2.999e+2, 3.050e+2, + 3.107e+2, 3.165e+2, 3.224e+2, 3.284e+2, 3.345e+2, + 3.408e+2, 3.471e+2, 3.536e+2, 3.591e+2, 3.648e+2, + 3.705e+2, 3.764e+2, 3.823e+2, 3.883e+2, 3.944e+2, + 4.007e+2, 4.070e+2, 4.134e+2, 4.199e+2, 4.265e+2, + 4.332e+2, 4.400e+2, 4.470e+2, 4.540e+2, 4.595e+2, + 4.650e+2, 4.706e+2, 4.763e+2, 4.821e+2, 4.879e+2, + 4.937e+2, 4.997e+2, 5.057e+2, 5.118e+2, 5.180e+2, + 5.243e+2, 5.306e+2, 5.370e+2, 5.435e+2, 5.500e+2, + 5.581e+2, 5.662e+2, 5.745e+2, 5.830e+2, 5.932e+2, + 6.036e+2, 6.142e+2, 6.250e+2, 6.359e+2, 6.471e+2, + 6.585e+2, 6.700e+2, 6.765e+2, 6.830e+2, 6.909e+2, + 6.988e+2, 7.069e+2, 7.150e+2, 7.232e+2, 7.316e+2, + 7.400e+2, 7.485e+2, 7.598e+2, 7.712e+2, 7.827e+2, + 7.945e+2, 8.064e+2, 8.185e+2, 8.308e+2, 8.433e+2, + 8.559e+2, 8.688e+2, 8.818e+2, 8.950e+2, 9.085e+2, + 9.221e+2, 9.360e+2, 9.500e+2, 9.555e+2, 9.611e+2, + 9.720e+2, 9.829e+2, 9.940e+2, 1.005e+3, 1.017e+3, + 1.028e+3, 1.040e+3, 1.051e+3, 1.063e+3, 1.075e+3, + 1.087e+3, 1.100e+3, 1.112e+3, 1.125e+3, 1.137e+3, + 1.150e+3, 1.171e+3, 1.191e+3, 1.213e+3, 1.234e+3, + 1.249e+3, 1.265e+3, 1.280e+3, 1.296e+3, 1.312e+3, + 1.328e+3, 1.344e+3, 1.361e+3, 1.377e+3, 1.394e+3, + 1.411e+3, 1.429e+3, 1.446e+3, 1.464e+3, 1.482e+3, + 1.500e+3, 1.525e+3, 1.550e+3, 1.585e+3, 1.610e+3, + 1.636e+3, 1.662e+3, 1.689e+3, 1.716e+3, 1.744e+3, + 1.772e+3, 1.800e+3, 1.828e+3, 1.856e+3, 1.885e+3, + 1.914e+3, 1.943e+3, 1.973e+3, 2.004e+3, 2.035e+3, + 2.075e+3, 2.116e+3, 2.158e+3, 2.200e+3, 2.250e+3, + 2.290e+3, 2.337e+3, 2.386e+3, 2.435e+3, 2.500e+3, + 2.532e+3, 2.580e+3, 2.613e+3, 2.679e+3, 2.747e+3, + 2.808e+3, 2.871e+3, 2.935e+3, 3.000e+3, 3.035e+3, + 3.112e+3, 3.191e+3, 3.272e+3, 3.355e+3, 3.440e+3, + 3.527e+3, 3.616e+3, 3.707e+3, 3.740e+3, 3.819e+3, + 3.900e+3, 3.998e+3, 4.099e+3, 4.202e+3, 4.307e+3, + 4.400e+3, 4.500e+3, 4.620e+3, 4.740e+3, 4.850e+3, + 4.960e+3, 5.100e+3, 5.250e+3, 5.400e+3, 5.531e+3, + 5.645e+3, 5.700e+3, 5.879e+3, 6.000e+3, 6.128e+3, + 6.258e+3, 6.392e+3, 6.528e+3, 6.667e+3, 6.809e+3, + 6.954e+3, 7.102e+3, 7.212e+3, 7.323e+3, 7.437e+3, + 7.552e+3, 7.669e+3, 7.787e+3, 7.908e+3, 8.030e+3, + 8.159e+3, 8.289e+3, 8.422e+3, 8.557e+3, 8.694e+3, + 8.834e+3, 8.975e+3, 9.119e+3, 9.307e+3, 9.500e+3, + 9.763e+3, 1.003e+4, 1.031e+4, 1.060e+4, 1.086e+4, + 1.114e+4, 1.142e+4, 1.171e+4, 1.202e+4, 1.234e+4, + 1.266e+4, 1.300e+4, 1.324e+4, 1.348e+4, 1.373e+4, + 1.398e+4, 1.424e+4, 1.450e+4, 1.476e+4, 1.503e+4, + 1.527e+4, 1.550e+4, 1.574e+4, 1.599e+4, 1.623e+4, + 1.649e+4, 1.674e+4, 1.700e+4, 1.727e+4, 1.755e+4, + 1.783e+4, 1.812e+4, 1.841e+4, 1.870e+4, 1.900e+4, + 1.931e+4, 1.965e+4, 2.000e+4, 2.045e+4, 2.092e+4, + 2.139e+4, 2.188e+4, 2.229e+4, 2.271e+4, 2.314e+4, + 2.358e+4, 2.388e+4, 2.418e+4, 2.450e+4, 2.479e+4, + 2.500e+4, 2.520e+4, 2.552e+4, 2.580e+4, 2.606e+4, + 2.653e+4, 2.700e+4, 2.737e+4, 2.774e+4, 2.812e+4, + 2.850e+4, 2.887e+4, 2.924e+4, 2.962e+4, 3.000e+4, + 3.045e+4, 3.090e+4, 3.136e+4, 3.183e+4, 3.243e+4, + 3.304e+4, 3.367e+4, 3.431e+4, 3.468e+4, 3.507e+4, + 3.545e+4, 3.584e+4, 3.624e+4, 3.663e+4, 3.704e+4, + 3.744e+4, 3.786e+4, 3.827e+4, 3.869e+4, 3.912e+4, + 3.955e+4, 3.998e+4, 4.042e+4, 4.087e+4, 4.136e+4, + 4.186e+4, 4.237e+4, 4.288e+4, 4.340e+4, 4.393e+4, + 4.446e+4, 4.500e+4, 4.565e+4, 4.631e+4, 4.721e+4, + 4.812e+4, 4.905e+4, 5.000e+4, 5.099e+4, 5.200e+4, + 5.248e+4, 5.347e+4, 5.448e+4, 5.551e+4, 5.656e+4, + 5.740e+4, 5.826e+4, 5.912e+4, 6.000e+4, 6.088e+4, + 6.177e+4, 6.267e+4, 6.358e+4, 6.451e+4, 6.545e+4, + 6.641e+4, 6.738e+4, 6.851e+4, 6.965e+4, 7.081e+4, + 7.200e+4, 7.300e+4, 7.399e+4, 7.500e+4, 7.610e+4, + 7.722e+4, 7.835e+4, 7.950e+4, 8.074e+4, 8.200e+4, + 8.250e+4, 8.374e+4, 8.500e+4, 8.652e+4, 8.788e+4, + 8.926e+4, 9.067e+4, 9.210e+4, 9.355e+4, 9.502e+4, + 9.652e+4, 9.804e+4, 1.000e+5, 1.013e+5, 1.027e+5, + 1.040e+5, 1.054e+5, 1.068e+5, 1.082e+5, 1.096e+5, + 1.111e+5, 1.125e+5, 1.139e+5, 1.153e+5, 1.168e+5, + 1.183e+5, 1.197e+5, 1.213e+5, 1.228e+5, 1.241e+5, + 1.255e+5, 1.269e+5, 1.283e+5, 1.291e+5, 1.307e+5, + 1.323e+5, 1.340e+5, 1.357e+5, 1.374e+5, 1.391e+5, + 1.409e+5, 1.426e+5, 1.445e+5, 1.463e+5, 1.481e+5, + 1.490e+5, 1.519e+5, 1.538e+5, 1.557e+5, 1.576e+5, + 1.596e+5, 1.616e+5, 1.637e+5, 1.657e+5, 1.678e+5, + 1.699e+5, 1.721e+5, 1.742e+5, 1.764e+5, 1.786e+5, + 1.809e+5, 1.832e+5, 1.855e+5, 1.878e+5, 1.902e+5, + 1.926e+5, 1.962e+5, 2.000e+5, 2.024e+5, 2.050e+5, + 2.076e+5, 2.102e+5, 2.128e+5, 2.155e+5, 2.182e+5, + 2.209e+5, 2.237e+5, 2.265e+5, 2.294e+5, 2.323e+5, + 2.352e+5, 2.381e+5, 2.411e+5, 2.442e+5, 2.472e+5, + 2.500e+5, 2.527e+5, 2.555e+5, 2.584e+5, 2.612e+5, + 2.641e+5, 2.670e+5, 2.700e+5, 2.732e+5, 2.767e+5, + 2.802e+5, 2.837e+5, 2.873e+5, 2.909e+5, 2.945e+5, + 2.972e+5, 2.985e+5, 3.020e+5, 3.053e+5, 3.088e+5, + 3.122e+5, 3.157e+5, 3.192e+5, 3.228e+5, 3.264e+5, + 3.300e+5, 3.337e+5, 3.379e+5, 3.422e+5, 3.465e+5, + 3.508e+5, 3.553e+5, 3.597e+5, 3.643e+5, 3.688e+5, + 3.735e+5, 3.782e+5, 3.829e+5, 3.877e+5, 3.938e+5, + 4.000e+5, 4.076e+5, 4.138e+5, 4.200e+5, 4.249e+5, + 4.299e+5, 4.349e+5, 4.400e+5, 4.452e+5, 4.505e+5, + 4.553e+5, 4.601e+5, 4.650e+5, 4.700e+5, 4.772e+5, + 4.845e+5, 4.920e+5, 4.995e+5, 5.054e+5, 5.113e+5, + 5.173e+5, 5.234e+5, 5.299e+5, 5.365e+5, 5.432e+5, + 5.500e+5, 5.557e+5, 5.614e+5, 5.672e+5, 5.730e+5, + 5.784e+5, 5.891e+5, 6.000e+5, 6.081e+5, 6.158e+5, + 6.235e+5, 6.313e+5, 6.393e+5, 6.468e+5, 6.545e+5, + 6.622e+5, 6.700e+5, 6.790e+5, 6.926e+5, 7.065e+5, + 7.154e+5, 7.244e+5, 7.335e+5, 7.427e+5, 7.500e+5, + 7.576e+5, 7.653e+5, 7.730e+5, 7.808e+5, 7.904e+5, + 8.002e+5, 8.100e+5, 8.200e+5, 8.301e+5, 8.403e+5, + 8.506e+5, 8.611e+5, 8.750e+5, 8.874e+5, 9.000e+5, + 9.072e+5, 9.200e+5, 9.400e+5, 9.616e+5, 9.800e+5, + 1.003e+6, 1.010e+6, 1.040e+6, 1.070e+6, 1.100e+6, + 1.108e+6, 1.136e+6, 1.165e+6, 1.200e+6, 1.225e+6, + 1.250e+6, 1.287e+6, 1.317e+6, 1.356e+6, 1.400e+6, + 1.423e+6, 1.461e+6, 1.500e+6, 1.536e+6, 1.572e+6, + 1.612e+6, 1.653e+6, 1.695e+6, 1.738e+6, 1.782e+6, + 1.827e+6, 1.850e+6, 1.921e+6, 1.969e+6, 2.019e+6, + 2.070e+6, 2.123e+6, 2.176e+6, 2.231e+6, 2.307e+6, + 2.354e+6, 2.365e+6, 2.385e+6, 2.466e+6, 2.479e+6, + 2.535e+6, 2.592e+6, 2.658e+6, 2.725e+6, 2.794e+6, + 2.865e+6, 2.932e+6, 3.000e+6, 3.080e+6, 3.166e+6, + 3.247e+6, 3.329e+6, 3.413e+6, 3.499e+6, 3.588e+6, + 3.679e+6, 3.772e+6, 3.867e+6, 3.965e+6, 4.066e+6, + 4.183e+6, 4.304e+6, 4.398e+6, 4.493e+6, 4.607e+6, + 4.724e+6, 4.800e+6, 4.882e+6, 4.966e+6, 5.092e+6, + 5.221e+6, 5.353e+6, 5.488e+6, 5.627e+6, 5.770e+6, + 5.916e+6, 6.065e+6, 6.219e+6, 6.376e+6, 6.434e+6, + 6.592e+6, 6.703e+6, 6.873e+6, 7.047e+6, 7.225e+6, + 7.408e+6, 7.596e+6, 7.788e+6, 7.985e+6, 8.187e+6, + 8.395e+6, 8.607e+6, 8.825e+6, 9.048e+6, 9.278e+6, + 9.512e+6, 9.753e+6, 1.000e+7, 1.025e+7, 1.051e+7, + 1.078e+7, 1.105e+7, 1.133e+7, 1.162e+7, 1.191e+7, + 1.221e+7, 1.252e+7, 1.284e+7, 1.317e+7, 1.350e+7, + 1.384e+7, 1.419e+7, 1.455e+7, 1.492e+7, 1.530e+7, + 1.568e+7, 1.608e+7, 1.649e+7, 1.691e+7, 1.733e+7, + 1.790e+7, 1.845e+7, 1.900e+7, 1.964e+7, 2.000e+7]) GROUP_STRUCTURES['UKAEA-1102'] = np.array([ 1.0000e-5, 1.0471e-5, 1.0965e-5, 1.1482e-5, 1.2023e-5, 1.2589e-5, 1.3183e-5, 1.3804e-5, 1.4454e-5, 1.5136e-5, From 8cd3911cbe0fa277b889effa1c5c1566b0683f55 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 12 Nov 2025 00:01:18 -0600 Subject: [PATCH 43/76] Reset DAGMC history when reviving from source. (#3601) Co-authored-by: Paul Romano --- src/particle.cpp | 3 + .../weightwindows/dagmc/__init__.py | 0 .../dagmc/nested_shell_geometry.h5m | Bin 0 -> 58680 bytes tests/unit_tests/weightwindows/dagmc/test.py | 98 ++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 tests/unit_tests/weightwindows/dagmc/__init__.py create mode 100644 tests/unit_tests/weightwindows/dagmc/nested_shell_geometry.h5m create mode 100644 tests/unit_tests/weightwindows/dagmc/test.py diff --git a/src/particle.cpp b/src/particle.cpp index 6b4c332a8b..6ba8ebf128 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -121,6 +121,9 @@ void Particle::from_source(const SourceSite* src) fission() = false; zero_flux_derivs(); lifetime() = 0.0; +#ifdef OPENMC_DAGMC_ENABLED + history().reset(); +#endif // Copy attributes from source bank site type() = src->particle; diff --git a/tests/unit_tests/weightwindows/dagmc/__init__.py b/tests/unit_tests/weightwindows/dagmc/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/unit_tests/weightwindows/dagmc/nested_shell_geometry.h5m b/tests/unit_tests/weightwindows/dagmc/nested_shell_geometry.h5m new file mode 100644 index 0000000000000000000000000000000000000000..af1d5563d9255b518d42b551b7527cdf45eeaaf3 GIT binary patch literal 58680 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 ZKJ@mkzRs4Wo;}NVH#PV5?Swso{}1hu%5MMw literal 0 HcmV?d00001 diff --git a/tests/unit_tests/weightwindows/dagmc/test.py b/tests/unit_tests/weightwindows/dagmc/test.py new file mode 100644 index 0000000000..ed01a93ed3 --- /dev/null +++ b/tests/unit_tests/weightwindows/dagmc/test.py @@ -0,0 +1,98 @@ +import pytest + +import openmc +import openmc.lib + +pytestmark = pytest.mark.skipif( + not openmc.lib._dagmc_enabled(), + reason="DAGMC CAD geometry is not enabled.", +) + + +def test_dagmc_weight_windows_near_boundary(run_in_tmpdir, request): + """Ensure splitting near a boundary doesn't lose particles due to + a stale DAGMC history on the particle object.""" + + # DAGMC model overview: + # * Three nested cubes; innermost cube contains a fusion neutron source. + # * Two outer cubes filled with tungsten. Weight windows defined on a mesh + # cause particles to split moving outward. + # Outer cubes are similar in size (outer slightly larger) so particles + # frequently cross the problem boundary immediately after splitting. No lost + # particles are allowed to the correct DAGMC history after splitting is used. + model = openmc.Model() + + dagmc_file = request.path.parent / 'nested_shell_geometry.h5m' + dagmc_univ = openmc.DAGMCUniverse(dagmc_file) + model.geometry = openmc.Geometry(dagmc_univ) + + tungsten = openmc.Material(name='shell') + tungsten.add_element('W', 1.0) + tungsten.set_density('g/cm3', 7.8) + materials = openmc.Materials([tungsten]) + model.materials = materials + + settings = openmc.Settings() + settings.output = {'tallies': False, 'summary': False} + + source = openmc.IndependentSource() + source.space = openmc.stats.Point((0.0, 0.0, 0.0)) + source.angle = openmc.stats.Isotropic() + source.energy = openmc.stats.Discrete([14.1e6], [1.0]) + settings.source = source + + settings.batches = 2 + settings.particles = 500 + settings.run_mode = 'fixed source' + settings.survival_biasing = False + settings.max_lost_particles = 1 + settings.max_history_splits = 10_000_000 + + settings.weight_window_checkpoints = { + 'surface': True, + 'collision': True, + } + + mesh = openmc.RegularMesh() + mesh.lower_left = (-60.0, -60.0, -60.0) + mesh.upper_right = (60.0, 60.0, 60.0) + mesh.dimension = (24, 1, 1) + + weight_windows_lower = [ + 0.030750733294361156, + 0.056110505674355333, + 0.08187875047968339, + 0.1101743496347699, + 0.13982370013053508, + 0.17443799246829372, + 0.21576286623367483, + 0.26416659508033646, + 0.318574932646899, + 0.3804031702117963, + 0.42899359749256355, + 0.4954283294279403, + 0.49999999999999994, + 0.43432341070872266, + 0.38302303850488206, + 0.32148375935490886, + 0.2637416945702018, + 0.21498369367288853, + 0.17163611765361744, + 0.13832102142074995, + 0.10717772257151495, + 0.07986176041282561, + 0.05499644859408233, + 0.03058023506703803, + ] + + weight_windows = openmc.WeightWindows( + mesh, + lower_ww_bounds=weight_windows_lower, + upper_bound_ratio=5.0, + ) + weight_windows.max_lower_bound_ratio = 1.0 + settings.weight_windows = weight_windows + settings.weight_windows_on = True + model.settings = settings + + model.run() \ No newline at end of file From 5c2bfe771eb94c759923c63be5ba3eb01a6b3ec9 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 12 Nov 2025 00:29:19 -0600 Subject: [PATCH 44/76] Write particle states as separate lines in track VTK files. (#3628) --- openmc/tracks.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openmc/tracks.py b/openmc/tracks.py index 61e5a72442..81646e7d2e 100644 --- a/openmc/tracks.py +++ b/openmc/tracks.py @@ -296,16 +296,16 @@ class Tracks(list): for state in pt.states: points.InsertNextPoint(state['r']) - # Create VTK line and assign points to line. - n = pt.states.size - line = vtk.vtkPolyLine() - line.GetPointIds().SetNumberOfIds(n) - for i in range(n): - line.GetPointIds().SetId(i, point_offset + i) - point_offset += n + # Create VTK line and assign points to line. + n = pt.states.size + line = vtk.vtkPolyLine() + line.GetPointIds().SetNumberOfIds(n) + for i in range(n): + line.GetPointIds().SetId(i, point_offset + i) + point_offset += n - # Add line to cell array - cells.InsertNextCell(line) + # Add line to cell array + cells.InsertNextCell(line) data = vtk.vtkPolyData() data.SetPoints(points) From e5348d3f62a821f84513a026977eef0f8bef01ad Mon Sep 17 00:00:00 2001 From: Marco De Pietri Date: Wed, 12 Nov 2025 05:35:07 -0500 Subject: [PATCH 45/76] Avoid divide-by-zero in `from_multigroup_flux` when flux is zero (#3624) Co-authored-by: Paul Romano --- openmc/deplete/microxs.py | 12 ++++++++---- tests/unit_tests/test_deplete_microxs.py | 13 +++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index e351c923df..d7624955e8 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -356,13 +356,17 @@ class MicroXS: reactions = chain.reactions mts = [REACTION_MT[name] for name in reactions] - # Normalize multigroup flux - multigroup_flux = np.array(multigroup_flux) - multigroup_flux /= multigroup_flux.sum() - # Create 3D array for microscopic cross sections microxs_arr = np.zeros((len(nuclides), len(mts), 1)) + # If flux is zero, safely return zero cross sections + multigroup_flux = np.array(multigroup_flux) + if (flux_sum := multigroup_flux.sum()) == 0.0: + return cls(microxs_arr, nuclides, reactions) + + # Normalize multigroup flux + multigroup_flux /= flux_sum + # Compute microscopic cross sections within a temporary session with openmc.lib.TemporarySession(**init_kwargs): # For each nuclide and reaction, compute the flux-averaged xs diff --git a/tests/unit_tests/test_deplete_microxs.py b/tests/unit_tests/test_deplete_microxs.py index 073b3f162d..5762a8511b 100644 --- a/tests/unit_tests/test_deplete_microxs.py +++ b/tests/unit_tests/test_deplete_microxs.py @@ -111,3 +111,16 @@ def test_multigroup_flux_same(): energies=energies, multigroup_flux=flux, chain_file=chain_file) assert microxs_4g.data == pytest.approx(microxs_2g.data) + + +def test_microxs_zero_flux(): + chain_file = Path(__file__).parents[1] / 'chain_simple.xml' + + # Generate micro XS based on zero flux + energies = [0., 6.25e-1, 5.53e3, 8.21e5, 2.e7] + flux = [0.0, 0.0, 0.0, 0.0] + microxs = MicroXS.from_multigroup_flux( + energies=energies, multigroup_flux=flux, chain_file=chain_file) + + # All microscopic cross sections should be zero + assert np.all(microxs.data == 0.0) From 2d77544b0c045f7e693146dc466e5cc290fbdc49 Mon Sep 17 00:00:00 2001 From: Gregoire Biot Date: Wed, 12 Nov 2025 11:41:37 -0500 Subject: [PATCH 46/76] Adding variance of variance and normality tests for tally statistics (#3454) Co-authored-by: Ethan Peterson Co-authored-by: Paul Romano --- docs/source/io_formats/statepoint.rst | 2 + docs/source/methods/tallies.rst | 107 +++++- include/openmc/constants.h | 2 +- include/openmc/hdf5_interface.h | 10 +- include/openmc/tallies/tally.h | 5 + openmc/statepoint.py | 4 + openmc/tallies.py | 524 +++++++++++++++++++++++++- src/hdf5_interface.cpp | 16 +- src/state_point.cpp | 17 +- src/tallies/tally.cpp | 42 ++- src/weight_windows.cpp | 8 +- tests/unit_tests/test_tallies.py | 213 +++++++++++ 12 files changed, 915 insertions(+), 35 deletions(-) diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index 3b10317696..2309643dc8 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -149,6 +149,8 @@ The current version of the statepoint file format is 18.1. tallies will have a value of 0 unless otherwise instructed. - **multiply_density** (*int*) -- Flag indicating whether reaction rates should be multiplied by atom density (1) or not (0). + - **higher_moments** (*int*) -- Flag indicating whether + higher-order tally moments are enabled (1) or not (0). :Datasets: - **n_realizations** (*int*) -- Number of realizations. - **n_filters** (*int*) -- Number of filters used. diff --git a/docs/source/methods/tallies.rst b/docs/source/methods/tallies.rst index 79a63fbdd8..27a3f873ab 100644 --- a/docs/source/methods/tallies.rst +++ b/docs/source/methods/tallies.rst @@ -387,6 +387,101 @@ of this is that the longer you run a simulation, the better you know your results. Therefore, by running a simulation long enough, it is possible to reduce the stochastic uncertainty to arbitrarily low levels. +Skewness +++++++++ + +The `skewness`_ of a population quantifies the asymmetry of the probability +distribution around its mean. Positive and negative skewness indicate a +longer/heavier right and left tail respectively. Let :math:`x_1,\ldots,x_n` be +the per-realization values for a bin, with sample mean :math:`\bar{x}` and +sample central moments: + +.. math:: + + m_k \;=\; \frac{1}{n}\sum_{i=1}^{n}\bigl(x_i-\bar{x}\bigr)^k. + +OpenMC reports the *adjusted Fisher-Pearson skewness* (defined for :math:`n \ge +3`), which is commonly used in many statistical packages: + +.. math:: + + G_1 \;=\; \frac{\sqrt{n \cdot (n-1)}}{\,n-2\,}\cdot\frac{m_3}{m_2^{3/2}}. + +where :math:`m_2` and :math:`m_3` correspond to the biased sample second and +third central moment respectively. + +Kurtosis +++++++++ + +The `kurtosis`_ of a population quantifies tail weight (also called tailedness) +of the probability distribution relative to a normal distribution. Positive +excess kurtosis indicates *heavier tails* whereas negative excess kurtosis +indicates *lighter tails*. Kurtosis is especially useful for identifying bins +where occasional extreme scores dominate uncertainty. OpenMC reports the +*adjusted excess kurtosis* (defined for :math:`n \ge 4`): + +.. math:: + + G_2 \;=\; \frac{(n-1)}{(n-2)(n-3)} + \left[(n+1)\,\frac{m_4}{m_2^{2}} \;-\; 3(n-1)\right]. + +where :math:`m_2` and :math:`m_4` correspond to the biased sample second and +fourth central moment respectively. For a perfectly normal distribution, the +excess kurtosis is :math:`0`. + +Variance of Variance +++++++++++++++++++++ + +The variance of the variance (also known as the coefficient of variation +squared) measures *stability of the sample variance* :math:`s^2` and, by +extension, the reliability of reported relative errors. High VOV means that +error bars themselves are noisy—often due to heavy tails, skewness, or too few +realizations. + +.. math:: + + VOV = \frac{s^2(s_{\bar{X}}^2)}{s_{\bar{X}}^4 } = \frac{m_4}{m_2^2} - \frac{1}{n} + +where :math:`s_{\bar{X}}^2` is the estimated variance of the mean and +:math:`s^2(s_{\bar{X}}^2)` is the estimated variance in :math:`s_{\bar{X}}^2`. +The MCNP manual suggests a hard threshold such that :math:`VOV < 0.1` to improve +the probability of forming a reliable confidence interval. However, OpenMC does +not enforce an universal cut-off because the suitability of any single threshold +depends strongly on problem specifics (estimator choice, variance-reduction +settings, tally binning, or even effective sample size). + + +Normality Tests (D'Agostino-Pearson) +++++++++++++++++++++++++++++++++++++ + +These normality test verify the hypothesis that fluctuations are *approximately +normal*, a working assumption behind many Monte Carlo diagnostics and +`confidence-interval heuristics`_. Tests are provided for: (i) skewness-only, +(ii) kurtosis-only, and (iii) the *omnibus* combination. OpenMC uses the +finite-sample-adjusted skewness :math:`G_1` and excess kurtosis :math:`G_2` +above to construct standardized normal scores :math:`Z_1` (from :math:`G_1`) and +:math:`Z_2` (from :math:`G_2`) via the D'Agostino-Pearson transformations. The +omnibus statistic is + +.. math:: + + K^2 \;=\; Z_1^{\,2} \;+\; Z_2^{\,2} + \;\sim\; \chi^2_{(2)} \quad \text{under } H_0:\ \text{normality}. + +OpenMC reports :math:`Z_1`, :math:`Z_2`, :math:`K^2`, and their p-values when +prerequisites are met (skewness for :math:`n\ge 3`, kurtosis and omnibus for +:math:`n\ge 4`). Given a user-chosen significance level :math:`\alpha` (default +is :math:`0.05`), reject :math:`H_0` if :math:`\text{p-value}<\alpha`; otherwise +fail to reject. OpenMC leaves the interpretation to the user, who should +consider VOV together with skewness, kurtosis, and normality tests results when +judging whether reported confidence intervals are credible for their application +[#norm-tests]_. + +.. [#norm-tests] + Higher-moments accumulation must be enabled with ``higher_moments = True`` + for running these diagnostics including the skewness, kurtosis, and normality + tests. + Figure of Merit +++++++++++++++ @@ -405,14 +500,16 @@ defined as .. math:: :label: relative_error - r = \frac{s_\bar{X}}{\bar{x}}. + r = \frac{s_{\bar{X}}}{\bar{x}}. Based on this definition, one can see that a higher FOM is desirable. The FOM is useful as a comparative tool. For example, if a variance reduction technique is being applied to a simulation, the FOM with variance reduction can be compared to the FOM without variance reduction to ascertain whether the reduction in variance outweighs the potential increase in execution time (e.g., due to -particle splitting). +particle splitting). It is important to note that MCNP reports the FOM using CPU +time (wall-clock time multiplied by the number of threads/cores), whereas OpenMC +reports the FOM using only the wall-clock time :math:`t`. Confidence Intervals ++++++++++++++++++++ @@ -521,6 +618,8 @@ improve the estimate of the percentile. .. rubric:: References +.. _confidence-interval heuristics: https://doi.org/10.1080/00031305.1990.10475751 + .. _following approximation: https://doi.org/10.1080/03610918708812641 .. _Bessel's correction: https://en.wikipedia.org/wiki/Bessel's_correction @@ -541,6 +640,10 @@ improve the estimate of the percentile. .. _converges in distribution: https://en.wikipedia.org/wiki/Convergence_of_random_variables#Convergence_in_distribution +.. _skewness: https://en.wikipedia.org/wiki/Skewness + +.. _kurtosis: https://en.wikipedia.org/wiki/Kurtosis + .. _confidence intervals: https://en.wikipedia.org/wiki/Confidence_interval .. _Student's t-distribution: https://en.wikipedia.org/wiki/Student%27s_t-distribution diff --git a/include/openmc/constants.h b/include/openmc/constants.h index a0d1646131..b661934812 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -291,7 +291,7 @@ enum class MgxsType { // ============================================================================ // TALLY-RELATED CONSTANTS -enum class TallyResult { VALUE, SUM, SUM_SQ, SIZE }; +enum class TallyResult { VALUE, SUM, SUM_SQ, SUM_THIRD, SUM_FOURTH }; enum class TallyType { VOLUME, MESH_SURFACE, SURFACE, PULSE_HEIGHT }; diff --git a/include/openmc/hdf5_interface.h b/include/openmc/hdf5_interface.h index 0092c08f8d..28b0d2b113 100644 --- a/include/openmc/hdf5_interface.h +++ b/include/openmc/hdf5_interface.h @@ -100,8 +100,8 @@ void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep); void read_string( hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep); -void read_tally_results( - hid_t group_id, hsize_t n_filter, hsize_t n_score, double* results); +void read_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, + hsize_t n_results, double* results); void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims, const char* name, const double* buffer); void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims, @@ -114,9 +114,9 @@ void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name, void write_llong(hid_t group_id, int ndim, const hsize_t* dims, const char* name, const long long* buffer, bool indep); void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen, - const char* name, char const* buffer, bool indep); -void write_tally_results( - hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results); + const char* name, const char* buffer, bool indep); +void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, + hsize_t n_results, const double* results); } // extern "C" //============================================================================== diff --git a/include/openmc/tallies/tally.h b/include/openmc/tallies/tally.h index 3beeb9d5ac..374daff92a 100644 --- a/include/openmc/tallies/tally.h +++ b/include/openmc/tallies/tally.h @@ -106,6 +106,8 @@ public: bool writable() const { return writable_; } + bool higher_moments() const { return higher_moments_; } + //---------------------------------------------------------------------------- // Other methods. @@ -190,6 +192,9 @@ private: //! Whether to multiply by atom density for reaction rates bool multiply_density_ {true}; + //! Whether to accumulate higher moments (third and fourth) + bool higher_moments_ {false}; + int64_t index_; }; diff --git a/openmc/statepoint.py b/openmc/statepoint.py index a763db3971..11986841f0 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -434,6 +434,10 @@ class StatePoint: if "multiply_density" in group.attrs: tally.multiply_density = group.attrs["multiply_density"].item() > 0 + # Check if tally has higher_moments attribute + if 'higher_moments' in group.attrs: + tally.higher_moments = bool(group.attrs['higher_moments'][()]) + # Read the number of realizations n_realizations = group['n_realizations'][()] diff --git a/openmc/tallies.py b/openmc/tallies.py index 075b1e9911..25ec29a585 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -3,6 +3,7 @@ from collections.abc import Iterable, MutableSequence import copy from functools import partial, reduce, wraps from itertools import product +from math import sqrt, log from numbers import Integral, Real import operator from pathlib import Path @@ -12,6 +13,7 @@ import h5py import numpy as np import pandas as pd import scipy.sparse as sps +from scipy.stats import chi2, norm import openmc import openmc.checkvalue as cv @@ -91,10 +93,20 @@ class Tally(IDManagerMixin): sum_sq : numpy.ndarray An array containing the sum of each independent realization squared for each bin + sum_third : numpy.ndarray + An array containing the sum of each independent realization to the third power for + each bin + sum_fourth : numpy.ndarray + An array containing the sum of each independent realization to the fourth power for + each bin mean : numpy.ndarray An array containing the sample mean for each bin std_dev : numpy.ndarray An array containing the sample standard deviation for each bin + vov : numpy.ndarray + An array containing the variance of the variance for each tally bin + higher_moments : bool + Whether or not the tally accumulates the sums third and fourth to compute higher-order moments figure_of_merit : numpy.ndarray An array containing the figure of merit for each bin @@ -129,8 +141,12 @@ class Tally(IDManagerMixin): self._sum = None self._sum_sq = None + self._sum_third = None + self._sum_fourth = None self._mean = None self._std_dev = None + self._vov = None + self._higher_moments = False self._simulation_time = None self._with_batch_statistics = False self._derived = False @@ -221,6 +237,15 @@ class Tally(IDManagerMixin): cv.check_type('multiply density', value, bool) self._multiply_density = value + @property + def higher_moments(self) -> bool: + return self._higher_moments + + @higher_moments.setter + def higher_moments(self, value): + cv.check_type("higher_moments", value, bool) + self._higher_moments = value + @property def filters(self): return self._filters @@ -371,6 +396,11 @@ class Tally(IDManagerMixin): # Update nuclides nuclide_names = group['nuclides'][()] self._nuclides = [name.decode().strip() for name in nuclide_names] + # Check for higher_moments attribute + if "higher_moments" in group.attrs: + self._higher_moments = bool(group.attrs["higher_moments"][()]) + else: + self._higher_moments = False # Extract Tally data from the file data = group['results'] @@ -385,10 +415,25 @@ class Tally(IDManagerMixin): self._sum = sum_ self._sum_sq = sum_sq + if self._higher_moments: + # Extract additional Tally data when higher moments enabled + sum_third = data[:, :, 2] + sum_fourth = data[:, :, 3] + + # Reshape the results arrays + sum_third = np.reshape(sum_third, self.shape) + sum_fourth = np.reshape(sum_fourth, self.shape) + + # Set the additional data for this Tally + self._sum_third = sum_third + self._sum_fourth = sum_fourth + # Convert NumPy arrays to SciPy sparse LIL matrices if self.sparse: self._sum = sps.lil_matrix(self._sum.flatten(), self._sum.shape) self._sum_sq = sps.lil_matrix(self._sum_sq.flatten(), self._sum_sq.shape) + self._sum_third = sps.lil_matrix(self._sum_third.flatten(), self._sum_third.shape) + self._sum_fourth = sps.lil_matrix(self.sum_fourth.flatten(), self._sum_fourth.shape) # Read simulation time (needed for figure of merit) self._simulation_time = f["runtime"]["simulation"][()] @@ -428,6 +473,52 @@ class Tally(IDManagerMixin): cv.check_type('sum_sq', sum_sq, Iterable) self._sum_sq = sum_sq + @property + @ensure_results + def sum_third(self): + if not self._higher_moments: + raise ValueError( + "Higher moments have not been enabled for this tally. To make " + "higher moments available, set the higher_moments attribute to " + "True before running a simulation." + ) + + if not self._sp_filename or self.derived: + return None + + if self.sparse: + return np.reshape(self._sum_third.toarray(), self.shape) + else: + return self._sum_third + + @sum_third.setter + def sum_third(self, sum_third): + cv.check_type("sum_third", sum_third, Iterable) + self._sum_third = sum_third + + @property + @ensure_results + def sum_fourth(self): + if not self._higher_moments: + raise ValueError( + "Higher moments have not been enabled for this tally. To make " + "higher moments available, set the higher_moments attribute to " + "True before running a simulation." + ) + + if not self._sp_filename or self.derived: + return None + + if self.sparse: + return np.reshape(self._sum_fourth.toarray(), self.shape) + else: + return self._sum_fourth + + @sum_fourth.setter + def sum_fourth(self, sum_fourth): + cv.check_type("sum_fourth", sum_fourth, Iterable) + self._sum_fourth = sum_fourth + @property def mean(self): if self._mean is None: @@ -470,14 +561,370 @@ class Tally(IDManagerMixin): else: return self._std_dev + @property + def vov(self): + if self._vov is None: + n = self.num_realizations + sum1 = self.sum + sum2 = self.sum_sq + sum3 = self.sum_third + sum4 = self.sum_fourth + self._vov = np.zeros_like(sum1, dtype=float) + + # Calculate the variance of the variance (Eq. 2.232 in + # https://doi.org/10.2172/2372634) + numerator = (sum4 - (4.0*sum3*sum1)/n + + (6.0*sum2*(sum1**2))/(n**2) + - (3.0*(sum1)**4)/(n**3)) + denominator = (sum2 - (1.0/n)*(sum1**2))**2 + + mask = denominator > 0.0 + + self._vov[mask] = numerator[mask]/denominator[mask] - 1.0/n + + if self.sparse: + self._vov = sps.lil_matrix(self._vov.flatten(), self._vov.shape) + + if self.sparse: + return np.reshape(self._vov.toarray(), self.shape) + else: + return self._vov + + @property + def m2(self): + n = self.num_realizations + return self.sum_sq/n - self.mean**2 + + @property + def m3(self): + n = self.num_realizations + mean = self.mean + sum2 = self.sum_sq/n + sum3 = self.sum_third/n + + return sum3 - 3.0*mean*sum2 + 2.0*mean**3 + + @property + def m4(self): + n = self.num_realizations + mean = self.mean + sum2 = self.sum_sq/n + sum3 = self.sum_third/n + sum4 = self.sum_fourth/n + + return sum4 - 4.0*mean*sum3 + 6.0*(mean**2)*sum2 - 3.0*mean**4 + + def skew(self, bias=False) -> np.ndarray: + """Return the sample skewness of each tally bin. + + This method computes and returns the unadjusted or adjusted + Fisher-Pearson coefficient of skewness. + + Parameters + ---------- + bias : bool + If False, calculations are corrected for bias and the adjusted + Fisher-Pearson skewness (:math:`G_1`) is returned. If True, + calculations are not corrected for bias and the unadjusted skewness + (:math:`g_1`) is returned. + + Returns + ------- + float + The skewness of each tally bin + """ + n = self.num_realizations + m2 = self.m2 + m3 = self.m3 + + with np.errstate(divide="ignore", invalid="ignore"): + g1 = np.where(m2 > 0.0, m3/(m2**1.5), 0.0) + + if bias: + return g1 + else: + if n <= 2: + raise ValueError("Insufficient number of independent realizations" + f"for bias-corrected skewness: need n >= 3, got {n=}.") + else: + return sqrt(n*(n - 1))/(n - 2)*g1 + + def kurtosis(self, fisher=True, bias=False) -> np.ndarray: + r"""Return the sample kurtosis of each tally bin. + + This method computes and returns the sample kurtosis using either + Pearson's or Fisher's definition, with or without finite-sample bias + correction. The value returned depends on the `bias` and `fisher` + arguments as follows: + + - **bias=True, fisher=False**: Returns :math:`b_2` (Pearson's kurtosis) + This is the raw fourth standardized moment: :math:`m_4/m_2^2`. For a + normal distribution, :math:`b_2\approx 3`. + + - **bias=True, fisher=True**: Returns :math:`g_2` (excess kurtosis) This + is :math:`b_2 - 3`, centered at 0 for normal distributions. Positive + values indicate heavier tails, negative values lighter tails. + + - **bias=False, fisher=True** (default): Returns :math:`G_2` (adjusted + excess kurtosis). This applies finite-sample bias correction to + :math:`g_2`. This is the recommended estimator for statistical + inference. + + - **bias=False, fisher=False**: Returns bias-corrected Pearson's + kurtosis. This is :math:`G_2 + 3`. + + Parameters + ---------- + fisher : bool, optional + If True (default), Fisher's definition is used (excess kurtosis). If + False, Pearson's definition is used. + bias : bool, optional + If False (default), calculations are corrected for statistical bias + using finite-sample adjustments. If True, calculations use the + biased estimator (population formulas). + + Returns + ------- + numpy.ndarray + The kurtosis of each tally bin + + """ + n = self.num_realizations + m2 = self.m2 + m4 = self.m4 + + with np.errstate(divide="ignore", invalid="ignore"): + b2 = np.where(m2 > 0.0, m4/(m2**2), 0.0) + g2 = b2 - 3.0 + + if bias: + # Biased estimator (g2 or b2) + return g2 if fisher else b2 + else: + # Unbiased estimator with finite-sample correction + if n <= 3: + raise ValueError("Insufficient number of independent realizations" + f"for bias-corrected kurtosis: need n >= 4, got {n=}.") + else: + G2 = ((n - 1)/((n - 2)*(n - 3)))*((n + 1)*g2 + 6.0) + return G2 if fisher else G2 + 3.0 + + def skewtest(self, alternative: str = "two-sided"): + """Perform D'Agostino and Pearson's test for skewness. + + This method tests the null hypothesis that the skewness of the + population that the sample was drawn from is the same as that of a + corresponding normal distribution. + + Parameters + ---------- + alternative : {'two-sided', 'less', 'greater'}, optional + Defines the alternative hypothesis. The following options are + available: + + * 'two-sided': the skewness of the distribution is different from + that of the normal distribution (i.e., non-zero) + * 'less': the skewness of the distribution is less than that of the + normal distribution + * 'greater': the skewness of the distribution is greater than that + of the normal distribution + + Returns + ------- + statistic : np.ndarray + The computed z-score for the skewness test for each tally bin + pvalue : np.ndarray + The p-value for the hypothesis test for each tally bin + + Notes + ----- + This test is based on D'Agostino and Pearson's test [1]_. The test + requires at least 8 realizations to produce valid results. + + References + ---------- + .. [1] D'Agostino, R. B. (1971), "An omnibus test of normality for + moderate and large sample size", Biometrika, 58, 341-348 + + """ + n = self.num_realizations + if n < 8: + raise ValueError("Skewness test is not well-defined for n < 8.") + + g1 = self.skew(bias=True) + + # --- Z1 (skewness) --- + y = g1 * sqrt(((n + 1.0)*(n + 3.0))/(6.0*(n - 2.0))) + beta2 = (3.0*(n**2 + 27.0*n - 70.0)*(n + 1.0)*(n + 3.0) + )/((n - 2.0)*(n + 5.0)*(n + 7.0)*(n + 9.0)) + W2 = -1.0 + sqrt(2.0*(beta2 - 1.0)) + delta = 1.0 / sqrt(log(sqrt(W2))) + alpha = sqrt(2.0 / (W2 - 1.0)) + Zb1 = np.where( + y >= 0.0, + delta*np.log((y/alpha) + np.sqrt((y/alpha)**2 + 1.0)), + -delta*np.log((-y/alpha) + np.sqrt((y/alpha)**2 + 1.0)) + ) + + # p-value + if alternative == "two-sided": + p = 2.0 * (1.0 - norm.cdf(np.abs(Zb1))) + elif alternative == "greater": + p = 1.0 - norm.cdf(Zb1) + elif alternative == "less": + p = norm.cdf(Zb1) + else: + raise ValueError("alternative must be 'two-sided', 'greater', or 'less'") + + return Zb1, p + + def kurtosistest(self, alternative: str = "two-sided"): + """Perform D'Agostino and Pearson's test for kurtosis. + + This method tests the null hypothesis that the kurtosis of the + population that the sample was drawn from is the same as that of a + corresponding normal distribution. + + Parameters + ---------- + alternative : {'two-sided', 'less', 'greater'}, optional + Defines the alternative hypothesis. Default is 'two-sided'. + The following options are available: + + * 'two-sided': the kurtosis of the distribution is different from + that of the normal distribution + * 'less': the kurtosis of the distribution is less than that of the + normal distribution + * 'greater': the kurtosis of the distribution is greater than that + of the normal distribution + + Returns + ------- + statistic : np.ndarray + The computed z-score for the kurtosis test for each tally bin + pvalue : np.ndarray + The p-value for the hypothesis test for each tally bin + + Raises + ------ + ValueError + If the number of realizations is less than 20, or if an invalid + alternative hypothesis is specified. + + Notes + ----- + This test is based on D'Agostino and Pearson's test [1]_. The test + is typically recommended for at least 20 realizations to produce + valid results. + + References + ---------- + .. [1] D'Agostino, R. B. (1971), "An omnibus test of normality for + moderate and large sample size", Biometrika, 58, 341-348 + + """ + n = self.num_realizations + if n < 20: + raise ValueError("Kurtosis test is typically recommended for n >= 20.") + + b2 = self.kurtosis(bias=True, fisher=False) + + # --- Z2 (kurtosis) --- + mean_b2 = 3.0 * (n - 1.0) / (n + 1.0) + var_b2 = (24.0*n*(n - 2.0)*(n - 3.0)/( + (n + 1.0)**2*(n + 3.0)*(n + 5.0))) + x = (b2 - mean_b2)/np.sqrt(var_b2) + moment = ((6.0*(n**2 - 5.0*n + 2.0))/((n + 7.0)*(n + 9.0)) + )*sqrt((6.0*(n + 3.0)*(n + 5.0))/(n*(n - 2.0)*(n - 3.0))) + A = 6.0 + (8.0/moment)*((2.0/moment) + sqrt(1.0 + 4.0/(moment**2))) + Zb2 = (1.0- 2.0/(9.0*A) - ((1.0 - 2.0/A) / (1.0 + (x + )*sqrt(2.0/(A - 4.0))))**(1.0/3.0)) / sqrt(2.0/(9.0*A)) + + # p-value + if alternative == "two-sided": + p = 2.0 * (1.0 - norm.cdf(np.abs(Zb2))) + elif alternative == "greater": + p = 1.0 - norm.cdf(Zb2) + elif alternative == "less": + p = norm.cdf(Zb2) + else: + raise ValueError("alternative must be 'two-sided', 'greater', or 'less'") + + return Zb2, p + + def normaltest(self, alternative: str = "two-sided"): + """Perform D'Agostino and Pearson's omnibus test for normality. + + This method tests the null hypothesis that a sample comes from a + normal distribution. It combines skewness and kurtosis to produce an + omnibus test of normality. + + Parameters + ---------- + alternative : {'two-sided', 'less', 'greater'}, optional + Defines the alternative hypothesis used for the component skewness + and kurtosis tests. Default is 'two-sided'. The following options + are available: + + * 'two-sided': the distribution is different from normal + * 'less': used for the component tests + * 'greater': used for the component tests + + Returns + ------- + statistic : np.ndarray + The computed z-score for the normality test for each tally bin + pvalue : np.ndarray + The p-value for the hypothesis test for each tally bin + + Raises + ------ + ValueError + If the number of realizations is less than 20, or if an invalid + alternative hypothesis is specified. + + Notes + ----- + This test combines a test for skewness and a test for kurtosis to + produce an omnibus test [1]_. The test statistic is: + + .. math:: + + K^2 = Z_1^2 + Z_2^2 + + where :math:`Z_1` is the z-score from the skewness test and + :math:`Z_2` is the z-score from the kurtosis test. This statistic + follows a chi-square distribution with 2 degrees of freedom. + + The test requires at least 20 realizations to produce valid results. + + References + ---------- + .. [1] D'Agostino, R. B. and Pearson, E. S. (1973), "Tests for + departure from normality", Biometrika, 60, 613-622 + + """ + n = self.num_realizations + if n < 20: + raise ValueError("normaltest requires n >= 20 (per D'Agostino-Pearson).") + + # Use the component tests + Z1, _ = self.skewtest(alternative) + Z2, _ = self.kurtosistest(alternative) + + # Combine as chi-square with df=2 since we have skewness and kurtosis + K2 = Z1*Z1 + Z2*Z2 + p = chi2.sf(K2, df=2) + return K2, p + @property def figure_of_merit(self): mean = self.mean std_dev = self.std_dev fom = np.zeros_like(mean) nonzero = np.abs(mean) > 0 - fom[nonzero] = 1.0 / ( - (std_dev[nonzero] / mean[nonzero])**2 * self._simulation_time) + rel_err = std_dev[nonzero] / mean[nonzero] + fom[nonzero] = 1.0 / (rel_err**2 * self._simulation_time) return fom @property @@ -528,6 +975,12 @@ class Tally(IDManagerMixin): if self._sum_sq is not None: self._sum_sq = sps.lil_matrix(self._sum_sq.flatten(), self._sum_sq.shape) + if self._sum_third is not None: + self._sum_third = sps.lil_matrix(self._sum_third.flatten(), + self._sum_third.shape) + if self._sum_fourth is not None: + self._sum_fourth = sps.lil_matrix(self._sum_fourth.flatten(), + self._sum_fourth.shape) if self._mean is not None: self._mean = sps.lil_matrix(self._mean.flatten(), self._mean.shape) @@ -543,6 +996,10 @@ class Tally(IDManagerMixin): self._sum = np.reshape(self._sum.toarray(), self.shape) if self._sum_sq is not None: self._sum_sq = np.reshape(self._sum_sq.toarray(), self.shape) + if self._sum_third is not None: + self._sum_third = np.reshape(self._sum_third.toarray(), self.shape) + if self._sum_fourth is not None: + self._sum_fourth = np.reshape(self._sum_fourth.toarray(), self.shape) if self._mean is not None: self._mean = np.reshape(self._mean.toarray(), self.shape) if self._std_dev is not None: @@ -869,6 +1326,34 @@ class Tally(IDManagerMixin): merged_tally._sum_sq = np.reshape(merged_sum_sq, merged_tally.shape) + # Concatenate sum_third arrays if present in both tallies + if self._sum_third is not None and other._sum_third is not None: + self_sum_third = self.get_reshaped_data(value="sum_third") + other_sum_third = other_copy.get_reshaped_data(value="sum_third") + + if join_right: + merged_sum_third = np.concatenate((self_sum_third, other_sum_third), + axis=merge_axis) + else: + merged_sum_third = np.concatenate((other_sum_third, self_sum_third), + axis=merge_axis) + + merged_tally._sum_third = np.reshape(merged_sum_third, merged_tally.shape) + + # Concatenate sum_fourth arrays if present in both tallies + if self._sum_fourth is not None and other._sum_fourth is not None: + self_sum_fourth = self.get_reshaped_data(value="sum_fourth") + other_sum_fourth = other_copy.get_reshaped_data(value="sum_fourth") + + if join_right: + merged_sum_fourth = np.concatenate((self_sum_fourth, other_sum_fourth), + axis=merge_axis) + else: + merged_sum_fourth = np.concatenate((other_sum_fourth, self_sum_fourth), + axis=merge_axis) + + merged_tally._sum_fourth = np.reshape(merged_sum_fourth, merged_tally.shape) + # Concatenate mean arrays if present in both tallies if self.mean is not None and other.mean is not None: self_mean = self.get_reshaped_data(value='mean') @@ -958,6 +1443,11 @@ class Tally(IDManagerMixin): subelement = ET.SubElement(element, "derivative") subelement.text = str(self.derivative.id) + # Optional higher moments accumulation + if self.higher_moments: + subelement = ET.SubElement(element, "higher_moments") + subelement.text = str(self.higher_moments).lower() + return element def add_results(self, statepoint: cv.PathLike | openmc.StatePoint): @@ -984,8 +1474,12 @@ class Tally(IDManagerMixin): # point are based on the current statepoint file self._sum = None self._sum_sq = None + self._sum_third = None + self._sum_fourth = None self._mean = None self._std_dev = None + self._vov = None + self._higher_moments = False self._num_realizations = 0 self._results_read = False @@ -1355,7 +1849,9 @@ class Tally(IDManagerMixin): (value == 'std_dev' and self.std_dev is None) or \ (value == 'rel_err' and self.mean is None) or \ (value == 'sum' and self.sum is None) or \ - (value == 'sum_sq' and self.sum_sq is None): + (value == 'sum_sq' and self.sum_sq is None) or \ + (value == "sum_third" and self.sum_third is None) or \ + (value == "sum_fourth" and self.sum_fourth is None): msg = f'The Tally ID="{self.id}" has no data to return' raise ValueError(msg) @@ -1378,10 +1874,14 @@ class Tally(IDManagerMixin): data = self.sum[indices] elif value == 'sum_sq': data = self.sum_sq[indices] + elif value == "sum_third": + data = self.sum_third[indices] + elif value == "sum_fourth": + data = self.sum_fourth[indices] else: msg = f'Unable to return results from Tally ID="{value}" since ' \ f'the requested value "{self.id}" is not \'mean\', ' \ - '\'std_dev\', \'rel_err\', \'sum\', or \'sum_sq\'' + '\'std_dev\', \'rel_err\', \'sum\', \'sum_sq\', \'sum_third\' or \'sum_fourth\'' raise LookupError(msg) return data @@ -2711,6 +3211,16 @@ class Tally(IDManagerMixin): new_sum_sq = self.get_values(scores, filters, filter_bins, nuclides, 'sum_sq') new_tally.sum_sq = new_sum_sq + if not self.derived and self._sum_third is not None: + new_sum_third = self.get_values( + scores, filters, filter_bins, nuclides, "sum_third" + ) + new_tally._sum_third = new_sum_third + if not self.derived and self._sum_fourth is not None: + new_sum_fourth = self.get_values( + scores, filters, filter_bins, nuclides, "sum_fourth" + ) + new_tally._sum_fourth = new_sum_fourth if self.mean is not None: new_mean = self.get_values(scores, filters, filter_bins, nuclides, 'mean') @@ -3151,6 +3661,12 @@ class Tally(IDManagerMixin): if not self.derived and self.sum_sq is not None: new_tally._sum_sq = np.zeros(new_tally.shape, dtype=np.float64) new_tally._sum_sq[diag_indices, :, :] = self.sum_sq + if not self.derived and self._sum_third is not None: + new_tally._sum_third = np.zeros(new_tally.shape, dtype=np.float64) + new_tally._sum_third[diag_indices, :, :] = self.sum_third + if not self.derived and self._sum_fourth is not None: + new_tally._sum_fourth = np.zeros(new_tally.shape, dtype=np.float64) + new_tally._sum_fourth[diag_indices, :, :] = self.sum_fourth if self.mean is not None: new_tally._mean = np.zeros(new_tally.shape, dtype=np.float64) new_tally._mean[diag_indices, :, :] = self.mean diff --git a/src/hdf5_interface.cpp b/src/hdf5_interface.cpp index bf1f79549e..c56d485e28 100644 --- a/src/hdf5_interface.cpp +++ b/src/hdf5_interface.cpp @@ -536,14 +536,14 @@ void read_complex( H5Tclose(complex_id); } -void read_tally_results( - hid_t group_id, hsize_t n_filter, hsize_t n_score, double* results) +void read_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, + hsize_t n_results, double* results) { // Create dataspace for hyperslab in memory constexpr int ndim = 3; - hsize_t dims[ndim] {n_filter, n_score, 3}; + hsize_t dims[ndim] {n_filter, n_score, n_results}; hsize_t start[ndim] {0, 0, 1}; - hsize_t count[ndim] {n_filter, n_score, 2}; + hsize_t count[ndim] {n_filter, n_score, n_results - 1}; hid_t memspace = H5Screate_simple(ndim, dims, nullptr); H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); @@ -686,15 +686,15 @@ void write_string( group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep); } -void write_tally_results( - hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results) +void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score, + hsize_t n_results, const double* results) { // Set dimensions of sum/sum_sq hyperslab to store constexpr int ndim = 3; - hsize_t count[ndim] {n_filter, n_score, 2}; + hsize_t count[ndim] {n_filter, n_score, n_results - 1}; // Set dimensions of results array - hsize_t dims[ndim] {n_filter, n_score, 3}; + hsize_t dims[ndim] {n_filter, n_score, n_results}; hsize_t start[ndim] {0, 0, 1}; hid_t memspace = H5Screate_simple(ndim, dims, nullptr); H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr); diff --git a/src/state_point.cpp b/src/state_point.cpp index 8195c48650..0b0fed1324 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -201,6 +201,12 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) write_attribute(tally_group, "multiply_density", 0); } + if (tally->higher_moments()) { + write_attribute(tally_group, "higher_moments", 1); + } else { + write_attribute(tally_group, "higher_moments", 0); + } + if (tally->estimator_ == TallyEstimator::ANALOG) { write_dataset(tally_group, "estimator", "analog"); } else if (tally->estimator_ == TallyEstimator::TRACKLENGTH) { @@ -264,12 +270,13 @@ extern "C" int openmc_statepoint_write(const char* filename, bool* write_source) for (const auto& tally : model::tallies) { if (!tally->writable_) continue; - // Write sum and sum_sq for each bin + + // Write results for each bin std::string name = "tally " + std::to_string(tally->id_); hid_t tally_group = open_group(tallies_group, name.c_str()); auto& results = tally->results_; write_tally_results(tally_group, results.shape()[0], - results.shape()[1], results.data()); + results.shape()[1], results.shape()[2], results.data()); close_group(tally_group); } } else { @@ -509,7 +516,8 @@ extern "C" int openmc_statepoint_load(const char* filename) } else { auto& results = tally->results_; read_tally_results(tally_group, results.shape()[0], - results.shape()[1], results.data()); + results.shape()[1], results.shape()[2], results.data()); + read_dataset(tally_group, "n_realizations", tally->n_realizations_); close_group(tally_group); } @@ -1001,7 +1009,8 @@ void write_tally_results_nr(hid_t file_id) // Write reduced tally results to file auto shape = results_copy.shape(); - write_tally_results(tally_group, shape[0], shape[1], results_copy.data()); + write_tally_results( + tally_group, shape[0], shape[1], shape[2], results_copy.data()); close_group(tally_group); } else { diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 12ee3427eb..9daeb1d69f 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -107,6 +107,9 @@ Tally::Tally(pugi::xml_node node) multiply_density_ = get_node_value_bool(node, "multiply_density"); } + if (check_for_node(node, "higher_moments")) { + higher_moments_ = get_node_value_bool(node, "higher_moments"); + } // ======================================================================= // READ DATA FOR FILTERS @@ -800,7 +803,11 @@ void Tally::init_triggers(pugi::xml_node node) void Tally::init_results() { int n_scores = scores_.size() * nuclides_.size(); - results_ = xt::empty({n_filter_bins_, n_scores, 3}); + if (higher_moments_) { + results_ = xt::empty({n_filter_bins_, n_scores, 5}); + } else { + results_ = xt::empty({n_filter_bins_, n_scores, 3}); + } } void Tally::reset() @@ -838,14 +845,33 @@ void Tally::accumulate() norm = 1.0; } -// Accumulate each result + // Accumulate each result + if (higher_moments_) { #pragma omp parallel for - for (int i = 0; i < results_.shape()[0]; ++i) { - for (int j = 0; j < results_.shape()[1]; ++j) { - double val = results_(i, j, TallyResult::VALUE) * norm; - results_(i, j, TallyResult::VALUE) = 0.0; - results_(i, j, TallyResult::SUM) += val; - results_(i, j, TallyResult::SUM_SQ) += val * val; + // filter bins (specific cell, energy bins) + for (int i = 0; i < results_.shape()[0]; ++i) { + // score bins (flux, total reaction rate, fission reaction rate, etc.) + for (int j = 0; j < results_.shape()[1]; ++j) { + double val = results_(i, j, TallyResult::VALUE) * norm; + double val2 = val * val; + results_(i, j, TallyResult::VALUE) = 0.0; + results_(i, j, TallyResult::SUM) += val; + results_(i, j, TallyResult::SUM_SQ) += val2; + results_(i, j, TallyResult::SUM_THIRD) += val2 * val; + results_(i, j, TallyResult::SUM_FOURTH) += val2 * val2; + } + } + } else { +#pragma omp parallel for + // filter bins (specific cell, energy bins) + for (int i = 0; i < results_.shape()[0]; ++i) { + // score bins (flux, total reaction rate, fission reaction rate, etc.) + for (int j = 0; j < results_.shape()[1]; ++j) { + double val = results_(i, j, TallyResult::VALUE) * norm; + results_(i, j, TallyResult::VALUE) = 0.0; + results_(i, j, TallyResult::SUM) += val; + results_(i, j, TallyResult::SUM_SQ) += val * val; + } } } } diff --git a/src/weight_windows.cpp b/src/weight_windows.cpp index 674fae49c3..9333800bc3 100644 --- a/src/weight_windows.cpp +++ b/src/weight_windows.cpp @@ -547,8 +547,10 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value, // build a shape for a view of the tally results, this will always be // dimension 5 (3 filter dimensions, 1 score dimension, 1 results dimension) - std::array shape = { - 1, 1, 1, tally->n_scores(), static_cast(TallyResult::SIZE)}; + // Look for the size of the last dimension of the results array + const auto& results_arr = tally->results(); + const int results_dim = static_cast(results_arr.shape()[2]); + std::array shape = {1, 1, 1, tally->n_scores(), results_dim}; // set the shape for the filters applied on the tally for (int i = 0; i < tally->filters().size(); i++) { @@ -586,7 +588,7 @@ void WeightWindows::update_weights(const Tally* tally, const std::string& value, // get a fully reshaped view of the tally according to tally ordering of // filters - auto tally_values = xt::reshape_view(tally->results(), shape); + auto tally_values = xt::reshape_view(results_arr, shape); // get a that is (particle, energy, mesh, scores, values) auto transposed_view = xt::transpose(tally_values, transpose); diff --git a/tests/unit_tests/test_tallies.py b/tests/unit_tests/test_tallies.py index c38f067d58..7b1bf0a2fe 100644 --- a/tests/unit_tests/test_tallies.py +++ b/tests/unit_tests/test_tallies.py @@ -1,6 +1,8 @@ +from math import sqrt import numpy as np import pytest import openmc +import scipy.stats as sps def test_xml_roundtrip(run_in_tmpdir): @@ -163,3 +165,214 @@ def test_tally_application(sphere_model, run_in_tmpdir): assert (sp_tally.std_dev == tally.std_dev).all() assert (sp_tally.mean == tally.mean).all() assert sp_tally.nuclides == tally.nuclides + +def _tally_from_data(x, *, higher_moments=True, normality=True): + t = openmc.Tally() + t.scores = ["flux"] # 1 score + t.nuclides = [openmc.Nuclide("H1")] # 1 nuclide + t._sp_filename = "dummy.h5" # mark "results available" + t._results_read = True # don't try to read from disk + t._num_realizations = int(len(x)) # n + t.higher_moments = bool(higher_moments) + + x = np.asarray(x, dtype=float) + # (num_filter_bins=1, num_nuclides=1, num_scores=1) -> (1,1,1) arrays + t._sum = np.array([[[np.sum(x)]]], dtype=float) + t._sum_sq = np.array([[[np.sum(x**2)]]], dtype=float) + if higher_moments: + t._sum_third = np.array([[[np.sum(x**3)]]], dtype=float) + t._sum_fourth = np.array([[[np.sum(x**4)]]], dtype=float) + return t + +@pytest.mark.parametrize( + "x, skew_true, kurt_true", + [ # Rademacher distribution + (np.array([1.0, -1.0] * 200), 0.0, 1.0), + # Two-point {0,3} with p(0)=3/4, p(3)=1/4 + (np.concatenate([np.zeros(600), np.full(200, 3.0)]), 2.0 / sqrt(3.0), 7.0 / 3.0), + # Bernoulli distribution + (np.concatenate([np.ones(300), np.zeros(700)]), (1 - 2 * 0.3) / sqrt(0.3 * 0.7), (1 - 3 * 0.3 + 3 * 0.3**2) / (0.3 * 0.7)), + ], +) +def test_b1_b2_analytical_against_tally(x, skew_true, kurt_true): + t = _tally_from_data(x, higher_moments=True, normality=False) + + g1 = t.skew(bias=True)[0, 0, 0] + b2 = t.kurtosis(bias=True, fisher=False)[0, 0, 0] + + assert np.isclose(g1, skew_true, rtol=0, atol=1e-12) + assert np.isclose(b2, kurt_true, rtol=0, atol=1e-12) + +@pytest.mark.parametrize( + "draw, skew_true, kurt_true", + [(lambda rng, n: rng.normal(0, 1, n), 0.0, 3.0), # Normal + (lambda rng, n: rng.random(n), 0.0, 1.8), # Uniform(0,1) + (lambda rng, n: rng.exponential(1.0, n), 2.0, 9.0), # Exp(1) + (lambda rng, n: (rng.random(n) < 0.3).astype(float), + (1 - 2 * 0.3) / sqrt(0.3 * 0.7), + (1 - 3 * 0.3 + 3 * 0.3**2) / (0.3 * 0.7),),],) + +def test_b1_b2_scipy_and_theory(draw, skew_true, kurt_true): + rng = np.random.default_rng(12345) + N = 200_000 + x = draw(rng, N) + + # Tally outputs + t = _tally_from_data(x, higher_moments=True, normality=False) + g1_t = t.skew(bias=True)[0, 0, 0] + b2_t = t.kurtosis(bias=True, fisher=False)[0, 0, 0] + + # SciPy (population, bias=True to match population-moment style) + skew_sp = sps.skew(x, bias=True) + kurt_sp = sps.kurtosis(x, fisher=False, bias=True) + + # Compare to SciPy numerically + assert np.isclose(g1_t, skew_sp, rtol=0, atol=5e-3) + assert np.isclose(b2_t, kurt_sp, rtol=0, atol=5e-3) + + # Compare to analytical targets with size-dependent tolerances + tol_skew = 0.02 if abs(skew_true) < 0.5 else 0.05 + tol_kurt = 0.03 if kurt_true < 4 else 0.1 + assert abs(g1_t - skew_true) < tol_skew + assert abs(b2_t - kurt_true) < tol_kurt + + +def test_kurtosis_bias_fisher_combinations(): + """Test that all combinations of bias and fisher match scipy.stats.kurtosis""" + rng = np.random.default_rng(42) + x = rng.normal(0, 1, 10000) + + t = _tally_from_data(x, higher_moments=True, normality=False) # Test all four combinations + # 1. bias=True, fisher=False (Pearson's kurtosis, b2) + b2_tally = t.kurtosis(bias=True, fisher=False)[0, 0, 0] + b2_scipy = sps.kurtosis(x, fisher=False, bias=True) + assert np.isclose(b2_tally, b2_scipy, rtol=0, atol=1e-10) + assert np.isclose(b2_tally, 3.0, rtol=0.05, atol=0.1) # Should be ~3 for normal + + # 2. bias=True, fisher=True (excess kurtosis, g2) + g2_tally = t.kurtosis(bias=True, fisher=True)[0, 0, 0] + g2_scipy = sps.kurtosis(x, fisher=True, bias=True) + assert np.isclose(g2_tally, g2_scipy, rtol=0, atol=1e-10) + assert np.isclose(g2_tally, 0.0, rtol=0, atol=0.1) # Should be ~0 for normal + assert np.isclose(g2_tally, b2_tally - 3.0, rtol=0, atol=1e-10) # g2 = b2 - 3 + + # 3. bias=False, fisher=True (adjusted excess kurtosis, G2) + G2_tally = t.kurtosis(bias=False, fisher=True)[0, 0, 0] + G2_tally_default = t.kurtosis()[0, 0, 0] # Should be same as default + G2_scipy = sps.kurtosis(x, fisher=True, bias=False) + assert np.isclose(G2_tally, G2_tally_default, rtol=0, atol=1e-10) + assert np.isclose(G2_tally, G2_scipy, rtol=0, atol=1e-10) + assert np.isclose(G2_tally, 0.0, rtol=0, atol=0.1) # Should be ~0 for normal + + # 4. bias=False, fisher=False (adjusted Pearson's kurtosis) + adj_b2_tally = t.kurtosis(bias=False, fisher=False)[0, 0, 0] + adj_b2_scipy = sps.kurtosis(x, fisher=False, bias=False) + assert np.isclose(adj_b2_tally, adj_b2_scipy, rtol=0, atol=1e-10) + assert np.isclose(adj_b2_tally, 3.0, rtol=0.05, atol=0.1) # Should be ~3 for normal + assert np.isclose(adj_b2_tally, G2_tally + 3.0, rtol=0, atol=1e-10) # adj_b2 = G2 + 3 + + +def test_ztests_scipy_comparison(): + rng = np.random.default_rng(987) + x_norm = rng.normal(size=50_000) + x_exp = rng.exponential(size=50_000) + + # -------- Normal dataset (should not reject) -------- + t0 = _tally_from_data(x_norm, higher_moments=True, normality=True) + Zb1_0, p_skew_0 = t0.skewtest(alternative="two-sided") + Zb2_0, p_kurt_0 = t0.kurtosistest(alternative="two-sided") + K2_0, p_omni_0 = t0.normaltest(alternative="two-sided") + + Zb1_0 = Zb1_0.ravel()[0] + p_skew_0 = p_skew_0.ravel()[0] + Zb2_0 = Zb2_0.ravel()[0] + p_kurt_0 = p_kurt_0.ravel()[0] + K2_0 = K2_0.ravel()[0] + p_omni_0 = p_omni_0.ravel()[0] + + z_skew_sp0, p_skew_sp0 = sps.skewtest(x_norm) + z_kurt_sp0, p_kurt_sp0 = sps.kurtosistest(x_norm) + k2_sp0, p_omni_sp0 = sps.normaltest(x_norm) + + assert np.isclose(Zb1_0, z_skew_sp0, atol=0.15) + assert np.isclose(Zb2_0, z_kurt_sp0, atol=0.15) + assert np.isclose(K2_0, k2_sp0, atol=0.30) + assert np.isclose(p_skew_0, p_skew_sp0, atol=5e-3) + assert np.isclose(p_kurt_0, p_kurt_sp0, atol=5e-3) + assert np.isclose(p_omni_0, p_omni_sp0, atol=5e-3) + + # -------- Exponential dataset (should strongly reject) -------- + t1 = _tally_from_data(x_exp, higher_moments=True, normality=True) + + Zb1_1, p_skew_1 = t1.skewtest(alternative="two-sided") + Zb2_1, p_kurt_1 = t1.kurtosistest(alternative="two-sided") + K2_1, p_omni_1 = t1.normaltest(alternative="two-sided") + + Zb1_1 = Zb1_1.ravel()[0] + p_skew_1 = p_skew_1.ravel()[0] + Zb2_1 = Zb2_1.ravel()[0] + p_kurt_1 = p_kurt_1.ravel()[0] + K2_1 = K2_1.ravel()[0] + p_omni_1 = p_omni_1.ravel()[0] + + z_skew_sp1, p_skew_sp1 = sps.skewtest(x_exp) + z_kurt_sp1, p_kurt_sp1 = sps.kurtosistest(x_exp) + k2_sp1, p_omni_sp1 = sps.normaltest(x_exp) + + # Both pipelines should reject very strongly + assert p_skew_1 < 1e-6 and p_skew_sp1 < 1e-6 + assert p_kurt_1 < 1e-6 and p_kurt_sp1 < 1e-6 + assert p_omni_1 < 1e-6 and p_omni_sp1 < 1e-6 + + # Right-skewed and heavy-tailed → large positive Z-statistics + assert Zb1_1 > 30 and z_skew_sp1 > 30 + assert Zb2_1 > 30 and z_kurt_sp1 > 30 + assert K2_1 > 2000 and k2_sp1 > 2000 + +def test_vov_stochastic(sphere_model, run_in_tmpdir): + tally = openmc.Tally(name="test tally") + ef = openmc.EnergyFilter([0.0, 0.1, 1.0, 10.0e6]) + mesh = openmc.RegularMesh.from_domain(sphere_model.geometry, (2, 2, 2)) + mf = openmc.MeshFilter(mesh) + tally.filters = [ef, mf] + tally.scores = ["flux", "absorption", "fission", "scatter"] + tally.higher_moments = True + sphere_model.tallies = [tally] + + sp_file = sphere_model.run(apply_tally_results=True) + + assert tally._mean is None + assert tally._std_dev is None + assert tally._sum is None + assert tally._sum_sq is None + assert tally._sum_third is None + assert tally._sum_fourth is None + assert tally._num_realizations == 0 + assert tally._sp_filename == sp_file + + with openmc.StatePoint(sp_file) as sp: + assert tally in sp.tallies.values() + sp_tally = sp.tallies[tally.id] + + assert np.all(sp_tally.std_dev == tally.std_dev) + assert np.all(sp_tally.mean == tally.mean) + assert np.all(sp_tally.vov == tally.vov) + assert sp_tally.nuclides == tally.nuclides + + n = sp_tally.num_realizations + mean = sp_tally.mean + sum_ = sp_tally._sum + sum_sq = sp_tally._sum_sq + sum_third = sp_tally._sum_third + sum_fourth = sp_tally._sum_fourth + + expected_vov = np.zeros_like(mean) + nonzero = np.abs(mean) > 0 + + num = (sum_fourth - (4.0*sum_third*sum_)/n + (6.0*sum_sq*sum_**2)/(n**2) + - (3.0*sum_**4)/(n**3)) + den = (sum_sq - (1.0/n)*sum_**2)**2 + + expected_vov[nonzero] = num[nonzero]/den[nonzero] - 1.0/n + + assert np.allclose(expected_vov, sp_tally.vov, rtol=1e-7, atol=0.0) From 4e24c2d933dcf92b4ddb51dfca362a20ef82f2f6 Mon Sep 17 00:00:00 2001 From: April Novak Date: Wed, 12 Nov 2025 15:59:45 -0600 Subject: [PATCH 47/76] Update documentation for particle tracks (#3627) Co-authored-by: Paul Romano --- docs/source/usersguide/processing.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index 8b5ae53fac..fe6ab0826f 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -68,17 +68,17 @@ generation, and particle number of the desired particle. For example, to create a track file for particle 4 of batch 1 and generation 2:: settings = openmc.Settings() - settings.track = (1, 2, 4) + settings.track = [(1, 2, 4)] -To specify multiple particles, the length of the iterable should be a multiple -of three, e.g., if we wanted particles 3 and 4 from batch 1 and generation 2:: +To specify multiple particles, specify a list of tuples, e.g., if we wanted +particles 3 and 4 from batch 1 and generation 2:: - settings.track = (1, 2, 3, 1, 2, 4) + settings.track = [(1, 2, 3), (1, 2, 4)] -After running OpenMC, the working directory will contain a file of the form -"track_(batch #)_(generation #)_(particle #).h5" for each particle tracked. -These track files can be converted into VTK poly data files with the -:class:`openmc.Tracks` class. +After running OpenMC (now, without the ``-t`` argument), the working directory +will contain a file named `tracks.h5`, which contains a collection of particle +tracks. These track files can be converted into VTK poly data files or +matplotlib plots with the :class:`openmc.Tracks` class. ---------------------- Source Site Processing From 50bb0df191053e6fc58b9d779022402ac159115e Mon Sep 17 00:00:00 2001 From: Lorenzo Chierici Date: Wed, 12 Nov 2025 23:45:48 +0100 Subject: [PATCH 48/76] depletion-thermochemistry: Redox control transfer rates (#2783) Co-authored-by: Gavin Ridley Co-authored-by: Paul Romano --- openmc/deplete/abc.py | 30 ++++++++++ openmc/deplete/chain.py | 54 ++++++++++++++++++ openmc/deplete/pool.py | 13 +++++ openmc/deplete/transfer_rates.py | 43 +++++++++++++- .../ref_depletion_with_ext_source.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_feed.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_redox.h5 | Bin 0 -> 37328 bytes .../ref_depletion_with_removal.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_removal_and_redox.h5 | Bin 0 -> 37328 bytes .../ref_depletion_with_transfer.h5 | Bin 37328 -> 37328 bytes .../ref_depletion_with_transfer_and_redox.h5 | Bin 0 -> 37328 bytes .../ref_no_depletion_only_feed.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_only_removal.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_with_ext_source.h5 | Bin 37328 -> 37328 bytes .../ref_no_depletion_with_transfer.h5 | Bin 37328 -> 37328 bytes .../deplete_with_transfer_rates/test.py | 22 ++++--- .../unit_tests/test_deplete_transfer_rates.py | 32 +++++++++++ 17 files changed, 185 insertions(+), 9 deletions(-) create mode 100644 tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_redox.h5 create mode 100644 tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal_and_redox.h5 create mode 100644 tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_transfer_and_redox.h5 diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index c5a6219c7b..fb18d86afc 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -1013,6 +1013,36 @@ class Integrator(ABC): material, composition, rate, rate_units, timesteps) + def add_redox(self, material, buffer, oxidation_states, timesteps=None): + """Add redox control to depletable material. + + Parameters + ---------- + material : openmc.Material or str or int + Depletable material + buffer : dict + Dictionary of buffer nuclides used to maintain redox balance. Keys + are nuclide names (strings) and values are their respective + fractions (float) that collectively sum to 1. + oxidation_states : dict + User-defined oxidation states for elements. Keys are element symbols + (e.g., 'H', 'He'), and values are their corresponding oxidation + states as integers (e.g., +1, 0). + timesteps : list of int, optional + List of timestep indices where to set external source rates. + Defaults to None, which means the external source rate is set for + all timesteps. + """ + if self.transfer_rates is None: + if hasattr(self.operator, 'model'): + materials = self.operator.model.materials + elif hasattr(self.operator, 'materials'): + materials = self.operator.materials + self.transfer_rates = TransferRates( + self.operator, materials, len(self.timesteps)) + + self.transfer_rates.set_redox(material, buffer, oxidation_states, timesteps) + @add_params class SIIntegrator(Integrator): r"""Abstract class for the Stochastic Implicit Euler integrators diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index ac5c02aa50..f34416d561 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -7,6 +7,7 @@ loaded from an .xml file and all the nuclides are linked together. from io import StringIO from itertools import chain import math +import numpy as np import re from collections import defaultdict, namedtuple from collections.abc import Mapping, Iterable @@ -714,6 +715,59 @@ class Chain: # Return CSC representation instead of DOK return sp.csc_matrix((vals, (rows, cols)), shape=(n, n)) + def add_redox_term(self, matrix, buffer, oxidation_states): + """Adds a redox term to the depletion matrix from data contained in + the matrix itself and a few user-inputs. + + The redox term to add to the buffer nuclide :math:`N_j` can be written + as: :math:`\frac{dN_j(t)}{dt} = + \cdots - \frac{1}{OS_j}\sum_i N_i a_{ij} \cdot OS_i ` + + where :math:`OS` is the oxidation states vector and `a_{ij}` the + corresponding term in the Bateman matrix. + + Parameters + ---------- + matrix : scipy.sparse.csc_matrix + Sparse matrix representing depletion + buffer : dict + Dictionary of buffer nuclides used to maintain anoins net balance. + Keys are nuclide names (strings) and values are their respective + fractions (float) that collectively sum to 1. + oxidation_states : dict + User-defined oxidation states for elements. Keys are element symbols + (e.g., 'H', 'He'), and values are their corresponding oxidation + states as integers (e.g., +1, 0). + Returns + ------- + matrix : scipy.sparse.csc_matrix + Sparse matrix with redox term added + """ + # Elements list with the same size as self.nuclides + elements = [re.split(r'\d+', nuc.name)[0] for nuc in self.nuclides] + + # Match oxidation states with all elements and add 0 if not data + os = np.array([oxidation_states[elm] if elm in oxidation_states else 0 + for elm in elements]) + + # Buffer idx with nuclide index as value + buffer_idx = {nuc: self.nuclide_dict[nuc] for nuc in buffer} + array = matrix.toarray() + redox_change = np.array([]) + + # calculate the redox array + for i in range(len(self)): + # Net redox impact of reaction: multiply the i-th column of the + # depletion matrix by the oxidation states + redox_change = np.append(redox_change, sum(array[:, i]*os)) + + # Subtract redox vector to the buffer nuclides in the matrix scaling by + # their respective oxidation states + for nuc, idx in buffer_idx.items(): + array[idx] -= redox_change * buffer[nuc] / os[idx] + + return sp.csc_matrix(array) + def form_rr_term(self, tr_rates, current_timestep, mats): """Function to form the transfer rate term matrices. diff --git a/openmc/deplete/pool.py b/openmc/deplete/pool.py index 03b050af38..aa348c02aa 100644 --- a/openmc/deplete/pool.py +++ b/openmc/deplete/pool.py @@ -109,6 +109,13 @@ def deplete(func, chain, n, rates, dt, current_timestep=None, matrix_func=None, matrices = [matrix - transfer for (matrix, transfer) in zip(matrices, transfers)] + if transfer_rates.redox: + for mat_idx, mat_id in enumerate(transfer_rates.local_mats): + if mat_id in transfer_rates.redox: + matrices[mat_idx] = chain.add_redox_term(matrices[mat_idx], + transfer_rates.redox[mat_id][0], + transfer_rates.redox[mat_id][1]) + if current_timestep in transfer_rates.index_transfer: # Gather all on comm.rank 0 matrices = comm.gather(matrices) @@ -125,6 +132,12 @@ def deplete(func, chain, n, rates, dt, current_timestep=None, matrix_func=None, transfer_matrix = chain.form_rr_term(transfer_rates, current_timestep, mat_pair) + + # check if destination material has a redox control + if mat_pair[0] in transfer_rates.redox: + transfer_matrix = chain.add_redox_term(transfer_matrix, + transfer_rates.redox[mat_pair[0]][0], + transfer_rates.redox[mat_pair[0]][1]) transfer_pair[mat_pair] = transfer_matrix # Combine all matrices together in a single matrix of matrices diff --git a/openmc/deplete/transfer_rates.py b/openmc/deplete/transfer_rates.py index 4f2b9aba5f..ea9fc9185e 100644 --- a/openmc/deplete/transfer_rates.py +++ b/openmc/deplete/transfer_rates.py @@ -49,9 +49,10 @@ class ExternalRates: self.local_mats = operator.local_mats self.number_of_timesteps = number_of_timesteps - # initialize transfer rates container dict + #initialize transfer rates container dict self.external_rates = {mat: defaultdict(list) for mat in self.burnable_mats} self.external_timesteps = [] + self.redox = {} def _get_material_id(self, val): """Helper method for getting material id from Material obj or name. @@ -300,6 +301,46 @@ class TransferRates(ExternalRates): self.external_timesteps = np.unique(np.concatenate( [self.external_timesteps, timesteps])) + def set_redox(self, material, buffer, oxidation_states, timesteps=None): + """Add redox control to depletable material. + + Parameters + ---------- + material : openmc.Material or str or int + Depletable material + buffer : dict + Dictionary of buffer nuclides used to maintain redox balance. + Keys are nuclide names (strings) and values are their respective + fractions (float) that collectively sum to 1. + oxidation_states : dict + User-defined oxidation states for elements. + Keys are element symbols (e.g., 'H', 'He'), and values are their + corresponding oxidation states as integers (e.g., +1, 0). + timesteps : list of int, optional + List of timestep indices where to set external source rates. + Defaults to None, which means the external source rate is set for + all timesteps. + + """ + material_id = self._get_material_id(material) + if timesteps is not None: + for timestep in timesteps: + check_value('timestep', timestep, range(self.number_of_timesteps)) + timesteps = np.array(timesteps) + else: + timesteps = np.arange(self.number_of_timesteps) + #Check nuclides in buffer exist + for nuc in buffer: + if nuc not in self.chain_nuclides: + raise ValueError(f'{nuc} is not a valid nuclide.') + # Checks element in oxidation states exist + for elm in oxidation_states: + if elm not in ELEMENT_SYMBOL.values(): + raise ValueError(f'{elm} is not a valid element.') + + self.redox[material_id] = (buffer, oxidation_states) + self.external_timesteps = np.unique(np.concatenate( + [self.external_timesteps, timesteps])) class ExternalSourceRates(ExternalRates): """Class for defining external source rates. diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_ext_source.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_ext_source.h5 index 3ed38f3d6ce3973fd63e7967b1246c8012ebf063..2f9951a42aaa0613c0b4a20351ae2c0df985b0bc 100644 GIT binary patch delta 569 zcmcbxnCZe|rVS2#j53oQ`{L`jC9l$uo6Bd%00mo5bLh;i`vB*6-8Fg^a%@Z|^%tzWFI=h?g8OIAU8Q+5L;d0Wiy{t}+CheB5fg=BG-o^RH!sw#G-cKV@?+ lvt52=hS{y(9<~z?PT;!2+W+$S!`t>#eokIBQHcfQX8^fN!^Qvr delta 569 zcmcbxnCZe|rVS2#jIxs*`{L_&C$G|wo6Bd%00p~FbLh;i`vB+9zH9U>A<9GwvP;sMMu~xzzyKY&yn6*$7~OC!0S~X{%IR5 zfIH~(R?pA-SLnmlFa6CcVRLUEoFD6wD}C|0DV%?T@qMWGIZr5Ghk>DNxAxX|6D;8h z!uRO(8|Rq7`3BtGg7OzW*zbHj`BcA>Pr~V`_9Ai?hL(RfIj?-IXu)%AiL?06R;z-| zJDfKbB~3rKWrnlezFmg858|97_9uO*KcDM-K)2w9eprA@^!-^6e!oB9@-EZjXwU$|5)1ozM82TJp1hWf+#f#MFA+A<9Gwl@uqMMu~xzztx@&yn6*$7~OC0RQR_|FjJj zz#SyJ&GYmA75Z@X7k=|f*xcI(=U2MqN?*Kg3g_=&d>`t4&J)VlVPL4(t-bZ#1WULA z?L9jE#yKW%zAtyTp!|go_8VVMKGm;eYMy)4p7roO@nbax&i1Xxp0O+IIp?XaT-X2G z-&si`evf9Gw)3wSZ=X!ra>~idzshk<{vD^2lNBe#*FWgkJSnRZ5!7DGvL?Kcc@MWp zd+k@Q#?^?R{&hwBn8;rdxct>wS&HXgE{F3E1^K6nY*B*qt=xn)Z+)<~W1IU>{{7^C zw(F$#N!OoJx4W+YZrzO+z@S!>jLbeY@4xMJnS~F(zr1SurDjo);Q>Xs0cWOPU+YrE z4iD;j&zaoGrw~D1U8cVxayP=ly?f^ssVzJN*YBUTQRZ1TBB)g*n)PzcgQ4=kptjt2 mSHW(N1zbbsbFtQv79%*n?DLVpyHy|US4U4?HBpHL6x0C2(a??n delta 688 zcmcbxnCZe|rVS2#jIxs*`{L{8C9l$uo6Bd%00nDKbLh;i`vB+fxNGz*A<9Gw&x6vMMu~xzzyKc&yn6*$7~OCz|~bB{%IR5 zfIH~sR?pA-SLnmlXaDAvu(`Jn&Np<)mA-i06wW`*_&(J8oF|m8!@$tGTYKxf36^jL zA$xTCjdM)kd~fb5d`FEVoPga}|Uw^G*^Q5dwL{Jwl%bM^)<~`gZ z$F*O%8doEN`oR_LVY`dXJN zc6d-1dCufcK7|PCiZcBbk-HHV?%q4ENNwRExPHH^jWW-&5kW03(X5wi9t@QS2DQt^ ny9#!DEZ`c-pNqAYv>3tp)t`?9-mUs*?+`Y5)kGy0P*4K^K)BOB diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_redox.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_redox.h5 new file mode 100644 index 0000000000000000000000000000000000000000..c7f002ba14a29133887bb7b7d06cc0a6378a71ec GIT binary patch literal 37328 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 literal 0 HcmV?d00001 diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal.h5 index 3d48105d7b444cc16f5b6438f97f897d2c1657fd..c3121a9535097cbd3bc2457b664ff774ca654e2c 100644 GIT binary patch delta 670 zcmcbxnCZe|rVS2#j53oQ`{L_&B(Ktto6Bd%00o;)bLh;i`vB)Jx@+_-A<9Gws#GVMMu~xzzyKa&yn6*$7~OC0Qc$-|FjJj zz#a5utLNwaEA-*&zy9Wxu(`Jn&i8Q1mA-i06wcqn_&(J8oF|m8!@y9!TYKxf36^jL zv3qp-jdM)k{BZ7WLHP?G>`y$Ke5zl`luz@NJT(XoTCHz?k32oIA3}(w0l2|Vr!&ni1-^&# z&9=`ztNUUC+-Db=>$Yl5mx9ZGh{~C^=j3uYKVa88i=i7=GEVh&%zk>SYbyTR{^~xxdBVvnwgz4i2di9_;0BcayLV^9 zOg4B>Uv^^fW6N3ycTl?2aigtQRpIItk4CJtQ920cPht(=UOL|j&gV63vJXBP0_6)c fFhrcY#JKz_BBA<9GwjT_RMMu~xzztx@&yn6*$7~OCz^7Fo{%IR5 zfIH~;R?pA-SLnmlxBupqu(`Jn&JTCVmA-i06wZIk_&(J8oF|m8!@#g;xAxX|6D;8h zTK4Gl8|Rq7`L^8Mg7OzW*!Mr0e5zl`bi>_A_H2jmi65&maE=b-yPF`V;(YJLj7yfU zteis+&*nYhrsDkO#oH%Sww!V@@UL=QlYhtQ{A9%m@%8btXQeu%1mFhioX#}66!;#_ zSKmJStnP~maG%{{uG^|LT?#ILEh=Z)o|DVre3M=8ELL)B!}+yOo-wv;x3-(OB2r_L z*I(N|ExJ2Bk80S}&0fJ`EaOyf$LFWFx~Ag4?eFf>nOD>jer#C_;SOq-I&QS}sw!N)=+TIkHcAKK`~ubh?xpjs;Cwa1Ci~!%AyB?B f1B1r7ON`5}B7!=0^2CYaO#D)lS4~u60R=1or!~mt diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal_and_redox.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_removal_and_redox.h5 new file mode 100644 index 0000000000000000000000000000000000000000..80ce771fceae774cd606fef7888c325128b7462f GIT binary patch literal 37328 zcmeHPeQ;D)6~Avcp$h~EErk?n`cj#8O;Xu>&?bc4Y}gPJ93>E_tL?O#k1eE=FOw_= zMa)R6adafK&NSlSq|TtBEp7VcfOPCu`jOfW6Dn3lfr(>Bqr=oy+YzgP@4b7@d)b?P zyX+%NxAg2Ed*8YD+;h+Uz4JTo-nZ}VcWSF^=FM3;hp8WjgJrO6?GV2%!e@LBuR$5x z18^WgIRNE|jUPygMYSyl>a)SVZ08lDP`_#8+O>??7~01Yn%UqiepCh(^@_Io325K+ zb+scBz##z9d+LwQ$EI zi8BM}phP(TAYZV|VxZ4vEBzhpzSg#2@Aj@BsI%)7#f6H1`YpjOML`)+?hf{Z+Io9H zQBpKi9poGOe-8MT13cn%WLs7ISG6lh`a}{o-J)9W6mM=T2L{2-DAE zJo8EH8n#I3x2>}+)UK>j7Rr?{gqM}hWu+H|JlnjZsqXlZKUSLMB^TsZ%1Z*^B*sL* zEH9lDc#ipErt%WQZ+j%K5d({3D@Apis;_YY`hEa55-ya%S%r!

%x-v&8GFh?j9+>{@M|+SuFKE_a05 zn}Xdku36O?nXOx48LIU4Y7>`~Rjaz*?G83J^V?^Qy}>D#64^1!R}naGl&>_H=_>&O zX8CFe;t0EAewe9zg*+4UjlmCVJj(=!4LjC&hIY(&=KlmAhqJ;(FKMhc%v|*M=Qy zJVQHXJaaDR8pJb1ipqEhnDK1H^I_@FFw#<-iQ`}*jUucxSF zr6PQ$rD&!4le}8qp_FyJnr$vF(SEU4N>xpjwFkQVL9U>dYCrTZpem){gU|Uo!S>cX zet_eO`%D+;jl;Sa^~7~De>#n^GBAvK;&t8&_J$!Zp`MthYC+Gjf*+us3*>s?yn^}_ zEAaOm(H|o(TFbBao`PY=T7E@43Ewv;=aAv=-d7Aj8YnFg5c8%CUX8$WMd+lnqi{=O zdwb)jpyIyP9__swYN}Mt0k*iA~&T)v>AgsHX8UryM4`qT)uy?{?)e%kI|3HhfRHBh=j1+7d)je;yMn z_#>W7ua~OT`1@4e>zvGVmDrnt_LEE=}>^=TH3K1H{4l{B08t8uOpR zgMq{+?Fwq(`v6`Tv%WI^;7(|E3hR6Ey_&6{=kmq37l3AYO?=$UCkWNuRz7PV003kpK5CVh%A&?jWvvp&l=fWmn-H3X4-&heb1G)c;IZ~qTvS_-#D17w>S4!4&8O?r@HJpeDoK8Snbs1)%S1z=Zi0__H-XE zeDlIn7u-dU^t@LSae96jnJqp1T9v1%;nDJQFI{wZeygG>{LtI(f4E+~%U>z${cq@O zTlV};yZ$dviyn_$C~yty{#^I-x_`YmvO?E??Z5MKR-gH$F7K&sUv~U=D|Pv-^!Lr5 zJyxg7Uq4dt{JVqYx?KK3;qH>QQeAGJ``v{%jYlerCZCz8IPzoN4-K!J_q|#f4r=AH zidQP_N6##Ib%)F6-!T7lAa}X%<$qh{+jR6t^TukH``#}I-!t&1M}6+~U#)tg z^VFKxk4bgAl=JI&`ah=*|Jz+X`oX&EADO}PyZO%T%Ql{!r_X2a{&i=5zxJ#yKRHo- zXz7_j9nZ0X-Z=~M7whf23O0OjVApuxSSzs7TCaKk(6pSkGX zdwVFa>T#!MZ`p(Y``M8y&zExZpKUnCJO|(TitpvWyzTx?z9*~ni#O~2Z`t0I_vzbj#Uk?pXmO0pZ!AM+Z&DX)-3JnoL}@Sz5h+`<(2Gn7VC29yDck1HJ{VvhVrb6 r6H6*|x&K7To8Nn5l`e-o3%>A<9Gwl55hMMu~xzzq<{&yn6*$7~OCfZFO0|FjJj zz#ZhZ&GYmA75Z@X8-Mdk*xcI(=TCFVmA-i06wd$6_&(J8oF|m8&A?E&TYKxf36^jL z!FzQ2jdM)kd_V4PLHP?G?4M6Q*{^JxAW&`3eE6RDu^I#C@Ib!1334jVH(t!RWckX< zIrQ*s-V<&r&VOFKeKKXsDJLucD#tbXcbra6R-7O&m>}J^Zs&pTPPN${3vX`Man_w2 zI6=SOJ>FEg%MYsX17rIU?4rhUff8Ci)C;mT2gum`8`#JKgT5$F2L_>AAg&&0T zw`t!p_?Br5=if<`KCk~K5X#qKU@%&myZ1l^BK)o8?kKz}H-u|=wB~g4EP;>qYmQD{ KHBpHL6afHS{MF3> delta 709 zcmcbxnCZe|rVS2#jIxs*`{L`DC9l$uo6Bd%00p~FbLh;i`vB)}x@+_-cf;rNC>vkUa?o^xYvGC@09cPot zffMxWo&RKSGXBL6x9x6RlTzGVMEEP$?Rw6*aRS`C^9xHBepVNStKam}H}24d6>z?w zn@N+`a&JF5Ax5ReE~DLlJJkhVxw~7KgLI!@u~v!mHixfRxP;thoYgn+rkgR z`75+<8GOq$hV%C&N}tz%6A0z&Ffc?c&E0#T0ulbMa(5J7l^en}JY93Td6vLOdxH~` LS4~u60Yv}+O6u9M diff --git a/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_transfer_and_redox.h5 b/tests/regression_tests/deplete_with_transfer_rates/ref_depletion_with_transfer_and_redox.h5 new file mode 100644 index 0000000000000000000000000000000000000000..6847fd7dfe6960da89a0e4fdf0be9f35eb56d7f4 GIT binary patch literal 37328 zcmeHPeQ;FO6~AvcfyFEkD9BbUJ_?mZLRm8)#x@Bn7nTz}OARLSi=`%~yj} zWTv!@b_OCXL#Apc>GUJoVpFTqG%0LliV+ zn|)+4#j}6xedpeD&pr2d&+okZ-oCewNjs(w~jFzL;F}lGi#o}kFuenP|;RDLG7Eq zZgd3l*X0(fbHsSTI1BodJM(D}uQ(pYwUgy*153=ooJw>zglcNbt14N#L!pt@!X1+& z&J3V~65;%Ve8JMmK%Y%g`a9V6@^GkbXLShF*{2l6X^MdQrJ-s?K^al53Dwqz>uNz! zQZ!T@NkLIb&yB6eImuWr@BsZ3d4cncOy%}aZvbS+bY7ng!})!& z$Njik&Ca|1Y22e`aE#{xW|{{+F8^uV@qvJt2ard8I6t75$P?rv)>|!k9Kr6D!v4%@#7(|0nS z`6M=x%~1L^RE6s+lwHa+IR}RDv#d0hbydi-B@b>ZIN9}=9J9RSf&5B&NdTP05fL!U zOML>*F<*>TUP3;Jc_mRkp0sJ3iyxp~ z5y*|7=JhVnYq=#_F9LG^t-M|aJvJv=&kb_Eu7HZ;v&8eNh?j9+Y`V5jEv~DokSpse zwuNeB+_S1PGTXPpHdN{B*CsA0yH<6-TN5fS;kVC<>q0{;#j|6UuLfb=C|_wX(^nh> z%<@$W#1VGK{4iGe3V9~x8-pL#c$Nwd8+NSm4DFcltmrd*AmSND2$iuAFyk46IKsZk z;+c59HuzzUXDQ&YVaFQJ(2g0;A~GL{c!m)|Wh?~DcvdDy_evJe#Qm1 zMSO&T#k@55VeNc|ej0YH@eJ*l@hpSnc6S*N~x-;vi3k%QHU$3rP>eu3#v*<_~3KCZm?Z8 zmmlD`;&rA6^m<`mjC$fenLnMzST-0&J@Gv62YaoMmrzg4Q~99hSi%ob&jWIyu&$tf z-3t6YNA$$-qdDF9+*P}m0AUAq>{U_}k&yONri9WB3xS2iQI0*RS`cqy(#Hbtz0kgc)BJdP> zjBz!RtwidO4`N~a`mUaK3>6Z-7n{N>aQ}z;C{F^X@jY*|cDwQ>tJ-Gveo3nG zET7tLv)eQi4kl}s?Y7jG_1clvtf?rXIxM8{u|kv&g5SgODAJmwRL#9%@BfN;pd1eu z)Jq&6eqm&{P3YguomL$iijQg4}%^ABb#lvS36~9B)C1^OE#G~POa0DezH$9#)9uWtW6Q92e z=5Me5I-eKDCd|DtiL;GwdbD_8ydfSaUjrWP-!$-0&5ct$`1*_CMV;1Jb9^4JhZef2fzE@KQdY(XRdqHTH*T&Wx@2%?oSsLO0V44$j zJbf?kfc=n%@yrbFi`Kw?SYm#|eaw)6jP6JhAwUQa0)zk|KnM^5ga9Ex2oM5^f4$3%LZnXoc%Z?4PKa-FP7i<6?g-#p_Cx>H0Fkg(7uAfDj-A2mwNX5Fi8y0YZQf zAOr{jLf{$@FuR|SK1!Pr_+1(G@w(rvd+TG-EvSzr-5-d?ha^IP5Fi8y0YZQfAOr{j zLSQ^0VD=zTlsxU8^W+pC+UtJBk@4iN zL0vv_e%afbU*4zxYvPejKS+7_&>X$JYdbic%CD|?GY{5&uzt|(dwg(`^!=A|ePx^4R$lzWRqyuitlk#cf5!Wc=lGVQ99i$b zq$)i7`CWGXU!HFJ#o(1io>twT87~yPf3$sxuK&h=C%e{MIHJo9c@?uyzP? zo-e*upvzmk7Crxu=9Rjpykxczpo11d+hPaJ?rNOK3WvHuj#LCf$R+r zei+}f94lM242tgqwOAD!#`(3{tB>8_avhpg|0*?XVqjC{Cu&)4$X-Z-2Q`0UK^ z37hx*wc5C&_&RaaSvc~m+!B*)R6zg8sFK*x6a;uius)TPcP`YYoX8n!k;T#-MPN0KR@|I z%A3p=E=@bM=dCl|3tRiVoBHSK{g2*v<&I}-Q*>Pa^K|#04sL1F*LU9OS(n}mF4pxA zyu0}Ji3?xU Date: Thu, 13 Nov 2025 21:35:33 +0100 Subject: [PATCH 49/76] Addition of a collision tracking feature (#3417) Co-authored-by: Paul Romano --- CMakeLists.txt | 1 + docs/source/io_formats/collision_track.rst | 46 ++++ docs/source/io_formats/index.rst | 1 + docs/source/io_formats/settings.rst | 79 ++++++ docs/source/pythonapi/base.rst | 3 + docs/source/usersguide/settings.rst | 56 ++++ include/openmc/bank.h | 2 + include/openmc/bank_io.h | 103 +++++++ include/openmc/collision_track.h | 23 ++ include/openmc/constants.h | 1 + include/openmc/mcpl_interface.h | 15 ++ include/openmc/message_passing.h | 1 + include/openmc/particle_data.h | 19 ++ include/openmc/settings.h | 20 ++ include/openmc/simulation.h | 1 + include/openmc/urr.h | 8 +- openmc/settings.py | 246 ++++++++++++++--- openmc/source.py | 175 ++++++++++-- src/bank.cpp | 3 + src/collision_track.cpp | 238 ++++++++++++++++ src/finalize.cpp | 5 + src/initialize.cpp | 31 +++ src/mcpl_interface.cpp | 155 +++++++++++ src/message_passing.cpp | 1 + src/particle.cpp | 6 + src/physics.cpp | 5 +- src/settings.cpp | 76 +++++- src/simulation.cpp | 13 +- src/state_point.cpp | 90 +------ .../collision_track/__init__.py | 0 .../case_1_Reactions/inputs_true.dat | 58 ++++ .../case_1_Reactions/results_true.dat | 2 + .../case_2_Cell_ID/inputs_true.dat | 58 ++++ .../case_2_Cell_ID/results_true.dat | 2 + .../case_3_Material_ID/inputs_true.dat | 58 ++++ .../case_3_Material_ID/results_true.dat | 2 + .../case_4_Nuclide_ID/inputs_true.dat | 58 ++++ .../case_4_Nuclide_ID/results_true.dat | 2 + .../case_5_Universe_ID/inputs_true.dat | 59 ++++ .../case_5_Universe_ID/results_true.dat | 2 + .../inputs_true.dat | 58 ++++ .../results_true.dat | 2 + .../inputs_true.dat | 63 +++++ .../results_true.dat | 2 + .../case_8_2threads/inputs_true.dat | 57 ++++ .../case_8_2threads/results_true.dat | 2 + .../regression_tests/collision_track/test.py | 255 ++++++++++++++++++ tests/testing_harness.py | 126 ++++++++- tests/unit_tests/test_collision_track.py | 127 +++++++++ 49 files changed, 2268 insertions(+), 148 deletions(-) create mode 100644 docs/source/io_formats/collision_track.rst create mode 100644 include/openmc/bank_io.h create mode 100644 include/openmc/collision_track.h create mode 100644 src/collision_track.cpp create mode 100644 tests/regression_tests/collision_track/__init__.py create mode 100644 tests/regression_tests/collision_track/case_1_Reactions/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_1_Reactions/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_2_Cell_ID/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_2_Cell_ID/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_3_Material_ID/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_3_Material_ID/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_4_Nuclide_ID/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_4_Nuclide_ID/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_5_Universe_ID/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_5_Universe_ID/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_6_deposited_energy_threshold/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_6_deposited_energy_threshold/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_7_all_parameters_used_together/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_7_all_parameters_used_together/results_true.dat create mode 100644 tests/regression_tests/collision_track/case_8_2threads/inputs_true.dat create mode 100644 tests/regression_tests/collision_track/case_8_2threads/results_true.dat create mode 100644 tests/regression_tests/collision_track/test.py create mode 100644 tests/unit_tests/test_collision_track.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 474451c8ae..87b8789d10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -338,6 +338,7 @@ list(APPEND libopenmc_SOURCES src/cell.cpp src/chain.cpp src/cmfd_solver.cpp + src/collision_track.cpp src/cross_sections.cpp src/dagmc.cpp src/distribution.cpp diff --git a/docs/source/io_formats/collision_track.rst b/docs/source/io_formats/collision_track.rst new file mode 100644 index 0000000000..a364597544 --- /dev/null +++ b/docs/source/io_formats/collision_track.rst @@ -0,0 +1,46 @@ +.. _io_collision_track: + +=========================== +Collision Track File Format +=========================== + +When collision tracking is enabled with ``mcpl=false`` (the default), OpenMC +writes binary data to an HDF5 file named ``collision_track.h5``. The same data +may also be written after each batch when multiple files are requested +(``collision_track.N.h5``) or when the run is performed in parallel. The file +contains the information needed to reconstruct each recorded collision. + +The current revision of the collision track file format is 1.0. + +**/** + +:Attributes: + - **filetype** (*char[]*) -- String indicating the type of file. + For collision-track files the value is ``"collision_track"``. + +:Datasets: + + - **collision_track_bank** (Compound type) -- Collision information + for each stored event. Each entry in the dataset corresponds to one + collision and contains the following fields: + + - ``r`` (*double[3]*) -- Position of the collision in [cm]. + - ``u`` (*double[3]*) -- Direction unit vector immediately after the collision. + - ``E`` (*double*) -- Incident particle energy before the collision in [eV]. + - ``dE`` (*double*) -- Energy loss over the collision (:math:`E_\text{before} - E_\text{after}`) in [eV]. + - ``time`` (*double*) -- Time of the collision in [s]. + - ``wgt`` (*double*) -- Particle weight at the collision. + - ``event_mt`` (*int*) -- ENDF MT number identifying the reaction. + - ``delayed_group`` (*int*) -- Delayed neutron group index (non-zero for delayed events). + - ``cell_id`` (*int*) -- ID of the cell in which the collision occurred. + - ``nuclide_id`` (*int*) -- ZA identifier of the nuclide (ZZZAAAM format). + - ``material_id`` (*int*) -- ID of the material containing the collision site. + - ``universe_id`` (*int*) -- ID of the universe containing the collision site. + - ``n_collision`` (*int*) -- Collision counter for the particle history. + - ``particle`` (*int*) -- Particle type (0=neutron, 1=photon, 2=electron, 3=positron). + - ``parent_id`` (*int64*) -- Unique ID of the parent particle. + - ``progeny_id`` (*int64*) -- Progeny ID of the particle. + +In an MPI run, OpenMC writes the combined dataset by gathering collision-track +entries from all ranks before flushing them to disk, so the final file appears +as though it were produced serially. diff --git a/docs/source/io_formats/index.rst b/docs/source/io_formats/index.rst index 4bbaa961a6..5b4efea669 100644 --- a/docs/source/io_formats/index.rst +++ b/docs/source/io_formats/index.rst @@ -44,6 +44,7 @@ Output Files statepoint source + collision_track summary properties depletion_results diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 720846c851..b7874fcf2f 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -20,6 +20,85 @@ source neutrons. *Default*: None +----------------------------- +```` Element +----------------------------- + +The ```` element indicates to track information about particle +collisions based on a set of criteria and store these events in a file named +``collision_track.h5``. This file records details such as the position of the +interaction, direction of the incoming particle, incident energy and deposited +energy, weight, time of the interaction, and the delayed neutron group (0 for +prompt neutrons). Additional information such as the cell ID, material ID, +universe ID, nuclide ZAID, particle type, and event MT number are also stored. +Users can specify one or more criterion to filter collisions. If no criteria are +specified, it defaults to tracking all collisions across the model. + +.. warning:: + Storing all collisions can be very memory intensive. For more targeted + tracking, users can employ a variety of parameters such as ``cell_ids``, + ``reactions``, ``universe_ids``, ``material_ids``, ``nuclides``, and + ``deposited_E_threshold`` to refine the selection of particle interactions + to be banked. + +This element can contain one or more of the following attributes or +sub-elements: + + :max_collisions: + An integer indicating the maximum number of collisions to be banked per file. + + *Default*: 1000 + + :max_collision_track_files: + An integer indicating the number of collision_track files to be used. + + *Default*: 1 + + :mcpl: + An optional boolean to enable MCPL_-format instead of the native HDF5-based + format. If activated, the output file name and type is changed to + ``collision_track.mcpl``. + + *Default*: false + + .. _MCPL: https://mctools.github.io/mcpl/mcpl.pdf + + :cell_ids: + A list of integers representing cell IDs to define specific cells in which + collisions are to be banked. + + *Default*: None + + :universe_ids: + A list of integers representing the universe IDs to define specific + universes in which collisions are to be banked. + + *Default*: None + + :material_ids: + A list of integers representing the material IDs to define specific + materials in which collisions are to be banked. + + *Default*: None + + :nuclides: + A list of strings representing the nuclide, to define specific + define specific target nuclide collisions to be banked. + + *Default*: None + + :reactions: + A list of integers representing the ENDF-6 format MT numbers or strings + (e.g. (n,fission)) to define specific reaction types to be banked. + + *Default*: None + + :deposited_E_threshold: + A float defining the minimum deposited energy per collision (in eV) to + trigger banking. + + *Default*: 0.0 + ---------------------------------- ```` Element ---------------------------------- diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index 2a9d0876cd..ce2f6f0f85 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -216,6 +216,9 @@ Post-processing :nosignatures: :template: myfunction.rst + openmc.read_collision_track_file + openmc.read_collision_track_hdf5 + openmc.read_collision_track_mcpl openmc.voxel_to_vtk The following classes and functions are used for functional expansion reconstruction. diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index 1b2d4bc1a5..f973f14655 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -756,6 +756,62 @@ instance, whereas the :meth:`openmc.Track.filter` method returns a new track_files = [f"tracks_p{rank}.h5" for rank in range(32)] openmc.Tracks.combine(track_files, "tracks.h5") +Collision Track File +--------------------- + +OpenMC can generate a collision track file that contains detailed collision +information (position, direction, energy, deposited energy, time, weight, cell +ID, material ID, universe ID, nuclide ZAID, particle type, particle delayed +group and particle ID) for each particle collision depending on user-defined +parameters. To invoke this feature, set the +:attr:`~openmc.Settings.collision_track` attribute as shown in this example:: + + settings.collision_track = { + "max_collisions": 300, + "reactions": ["(n,fission)", "(n,2n)"], + "material_ids": [1,2], + "nuclides": ["U238", "O16"], + "cell_ids": [5, 12] + } + +In this example, collision track information is written to the +collision_track.h5 file at the end of the simulation. The file contains +300 recorded collisions that occurred in materials with IDs 1 or 2, involving +fission or (n,2n) reactions on the nuclides U-238 or O-16, within cells +with IDs 5 and 12. +The file can be read using :func:`openmc.read_collision_track_file`. +The example below shows how to extract the data from the collision_track +feature and displays the fields stored in the file: + +>>> data = openmc.read_collision_track_file('collision_track.h5') +>>> data.dtype + dtype([('r', [('x', ' source_bank; extern SharedArray surf_source_bank; +extern SharedArray collision_track_bank; + extern SharedArray fission_bank; extern vector> ifp_source_delayed_group_bank; diff --git a/include/openmc/bank_io.h b/include/openmc/bank_io.h new file mode 100644 index 0000000000..90ffd820fa --- /dev/null +++ b/include/openmc/bank_io.h @@ -0,0 +1,103 @@ +#ifndef OPENMC_BANK_IO_H +#define OPENMC_BANK_IO_H + +#include "hdf5.h" + +#include "openmc/message_passing.h" +#include "openmc/span.h" +#include "openmc/vector.h" + +#include + +#ifdef OPENMC_MPI +#include +#endif + +namespace openmc { + +template +void write_bank_dataset(const char* dataset_name, hid_t group_id, + span bank, const vector& bank_index, hid_t banktype +#ifdef OPENMC_MPI + , + MPI_Datatype mpi_dtype +#endif +) +{ + int64_t dims_size = bank_index.back(); + int64_t count_size = bank_index[mpi::rank + 1] - bank_index[mpi::rank]; + +#ifdef PHDF5 + hsize_t dims[] {static_cast(dims_size)}; + hid_t dspace = H5Screate_simple(1, dims, nullptr); + hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace, H5P_DEFAULT, + H5P_DEFAULT, H5P_DEFAULT); + + hsize_t count[] {static_cast(count_size)}; + hid_t memspace = H5Screate_simple(1, count, nullptr); + + hsize_t start[] {static_cast(bank_index[mpi::rank])}; + H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); + + hid_t plist = H5Pcreate(H5P_DATASET_XFER); + H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); + + H5Dwrite(dset, banktype, memspace, dspace, plist, bank.data()); + + H5Sclose(dspace); + H5Sclose(memspace); + H5Dclose(dset); + H5Pclose(plist); +#else + if (mpi::master) { + hsize_t dims[] {static_cast(dims_size)}; + hid_t dspace = H5Screate_simple(1, dims, nullptr); + hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + +#ifdef OPENMC_MPI + vector temp_bank {bank.begin(), bank.end()}; +#endif + + for (int i = 0; i < mpi::n_procs; ++i) { + hsize_t count[] {static_cast(bank_index[i + 1] - bank_index[i])}; + hid_t memspace = H5Screate_simple(1, count, nullptr); + +#ifdef OPENMC_MPI + if (i > 0) { + MPI_Recv(bank.data(), count[0], mpi_dtype, i, i, mpi::intracomm, + MPI_STATUS_IGNORE); + } +#endif + + hid_t dspace_rank = H5Dget_space(dset); + hsize_t start[] {static_cast(bank_index[i])}; + H5Sselect_hyperslab( + dspace_rank, H5S_SELECT_SET, start, nullptr, count, nullptr); + + H5Dwrite(dset, banktype, memspace, dspace_rank, H5P_DEFAULT, bank.data()); + + H5Sclose(memspace); + H5Sclose(dspace_rank); + } + + H5Dclose(dset); + +#ifdef OPENMC_MPI + std::copy(temp_bank.begin(), temp_bank.end(), bank.begin()); +#endif + } +#ifdef OPENMC_MPI + else { + if (!bank.empty()) { + MPI_Send( + bank.data(), bank.size(), mpi_dtype, 0, mpi::rank, mpi::intracomm); + } + } +#endif +#endif +} + +} // namespace openmc + +#endif // OPENMC_BANK_IO_H diff --git a/include/openmc/collision_track.h b/include/openmc/collision_track.h new file mode 100644 index 0000000000..208b8f6e1f --- /dev/null +++ b/include/openmc/collision_track.h @@ -0,0 +1,23 @@ +#ifndef OPENMC_COLLISION_TRACK_H +#define OPENMC_COLLISION_TRACK_H + +#include + +namespace openmc { + +class Particle; + +//! Reserve space in the collision track bank according to user settings. +void collision_track_reserve_bank(); + +//! Write collision track data to disk when the bank is full or the batch ends. +void collision_track_flush_bank(); + +//! Record the current particle as a collision-track entry when applicable. +//! +//! \param particle Particle whose collision should be recorded if eligible +void collision_track_record(Particle& particle); + +} // namespace openmc + +#endif // OPENMC_COLLISION_TRACK_H diff --git a/include/openmc/constants.h b/include/openmc/constants.h index b661934812..bba260c3a4 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -34,6 +34,7 @@ constexpr array VERSION_VOXEL {2, 0}; constexpr array VERSION_MGXS_LIBRARY {1, 0}; constexpr array VERSION_PROPERTIES {1, 1}; constexpr array VERSION_WEIGHT_WINDOWS {1, 0}; +constexpr array VERSION_COLLISION_TRACK {1, 0}; // ============================================================================ // ADJUSTABLE PARAMETERS diff --git a/include/openmc/mcpl_interface.h b/include/openmc/mcpl_interface.h index a76d72e649..a9cce3e69a 100644 --- a/include/openmc/mcpl_interface.h +++ b/include/openmc/mcpl_interface.h @@ -38,6 +38,21 @@ vector mcpl_source_sites(std::string path); void write_mcpl_source_point(const char* filename, span source_bank, const vector& bank_index); +//! Write an MCPL collision track file +//! +//! This function writes collision track data to an MCPL file. Additional +//! collision-specific metadata (such as energy deposition, material info, etc.) +//! is stored in the file header as blob data. +//! +//! \param[in] filename Path to MCPL file +//! \param[in] collision_track_bank Vector of CollisionTrackSites to write to +//! file for this MPI rank. +//! \param[in] bank_index Pointer to vector of site index ranges over all +//! MPI ranks. +void write_mcpl_collision_track(const char* filename, + span collision_track_bank, + const vector& bank_index); + //! Check if MCPL functionality is available bool is_mcpl_interface_available(); diff --git a/include/openmc/message_passing.h b/include/openmc/message_passing.h index a1641a9069..ce993776b7 100644 --- a/include/openmc/message_passing.h +++ b/include/openmc/message_passing.h @@ -18,6 +18,7 @@ extern bool master; #ifdef OPENMC_MPI extern MPI_Datatype source_site; +extern MPI_Datatype collision_track_site; extern MPI_Comm intracomm; #endif diff --git a/include/openmc/particle_data.h b/include/openmc/particle_data.h index 5383487d4f..fdacfa765b 100644 --- a/include/openmc/particle_data.h +++ b/include/openmc/particle_data.h @@ -56,6 +56,25 @@ struct SourceSite { int64_t progeny_id; }; +struct CollisionTrackSite { + Position r; + Direction u; + double E; + double dE; + double time {0.0}; + double wgt {1.0}; + int event_mt {0}; + int delayed_group {0}; + int cell_id {0}; + int nuclide_id; + int material_id {0}; + int universe_id {0}; + int n_collision {0}; + ParticleType particle; + int64_t parent_id; + int64_t progeny_id; +}; + //! State of a particle used for particle track files struct TrackState { Position r; //!< Position in [cm] diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 78bfa088e6..b369c99fef 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -32,6 +32,24 @@ enum class IFPParameter { GenerationTime, }; +struct CollisionTrackConfig { + bool mcpl_write {false}; //!< Write collision tracks using MCPL? + std::unordered_set + cell_ids; //!< Cell ids where collisions will be written + std::unordered_set + mt_numbers; //!< MT Numbers where collisions will be written + std::unordered_set + universe_ids; //!< Universe IDs where collisions will be written + std::unordered_set + material_ids; //!< Material IDs where collisions will be written + std::unordered_set + nuclides; //!< Nuclides where collisions will be written + double deposited_energy_threshold {0.0}; //!< Minimum deposited energy [eV] + int64_t max_collisions { + 1000}; //!< Maximum events recorded per collision track file + int64_t max_files {1}; //!< Maximum number of collision track files +}; + //============================================================================== // Global variable declarations //============================================================================== @@ -41,6 +59,7 @@ namespace settings { // Boolean flags extern bool assume_separate; //!< assume tallies are spatially separate? extern bool check_overlaps; //!< check overlaps in geometry? +extern bool collision_track; //!< flag to use collision track feature? extern bool confidence_intervals; //!< use confidence intervals for results? extern bool create_fission_neutrons; //!< create fission neutrons (fixed source)? @@ -145,6 +164,7 @@ extern std::unordered_set statepoint_batch; //!< Batches when state should be written extern std::unordered_set source_write_surf_id; //!< Surface ids where sources will be written +extern CollisionTrackConfig collision_track_config; extern double source_rejection_fraction; //!< Minimum fraction of source sites //!< that must be accepted extern double free_gas_threshold; //!< Threshold multiplier for free gas diff --git a/include/openmc/simulation.h b/include/openmc/simulation.h index 3e4e24e1d0..9a6cf1b213 100644 --- a/include/openmc/simulation.h +++ b/include/openmc/simulation.h @@ -22,6 +22,7 @@ constexpr int STATUS_EXIT_ON_TRIGGER {2}; namespace simulation { +extern int ct_current_file; //!< current collision track file index extern "C" int current_batch; //!< current batch extern "C" int current_gen; //!< current fission generation extern "C" bool initialized; //!< has simulation been initialized? diff --git a/include/openmc/urr.h b/include/openmc/urr.h index 3978c7b86a..1e60371584 100644 --- a/include/openmc/urr.h +++ b/include/openmc/urr.h @@ -27,10 +27,10 @@ public: double heating; }; - Interpolation interp_; //!< interpolation type - int inelastic_flag_; //!< inelastic competition flag - int absorption_flag_; //!< other absorption flag - bool multiply_smooth_; //!< multiply by smooth cross section? + Interpolation interp_; //!< interpolation type + int inelastic_flag_; //!< inelastic competition flag + int absorption_flag_; //!< other absorption flag + bool multiply_smooth_; //!< multiply by smooth cross section? vector energy_; //!< incident energies auto n_energy() const { return energy_.size(); } diff --git a/openmc/settings.py b/openmc/settings.py index 2f8a2b1248..43c1fe0698 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -6,7 +6,7 @@ from numbers import Integral, Real from pathlib import Path import lxml.etree as ET - +import warnings import openmc import openmc.checkvalue as cv from openmc.checkvalue import PathLike @@ -47,6 +47,21 @@ class Settings: half-width of the 95% two-sided confidence interval. If False, uncertainties on tally results will be reported as the sample standard deviation. + collision_track : dict + Options for writing collision information. Acceptable keys are: + + :max_collisions: Maximum number of collisions to be banked per file. (int) + :max_collision_track_files: Maximum number of collision_track files. (int) + :mcpl: Output in the form of an MCPL-file. (bool) + :cell_ids: List of cell IDs to define cells in which collisions should be banked. (list of int) + :universe_ids: List of universe IDs to define universes in which collisions should be banked. (list of int) + :material_ids: List of material IDs to define materials in which collisions should be banked. (list of int) + :nuclides: List of nuclides to define nuclides in which collisions should be banked. + (ex: ["I135m", "U233"] ). (list of str) + :reactions: List of reaction to define specific reactions that should be banked + (ex: ["(n,fission)", 2, "(n,2n)"] ). (list of str or int) + :deposited_E_threshold: Number to define the minimum deposited energy during + per collision to trigger banking. (float) create_fission_neutrons : bool Indicate whether fission neutrons should be created or not. cutoff : dict @@ -395,6 +410,9 @@ class Settings: # Iterated Fission Probability self._ifp_n_generation = None + # Collision track feature + self._collision_track = {} + # Output options self._statepoint = {} self._sourcepoint = {} @@ -434,7 +452,8 @@ class Settings: self._max_particle_events = None self._write_initial_source = None self._weight_windows = WeightWindowsList() - self._weight_window_generators = cv.CheckedList(WeightWindowGenerator, 'weight window generators') + self._weight_window_generators = cv.CheckedList( + WeightWindowGenerator, 'weight window generators') self._weight_windows_on = None self._weight_windows_file = None self._weight_window_checkpoints = {} @@ -475,8 +494,9 @@ class Settings: @generations_per_batch.setter def generations_per_batch(self, generations_per_batch: int): - cv.check_type('generations per patch', generations_per_batch, Integral) - cv.check_greater_than('generations per batch', generations_per_batch, 0) + cv.check_type('generations per batch', generations_per_batch, Integral) + cv.check_greater_than('generations per batch', + generations_per_batch, 0) self._generations_per_batch = generations_per_batch @property @@ -506,7 +526,8 @@ class Settings: @rel_max_lost_particles.setter def rel_max_lost_particles(self, rel_max_lost_particles: float): cv.check_type('rel_max_lost_particles', rel_max_lost_particles, Real) - cv.check_greater_than('rel_max_lost_particles', rel_max_lost_particles, 0) + cv.check_greater_than('rel_max_lost_particles', + rel_max_lost_particles, 0) cv.check_less_than('rel_max_lost_particles', rel_max_lost_particles, 1) self._rel_max_lost_particles = rel_max_lost_particles @@ -516,8 +537,10 @@ class Settings: @max_write_lost_particles.setter def max_write_lost_particles(self, max_write_lost_particles: int): - cv.check_type('max_write_lost_particles', max_write_lost_particles, Integral) - cv.check_greater_than('max_write_lost_particles', max_write_lost_particles, 0) + cv.check_type('max_write_lost_particles', + max_write_lost_particles, Integral) + cv.check_greater_than('max_write_lost_particles', + max_write_lost_particles, 0) self._max_write_lost_particles = max_write_lost_particles @property @@ -538,12 +561,12 @@ class Settings: def keff_trigger(self, keff_trigger: dict): if not isinstance(keff_trigger, dict): msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ - 'which is not a Python dictionary' + 'which is not a Python dictionary' raise ValueError(msg) elif 'type' not in keff_trigger: msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ - 'which does not have a "type" key' + 'which does not have a "type" key' raise ValueError(msg) elif keff_trigger['type'] not in ['variance', 'std_dev', 'rel_err']: @@ -553,7 +576,7 @@ class Settings: elif 'threshold' not in keff_trigger: msg = f'Unable to set a trigger on keff from "{keff_trigger}" ' \ - 'which does not have a "threshold" key' + 'which does not have a "threshold" key' raise ValueError(msg) elif not isinstance(keff_trigger['threshold'], Real): @@ -570,7 +593,7 @@ class Settings: @energy_mode.setter def energy_mode(self, energy_mode: str): cv.check_value('energy mode', energy_mode, - ['continuous-energy', 'multi-group']) + ['continuous-energy', 'multi-group']) self._energy_mode = energy_mode @property @@ -593,7 +616,8 @@ class Settings: def source(self, source: SourceBase | Iterable[SourceBase]): if not isinstance(source, MutableSequence): source = [source] - self._source = cv.CheckedList(SourceBase, 'source distributions', source) + self._source = cv.CheckedList( + SourceBase, 'source distributions', source) @property def confidence_intervals(self) -> bool: @@ -610,7 +634,8 @@ class Settings: @electron_treatment.setter def electron_treatment(self, electron_treatment: str): - cv.check_value('electron treatment', electron_treatment, ['led', 'ttb']) + cv.check_value('electron treatment', + electron_treatment, ['led', 'ttb']) self._electron_treatment = electron_treatment @property @@ -704,7 +729,8 @@ class Settings: @trigger_max_batches.setter def trigger_max_batches(self, trigger_max_batches: int): cv.check_type('trigger maximum batches', trigger_max_batches, Integral) - cv.check_greater_than('trigger maximum batches', trigger_max_batches, 0) + cv.check_greater_than('trigger maximum batches', + trigger_max_batches, 0) self._trigger_max_batches = trigger_max_batches @property @@ -713,8 +739,10 @@ class Settings: @trigger_batch_interval.setter def trigger_batch_interval(self, trigger_batch_interval: int): - cv.check_type('trigger batch interval', trigger_batch_interval, Integral) - cv.check_greater_than('trigger batch interval', trigger_batch_interval, 0) + cv.check_type('trigger batch interval', + trigger_batch_interval, Integral) + cv.check_greater_than('trigger batch interval', + trigger_batch_interval, 0) self._trigger_batch_interval = trigger_batch_interval @property @@ -798,19 +826,22 @@ class Settings: @surf_source_write.setter def surf_source_write(self, surf_source_write: dict): - cv.check_type("surface source writing options", surf_source_write, Mapping) + cv.check_type("surface source writing options", + surf_source_write, Mapping) for key, value in surf_source_write.items(): cv.check_value( "surface source writing key", key, - ("surface_ids", "max_particles", "max_source_files", "mcpl", "cell", "cellfrom", "cellto"), + ("surface_ids", "max_particles", "max_source_files", + "mcpl", "cell", "cellfrom", "cellto"), ) if key == "surface_ids": cv.check_type( "surface ids for source banking", value, Iterable, Integral ) for surf_id in value: - cv.check_greater_than("surface id for source banking", surf_id, 0) + cv.check_greater_than( + "surface id for source banking", surf_id, 0) elif key == "mcpl": cv.check_type("write to an MCPL-format file", value, bool) @@ -827,6 +858,79 @@ class Settings: self._surf_source_write = surf_source_write + @property + def collision_track(self) -> dict: + return self._collision_track + + @collision_track.setter + def collision_track(self, collision_track: dict): + cv.check_type('Collision tracking options', collision_track, Mapping) + for key, value in collision_track.items(): + cv.check_value('collision_track key', key, + ('cell_ids', 'reactions', 'universe_ids', 'material_ids', 'nuclides', + 'deposited_E_threshold', 'max_collisions', 'max_collision_track_files', 'mcpl')) + if key == 'cell_ids': + cv.check_type('cell ids for collision tracking data banking', value, + Iterable, Integral) + for cell_id in value: + cv.check_greater_than('cell id for collision tracking data banking', + cell_id, 0) + elif key == 'reactions': + cv.check_type('MT numbers for collision tracking data banking', value, + Iterable) + for reaction in value: + if isinstance(reaction, int): + cv.check_greater_than( + 'MT number for collision tracking data banking', reaction, 0 + ) + elif isinstance(reaction, str): + # check against allowed strings? so far let C++ code handle it + pass + else: + raise TypeError( + f"MT number for collision tracking data banking must be a positive int or string, " + f"got {type(reaction).__name__}") + elif key == 'universe_ids': + cv.check_type('universe ids for collision tracking data banking', value, + Iterable, Integral) + for universe_id in value: + cv.check_greater_than('universe id for collision tracking data banking', + universe_id, 0) + elif key == 'material_ids': + cv.check_type('material ids for collision tracking data banking', value, + Iterable, Integral) + for material_id in value: + cv.check_greater_than('material id for collision tracking data banking', + material_id, 0) + elif key == 'nuclides': + cv.check_type('nuclides for collision tracking data banking', value, + Iterable, str) + for nuclide in value: + # If nuclide name doesn't look valid, give a warning + try: + openmc.data.zam(nuclide) + except ValueError: + warnings.warn(f"Nuclide {nuclide} is not valid") + elif key == 'deposited_E_threshold': + cv.check_type('Deposited Energy Threshold for collision tracking data banking', + value, Real) + cv.check_greater_than('Deposited Energy Threshold for collision tracking data banking', + value, 0) + elif key == 'max_collisions': + cv.check_type('maximum collisions banks per file', + value, Integral) + cv.check_greater_than('maximum collisions banks in collision tracking', + value, 0) + elif key == 'max_collision_track_files': + cv.check_type('maximum collisions banks', + value, Integral) + cv.check_greater_than('maximum number of collision_track files ', + value, 0) + elif key == 'mcpl': + cv.check_type('write to an MCPL-format file', value, bool) + + self._collision_track = collision_track + @property def no_reduce(self) -> bool: return self._no_reduce @@ -943,7 +1047,7 @@ class Settings: def cutoff(self, cutoff: dict): if not isinstance(cutoff, Mapping): msg = f'Unable to set cutoff from "{cutoff}" which is not a '\ - 'Python dictionary' + 'Python dictionary' raise ValueError(msg) for key in cutoff: if key == 'weight': @@ -961,7 +1065,7 @@ class Settings: cv.check_greater_than('energy cutoff', cutoff[key], 0.0) else: msg = f'Unable to set cutoff to "{key}" which is unsupported ' \ - 'by OpenMC' + 'by OpenMC' self._cutoff = cutoff @@ -1130,12 +1234,14 @@ class Settings: @weight_window_checkpoints.setter def weight_window_checkpoints(self, weight_window_checkpoints: dict): for key in weight_window_checkpoints.keys(): - cv.check_value('weight_window_checkpoints', key, ('collision', 'surface')) + cv.check_value('weight_window_checkpoints', + key, ('collision', 'surface')) self._weight_window_checkpoints = weight_window_checkpoints @property def max_splits(self): - raise AttributeError('max_splits has been deprecated. Please use max_history_splits instead') + raise AttributeError( + 'max_splits has been deprecated. Please use max_history_splits instead') @property def max_history_splits(self) -> int: @@ -1184,7 +1290,8 @@ class Settings: def weight_window_generators(self, wwgs): if not isinstance(wwgs, MutableSequence): wwgs = [wwgs] - self._weight_window_generators = cv.CheckedList(WeightWindowGenerator, 'weight window generators', wwgs) + self._weight_window_generators = cv.CheckedList( + WeightWindowGenerator, 'weight window generators', wwgs) @property def random_ray(self) -> dict: @@ -1221,7 +1328,8 @@ class Settings: for mesh, domains in value: cv.check_type('mesh', mesh, MeshBase) cv.check_type('domains', domains, Iterable) - valid_types = (openmc.Material, openmc.Cell, openmc.Universe) + valid_types = (openmc.Material, + openmc.Cell, openmc.Universe) for domain in domains: if not isinstance(domain, valid_types): raise ValueError( @@ -1255,9 +1363,12 @@ class Settings: @source_rejection_fraction.setter def source_rejection_fraction(self, source_rejection_fraction: float): - cv.check_type('source_rejection_fraction', source_rejection_fraction, Real) - cv.check_greater_than('source_rejection_fraction', source_rejection_fraction, 0) - cv.check_less_than('source_rejection_fraction', source_rejection_fraction, 1) + cv.check_type('source_rejection_fraction', + source_rejection_fraction, Real) + cv.check_greater_than('source_rejection_fraction', + source_rejection_fraction, 0) + cv.check_less_than('source_rejection_fraction', + source_rejection_fraction, 1) self._source_rejection_fraction = source_rejection_fraction @property @@ -1422,6 +1533,45 @@ class Settings: subelement = ET.SubElement(element, key) subelement.text = str(self._surf_source_write[key]) + def _create_collision_track_subelement(self, root): + if self._collision_track: + element = ET.SubElement(root, "collision_track") + if 'cell_ids' in self._collision_track: + subelement = ET.SubElement(element, "cell_ids") + subelement.text = ' '.join( + str(x) for x in self._collision_track['cell_ids']) + if 'reactions' in self._collision_track: + subelement = ET.SubElement(element, "reactions") + subelement.text = ' '.join( + str(x) for x in self._collision_track['reactions']) + if 'universe_ids' in self._collision_track: + subelement = ET.SubElement(element, "universe_ids") + subelement.text = ' '.join( + str(x) for x in self._collision_track['universe_ids']) + if 'material_ids' in self._collision_track: + subelement = ET.SubElement(element, "material_ids") + subelement.text = ' '.join( + str(x) for x in self._collision_track['material_ids']) + if 'nuclides' in self._collision_track: + subelement = ET.SubElement(element, "nuclides") + subelement.text = ' '.join( + str(x) for x in self._collision_track['nuclides']) + if 'deposited_E_threshold' in self._collision_track: + subelement = ET.SubElement(element, "deposited_E_threshold") + subelement.text = str( + self._collision_track['deposited_E_threshold']) + if 'max_collisions' in self._collision_track: + subelement = ET.SubElement(element, "max_collisions") + subelement.text = str(self._collision_track['max_collisions']) + if 'max_collision_track_files' in self._collision_track: + subelement = ET.SubElement( + element, "max_collision_track_files") + subelement.text = str( + self._collision_track['max_collision_track_files']) + if 'mcpl' in self._collision_track: + subelement = ET.SubElement(element, "mcpl") + subelement.text = str(self._collision_track['mcpl']).lower() + def _create_confidence_intervals(self, root): if self._confidence_intervals is not None: element = ET.SubElement(root, "confidence_intervals") @@ -1477,8 +1627,8 @@ class Settings: # use default heuristic for entropy mesh if not set by user if self.entropy_mesh.dimension is None: if self.particles is None: - raise RuntimeError("Number of particles must be set in order to " \ - "use entropy mesh dimension heuristic") + raise RuntimeError("Number of particles must be set in order to " + "use entropy mesh dimension heuristic") else: n = ceil((self.particles / 20.0)**(1.0 / 3.0)) d = len(self.entropy_mesh.lower_left) @@ -1568,7 +1718,8 @@ class Settings: path = f"./mesh[@id='{self.ufs_mesh.id}']" if root.find(path) is None: root.append(self.ufs_mesh.to_xml_element()) - if mesh_memo is not None: mesh_memo.add(self.ufs_mesh.id) + if mesh_memo is not None: + mesh_memo.add(self.ufs_mesh.id) def _create_use_decay_photons_subelement(self, root): if self._use_decay_photons is not None: @@ -1694,11 +1845,13 @@ class Settings: if 'collision' in self._weight_window_checkpoints: subelement = ET.SubElement(element, "collision") - subelement.text = str(self._weight_window_checkpoints['collision']).lower() + subelement.text = str( + self._weight_window_checkpoints['collision']).lower() if 'surface' in self._weight_window_checkpoints: subelement = ET.SubElement(element, "surface") - subelement.text = str(self._weight_window_checkpoints['surface']).lower() + subelement.text = str( + self._weight_window_checkpoints['surface']).lower() def _create_max_history_splits_subelement(self, root): if self._max_history_splits is not None: @@ -1730,6 +1883,9 @@ class Settings: for domain in domains: domain_elem = ET.SubElement(mesh_elem, 'domain') domain_elem.set('id', str(domain.id)) + domain_elem.set( + 'type', domain.__class__.__name__.lower()) + if mesh_memo is not None and mesh.id not in mesh_memo: domain_elem.set('type', domain.__class__.__name__.lower()) # See if a element already exists -- if not, add it path = f"./mesh[@id='{mesh.id}']" @@ -1881,6 +2037,25 @@ class Settings: value = int(value) self.surf_source_write[key] = value + def _collision_track_from_xml_element(self, root): + elem = root.find('collision_track') + if elem is not None: + for key in ('cell_ids', 'reactions', 'universe_ids', 'material_ids', 'nuclides', + 'deposited_E_threshold', 'max_collisions', "max_collision_track_files", 'mcpl'): + value = get_text(elem, key) + if value is not None: + if key in ('cell_ids', 'universe_ids', 'material_ids'): + value = [int(x) for x in value.split()] + elif key in ('reactions', 'nuclides'): + value = value.split() + elif key in ('max_collisions', 'max_collision_track_files'): + value = int(value) + elif key == 'deposited_E_threshold': + value = float(value) + elif key == 'mcpl': + value = value in ('true', '1') + self.collision_track[key] = value + def _confidence_intervals_from_xml_element(self, root): text = get_text(root, 'confidence_intervals') if text is not None: @@ -2180,7 +2355,8 @@ class Settings: elif domain_type == 'universe': domain = openmc.Universe(domain_id) domains.append(domain) - self.random_ray['source_region_meshes'].append((mesh, domains)) + self.random_ray['source_region_meshes'].append( + (mesh, domains)) def _use_decay_photons_from_xml_element(self, root): text = get_text(root, 'use_decay_photons') @@ -2223,6 +2399,7 @@ class Settings: self._create_sourcepoint_subelement(element) self._create_surf_source_read_subelement(element) self._create_surf_source_write_subelement(element) + self._create_collision_track_subelement(element) self._create_confidence_intervals(element) self._create_electron_treatment_subelement(element) self._create_energy_mode_subelement(element) @@ -2336,6 +2513,7 @@ class Settings: settings._sourcepoint_from_xml_element(elem) settings._surf_source_read_from_xml_element(elem) settings._surf_source_write_from_xml_element(elem) + settings._collision_track_from_xml_element(elem) settings._confidence_intervals_from_xml_element(elem) settings._electron_treatment_from_xml_element(elem) settings._energy_mode_from_xml_element(elem) diff --git a/openmc/source.py b/openmc/source.py index 9b730cf1de..84d8a9619d 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -6,7 +6,6 @@ from numbers import Real from pathlib import Path import warnings from typing import Any -from pathlib import Path import lxml.etree as ET import numpy as np @@ -107,10 +106,12 @@ class SourceBase(ABC): cv.check_type('fissionable', value, bool) self._constraints['fissionable'] = value elif key == 'rejection_strategy': - cv.check_value('rejection strategy', value, ('resample', 'kill')) + cv.check_value('rejection strategy', + value, ('resample', 'kill')) self._constraints['rejection_strategy'] = value else: - raise ValueError(f'Unknown key in constraints dictionary: {key}') + raise ValueError( + f'Unknown key in constraints dictionary: {key}') @abstractmethod def populate_xml_element(self, element): @@ -144,13 +145,16 @@ class SourceBase(ABC): dt_elem = ET.SubElement(constraints_elem, "domain_type") dt_elem.text = constraints["domain_type"] id_elem = ET.SubElement(constraints_elem, "domain_ids") - id_elem.text = ' '.join(str(uid) for uid in constraints["domain_ids"]) + id_elem.text = ' '.join(str(uid) + for uid in constraints["domain_ids"]) if "time_bounds" in constraints: dt_elem = ET.SubElement(constraints_elem, "time_bounds") - dt_elem.text = ' '.join(str(t) for t in constraints["time_bounds"]) + dt_elem.text = ' '.join(str(t) + for t in constraints["time_bounds"]) if "energy_bounds" in constraints: dt_elem = ET.SubElement(constraints_elem, "energy_bounds") - dt_elem.text = ' '.join(str(E) for E in constraints["energy_bounds"]) + dt_elem.text = ' '.join(str(E) + for E in constraints["energy_bounds"]) if "fissionable" in constraints: dt_elem = ET.SubElement(constraints_elem, "fissionable") dt_elem.text = str(constraints["fissionable"]).lower() @@ -199,7 +203,8 @@ class SourceBase(ABC): elif source_type == 'mesh': return MeshSource.from_xml_element(elem, meshes) else: - raise ValueError(f'Source type {source_type} is not recognized') + raise ValueError( + f'Source type {source_type} is not recognized') @staticmethod def _get_constraints(elem: ET.Element) -> dict[str, Any]: @@ -316,7 +321,8 @@ class IndependentSource(SourceBase): time: openmc.stats.Univariate | None = None, strength: float = 1.0, particle: str = 'neutron', - domains: Sequence[openmc.Cell | openmc.Material | openmc.Universe] | None = None, + domains: Sequence[openmc.Cell | openmc.Material | + openmc.Universe] | None = None, constraints: dict[str, Any] | None = None ): if domains is not None: @@ -527,11 +533,12 @@ class MeshSource(SourceBase): 'fissionable', and 'rejection_strategy'. """ + def __init__( self, mesh: MeshBase, sources: Sequence[SourceBase], - constraints: dict[str, Any] | None = None, + constraints: dict[str, Any] | None = None, ): super().__init__(strength=None, constraints=constraints) self.mesh = mesh @@ -577,7 +584,8 @@ class MeshSource(SourceBase): elif isinstance(self.mesh, UnstructuredMesh): if s.ndim > 1: - raise ValueError('Sources must be a 1-D array for unstructured mesh') + raise ValueError( + 'Sources must be a 1-D array for unstructured mesh') self._sources = s for src in self._sources: @@ -646,7 +654,8 @@ class MeshSource(SourceBase): mesh_id = int(get_text(elem, 'mesh')) mesh = meshes[mesh_id] - sources = [SourceBase.from_xml_element(e) for e in elem.iterchildren('source')] + sources = [SourceBase.from_xml_element( + e) for e in elem.iterchildren('source')] constraints = cls._get_constraints(elem) return cls(mesh, sources, constraints=constraints) @@ -656,7 +665,8 @@ def Source(*args, **kwargs): A function for backward compatibility of sources. Will be removed in the future. Please update to IndependentSource. """ - warnings.warn("This class is deprecated in favor of 'IndependentSource'", FutureWarning) + warnings.warn( + "This class is deprecated in favor of 'IndependentSource'", FutureWarning) return openmc.IndependentSource(*args, **kwargs) @@ -703,6 +713,7 @@ class CompiledSource(SourceBase): 'fissionable', and 'rejection_strategy'. """ + def __init__( self, library: PathLike, @@ -914,7 +925,8 @@ class ParticleType(IntEnum): try: return cls[value.upper()] except KeyError: - raise ValueError(f"Invalid string for creation of {cls.__name__}: {value}") + raise ValueError( + f"Invalid string for creation of {cls.__name__}: {value}") @classmethod def from_pdg_number(cls, pdg_number: int) -> ParticleType: @@ -984,6 +996,7 @@ class SourceParticle: Type of the particle """ + def __init__( self, r: Iterable[float] = (0., 0., 0.), @@ -1042,7 +1055,8 @@ def write_source_file( openmc.SourceParticle """ - cv.check_iterable_type("source particles", source_particles, SourceParticle) + cv.check_iterable_type( + "source particles", source_particles, SourceParticle) pl = ParticleList(source_particles) pl.export_to_hdf5(filename, **kwargs) @@ -1104,7 +1118,8 @@ class ParticleList(list): for particle in f.particles: # Determine particle type based on the PDG number try: - particle_type = ParticleType.from_pdg_number(particle.pdgcode) + particle_type = ParticleType.from_pdg_number( + particle.pdgcode) except ValueError: particle_type = "UNKNOWN" @@ -1241,3 +1256,133 @@ def read_source_file(filename: PathLike) -> ParticleList: return ParticleList.from_hdf5(filename) else: return ParticleList.from_mcpl(filename) + + +def read_collision_track_hdf5(filename): + """Read a collision track file in HDF5 format. + + Parameters + ---------- + filename : str or path-like + Path to the HDF5 collision track file. + + Returns + ------- + numpy.ndarray + Structured array containing collision track data. + + See Also + -------- + read_collision_track_mcpl + read_collision_track_file + """ + + with h5py.File(filename, 'r') as file: + data = file['collision_track_bank'][:] + + return data + + +def read_collision_track_mcpl(file_path): + """Read a collision track file in MCPL format. + + Parameters + ---------- + file_path : str or path-like + Path to the MCPL collision track file. + + Returns + ------- + numpy.ndarray + Structured array of particle collision track information, including + position, direction, energy, weight, reaction data, and identifiers. + + See Also + -------- + read_collision_track_hdf5 + read_collision_track_file + """ + import mcpl + myfile = mcpl.MCPLFile(file_path) + data = { + 'r': [], # for position (x, y, z) + 'u': [], # for direction (ux, uy, uz) + 'E': [], 'dE': [], 'time': [], + 'wgt': [], 'event_mt': [], 'delayed_group': [], + 'cell_id': [], 'nuclide_id': [], 'material_id': [], + 'universe_id': [], 'n_collision': [], 'particle': [], + 'parent_id': [], 'progeny_id': [] + } + + # Read and collect data from the MCPL file + for i, p in enumerate(myfile.particles): + if f'blob_{i}' in myfile.blobs: + blob_data = myfile.blobs[f'blob_{i}'] + decoded_str = blob_data.decode('utf-8') + pairs = decoded_str.split(';') + values_dict = {k.strip(): v.strip() + for k, v in (pair.split(':') for pair in pairs if pair.strip())} + + data['r'].append((p.x, p.y, p.z)) # Append as tuple + data['u'].append((p.ux, p.uy, p.uz)) # Append as tuple + data['E'].append(p.ekin * 1e6) + data['dE'].append(float(values_dict.get('dE', 0))) + data['time'].append(p.time * 1e-3) + data['wgt'].append(p.weight) + data['event_mt'].append(int(values_dict.get('event_mt', 0))) + data['delayed_group'].append( + int(values_dict.get('delayed_group', 0))) + data['cell_id'].append(int(values_dict.get('cell_id', 0))) + data['nuclide_id'].append(int(values_dict.get('nuclide_id', 0))) + data['material_id'].append(int(values_dict.get('material_id', 0))) + data['universe_id'].append(int(values_dict.get('universe_id', 0))) + data['n_collision'].append(int(values_dict.get('n_collision', 0))) + data['particle'].append(ParticleType.from_pdg_number(p.pdgcode)) + data['parent_id'].append(int(values_dict.get('parent_id', 0))) + data['progeny_id'].append(int(values_dict.get('progeny_id', 0))) + + dtypes = [ + ('r', [('x', 'f8'), ('y', 'f8'), ('z', 'f8')]), + ('u', [('x', 'f8'), ('y', 'f8'), ('z', 'f8')]), + ('E', 'f8'), ('dE', 'f8'), ('time', 'f8'), ('wgt', 'f8'), + ('event_mt', 'f8'), ('delayed_group', 'i4'), ('cell_id', 'i4'), + ('nuclide_id', 'i4'), ('material_id', 'i4'), ('universe_id', 'i4'), + ('n_collision', 'i4'), ('particle', 'i4'), + ('parent_id', 'i8'), ('progeny_id', 'i8') + ] + + structured_array = np.zeros(len(data['r']), dtype=dtypes) + for key in data: + structured_array[key] = data[key] # Assign data + + return structured_array + + +def read_collision_track_file(filename): + """Read a collision track file (HDF5 or MCPL) and return its data. + + Parameters + ---------- + filename : str or path-like + Path to the collision track file to read. Must end with + ``.h5`` or ``.mcpl``. + + Returns + ------- + numpy.ndarray + Structured array containing collision track data. + + See Also + -------- + read_collision_track_hdf5 + read_collision_track_mcpl + """ + + filename = Path(filename) + if filename.suffix not in ('.h5', '.mcpl'): + raise ValueError('Collision track file must have a .h5 or .mcpl extension.') + + if filename.suffix == '.h5': + return read_collision_track_hdf5(filename) + else: + return read_collision_track_mcpl(filename) diff --git a/src/bank.cpp b/src/bank.cpp index 3e806b3c0b..33790379b8 100644 --- a/src/bank.cpp +++ b/src/bank.cpp @@ -20,6 +20,8 @@ vector source_bank; SharedArray surf_source_bank; +SharedArray collision_track_bank; + // The fission bank is allocated as a SharedArray, rather than a vector, as it // will be shared by all threads in the simulation. It will be allocated to a // fixed maximum capacity in the init_fission_bank() function. Then, Elements @@ -50,6 +52,7 @@ void free_memory_bank() { simulation::source_bank.clear(); simulation::surf_source_bank.clear(); + simulation::collision_track_bank.clear(); simulation::fission_bank.clear(); simulation::progeny_per_particle.clear(); simulation::ifp_source_delayed_group_bank.clear(); diff --git a/src/collision_track.cpp b/src/collision_track.cpp new file mode 100644 index 0000000000..75e56574a6 --- /dev/null +++ b/src/collision_track.cpp @@ -0,0 +1,238 @@ +#include "openmc/collision_track.h" + +#include +#include + +#include + +#include "openmc/bank.h" +#include "openmc/bank_io.h" +#include "openmc/cell.h" +#include "openmc/constants.h" +#include "openmc/error.h" +#include "openmc/file_utils.h" +#include "openmc/hdf5_interface.h" +#include "openmc/material.h" +#include "openmc/mcpl_interface.h" +#include "openmc/message_passing.h" +#include "openmc/nuclide.h" +#include "openmc/output.h" +#include "openmc/particle.h" +#include "openmc/settings.h" +#include "openmc/simulation.h" +#include "openmc/universe.h" + +#ifdef OPENMC_MPI +#include +#endif + +namespace openmc { + +namespace { + +hid_t h5_collision_track_banktype() +{ + hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(Position)); + H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE); + H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE); + H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE); + + hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(CollisionTrackSite)); + + H5Tinsert(banktype, "r", HOFFSET(CollisionTrackSite, r), postype); + H5Tinsert(banktype, "u", HOFFSET(CollisionTrackSite, u), postype); + H5Tinsert(banktype, "E", HOFFSET(CollisionTrackSite, E), H5T_NATIVE_DOUBLE); + H5Tinsert(banktype, "dE", HOFFSET(CollisionTrackSite, dE), H5T_NATIVE_DOUBLE); + H5Tinsert( + banktype, "time", HOFFSET(CollisionTrackSite, time), H5T_NATIVE_DOUBLE); + H5Tinsert( + banktype, "wgt", HOFFSET(CollisionTrackSite, wgt), H5T_NATIVE_DOUBLE); + H5Tinsert(banktype, "event_mt", HOFFSET(CollisionTrackSite, event_mt), + H5T_NATIVE_INT); + H5Tinsert(banktype, "delayed_group", + HOFFSET(CollisionTrackSite, delayed_group), H5T_NATIVE_INT); + H5Tinsert( + banktype, "cell_id", HOFFSET(CollisionTrackSite, cell_id), H5T_NATIVE_INT); + H5Tinsert(banktype, "nuclide_id", HOFFSET(CollisionTrackSite, nuclide_id), + H5T_NATIVE_INT); + H5Tinsert(banktype, "material_id", HOFFSET(CollisionTrackSite, material_id), + H5T_NATIVE_INT); + H5Tinsert(banktype, "universe_id", HOFFSET(CollisionTrackSite, universe_id), + H5T_NATIVE_INT); + H5Tinsert(banktype, "n_collision", HOFFSET(CollisionTrackSite, n_collision), + H5T_NATIVE_INT); + H5Tinsert(banktype, "particle", HOFFSET(CollisionTrackSite, particle), + H5T_NATIVE_INT); + H5Tinsert(banktype, "parent_id", HOFFSET(CollisionTrackSite, parent_id), + H5T_NATIVE_INT64); + H5Tinsert(banktype, "progeny_id", HOFFSET(CollisionTrackSite, progeny_id), + H5T_NATIVE_INT64); + H5Tclose(postype); + return banktype; +} + +void write_collision_track_bank(hid_t group_id, + openmc::span collision_track_bank, + const openmc::vector& bank_index) +{ + hid_t banktype = h5_collision_track_banktype(); +#ifdef OPENMC_MPI + write_bank_dataset("collision_track_bank", group_id, collision_track_bank, + bank_index, banktype, mpi::collision_track_site); +#else + write_bank_dataset("collision_track_bank", group_id, collision_track_bank, + bank_index, banktype); +#endif + + H5Tclose(banktype); +} + +void write_h5_collision_track(const char* filename, + openmc::span collision_track_bank, + const openmc::vector& bank_index) +{ +#ifdef PHDF5 + bool parallel = true; +#else + bool parallel = false; +#endif + + if (!filename) + fatal_error("write_h5_collision_track filename needs a nonempty name."); + + std::string filename_(filename); + const auto extension = get_file_extension(filename_); + if (extension.empty()) { + filename_.append(".h5"); + } else if (extension != "h5") { + warning("write_h5_collision_track was passed a file extension differing " + "from .h5, but an hdf5 file will be written."); + } + + hid_t file_id; + if (mpi::master || parallel) { + file_id = file_open(filename_.c_str(), 'w', true); + + // Write filetype and version info + write_attribute(file_id, "filetype", "collision_track"); + write_attribute(file_id, "version", VERSION_COLLISION_TRACK); + } + + write_collision_track_bank(file_id, collision_track_bank, bank_index); + + if (mpi::master || parallel) + file_close(file_id); +} + +} // namespace + +bool should_record_event(int id_cell, int mt_event, const std::string& nuclide, + int id_universe, int id_material, double energy_loss) +{ + auto matches_filter = [](const auto& filter_set, const auto& value) { + return filter_set.empty() || filter_set.count(value) > 0; + }; + + const auto& cfg = settings::collision_track_config; + return simulation::current_batch > settings::n_inactive && + !simulation::collision_track_bank.full() && + matches_filter(cfg.cell_ids, id_cell) && + matches_filter(cfg.mt_numbers, mt_event) && + matches_filter(cfg.universe_ids, id_universe) && + matches_filter(cfg.material_ids, id_material) && + matches_filter(cfg.nuclides, nuclide) && + (cfg.deposited_energy_threshold == 0 || + cfg.deposited_energy_threshold < energy_loss); +} + +void collision_track_reserve_bank() +{ + simulation::collision_track_bank.reserve( + settings::collision_track_config.max_collisions); +} + +void collision_track_flush_bank() +{ + const auto& cfg = settings::collision_track_config; + if (simulation::ct_current_file > cfg.max_files) + return; + + bool last_batch = (simulation::current_batch == settings::n_batches); + if (!simulation::collision_track_bank.full() && !last_batch) + return; + + auto size = simulation::collision_track_bank.size(); + if (size == 0 && !last_batch) + return; + + auto collision_track_work_index = mpi::calculate_parallel_index_vector(size); + openmc::span collisiontrackbankspan( + simulation::collision_track_bank.begin(), size); + + std::string ext = cfg.mcpl_write ? "mcpl" : "h5"; + auto filename = fmt::format("{}collision_track.{}.{}", settings::path_output, + simulation::ct_current_file, ext); + + if (cfg.max_files == 1 || (simulation::ct_current_file == 1 && last_batch)) { + filename = settings::path_output + "collision_track." + ext; + } + write_message("Creating {}...", filename, 4); + + if (cfg.mcpl_write) { + write_mcpl_collision_track( + filename.c_str(), collisiontrackbankspan, collision_track_work_index); + } else { + write_h5_collision_track( + filename.c_str(), collisiontrackbankspan, collision_track_work_index); + } + + simulation::collision_track_bank.clear(); + if (!last_batch && cfg.max_files >= 1) { + collision_track_reserve_bank(); + } + ++simulation::ct_current_file; +} + +void collision_track_record(Particle& particle) +{ + int cell_index = particle.lowest_coord().cell(); + if (cell_index == C_NONE) + return; + + int cell_id = model::cells[cell_index]->id_; + const auto* nuclide_ptr = data::nuclides[particle.event_nuclide()].get(); + std::string nuclide = nuclide_ptr->name_; + int universe_id = model::universes[particle.lowest_coord().universe()]->id_; + double delta_E = particle.E_last() - particle.E(); + int material_index = particle.material(); + if (material_index == C_NONE) + return; + + int material_id = model::materials[material_index]->id_; + + if (!should_record_event(cell_id, particle.event_mt(), nuclide, universe_id, + material_id, delta_E)) + return; + + CollisionTrackSite site; + site.r = particle.r(); + site.u = particle.u(); + site.E = particle.E_last(); + site.dE = delta_E; + site.time = particle.time(); + site.wgt = particle.wgt(); + site.event_mt = particle.event_mt(); + site.delayed_group = particle.delayed_group(); + site.cell_id = cell_id; + site.nuclide_id = + 10000 * nuclide_ptr->Z_ + 10 * nuclide_ptr->A_ + nuclide_ptr->metastable_; + site.material_id = material_id; + site.universe_id = universe_id; + site.n_collision = particle.n_collision(); + site.particle = particle.type(); + site.parent_id = particle.id(); + site.progeny_id = particle.n_progeny(); + simulation::collision_track_bank.thread_safe_append(site); +} + +} // namespace openmc diff --git a/src/finalize.cpp b/src/finalize.cpp index 659f390b39..9ee9434099 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -3,6 +3,7 @@ #include "openmc/bank.h" #include "openmc/capi.h" #include "openmc/cmfd_solver.h" +#include "openmc/collision_track.h" #include "openmc/constants.h" #include "openmc/cross_sections.h" #include "openmc/dagmc.h" @@ -76,6 +77,7 @@ int openmc_finalize() // Reset global variables settings::assume_separate = false; settings::check_overlaps = false; + settings::collision_track_config = CollisionTrackConfig {}; settings::confidence_intervals = false; settings::create_fission_neutrons = true; settings::create_delayed_neutrons = true; @@ -177,6 +179,9 @@ int openmc_finalize() if (mpi::source_site != MPI_DATATYPE_NULL) { MPI_Type_free(&mpi::source_site); } + if (mpi::collision_track_site != MPI_DATATYPE_NULL) { + MPI_Type_free(&mpi::collision_track_site); + } #endif openmc_reset_random_ray(); diff --git a/src/initialize.cpp b/src/initialize.cpp index 36f3261169..e2a5b97433 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -178,6 +178,37 @@ void initialize_mpi(MPI_Comm intracomm) MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_LONG, MPI_LONG}; MPI_Type_create_struct(11, blocks, disp, types, &mpi::source_site); MPI_Type_commit(&mpi::source_site); + + CollisionTrackSite bc; + MPI_Aint dispc[16]; + MPI_Get_address(&bc.r, &dispc[0]); // double + MPI_Get_address(&bc.u, &dispc[1]); // double + MPI_Get_address(&bc.E, &dispc[2]); // double + MPI_Get_address(&bc.dE, &dispc[3]); // double + MPI_Get_address(&bc.time, &dispc[4]); // double + MPI_Get_address(&bc.wgt, &dispc[5]); // double + MPI_Get_address(&bc.event_mt, &dispc[6]); // int + MPI_Get_address(&bc.delayed_group, &dispc[7]); // int + MPI_Get_address(&bc.cell_id, &dispc[8]); // int + MPI_Get_address(&bc.nuclide_id, &dispc[9]); // int + MPI_Get_address(&bc.material_id, &dispc[10]); // int + MPI_Get_address(&bc.universe_id, &dispc[11]); // int + MPI_Get_address(&bc.n_collision, &dispc[12]); // int + MPI_Get_address(&bc.particle, &dispc[13]); // int + MPI_Get_address(&bc.parent_id, &dispc[14]); // int64_t + MPI_Get_address(&bc.progeny_id, &dispc[15]); // int64_t + for (int i = 15; i >= 0; --i) { + dispc[i] -= dispc[0]; + } + + int blocksc[] = {3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + MPI_Datatype typesc[] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, + MPI_DOUBLE, MPI_DOUBLE, MPI_INT, MPI_INT, MPI_INT, MPI_INT, MPI_INT, + MPI_INT, MPI_INT, MPI_INT, MPI_INT64_T, MPI_INT64_T}; + + MPI_Type_create_struct( + 16, blocksc, dispc, typesc, &mpi::collision_track_site); + MPI_Type_commit(&mpi::collision_track_site); } #endif // OPENMC_MPI diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index b8e7807100..1294073019 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,8 @@ using mcpl_hdr_nparticles_fpt = uint64_t (*)(mcpl_file_t* file_handle); using mcpl_read_fpt = const mcpl_particle_repr_t* (*)(mcpl_file_t* file_handle); using mcpl_close_file_fpt = void (*)(mcpl_file_t* file_handle); +using mcpl_hdr_add_data_fpt = void (*)(mcpl_outfile_t* file_handle, + const char* key, int32_t ldata, const char* data); using mcpl_create_outfile_fpt = mcpl_outfile_t* (*)(const char* filename); using mcpl_hdr_set_srcname_fpt = void (*)( mcpl_outfile_t* outfile_handle, const char* srcname); @@ -110,6 +113,7 @@ struct McplApi { mcpl_close_file_fpt close_file; mcpl_create_outfile_fpt create_outfile; mcpl_hdr_set_srcname_fpt hdr_set_srcname; + mcpl_hdr_add_data_fpt hdr_add_data; mcpl_add_particle_fpt add_particle; mcpl_close_outfile_fpt close_outfile; mcpl_hdr_add_stat_sum_fpt hdr_add_stat_sum; @@ -146,6 +150,8 @@ struct McplApi { load_symbol_platform("mcpl_create_outfile")); hdr_set_srcname = reinterpret_cast( load_symbol_platform("mcpl_hdr_set_srcname")); + hdr_add_data = reinterpret_cast( + load_symbol_platform("mcpl_hdr_add_data")); add_particle = reinterpret_cast( load_symbol_platform("mcpl_add_particle")); close_outfile = reinterpret_cast( @@ -545,4 +551,153 @@ void write_mcpl_source_point(const char* filename, span source_bank, } } +// Collision track feature with MCPL +void write_mcpl_collision_track_internal(mcpl_outfile_t* file_id, + span collision_track_bank, + const vector& bank_index_all_ranks) +{ + if (mpi::master) { + if (!file_id) { + fatal_error("MCPL: Internal error - master rank called " + "write_mcpl_source_bank_internal with null file_id."); + } + vector receive_buffer; + vector all_sites; + all_sites.reserve(static_cast(bank_index_all_ranks.back())); + vector all_blobs; + all_blobs.reserve(static_cast(bank_index_all_ranks.back())); + + for (int rank_idx = 0; rank_idx < mpi::n_procs; ++rank_idx) { + size_t num_sites_on_rank = static_cast( + bank_index_all_ranks[rank_idx + 1] - bank_index_all_ranks[rank_idx]); + if (num_sites_on_rank == 0) + continue; + + span sites_to_process; +#ifdef OPENMC_MPI + if (rank_idx == mpi::rank) { + sites_to_process = openmc::span( + collision_track_bank.data(), num_sites_on_rank); + } else { + receive_buffer.resize(num_sites_on_rank); + MPI_Recv(receive_buffer.data(), num_sites_on_rank, + mpi::collision_track_site, rank_idx, rank_idx, mpi::intracomm, + MPI_STATUS_IGNORE); + sites_to_process = openmc::span( + receive_buffer.data(), num_sites_on_rank); + } +#else + sites_to_process = openmc::span( + collision_track_bank.data(), num_sites_on_rank); +#endif + + for (const auto& site : sites_to_process) { + std::ostringstream custom_data_stream; + custom_data_stream << " dE : " << site.dE + << " ; event_mt : " << site.event_mt + << " ; delayed_group : " << site.delayed_group + << " ; cell_id : " << site.cell_id + << " ; nuclide_id : " << site.nuclide_id + << " ; material_id : " << site.material_id + << " ; universe_id : " << site.universe_id + << " ; n_collision : " << site.n_collision + << " ; parent_id : " << site.parent_id + << " ; progeny_id : " << site.progeny_id; + + all_blobs.push_back(custom_data_stream.str()); + all_sites.push_back(site); + } + } + + for (size_t idx = 0; idx < all_blobs.size(); ++idx) { + const auto& blob = all_blobs[idx]; + std::string key = "blob_" + std::to_string(idx); + g_mcpl_api->hdr_add_data(file_id, key.c_str(), blob.size(), blob.c_str()); + } + + for (const auto& site : all_sites) { + mcpl_particle_repr_t p_repr {}; + p_repr.position[0] = site.r.x; + p_repr.position[1] = site.r.y; + p_repr.position[2] = site.r.z; + p_repr.direction[0] = site.u.x; + p_repr.direction[1] = site.u.y; + p_repr.direction[2] = site.u.z; + p_repr.ekin = site.E * 1e-6; + p_repr.time = site.time * 1e3; + p_repr.weight = site.wgt; + switch (site.particle) { + case ParticleType::neutron: + p_repr.pdgcode = 2112; + break; + case ParticleType::photon: + p_repr.pdgcode = 22; + break; + case ParticleType::electron: + p_repr.pdgcode = 11; + break; + case ParticleType::positron: + p_repr.pdgcode = -11; + break; + default: + continue; + } + g_mcpl_api->add_particle(file_id, &p_repr); + } + } else { +#ifdef OPENMC_MPI + if (!collision_track_bank.empty()) { + MPI_Send(collision_track_bank.data(), collision_track_bank.size(), + mpi::collision_track_site, 0, mpi::rank, mpi::intracomm); + } +#endif + } +} + +void write_mcpl_collision_track(const char* filename, + span collision_track_bank, + const vector& bank_index) +{ + ensure_mcpl_ready_or_fatal(); + + std::string filename_(filename); + const auto extension = get_file_extension(filename_); + if (extension.empty()) { + filename_.append(".mcpl"); + } else if (extension != "mcpl") { + warning(fmt::format("Specified filename '{}' has an extension '.{}', but " + "an MCPL file (.mcpl) will be written using this name.", + filename, extension)); + } + + mcpl_outfile_t* file_id = nullptr; + + if (mpi::master) { + file_id = g_mcpl_api->create_outfile(filename_.c_str()); + if (!file_id) { + fatal_error(fmt::format( + "MCPL: Failed to create output file '{}'. Check permissions and path.", + filename_)); + } + std::string src_line; + if (VERSION_DEV) { + src_line = fmt::format("OpenMC {}.{}.{}-dev{}", VERSION_MAJOR, + VERSION_MINOR, VERSION_RELEASE, VERSION_COMMIT_COUNT); + } else { + src_line = fmt::format( + "OpenMC {}.{}.{}", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE); + } + + g_mcpl_api->hdr_set_srcname(file_id, src_line.c_str()); + } + write_mcpl_collision_track_internal( + file_id, collision_track_bank, bank_index); + + if (mpi::master) { + if (file_id) { + g_mcpl_api->close_outfile(file_id); + } + } +} + } // namespace openmc diff --git a/src/message_passing.cpp b/src/message_passing.cpp index 374c1aa725..a160f6d73c 100644 --- a/src/message_passing.cpp +++ b/src/message_passing.cpp @@ -10,6 +10,7 @@ bool master {true}; #ifdef OPENMC_MPI MPI_Comm intracomm {MPI_COMM_NULL}; MPI_Datatype source_site {MPI_DATATYPE_NULL}; +MPI_Datatype collision_track_site {MPI_DATATYPE_NULL}; #endif extern "C" bool openmc_master() diff --git a/src/particle.cpp b/src/particle.cpp index 6ba8ebf128..2d70d715e2 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -8,6 +8,7 @@ #include "openmc/bank.h" #include "openmc/capi.h" #include "openmc/cell.h" +#include "openmc/collision_track.h" #include "openmc/constants.h" #include "openmc/dagmc.h" #include "openmc/error.h" @@ -351,6 +352,11 @@ void Particle::event_collide() collision_mg(*this); } + // Collision track feature to recording particle interaction + if (settings::collision_track) { + collision_track_record(*this); + } + // Score collision estimator tallies -- this is done after a collision // has occurred rather than before because we need information on the // outgoing energy for any tallies with an outgoing energy filter diff --git a/src/physics.cpp b/src/physics.cpp index 3a17077b36..41509af97b 100644 --- a/src/physics.cpp +++ b/src/physics.cpp @@ -122,6 +122,7 @@ void sample_neutron_reaction(Particle& p) "with k-effective close to or greater than one."); } } + p.event_mt() = rx.mt_; } // Create secondary photons @@ -663,7 +664,9 @@ void absorption(Particle& p, int i_nuclide) p.wgt() = 0.0; p.event() = TallyEvent::ABSORB; - p.event_mt() = N_DISAPPEAR; + if (!p.fission()) { + p.event_mt() = N_DISAPPEAR; + } } } } diff --git a/src/settings.cpp b/src/settings.cpp index 13b91b0e4f..9dcf7c8dbc 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -11,6 +11,7 @@ #endif #include "openmc/capi.h" +#include "openmc/collision_track.h" #include "openmc/constants.h" #include "openmc/container_util.h" #include "openmc/distribution.h" @@ -26,6 +27,7 @@ #include "openmc/plot.h" #include "openmc/random_lcg.h" #include "openmc/random_ray/random_ray.h" +#include "openmc/reaction.h" #include "openmc/simulation.h" #include "openmc/source.h" #include "openmc/string_utils.h" @@ -45,6 +47,7 @@ namespace settings { // Default values for boolean flags bool assume_separate {false}; bool check_overlaps {false}; +bool collision_track {false}; bool cmfd_run {false}; bool confidence_intervals {false}; bool create_delayed_neutrons {true}; @@ -128,6 +131,7 @@ std::unordered_set statepoint_batch; double source_rejection_fraction {0.05}; double free_gas_threshold {400.0}; std::unordered_set source_write_surf_id; +CollisionTrackConfig collision_track_config {}; int64_t ssw_max_particles; int64_t ssw_max_files; int64_t ssw_cell_id {C_NONE}; @@ -925,8 +929,72 @@ void read_settings_xml(pugi::xml_node root) } } - // If source is not separate and is to be written out in the statepoint file, - // make sure that the sourcepoint batch numbers are contained in the + // Check if the user has specified to write specific collisions + if (check_for_node(root, "collision_track")) { + settings::collision_track = true; + // Get collision track node + xml_node node_ct = root.child("collision_track"); + collision_track_config = CollisionTrackConfig {}; + + // Determine cell ids at which crossing particles are to be banked + if (check_for_node(node_ct, "cell_ids")) { + auto temp = get_node_array(node_ct, "cell_ids"); + for (const auto& b : temp) { + collision_track_config.cell_ids.insert(b); + } + } + if (check_for_node(node_ct, "reactions")) { + auto temp = get_node_array(node_ct, "reactions"); + for (const auto& b : temp) { + int reaction_int = reaction_type(b); + if (reaction_int > 0) { + collision_track_config.mt_numbers.insert(reaction_int); + } + } + } + if (check_for_node(node_ct, "universe_ids")) { + auto temp = get_node_array(node_ct, "universe_ids"); + for (const auto& b : temp) { + collision_track_config.universe_ids.insert(b); + } + } + if (check_for_node(node_ct, "material_ids")) { + auto temp = get_node_array(node_ct, "material_ids"); + for (const auto& b : temp) { + collision_track_config.material_ids.insert(b); + } + } + if (check_for_node(node_ct, "nuclides")) { + auto temp = get_node_array(node_ct, "nuclides"); + for (const auto& b : temp) { + collision_track_config.nuclides.insert(b); + } + } + if (check_for_node(node_ct, "deposited_E_threshold")) { + collision_track_config.deposited_energy_threshold = + std::stod(get_node_value(node_ct, "deposited_E_threshold")); + } + // Get maximum number of particles to be banked per collision + if (check_for_node(node_ct, "max_collisions")) { + collision_track_config.max_collisions = + std::stoll(get_node_value(node_ct, "max_collisions")); + } else { + warning("A maximum number of collisions needs to be specified. " + "By default the code sets 'max_collisions' parameter equals to " + "1000."); + } + // Get maximum number of collision_track files to be created + if (check_for_node(node_ct, "max_collision_track_files")) { + collision_track_config.max_files = + std::stoll(get_node_value(node_ct, "max_collision_track_files")); + } + if (check_for_node(node_ct, "mcpl")) { + collision_track_config.mcpl_write = get_node_value_bool(node_ct, "mcpl"); + } + } + + // If source is not separate and is to be written out in the statepoint + // file, make sure that the sourcepoint batch numbers are contained in the // statepoint list if (!source_separate) { for (const auto& b : sourcepoint_batch) { @@ -1171,8 +1239,8 @@ void read_settings_xml(pugi::xml_node root) variance_reduction::weight_windows_generators.emplace_back( std::make_unique(node_wwg)); } - // if any of the weight windows are intended to be generated otf, make sure - // they're applied + // if any of the weight windows are intended to be generated otf, make + // sure they're applied for (const auto& wwg : variance_reduction::weight_windows_generators) { if (wwg->on_the_fly_) { settings::weight_windows_on = true; diff --git a/src/simulation.cpp b/src/simulation.cpp index 05d5545260..b536ae5881 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -2,6 +2,7 @@ #include "openmc/bank.h" #include "openmc/capi.h" +#include "openmc/collision_track.h" #include "openmc/container_util.h" #include "openmc/eigenvalue.h" #include "openmc/error.h" @@ -9,7 +10,6 @@ #include "openmc/geometry_aux.h" #include "openmc/ifp.h" #include "openmc/material.h" -#include "openmc/mcpl_interface.h" #include "openmc/message_passing.h" #include "openmc/nuclide.h" #include "openmc/output.h" @@ -118,6 +118,7 @@ int openmc_simulation_init() // Reset global variables -- this is done before loading state point (as that // will potentially populate k_generation and entropy) simulation::current_batch = 0; + simulation::ct_current_file = 1; simulation::ssw_current_file = 1; simulation::k_generation.clear(); simulation::entropy.clear(); @@ -297,6 +298,7 @@ namespace openmc { namespace simulation { +int ct_current_file; int current_batch; int current_gen; bool initialized {false}; @@ -347,6 +349,11 @@ void allocate_banks() // Allocate surface source bank simulation::surf_source_bank.reserve(settings::ssw_max_particles); } + + if (settings::collision_track) { + // Allocate collision track bank + collision_track_reserve_bank(); + } } void initialize_batch() @@ -490,6 +497,10 @@ void finalize_batch() ++simulation::ssw_current_file; } } + // Write collision track file if requested + if (settings::collision_track) { + collision_track_flush_bank(); + } } void initialize_generation() diff --git a/src/state_point.cpp b/src/state_point.cpp index 0b0fed1324..47296da3a5 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -9,6 +9,7 @@ #include #include "openmc/bank.h" +#include "openmc/bank_io.h" #include "openmc/capi.h" #include "openmc/constants.h" #include "openmc/eigenvalue.h" @@ -642,91 +643,12 @@ void write_source_bank(hid_t group_id, span source_bank, { hid_t banktype = h5banktype(); - // Set total and individual process dataspace sizes for source bank - int64_t dims_size = bank_index.back(); - int64_t count_size = bank_index[mpi::rank + 1] - bank_index[mpi::rank]; - -#ifdef PHDF5 - // Set size of total dataspace for all procs and rank - hsize_t dims[] {static_cast(dims_size)}; - hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, H5P_DEFAULT, - H5P_DEFAULT, H5P_DEFAULT); - - // Create another data space but for each proc individually - hsize_t count[] {static_cast(count_size)}; - hid_t memspace = H5Screate_simple(1, count, nullptr); - - // Select hyperslab for this dataspace - hsize_t start[] {static_cast(bank_index[mpi::rank])}; - H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Set up the property list for parallel writing - hid_t plist = H5Pcreate(H5P_DATASET_XFER); - H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); - - // Write data to file in parallel - H5Dwrite(dset, banktype, memspace, dspace, plist, source_bank.data()); - - // Free resources - H5Sclose(dspace); - H5Sclose(memspace); - H5Dclose(dset); - H5Pclose(plist); - +#ifdef OPENMC_MPI + write_bank_dataset("source_bank", group_id, source_bank, bank_index, banktype, + mpi::source_site); #else - - if (mpi::master) { - // Create dataset big enough to hold all source sites - hsize_t dims[] {static_cast(dims_size)}; - hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, "source_bank", banktype, dspace, - H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - - // Save source bank sites since the array is overwritten below -#ifdef OPENMC_MPI - vector temp_source {source_bank.begin(), source_bank.end()}; -#endif - - for (int i = 0; i < mpi::n_procs; ++i) { - // Create memory space - hsize_t count[] {static_cast(bank_index[i + 1] - bank_index[i])}; - hid_t memspace = H5Screate_simple(1, count, nullptr); - -#ifdef OPENMC_MPI - // Receive source sites from other processes - if (i > 0) - MPI_Recv(source_bank.data(), count[0], mpi::source_site, i, i, - mpi::intracomm, MPI_STATUS_IGNORE); -#endif - - // Select hyperslab for this dataspace - dspace = H5Dget_space(dset); - hsize_t start[] {static_cast(bank_index[i])}; - H5Sselect_hyperslab( - dspace, H5S_SELECT_SET, start, nullptr, count, nullptr); - - // Write data to hyperslab - H5Dwrite( - dset, banktype, memspace, dspace, H5P_DEFAULT, source_bank.data()); - - H5Sclose(memspace); - H5Sclose(dspace); - } - - // Close all ids - H5Dclose(dset); - -#ifdef OPENMC_MPI - // Restore state of source bank - std::copy(temp_source.begin(), temp_source.end(), source_bank.begin()); -#endif - } else { -#ifdef OPENMC_MPI - MPI_Send(source_bank.data(), count_size, mpi::source_site, 0, mpi::rank, - mpi::intracomm); -#endif - } + write_bank_dataset( + "source_bank", group_id, source_bank, bank_index, banktype); #endif H5Tclose(banktype); diff --git a/tests/regression_tests/collision_track/__init__.py b/tests/regression_tests/collision_track/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/collision_track/case_1_Reactions/inputs_true.dat b/tests/regression_tests/collision_track/case_1_Reactions/inputs_true.dat new file mode 100644 index 0000000000..7533616c05 --- /dev/null +++ b/tests/regression_tests/collision_track/case_1_Reactions/inputs_true.dat @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + (n,fission) 101 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_1_Reactions/results_true.dat b/tests/regression_tests/collision_track/case_1_Reactions/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_1_Reactions/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_2_Cell_ID/inputs_true.dat b/tests/regression_tests/collision_track/case_2_Cell_ID/inputs_true.dat new file mode 100644 index 0000000000..55fb835de0 --- /dev/null +++ b/tests/regression_tests/collision_track/case_2_Cell_ID/inputs_true.dat @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 22 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_2_Cell_ID/results_true.dat b/tests/regression_tests/collision_track/case_2_Cell_ID/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_2_Cell_ID/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_3_Material_ID/inputs_true.dat b/tests/regression_tests/collision_track/case_3_Material_ID/inputs_true.dat new file mode 100644 index 0000000000..61890414ba --- /dev/null +++ b/tests/regression_tests/collision_track/case_3_Material_ID/inputs_true.dat @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 1 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_3_Material_ID/results_true.dat b/tests/regression_tests/collision_track/case_3_Material_ID/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_3_Material_ID/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_4_Nuclide_ID/inputs_true.dat b/tests/regression_tests/collision_track/case_4_Nuclide_ID/inputs_true.dat new file mode 100644 index 0000000000..8960dde5cb --- /dev/null +++ b/tests/regression_tests/collision_track/case_4_Nuclide_ID/inputs_true.dat @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + O16 U235 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_4_Nuclide_ID/results_true.dat b/tests/regression_tests/collision_track/case_4_Nuclide_ID/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_4_Nuclide_ID/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_5_Universe_ID/inputs_true.dat b/tests/regression_tests/collision_track/case_5_Universe_ID/inputs_true.dat new file mode 100644 index 0000000000..8c0d7aa8ee --- /dev/null +++ b/tests/regression_tests/collision_track/case_5_Universe_ID/inputs_true.dat @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 22 + 77 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_5_Universe_ID/results_true.dat b/tests/regression_tests/collision_track/case_5_Universe_ID/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_5_Universe_ID/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/inputs_true.dat b/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/inputs_true.dat new file mode 100644 index 0000000000..5173dc35cf --- /dev/null +++ b/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/inputs_true.dat @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 550000.0 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/results_true.dat b/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_6_deposited_energy_threshold/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_7_all_parameters_used_together/inputs_true.dat b/tests/regression_tests/collision_track/case_7_all_parameters_used_together/inputs_true.dat new file mode 100644 index 0000000000..005d9feb27 --- /dev/null +++ b/tests/regression_tests/collision_track/case_7_all_parameters_used_together/inputs_true.dat @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 22 33 + elastic 18 (n,disappear) + 77 + 1 11 + U238 U235 H1 U234 + 100000.0 + 300 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_7_all_parameters_used_together/results_true.dat b/tests/regression_tests/collision_track/case_7_all_parameters_used_together/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_7_all_parameters_used_together/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/case_8_2threads/inputs_true.dat b/tests/regression_tests/collision_track/case_8_2threads/inputs_true.dat new file mode 100644 index 0000000000..514932c1a6 --- /dev/null +++ b/tests/regression_tests/collision_track/case_8_2threads/inputs_true.dat @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 5 + 1 + + + -2.0 -2.0 -2.0 2.0 2.0 2.0 + + + true + + + + 200 + + 1 + + diff --git a/tests/regression_tests/collision_track/case_8_2threads/results_true.dat b/tests/regression_tests/collision_track/case_8_2threads/results_true.dat new file mode 100644 index 0000000000..d4d1d1e5ad --- /dev/null +++ b/tests/regression_tests/collision_track/case_8_2threads/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +5.642735E-02 1.494035E-02 diff --git a/tests/regression_tests/collision_track/test.py b/tests/regression_tests/collision_track/test.py new file mode 100644 index 0000000000..00e1e3de41 --- /dev/null +++ b/tests/regression_tests/collision_track/test.py @@ -0,0 +1,255 @@ +"""Test the 'collision_track' setting. + +Results +------- + +All results are generated using only 1 MPI process. + +All results are generated using 1 thread except for "test_consistency_low_realization_number". +This specific test verifies that when the number of realization (i.e., point being candidate +to be stored) is lower than the capacity, results are reproducible even with multiple +threads (i.e., there is no potential thread competition that would produce different +results in that case). + +All results are generated using the history-based mode except for cases e01 to e03. + +All results are visually verified using the '_visualize.py' script in the regression test folder. + +OpenMC models +------------- + +Four OpenMC models with CSG-only geometries are used to cover the transmission, vacuum, +reflective and periodic Boundary Conditions (BC): + +- model_1: cylindrical core in 2 boxes (vacuum and transmission BC), + +# Test cases for simulation parameters using CSG-only geometries +# ============================================================ +# Each test case is defined by a combination of folder name, model name, and specific parameters. +# Below is a summary of the parameters used in the test cases: +# +# - max_collisions: Maximum number of particles to track in the simulation. +# - reactions: List of MT numbers (reaction types- 2 for scattering, 18 for fission, 101 for absorbtion). +# - cell_ids: IDs of specific cells in the model. +# - mat_ids: Material IDs for filtering particles. +# - nuclides: Nuclides for filtering particles. +# - univ_ids: Universe IDs for filtering particles. +# - E_threshold: Energy threshold for filtering particles (optional). +# +# The test cases are designed to validate the behavior of the simulation under various configurations. + +*: BC stands for Boundary Conditions, T for Transmission, R for Reflective, and V for Vacuum. + +An additional case, called 'case-a01', is used to check that the results are comparable when +the number of threads is set to 2 if the number of realization is lower than the capacity. + + +*: BC stands for Boundary Conditions, T for Transmission, and V for Vacuum. + +Notes: + +- The test cases list is non-exhaustive compared to the number of possible combinations. + Test cases have been selected based on use and internal code logic. + + + +TODO: + +- Test with a lattice. + +""" + +import os + +import openmc +import openmc.lib +import pytest + +from tests.testing_harness import CollisionTrackTestHarness +from tests.regression_tests import config + + +@pytest.fixture(scope="function") +def two_threads(monkeypatch): + """Set the number of OMP threads to 2 for the test.""" + monkeypatch.setenv("OMP_NUM_THREADS", "2") + + +@pytest.fixture(scope="function") +def single_process(monkeypatch): + """Set the number of MPI process to 1 for the test.""" + monkeypatch.setitem(config, "mpi_np", "1") + + +@pytest.fixture(scope="module") +def model_1(): + """Cylindrical core contained in a first box which is contained in a larger box. + A lower universe is used to describe the interior of the first box which + contains the core and its surrounding space. + + """ + openmc.reset_auto_ids() + model = openmc.Model() + + # ============================================================================= + # Materials + # ============================================================================= + + fuel = openmc.Material(material_id=1) + fuel.add_nuclide("U234", 0.0004524) + fuel.add_nuclide("U235", 0.0506068) + fuel.add_nuclide("U238", 0.9487090) + fuel.add_nuclide("U236", 0.0002318) + fuel.add_nuclide("O16", 2.0) + fuel.set_density("g/cm3", 11.0) + + water = openmc.Material(material_id=11) + water.add_nuclide("H1", 2.0) + water.add_nuclide("O16", 1.0) + water.set_density("g/cm3", 1.0) + + # ============================================================================= + # Geometry + # ============================================================================= + + # ----------------------------------------------------------------------------- + # Cylindrical core + # ----------------------------------------------------------------------------- + + # Parameters + core_radius = 2.0 + core_height = 4.0 + + # Surfaces + core_cylinder = openmc.ZCylinder(r=core_radius) + core_lower_plane = openmc.ZPlane(-core_height / 2.0) + core_upper_plane = openmc.ZPlane(core_height / 2.0) + + # Region + core_region = -core_cylinder & +core_lower_plane & -core_upper_plane + + # Cells + core = openmc.Cell(fill=fuel, region=core_region, cell_id=22) + outside_core_region = +core_cylinder | -core_lower_plane | +core_upper_plane + outside_core = openmc.Cell( + fill=water, region=outside_core_region, cell_id=33) + + # Universe + inside_box1_universe = openmc.Universe( + cells=[core, outside_core], universe_id=77) + + # ----------------------------------------------------------------------------- + # Box 1 + # ----------------------------------------------------------------------------- + + # Parameters + box1_size = 6.0 + + # Surfaces + box1_rpp = openmc.model.RectangularParallelepiped( + -box1_size / 2.0, box1_size / 2.0, + -box1_size / 2.0, box1_size / 2.0, + -box1_size / 2.0, box1_size / 2.0, + ) + + # Cell + box1 = openmc.Cell(fill=inside_box1_universe, region=-box1_rpp, cell_id=5) + + # ----------------------------------------------------------------------------- + # Box 2 + # ----------------------------------------------------------------------------- + + # Parameters + box2_size = 8 + + # Surfaces + box2_rpp = openmc.model.RectangularParallelepiped( + -box2_size / 2.0, box2_size / 2.0, + -box2_size / 2.0, box2_size / 2.0, + -box2_size / 2.0, box2_size / 2.0, + boundary_type="vacuum" + ) + + # Cell + box2 = openmc.Cell(fill=water, region=-box2_rpp & +box1_rpp, cell_id=8) + + # Register geometry + model.geometry = openmc.Geometry([box1, box2]) + + # ============================================================================= + # Settings + # ============================================================================= + + model.settings = openmc.Settings() + model.settings.particles = 100 + model.settings.batches = 5 + model.settings.inactive = 1 + model.settings.seed = 1 + + bounds = [ + -core_radius, + -core_radius, + -core_height / 2.0, + core_radius, + core_radius, + core_height / 2.0, + ] + distribution = openmc.stats.Box(bounds[:3], bounds[3:]) + model.settings.source = openmc.IndependentSource( + space=distribution, constraints={'fissionable': True}) + + return model + + +@pytest.mark.parametrize( + "folder, model_name, parameter", + [("case_1_Reactions", "model_1", {"max_collisions": 300, "reactions": ["(n,fission)", 101]}), + ("case_2_Cell_ID", "model_1", { + "max_collisions": 300, "cell_ids": [22]}), + ("case_3_Material_ID", "model_1", { + "max_collisions": 300, "material_ids": [1]}), + ("case_4_Nuclide_ID", "model_1", { + "max_collisions": 300, "nuclides": ["O16", "U235"]}), + ("case_5_Universe_ID", "model_1", { + "max_collisions": 300, "cell_ids": [22], "universe_ids": [77]}), + ("case_6_deposited_energy_threshold", "model_1", { + "max_collisions": 300, "deposited_E_threshold": 5.5e5}), + ("case_7_all_parameters_used_together", "model_1", { + "max_collisions": 300, + "reactions": ["elastic", 18, "(n,disappear)"], + "material_ids": [1, 11], + "universe_ids": [77], + "nuclides": ["U238", "U235", "H1", "U234"], + "cell_ids": [22, 33], + "deposited_E_threshold": 1e5}) + ], +) +def test_collision_track_several_cases( + folder, model_name, parameter, request +): + # Since for these tests the actual number of collisions recorded is < max_collisions, + # we can run them with 1 or 2 threads, and in history or event mode. + model = request.getfixturevalue(model_name) + model.settings.collision_track = parameter + harness = CollisionTrackTestHarness( + "statepoint.5.h5", model=model, workdir=folder + ) + harness.main() + + +@pytest.mark.skipif(config["event"], reason="Results from history-based mode.") +def test_collision_track_2threads(model_1, two_threads, single_process): + # This test checks that the `max_collisions` setting is honored: + # no collisions beyond the specified limit should be recorded. + # + # For the result to be reproducible, the number of threads and + # the transport mode (history vs. event) must remain fixed. + assert os.environ["OMP_NUM_THREADS"] == "2" + assert config["mpi_np"] == "1" + model_1.settings.collision_track = { + "max_collisions": 200 + } + harness = CollisionTrackTestHarness( + "statepoint.5.h5", model=model_1, workdir="case_8_2threads" + ) + harness.main() diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 11ced5b38a..1ad91b7a89 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -68,7 +68,7 @@ class TestHarness: if config['mpi']: mpi_args = [config['mpiexec'], '-n', config['mpi_np']] openmc.run(openmc_exec=config['exe'], mpi_args=mpi_args, - event_based=config['event']) + event_based=config['event']) else: openmc.run(openmc_exec=config['exe'], event_based=config['event']) @@ -305,9 +305,12 @@ class PyAPITestHarness(TestHarness): else: self.execute_test() - def execute_test(self): + def execute_test(self, change_dir=False): """Build input XMLs, run OpenMC, and verify correct results.""" + base_dir = os.getcwd() if change_dir else None try: + if change_dir: + os.chdir(self.workdir) self._build_inputs() inputs = self._get_inputs() self._write_inputs(inputs) @@ -319,10 +322,15 @@ class PyAPITestHarness(TestHarness): self._compare_results() finally: self._cleanup() + if base_dir: + os.chdir(base_dir) - def update_results(self): + def update_results(self, change_dir=False): """Update results_true.dat and inputs_true.dat""" + base_dir = os.getcwd() if change_dir else None try: + if change_dir: + os.chdir(self.workdir) self._build_inputs() inputs = self._get_inputs() self._write_inputs(inputs) @@ -334,6 +342,8 @@ class PyAPITestHarness(TestHarness): self._overwrite_results() finally: self._cleanup() + if base_dir: + os.chdir(base_dir) def _build_inputs(self): """Write input XML files.""" @@ -371,7 +381,8 @@ class PyAPITestHarness(TestHarness): """Delete XMLs, statepoints, tally, and test files.""" super()._cleanup() output = ['materials.xml', 'geometry.xml', 'settings.xml', - 'tallies.xml', 'plots.xml', 'inputs_test.dat', 'model.xml'] + 'tallies.xml', 'plots.xml', 'inputs_test.dat', 'model.xml', + 'collision_track.h5', 'collision_track.mcpl'] for f in output: if os.path.exists(f): os.remove(f) @@ -389,6 +400,7 @@ class TolerantPyAPITestHarness(PyAPITestHarness): due to single precision usage (e.g., as in the random ray solver). """ + def _are_files_equal(self, actual_path, expected_path, tolerance): def isfloat(value): try: @@ -428,7 +440,8 @@ class TolerantPyAPITestHarness(PyAPITestHarness): def _compare_results(self): """Make sure the current results agree with the reference.""" - compare = self._are_files_equal('results_test.dat', 'results_true.dat', 1e-6) + compare = self._are_files_equal( + 'results_test.dat', 'results_true.dat', 1e-6) if not compare: expected = open('results_true.dat').readlines() actual = open('results_test.dat').readlines() @@ -476,6 +489,7 @@ class WeightWindowPyAPITestHarness(PyAPITestHarness): class PlotTestHarness(TestHarness): """Specialized TestHarness for running OpenMC plotting tests.""" + def __init__(self, plot_names, voxel_convert_checks=[]): super().__init__(None) self._plot_names = plot_names @@ -523,3 +537,105 @@ class PlotTestHarness(TestHarness): outstr = sha512.hexdigest() return outstr + + +class CollisionTrackTestHarness(PyAPITestHarness): + def __init__(self, statepoint_name, model=None, inputs_true=None, workdir=None): + super().__init__(statepoint_name, model, inputs_true) + self.workdir = workdir + + def _test_output_created(self): + """Make sure collision_track.h5 has also been created.""" + super()._test_output_created() + if self._model.settings.collision_track: + assert os.path.exists( + "collision_track.h5" + ), "collision_track file has not been created." + + def _compare_output(self): + """Compare collision_track.h5 files.""" + if self._model.settings.collision_track: + collision_track_true = self._return_collision_track_data( + "collision_track_true.h5") + collision_track_test = self._return_collision_track_data( + "collision_track.h5") + np.testing.assert_allclose( + collision_track_true, collision_track_test, rtol=1e-07) + + def main(self): + """Accept commandline arguments and either run or update tests.""" + if config["build_inputs"]: + self.build_inputs() + elif config["update"]: + self.update_results(change_dir=True) + else: + self.execute_test(change_dir=True) + + def build_inputs(self): + """Build inputs.""" + base_dir = os.getcwd() + try: + os.chdir(self.workdir) + self._build_inputs() + finally: + os.chdir(base_dir) + + def _overwrite_results(self): + """Also add the 'collision_track.h5' file during overwriting.""" + super()._overwrite_results() + if os.path.exists("collision_track.h5"): + shutil.copyfile("collision_track.h5", "collision_track_true.h5") + + @staticmethod + def _return_collision_track_data(filepath): + """ + Read a collision_track file and return a sorted array composed + of flatten arrays of collision information. + + Parameters + ---------- + filepath : str + Path to the collision_track file + + Returns + ------- + data : np.array + Sorted array composed of flatten arrays of collision_track data for + each collision information + """ + data = [] + keys = [] + + # Read source file + source = openmc.read_collision_track_file(filepath) + for src in source: + r = src['r'] + u = src['u'] + e = src['E'] + de = src['dE'] + time = src['time'] + wgt = src['wgt'] + delayed_group = src['delayed_group'] + cell_id = src['cell_id'] + nuclide_id = src['nuclide_id'] + material_id = src['material_id'] + universe_id = src['universe_id'] + n_collision = src['n_collision'] + event_mt = src['event_mt'] + key = ( + f"{r[0]:.10e} {r[1]:.10e} {r[2]:.10e} {u[0]:.10e} {u[1]:.10e} {u[2]:.10e}" + f"{e:.10e} {de:.10e} {time:.10e} {wgt:.10e} {event_mt} {delayed_group} {cell_id}" + f"{nuclide_id} {material_id} {universe_id} {n_collision} " + ) + keys.append(key) + values = [*r, *u, e, de, time, wgt, event_mt, + delayed_group, cell_id, nuclide_id, material_id, + universe_id, n_collision] + assert len(values) == 17 + data.append(values) + + data = np.array(data) + keys = np.array(keys) + sorted_idx = np.argsort(keys, kind='stable') + + return data[sorted_idx] diff --git a/tests/unit_tests/test_collision_track.py b/tests/unit_tests/test_collision_track.py new file mode 100644 index 0000000000..9bc6a8c15f --- /dev/null +++ b/tests/unit_tests/test_collision_track.py @@ -0,0 +1,127 @@ +"""Test the 'collision_track' setting used to store particle information +during specified collision conditions in a file for a given simulation.""" + +import openmc +import pytest +import h5py +import numpy as np + +from tests.testing_harness import CollisionTrackTestHarness as ctt + + +@pytest.fixture(scope="module") +def geometry(): + """Simple hydrogen sphere geometry""" + openmc.reset_auto_ids() + material = openmc.Material(name="H1") + material.add_element("H", 1.0) + sphere = openmc.Sphere(r=1.0, boundary_type="vacuum") + cell = openmc.Cell(region=-sphere, fill=material) + return openmc.Geometry([cell]) + + +@pytest.mark.parametrize( + "parameter", + [ + {"max_collisions": 200}, + {"max_collisions": 200, "reactions": ["(n,disappear)"]}, + {"max_collisions": 200, "cell_ids": [1]}, + {"max_collisions": 200, "material_ids": [1]}, + {"max_collisions": 200, "universe_ids": [1]}, + {"max_collisions": 200, "nuclides": ["H1"]}, + {"max_collisions": 200, "deposited_E_threshold": 200000.0}, + {"max_collisions": 200, "mcpl": True} + + ], +) +def test_xml_serialization(parameter, run_in_tmpdir): + """Check that the different use cases can be written and read in XML.""" + settings = openmc.Settings() + settings.collision_track = parameter + settings.export_to_xml() + + read_settings = openmc.Settings.from_xml() + assert read_settings.collision_track == parameter + + +@pytest.fixture(scope="module") +def model(): + """Simple hydrogen sphere divided in two hemispheres + by a z-plane to form 2 cells.""" + openmc.reset_auto_ids() + model = openmc.Model() + + # Material + material = openmc.Material(name="H1") + material.add_element("H", 1.0) + + # Geometry + radius = 1.0 + sphere = openmc.Sphere(r=radius, boundary_type="reflective") + plane = openmc.ZPlane(0.0) + cell_1 = openmc.Cell(region=-sphere & -plane, fill=material, cell_id=1) + cell_2 = openmc.Cell(region=-sphere & +plane, fill=material, cell_id=2) + root = openmc.Universe(cells=[cell_1, cell_2]) + model.geometry = openmc.Geometry(root) + + # Settings + model.settings = openmc.Settings() + model.settings.run_mode = "fixed source" + model.settings.particles = 1 + model.settings.batches = 1 + model.settings.seed = 2 + + bounds = [-radius, -radius, -radius, radius, radius, radius] + distribution = openmc.stats.Box(bounds[:3], bounds[3:]) + model.settings.source = openmc.IndependentSource(space=distribution) + + return model + + +def test_particle_location(run_in_tmpdir, model): + """Test the location of particles with respected to the "cell_ids" + and the location x, y, z of the particle itself. the upper sphere will + have positive z component and the bottom sphere a negative z compnent. + + """ + model.settings.collision_track = { + "max_collisions": 200, + "reactions": ["elastic"], + "cell_ids": [1, 2] + } + model.run() + + with h5py.File("collision_track.h5", "r") as f: + source = f["collision_track_bank"] + + assert len(source) == 60 + + # We want to verify that the collisions happenening are in the right cells + # and the position of the particle is either positive or negative relative + # to the z plane. In this case, we track the position of the particle + # relative to the cell_id already set. + for point in source: + if point['cell_id'] == 1: + assert point['r'][2] < 0.0 # z component negative + elif point['cell_id'] == 2: + assert point["r"][2] > 0.0 # z component positive + else: + assert False + + +def test_format_similarity(run_in_tmpdir, model): + model.settings.collision_track = {"max_collisions": 200, "reactions": ['elastic'], + "cell_ids": [1, 2], "mcpl": False} + model.run() + data_h5 = ctt._return_collision_track_data('collision_track.h5') + + model.settings.collision_track["mcpl"] = True + model.run() + data_mcpl = ctt._return_collision_track_data('collision_track.mcpl') + + assert len(data_h5) == 60 + assert len(data_mcpl) == 60 + + np.testing.assert_allclose(data_h5, data_mcpl, rtol=1e-05) + # tolerance not that low due to the strings that is saved in MCPL, + # not enough precision! From 8d618716b55d92e892314d966ac75ffe5b19b7d7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 13 Nov 2025 17:14:39 -0600 Subject: [PATCH 50/76] Avoid multiprocessing Pool when running depletion tests with MPI (#3633) --- tests/conftest.py | 21 +++++++++++++++++-- .../deplete_no_transport/test.py | 4 ++++ .../deplete_with_transport/test.py | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index fa6718502d..71dd5ebf5d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,12 +29,29 @@ def run_in_tmpdir(tmpdir): yield finally: orig.chdir() - + @pytest.fixture(scope="module") def endf_data(): - return os.environ['OPENMC_ENDF_DATA'] + return os.environ['OPENMC_ENDF_DATA'] @pytest.fixture(scope='session', autouse=True) def resolve_paths(): with openmc.config.patch('resolve_paths', False): yield + + +@pytest.fixture(scope='session', autouse=True) +def disable_depletion_multiprocessing_under_mpi(): + """Fork-based depletion multiprocessing may deadlock if MPI is active.""" + if not regression_config['mpi']: + yield + return + + from openmc.deplete import pool + + original_setting = pool.USE_MULTIPROCESSING + pool.USE_MULTIPROCESSING = False + try: + yield + finally: + pool.USE_MULTIPROCESSING = original_setting diff --git a/tests/regression_tests/deplete_no_transport/test.py b/tests/regression_tests/deplete_no_transport/test.py index 63ae584e11..5550ad0481 100644 --- a/tests/regression_tests/deplete_no_transport/test.py +++ b/tests/regression_tests/deplete_no_transport/test.py @@ -76,6 +76,8 @@ def test_against_self(run_in_tmpdir, dt = [360] # single step # Perform simulation using the predictor algorithm + if config['mpi'] and multiproc: + pytest.skip("Multiprocessing depletion is disabled when MPI is enabled.") openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator(op, dt, @@ -135,6 +137,8 @@ def test_against_coupled(run_in_tmpdir, dt = [dt] # single step # Perform simulation using the predictor algorithm + if config['mpi'] and multiproc: + pytest.skip("Multiprocessing depletion is disabled when MPI is enabled.") openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator( op, dt, power=174, timestep_units=time_units).integrate() diff --git a/tests/regression_tests/deplete_with_transport/test.py b/tests/regression_tests/deplete_with_transport/test.py index 0f7ebf00f3..a2be22c565 100644 --- a/tests/regression_tests/deplete_with_transport/test.py +++ b/tests/regression_tests/deplete_with_transport/test.py @@ -65,6 +65,8 @@ def test_full(run_in_tmpdir, problem, multiproc): power = 2.337e15*4*JOULE_PER_EV*1e6 # MeV/second cm from CASMO # Perform simulation using the predictor algorithm + if config['mpi'] and multiproc: + pytest.skip("Multiprocessing depletion is disabled when MPI is enabled.") openmc.deplete.pool.USE_MULTIPROCESSING = multiproc openmc.deplete.PredictorIntegrator(op, dt, power).integrate() From 7815d3a680de21362e7fec64c871ecbab1150421 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Thu, 13 Nov 2025 23:27:17 -0600 Subject: [PATCH 51/76] Fix typo in DAGMC lost particle test (#3634) --- tests/unit_tests/dagmc/test_lost_particles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit_tests/dagmc/test_lost_particles.py b/tests/unit_tests/dagmc/test_lost_particles.py index 502bd795e8..3a4166009d 100644 --- a/tests/unit_tests/dagmc/test_lost_particles.py +++ b/tests/unit_tests/dagmc/test_lost_particles.py @@ -70,12 +70,12 @@ def test_lost_particles(run_in_tmpdir, broken_dagmc_model): openmc.run() # run this again, but with the dagmc universe as the root unvierse + # to ensure that lost particles are still caught in this case for univ in broken_dagmc_model.geometry.get_all_universes().values(): if isinstance(univ, openmc.DAGMCUniverse): - broken_dagmc_model.geometry.root_unvierse = univ + broken_dagmc_model.geometry.root_universe = univ break broken_dagmc_model.export_to_xml() with pytest.raises(RuntimeError, match='Maximum number of lost particles has been reached.'): openmc.run() - From 5c63e0df21a25e2c9a25f8be6cfd23a09d6007b3 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 18 Nov 2025 17:57:12 -0600 Subject: [PATCH 52/76] Fix a few warnings, rename add_to_tallies_file (#3639) --- docs/source/usersguide/random_ray.rst | 2 +- openmc/deplete/chain.py | 13 +++--- openmc/mgxs/library.py | 18 +++++--- openmc/mgxs/mgxs.py | 4 +- openmc/model/model.py | 6 +-- openmc/tallies.py | 45 +++++++------------ .../mgxs_library_ce_to_mg/test.py | 2 +- .../mgxs_library_ce_to_mg_nuclides/test.py | 2 +- .../mgxs_library_condense/test.py | 2 +- .../mgxs_library_correction/test.py | 2 +- .../mgxs_library_distribcell/test.py | 2 +- .../mgxs_library_hdf5/test.py | 2 +- .../mgxs_library_histogram/test.py | 2 +- .../mgxs_library_mesh/test.py | 2 +- .../mgxs_library_no_nuclides/test.py | 2 +- .../mgxs_library_nuclides/test.py | 2 +- .../mgxs_library_specific_nuclides/test.py | 2 +- 17 files changed, 54 insertions(+), 56 deletions(-) diff --git a/docs/source/usersguide/random_ray.rst b/docs/source/usersguide/random_ray.rst index 138ae910c9..d5d752a834 100644 --- a/docs/source/usersguide/random_ray.rst +++ b/docs/source/usersguide/random_ray.rst @@ -765,7 +765,7 @@ energy decomposition:: # Create a "tallies.xml" file for the MGXS Library tallies = openmc.Tallies() - mgxs_lib.add_to_tallies_file(tallies, merge=True) + mgxs_lib.add_to_tallies(tallies, merge=True) # Export tallies.export_to_xml() diff --git a/openmc/deplete/chain.py b/openmc/deplete/chain.py index f34416d561..873d7ca892 100644 --- a/openmc/deplete/chain.py +++ b/openmc/deplete/chain.py @@ -630,7 +630,7 @@ class Chain: n = len(self) - # we accumulate indices and value entries for everything and create the matrix + # we accumulate indices and value entries for everything and create the matrix # in one step at the end to avoid expensive index checks scipy otherwise does. rows, cols, vals = [], [], [] def setval(i, j, val): @@ -716,14 +716,17 @@ class Chain: return sp.csc_matrix((vals, (rows, cols)), shape=(n, n)) def add_redox_term(self, matrix, buffer, oxidation_states): - """Adds a redox term to the depletion matrix from data contained in + r"""Adds a redox term to the depletion matrix from data contained in the matrix itself and a few user-inputs. The redox term to add to the buffer nuclide :math:`N_j` can be written - as: :math:`\frac{dN_j(t)}{dt} = - \cdots - \frac{1}{OS_j}\sum_i N_i a_{ij} \cdot OS_i ` + as: - where :math:`OS` is the oxidation states vector and `a_{ij}` the + .. math:: + \frac{dN_j(t)}{dt} = \cdots - \frac{1}{OS_j}\sum_i N_i a_{ij} + \cdot OS_i + + where :math:`OS` is the oxidation states vector and :math:`a_{ij}` the corresponding term in the Bateman matrix. Parameters diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index f782cbe9e5..b476de9020 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -556,14 +556,14 @@ class Library: self.all_mgxs[domain.id][mgxs_type] = mgxs - def add_to_tallies_file(self, tallies_file, merge=True): - """Add all tallies from all MGXS objects to a tallies file. + def add_to_tallies(self, tallies, merge=True): + """Add tallies from all MGXS objects to a tallies object. NOTE: This assumes that :meth:`Library.build_library` has been called Parameters ---------- - tallies_file : openmc.Tallies + tallies : openmc.Tallies A Tallies collection to add each MGXS' tallies to generate a 'tallies.xml' input file for OpenMC merge : bool @@ -572,7 +572,7 @@ class Library: """ - cv.check_type('tallies_file', tallies_file, openmc.Tallies) + cv.check_type('tallies', tallies, openmc.Tallies) # Add tallies from each MGXS for each domain and mgxs type for domain in self.domains: @@ -587,7 +587,15 @@ class Library: = list(range(1, self.num_delayed_groups + 1)) for tally in mgxs.tallies.values(): - tallies_file.append(tally, merge=merge) + tallies.append(tally, merge=merge) + + def add_to_tallies_file(self, tallies_file, merge=True): + warn( + "The Library.add_to_tallies_file(...) method has been renamed to" + "add_to_tallies(...) and will be removed in a future version of " + "OpenMC.", FutureWarning + ) + self.add_to_tallies(tallies_file, merge=merge) def load_from_statepoint(self, statepoint): """Extracts tallies in an OpenMC StatePoint with the data needed to diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 533ab0ad32..f621db092f 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -2127,8 +2127,8 @@ class MGXS: df['std. dev.'] /= np.tile(densities, tile_factor) # Replace NaNs by zeros (happens if nuclide density is zero) - df['mean'].replace(np.nan, 0.0, inplace=True) - df['std. dev.'].replace(np.nan, 0.0, inplace=True) + df['mean'] = df['mean'].replace(np.nan, 0.0) + df['std. dev.'] = df['std. dev.'].replace(np.nan, 0.0) # Sort the dataframe by domain type id (e.g., distribcell id) and # energy groups such that data is from fast to thermal diff --git a/openmc/model/model.py b/openmc/model/model.py index 64294c23cb..10e5cbfc74 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1791,7 +1791,7 @@ class Model: mgxs_lib.build_library() # Create a "tallies.xml" file for the MGXS Library - mgxs_lib.add_to_tallies_file(model.tallies, merge=True) + mgxs_lib.add_to_tallies(model.tallies, merge=True) # Run statepoint_filename = model.run(cwd=directory) @@ -1980,7 +1980,7 @@ class Model: mgxs_lib.build_library() # Create a "tallies.xml" file for the MGXS Library - mgxs_lib.add_to_tallies_file(model.tallies, merge=True) + mgxs_lib.add_to_tallies(model.tallies, merge=True) # Run statepoint_filename = model.run(cwd=directory) @@ -2075,7 +2075,7 @@ class Model: mgxs_lib.build_library() # Create a "tallies.xml" file for the MGXS Library - mgxs_lib.add_to_tallies_file(model.tallies, merge=True) + mgxs_lib.add_to_tallies(model.tallies, merge=True) # Run statepoint_filename = model.run(cwd=directory) diff --git a/openmc/tallies.py b/openmc/tallies.py index 25ec29a585..add3565798 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -738,13 +738,9 @@ class Tally(IDManagerMixin): Notes ----- - This test is based on D'Agostino and Pearson's test [1]_. The test - requires at least 8 realizations to produce valid results. - - References - ---------- - .. [1] D'Agostino, R. B. (1971), "An omnibus test of normality for - moderate and large sample size", Biometrika, 58, 341-348 + This test is based on `D'Agostino and Pearson's test + `_. The test requires at least + 8 realizations to produce valid results. """ n = self.num_realizations @@ -788,8 +784,8 @@ class Tally(IDManagerMixin): Parameters ---------- alternative : {'two-sided', 'less', 'greater'}, optional - Defines the alternative hypothesis. Default is 'two-sided'. - The following options are available: + Defines the alternative hypothesis. Default is 'two-sided'. The + following options are available: * 'two-sided': the kurtosis of the distribution is different from that of the normal distribution @@ -813,14 +809,9 @@ class Tally(IDManagerMixin): Notes ----- - This test is based on D'Agostino and Pearson's test [1]_. The test - is typically recommended for at least 20 realizations to produce - valid results. - - References - ---------- - .. [1] D'Agostino, R. B. (1971), "An omnibus test of normality for - moderate and large sample size", Biometrika, 58, 341-348 + This test is based on `D'Agostino and Pearson's test + `_. The test is typically + recommended for at least 20 realizations to produce valid results. """ n = self.num_realizations @@ -855,9 +846,9 @@ class Tally(IDManagerMixin): def normaltest(self, alternative: str = "two-sided"): """Perform D'Agostino and Pearson's omnibus test for normality. - This method tests the null hypothesis that a sample comes from a - normal distribution. It combines skewness and kurtosis to produce an - omnibus test of normality. + This method tests the null hypothesis that a sample comes from a normal + distribution. It combines skewness and kurtosis to produce an omnibus + test of normality. Parameters ---------- @@ -886,23 +877,19 @@ class Tally(IDManagerMixin): Notes ----- This test combines a test for skewness and a test for kurtosis to - produce an omnibus test [1]_. The test statistic is: + produce an `omnibus test `_. + The test statistic is: .. math:: K^2 = Z_1^2 + Z_2^2 - where :math:`Z_1` is the z-score from the skewness test and - :math:`Z_2` is the z-score from the kurtosis test. This statistic - follows a chi-square distribution with 2 degrees of freedom. + where :math:`Z_1` is the z-score from the skewness test and :math:`Z_2` + is the z-score from the kurtosis test. This statistic follows a + chi-square distribution with 2 degrees of freedom. The test requires at least 20 realizations to produce valid results. - References - ---------- - .. [1] D'Agostino, R. B. and Pearson, E. S. (1973), "Tests for - departure from normality", Biometrika, 60, 613-622 - """ n = self.num_realizations if n < 20: diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/test.py b/tests/regression_tests/mgxs_library_ce_to_mg/test.py index 48a715997a..075167f588 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg/test.py +++ b/tests/regression_tests/mgxs_library_ce_to_mg/test.py @@ -28,7 +28,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Initialize a tallies file - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _run_openmc(self): # Initial run diff --git a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py index a77ad24296..489105f8f5 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_ce_to_mg_nuclides/test.py @@ -28,7 +28,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Initialize a tallies file - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _run_openmc(self): # Initial run diff --git a/tests/regression_tests/mgxs_library_condense/test.py b/tests/regression_tests/mgxs_library_condense/test.py index a7e60617f0..bbc4c11bfa 100644 --- a/tests/regression_tests/mgxs_library_condense/test.py +++ b/tests/regression_tests/mgxs_library_condense/test.py @@ -36,7 +36,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=False): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_correction/test.py b/tests/regression_tests/mgxs_library_correction/test.py index 05eedfef82..64e638e442 100644 --- a/tests/regression_tests/mgxs_library_correction/test.py +++ b/tests/regression_tests/mgxs_library_correction/test.py @@ -29,7 +29,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=False): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_distribcell/test.py b/tests/regression_tests/mgxs_library_distribcell/test.py index fd6c8e9386..464b309c00 100644 --- a/tests/regression_tests/mgxs_library_distribcell/test.py +++ b/tests/regression_tests/mgxs_library_distribcell/test.py @@ -36,7 +36,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) self._model.tallies.export_to_xml() def _get_results(self, hash_output=False): diff --git a/tests/regression_tests/mgxs_library_hdf5/test.py b/tests/regression_tests/mgxs_library_hdf5/test.py index 06625c25f9..4fb4bf0936 100644 --- a/tests/regression_tests/mgxs_library_hdf5/test.py +++ b/tests/regression_tests/mgxs_library_hdf5/test.py @@ -40,7 +40,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=False): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_histogram/test.py b/tests/regression_tests/mgxs_library_histogram/test.py index b9905910ab..42fc1957a6 100644 --- a/tests/regression_tests/mgxs_library_histogram/test.py +++ b/tests/regression_tests/mgxs_library_histogram/test.py @@ -30,7 +30,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=False): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_mesh/test.py b/tests/regression_tests/mgxs_library_mesh/test.py index 89c68a75a3..c1a5980b5d 100644 --- a/tests/regression_tests/mgxs_library_mesh/test.py +++ b/tests/regression_tests/mgxs_library_mesh/test.py @@ -57,7 +57,7 @@ def model(): model.mgxs_lib.build_library() # Add tallies - model.mgxs_lib.add_to_tallies_file(model.tallies, merge=False) + model.mgxs_lib.add_to_tallies(model.tallies, merge=False) return model diff --git a/tests/regression_tests/mgxs_library_no_nuclides/test.py b/tests/regression_tests/mgxs_library_no_nuclides/test.py index af14a5dc8f..a02086af3e 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_no_nuclides/test.py @@ -39,7 +39,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=False): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_nuclides/test.py b/tests/regression_tests/mgxs_library_nuclides/test.py index 8a7673565e..a10070358a 100644 --- a/tests/regression_tests/mgxs_library_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_nuclides/test.py @@ -36,7 +36,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=False) def _get_results(self, hash_output=True): """Digest info in the statepoint and return as a string.""" diff --git a/tests/regression_tests/mgxs_library_specific_nuclides/test.py b/tests/regression_tests/mgxs_library_specific_nuclides/test.py index 61910e539e..0ccbb83bdb 100644 --- a/tests/regression_tests/mgxs_library_specific_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_specific_nuclides/test.py @@ -37,7 +37,7 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib.build_library() # Add tallies - self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=True) + self.mgxs_lib.add_to_tallies(self._model.tallies, merge=True) def _get_results(self, hash_output=True): """Digest info in the statepoint and return as a string.""" From 028f4404485407b01a31c44f30249852601a29c8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Nov 2025 11:19:27 -0600 Subject: [PATCH 53/76] Support MPI parallelism in R2SManager (#3632) --- openmc/deplete/microxs.py | 31 +++++++++++++------------ openmc/deplete/r2s.py | 48 ++++++++++++++++++++++++--------------- openmc/lib/core.py | 45 ++++++++++++++++++++++++++++-------- 3 files changed, 82 insertions(+), 42 deletions(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index d7624955e8..f4bdc67953 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -170,13 +170,14 @@ def get_microxs_and_flux( # Reinitialize with tallies openmc.lib.init(intracomm=comm) - # create temporary run with TemporaryDirectory() as temp_dir: - if run_kwargs is None: - run_kwargs = {} - else: - run_kwargs = dict(run_kwargs) - run_kwargs.setdefault('cwd', temp_dir) + # Indicate to run in temporary directory unless being executed through + # openmc.lib, in which case we don't need to specify the cwd + run_kwargs = dict(run_kwargs) if run_kwargs else {} + if not openmc.lib.is_initialized: + run_kwargs.setdefault('cwd', temp_dir) + + # Run transport simulation statepoint_path = model.run(**run_kwargs) if comm.rank == 0: @@ -189,15 +190,18 @@ def get_microxs_and_flux( if path_input is not None: model.export_to_model_xml(path_input) - with StatePoint(statepoint_path) as sp: - if reaction_rate_mode == 'direct': - rr_tally = sp.tallies[rr_tally.id] - rr_tally._read_results() - flux_tally = sp.tallies[flux_tally.id] - flux_tally._read_results() + # Broadcast updated statepoint path to all ranks + statepoint_path = comm.bcast(statepoint_path) + + # Read in tally results (on all ranks) + with StatePoint(statepoint_path) as sp: + if reaction_rate_mode == 'direct': + rr_tally = sp.tallies[rr_tally.id] + rr_tally._read_results() + flux_tally = sp.tallies[flux_tally.id] + flux_tally._read_results() # Get flux values and make energy groups last dimension - flux_tally = comm.bcast(flux_tally) flux = flux_tally.get_reshaped_data() # (domains, groups, 1, 1) flux = np.moveaxis(flux, 1, -1) # (domains, 1, 1, groups) @@ -206,7 +210,6 @@ def get_microxs_and_flux( if reaction_rate_mode == 'direct': # Get reaction rates - rr_tally = comm.bcast(rr_tally) reaction_rates = rr_tally.get_reshaped_data() # (domains, groups, nuclides, reactions) # Make energy groups last dimension diff --git a/openmc/deplete/r2s.py b/openmc/deplete/r2s.py index 7b5deddc23..7f3e94edd9 100644 --- a/openmc/deplete/r2s.py +++ b/openmc/deplete/r2s.py @@ -11,6 +11,9 @@ from . import IndependentOperator, PredictorIntegrator from .microxs import get_microxs_and_flux, write_microxs_hdf5, read_microxs_hdf5 from .results import Results from ..checkvalue import PathLike +from ..mpi import comm +from openmc.lib import TemporarySession +from openmc.utility_funcs import change_directory def get_activation_materials( @@ -199,8 +202,10 @@ class R2SManager: """ if output_dir is None: + # Create timestamped output directory and broadcast to all ranks for + # consistency (different ranks may have slightly different times) stamp = datetime.now().strftime('%Y-%m-%dT%H-%M-%S') - output_dir = Path(f'r2s_{stamp}') + output_dir = Path(comm.bcast(f'r2s_{stamp}')) # Set run_kwargs for the neutron transport step if micro_kwargs is None: @@ -257,18 +262,19 @@ class R2SManager: """ - output_dir = Path(output_dir) + output_dir = Path(output_dir).resolve() output_dir.mkdir(parents=True, exist_ok=True) if self.method == 'mesh-based': # Compute material volume fractions on the mesh if mat_vol_kwargs is None: mat_vol_kwargs = {} - self.results['mesh_material_volumes'] = mmv = \ - self.domains.material_volumes(self.neutron_model, **mat_vol_kwargs) + self.results['mesh_material_volumes'] = mmv = comm.bcast( + self.domains.material_volumes(self.neutron_model, **mat_vol_kwargs)) # Save results to file - mmv.save(output_dir / 'mesh_material_volumes.npz') + if comm.rank == 0: + mmv.save(output_dir / 'mesh_material_volumes.npz') # Create mesh-material filter based on what combos were found domains = openmc.MeshMaterialFilter.from_volumes(self.domains, mmv) @@ -299,13 +305,16 @@ class R2SManager: micro_kwargs.setdefault('path_statepoint', output_dir / 'statepoint.h5') micro_kwargs.setdefault('path_input', output_dir / 'model.xml') - # Run neutron transport and get fluxes and micros - self.results['fluxes'], self.results['micros'] = get_microxs_and_flux( - self.neutron_model, domains, **micro_kwargs) + # Run neutron transport and get fluxes and micros. Run via openmc.lib to + # maintain a consistent parallelism strategy with the activation step. + with TemporarySession(): + self.results['fluxes'], self.results['micros'] = get_microxs_and_flux( + self.neutron_model, domains, **micro_kwargs) # Save flux and micros to file - np.save(output_dir / 'fluxes.npy', self.results['fluxes']) - write_microxs_hdf5(self.results['micros'], output_dir / 'micros.h5') + if comm.rank == 0: + np.save(output_dir / 'fluxes.npy', self.results['fluxes']) + write_microxs_hdf5(self.results['micros'], output_dir / 'micros.h5') def step2_activation( self, @@ -457,15 +466,17 @@ class R2SManager: # photon model if it is different from the neutron model to account for # potential material changes if self.method == 'mesh-based' and different_photon_model: - self.results['mesh_material_volumes_photon'] = photon_mmv = \ - self.domains.material_volumes(self.photon_model, **mat_vol_kwargs) + self.results['mesh_material_volumes_photon'] = photon_mmv = comm.bcast( + self.domains.material_volumes(self.photon_model, **mat_vol_kwargs)) # Save photon MMV results to file - photon_mmv.save(output_dir / 'mesh_material_volumes.npz') + if comm.rank == 0: + photon_mmv.save(output_dir / 'mesh_material_volumes.npz') - tally_ids = [tally.id for tally in self.photon_model.tallies] - with open(output_dir / 'tally_ids.json', 'w') as f: - json.dump(tally_ids, f) + if comm.rank == 0: + tally_ids = [tally.id for tally in self.photon_model.tallies] + with open(output_dir / 'tally_ids.json', 'w') as f: + json.dump(tally_ids, f) self.results['photon_tallies'] = {} @@ -514,8 +525,9 @@ class R2SManager: time_index = len(self.results['depletion_results']) + time_index # Run photon transport calculation - run_kwargs['cwd'] = Path(output_dir) / f'time_{time_index}' - statepoint_path = self.photon_model.run(**run_kwargs) + photon_dir = Path(output_dir) / f'time_{time_index}' + with TemporarySession(self.photon_model, cwd=photon_dir): + statepoint_path = self.photon_model.run(**run_kwargs) # Store tally results with openmc.StatePoint(statepoint_path) as sp: diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 9f8db69d57..cfccecef2a 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -13,6 +13,7 @@ from numpy.ctypeslib import as_array from . import _dll from .error import _error_handler +from ..mpi import comm from openmc.checkvalue import PathLike import openmc.lib import openmc @@ -632,6 +633,9 @@ class TemporarySession: model : openmc.Model, optional OpenMC model to use for the session. If None, a minimal working model is created. + cwd : PathLike, optional + Working directory in which to run OpenMC. If None, a temporary directory + is created and deleted automatically. **init_kwargs Keyword arguments to pass to :func:`openmc.lib.init`. @@ -639,10 +643,13 @@ class TemporarySession: ---------- model : openmc.Model The OpenMC model used for the session. + comm : mpi4py.MPI.Intracomm + The MPI intracommunicator used for the session. """ - def __init__(self, model=None, **init_kwargs): - self.init_kwargs = init_kwargs + def __init__(self, model=None, cwd=None, **init_kwargs): + self.init_kwargs = dict(init_kwargs) + self.cwd = cwd if model is None: surf = openmc.Sphere(boundary_type="vacuum") cell = openmc.Cell(region=-surf) @@ -652,6 +659,10 @@ class TemporarySession: particles=1, batches=1, output={'summary': False}) self.model = model + # Determine MPI intercommunicator + self.init_kwargs.setdefault('intracomm', comm) + self.comm = self.init_kwargs['intracomm'] + def __enter__(self): """Initialize the OpenMC library in a temporary directory.""" # If already initialized, the context manager is a no-op @@ -662,14 +673,24 @@ class TemporarySession: # Store original working directory self.orig_dir = Path.cwd() - # Set up temporary directory - self.tmp_dir = TemporaryDirectory() - working_dir = Path(self.tmp_dir.name) - working_dir.mkdir(parents=True, exist_ok=True) - os.chdir(working_dir) + if self.cwd is None: + # Set up temporary directory on rank 0 + if self.comm.rank == 0: + self._tmp_dir = TemporaryDirectory() + self.cwd = self._tmp_dir.name - # Export model and initialize OpenMC - self.model.export_to_model_xml() + # Broadcast the path so that all ranks use the same directory + self.cwd = self.comm.bcast(self.cwd) + + # Create and change to specified directory + self.cwd = Path(self.cwd) + self.cwd.mkdir(parents=True, exist_ok=True) + os.chdir(self.cwd) + + # Export model on first rank and initialize OpenMC + if self.comm.rank == 0: + self.model.export_to_model_xml() + self.comm.barrier() openmc.lib.init(**self.init_kwargs) return self @@ -683,7 +704,11 @@ class TemporarySession: finalize() finally: os.chdir(self.orig_dir) - self.tmp_dir.cleanup() + + # Make sure all ranks have finalized before deleting temporary dir + self.comm.barrier() + if hasattr(self, '_tmp_dir'): + self._tmp_dir.cleanup() class _DLLGlobal: From f544d02e499248281050ef2272d042c4a7933858 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 19 Nov 2025 11:26:57 -0600 Subject: [PATCH 54/76] Don't write reaction rates in depletion results by default, remove per-stage data for multistage integrators (#3609) --- docs/source/io_formats/depletion_results.rst | 26 +-- openmc/deplete/abc.py | 153 ++++++++----- openmc/deplete/integrators.py | 85 +++---- openmc/deplete/results.py | 8 +- openmc/deplete/stepresult.py | 222 +++++++++++-------- tests/unit_tests/test_deplete_continue.py | 8 +- tests/unit_tests/test_deplete_integrator.py | 93 +++++--- tests/unit_tests/test_deplete_restart.py | 14 +- 8 files changed, 336 insertions(+), 273 deletions(-) diff --git a/docs/source/io_formats/depletion_results.rst b/docs/source/io_formats/depletion_results.rst index 7035fc9c9e..b2a726dad0 100644 --- a/docs/source/io_formats/depletion_results.rst +++ b/docs/source/io_formats/depletion_results.rst @@ -4,7 +4,7 @@ Depletion Results File Format ============================= -The current version of the depletion results file format is 1.1. +The current version of the depletion results file format is 1.2. **/** @@ -12,22 +12,20 @@ The current version of the depletion results file format is 1.1. - **version** (*int[2]*) -- Major and minor version of the statepoint file format. -:Datasets: - **eigenvalues** (*double[][][2]*) -- k-eigenvalues at each - time/stage. This array has shape (number of timesteps, number of - stages, value). The last axis contains the eigenvalue and the - associated uncertainty - - **number** (*double[][][][]*) -- Total number of atoms. This array - has shape (number of timesteps, number of stages, number of +:Datasets: - **eigenvalues** (*double[][2]*) -- k-eigenvalues at each timestep. + This array has shape (number of timesteps, 2). The second axis + contains the eigenvalue and its associated uncertainty. + - **number** (*double[][][]*) -- Total number of atoms at each + timestep. This array has shape (number of timesteps, number of materials, number of nuclides). - - **reaction rates** (*double[][][][][]*) -- Reaction rates used to - build depletion matrices. This array has shape (number of - timesteps, number of stages, number of materials, number of - nuclides, number of reactions). + - **reaction rates** (*double[][][][]*) -- Reaction rates at each + timestep. This array has shape (number of timesteps, number of + materials, number of nuclides, number of reactions). Only stored if + write_rates=True. - **time** (*double[][2]*) -- Time in [s] at beginning/end of each step. - - **source_rate** (*double[][]*) -- Power in [W] or source rate in - [neutron/sec]. This array has shape (number of timesteps, number - of stages). + - **source_rate** (*double[]*) -- Power in [W] or source rate in + [neutron/sec] for each timestep. - **depletion time** (*double[]*) -- Average process time in [s] spent depleting a material across all burnable materials and, if applicable, MPI processes. diff --git a/openmc/deplete/abc.py b/openmc/deplete/abc.py index fb18d86afc..32f468306d 100644 --- a/openmc/deplete/abc.py +++ b/openmc/deplete/abc.py @@ -631,17 +631,7 @@ class Integrator(ABC): solver: str = "cram48", continue_timesteps: bool = False, ): - # 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)) - elif continue_timesteps: + if continue_timesteps and operator.prev_res is None: raise ValueError("Continuation run requires passing prev_results.") self.operator = operator self.chain = operator.chain @@ -775,12 +765,8 @@ class Integrator(ABC): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of timestep """ @property @@ -811,9 +797,9 @@ class Integrator(ABC): """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]) + bos_conc = list(res.data) + rates = res.rates + k = ufloat(res.k[0], res.k[1]) if res.source_rate != 0.0: # Scale reaction rates by ratio of source rates @@ -855,7 +841,8 @@ class Integrator(ABC): self, final_step: bool = True, output: bool = True, - path: PathLike = 'depletion_results.h5' + path: PathLike = 'depletion_results.h5', + write_rates: bool = False ): """Perform the entire depletion process across all steps @@ -874,6 +861,11 @@ class Integrator(ABC): Path to file to write. Defaults to 'depletion_results.h5'. .. versionadded:: 0.15.0 + write_rates : bool, optional + Whether reaction rates should be written to the results file for + each step. Defaults to ``False`` to reduce file size. + + .. versionadded:: 0.15.3 """ with change_directory(self.operator.output_dir): n = self.operator.initial_condition() @@ -890,18 +882,22 @@ class Integrator(ABC): n, res = self._get_bos_data_from_restart(source_rate, n) # Solve Bateman equations over time interval - proc_time, n_list, res_list = self(n, res.rates, dt, source_rate, i) + proc_time, n_end = self(n, res.rates, dt, source_rate, i) - # Insert BOS concentration, transport results - n_list.insert(0, n) - res_list.insert(0, res) - - # Remove actual EOS concentration for next step - n = n_list.pop() - - StepResult.save(self.operator, n_list, res_list, [t, t + dt], - source_rate, self._i_res + i, proc_time, path) + StepResult.save( + self.operator, + n, + res, + [t, t + dt], + source_rate, + self._i_res + i, + proc_time, + write_rates=write_rates, + path=path + ) + # Update for next step + n = n_end t += dt # Final simulation -- in the case that final_step is False, a zero @@ -910,9 +906,18 @@ class Integrator(ABC): # solve) if output and final_step and comm.rank == 0: print(f"[openmc.deplete] t={t} (final operator evaluation)") - res_list = [self.operator(n, source_rate if final_step else 0.0)] - StepResult.save(self.operator, [n], res_list, [t, t], - source_rate, self._i_res + len(self), proc_time, path) + res_final = self.operator(n, source_rate if final_step else 0.0) + StepResult.save( + self.operator, + n, + res_final, + [t, t], + source_rate, + self._i_res + len(self), + proc_time, + write_rates=write_rates, + path=path + ) self.operator.write_bos_data(len(self) + self._i_res) self.operator.finalize() @@ -1171,10 +1176,40 @@ class SIIntegrator(Integrator): self.operator.settings.particles //= self.n_steps return inherited + @abstractmethod + def __call__(self, n, rates, dt, source_rate, i): + """Perform the integration across one time step + + Parameters + ---------- + n : list of numpy.ndarray + List of atom number arrays for each material. Each array has + shape ``(n_nucs,)`` where ``n_nucs`` is the number of nuclides + rates : openmc.deplete.ReactionRates + Reaction rates (from transport operator) + dt : float + Time step in [s] + source_rate : float + Power in [W] or source rate in [neutron/sec] + i : int + Current time step index + + Returns + ------- + proc_time : float + Time spent in transport simulation + n_end : list of numpy.ndarray + Updated atom number densities for each material + op_result : OperatorResult + Eigenvalue and reaction rates resulting from transport simulation + + """ + def integrate( self, output: bool = True, - path: PathLike = "depletion_results.h5" + path: PathLike = "depletion_results.h5", + write_rates: bool = False ): """Perform the entire depletion process across all steps @@ -1186,11 +1221,17 @@ class SIIntegrator(Integrator): Path to file to write. Defaults to 'depletion_results.h5'. .. versionadded:: 0.15.0 + write_rates : bool, optional + Whether reaction rates should be written to the results file for + each step. Defaults to ``False`` to reduce file size. + + .. versionadded:: 0.15.3 """ with change_directory(self.operator.output_dir): n = self.operator.initial_condition() t, self._i_res = self._get_start_data() + res_end = None # Will be set in first iteration for i, (dt, p) in enumerate(self): if output: print(f"[openmc.deplete] t={t} s, dt={dt} s, source={p}") @@ -1200,28 +1241,38 @@ class SIIntegrator(Integrator): n, res = self._get_bos_data_from_operator(i, p, n) else: n, res = self._get_bos_data_from_restart(p, n) - else: - # Pull rates, k from previous iteration w/o - # re-running transport - res = res_list[-1] # defined in previous i iteration - proc_time, n_list, res_list = self(n, res.rates, dt, p, i) + proc_time, n_end, res_end = self(n, res.rates, dt, p, i) - # Insert BOS concentration, transport results - n_list.insert(0, n) - res_list.insert(0, res) - - # Remove actual EOS concentration for next step - n = n_list.pop() - - StepResult.save(self.operator, n_list, res_list, [t, t + dt], - p, self._i_res + i, proc_time, path) + StepResult.save( + self.operator, + n, + res, + [t, t + dt], + p, + self._i_res + i, + proc_time, + write_rates=write_rates, + path=path + ) + # Update for next step + n = n_end + res = res_end t += dt # No final simulation for SIE, use last iteration results - StepResult.save(self.operator, [n], [res_list[-1]], [t, t], - p, self._i_res + len(self), proc_time, path) + StepResult.save( + self.operator, + n, + res_end, + [t, t], + p, + self._i_res + len(self), + proc_time, + write_rates=write_rates, + path=path + ) self.operator.write_bos_data(self._i_res + len(self)) self.operator.finalize() diff --git a/openmc/deplete/integrators.py b/openmc/deplete/integrators.py index 7c543a6cb8..25e64cb2ef 100644 --- a/openmc/deplete/integrators.py +++ b/openmc/deplete/integrators.py @@ -46,15 +46,12 @@ class PredictorIntegrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of list of numpy.ndarray + n_end : 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, n_end = self._timed_deplete(n, rates, dt, _i) - return proc_time, [n_end], [] + return proc_time, n_end @add_params @@ -98,11 +95,8 @@ class CECMIntegrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval """ # deplete across first half of interval time0, n_middle = self._timed_deplete(n, rates, dt / 2, _i) @@ -112,7 +106,7 @@ class CECMIntegrator(Integrator): # MOS reaction rates time1, n_end = self._timed_deplete(n, res_middle.rates, dt, _i) - return time0 + time1, [n_middle, n_end], [res_middle] + return time0 + time1, n_end @add_params @@ -162,12 +156,8 @@ class CF4Integrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_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 + n_end : list of numpy.ndarray + Concentrations at end of interval """ # Step 1: deplete with matrix 1/2*A(y0) time1, n_eos1 = self._timed_deplete( @@ -192,9 +182,7 @@ class CF4Integrator(Integrator): time5, n_eos5 = self._timed_deplete( n_inter, list_rates, dt, _i, matrix_func=cf4_f4) - return (time1 + time2 + time3 + time4 + time5, - [n_eos1, n_eos2, n_eos3, n_eos5], - [res1, res2, res3]) + return time1 + time2 + time3 + time4 + time5, n_eos5 @add_params @@ -240,12 +228,8 @@ class CELIIntegrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval """ # deplete to end using BOS rates proc_time, n_ce = self._timed_deplete(n_bos, rates, dt, _i) @@ -260,7 +244,7 @@ class CELIIntegrator(Integrator): time_le2, n_end = self._timed_deplete( n_inter, list_rates, dt, _i, matrix_func=celi_f2) - return proc_time + time_le1 + time_le1, [n_ce, n_end], [res_ce] + return proc_time + time_le1 + time_le2, n_end @add_params @@ -306,12 +290,8 @@ class EPCRK4Integrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval """ # Step 1: deplete with matrix A(y0) / 2 @@ -330,7 +310,7 @@ class EPCRK4Integrator(Integrator): list_rates = list(zip(rates, res1.rates, res2.rates, res3.rates)) time4, n4 = self._timed_deplete(n, list_rates, dt, _i, matrix_func=rk4_f4) - return (time1 + time2 + time3 + time4, [n1, n2, n3, n4], [res1, res2, res3]) + return time1 + time2 + time3 + time4, n4 @add_params @@ -388,12 +368,8 @@ class LEQIIntegrator(Integrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval """ if i == 0: if self._i_res < 1: # need at least previous transport solution @@ -402,7 +378,7 @@ class LEQIIntegrator(Integrator): self, n_bos, bos_rates, dt, source_rate, i) prev_res = self.operator.prev_res[-2] prev_dt = self.timesteps[i] - prev_res.time[0] - self._prev_rates = prev_res.rates[0] + self._prev_rates = prev_res.rates else: prev_dt = self.timesteps[i - 1] @@ -431,9 +407,7 @@ class LEQIIntegrator(Integrator): # store updated rates self._prev_rates = copy.deepcopy(bos_res.rates) - return ( - time1 + time2 + time3 + time4, [n_eos0, n_eos1], - [bos_res, res_inter]) + return time1 + time2 + time3 + time4, n_eos1 @add_params @@ -470,10 +444,9 @@ class SICELIIntegrator(SIIntegrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_bos_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval + op_result : openmc.deplete.OperatorResult Eigenvalue and reaction rates from intermediate transport simulations """ @@ -499,7 +472,7 @@ class SICELIIntegrator(SIIntegrator): proc_time += time1 + time2 # end iteration - return proc_time, [n_eos, n_inter], [res_bar] + return proc_time, n_inter, res_bar @add_params @@ -536,10 +509,9 @@ class SILEQIIntegrator(SIIntegrator): ------- proc_time : float Time spent in CRAM routines for all materials in [s] - n_list : list of 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 + n_end : list of numpy.ndarray + Concentrations at end of interval + op_result : openmc.deplete.OperatorResult Eigenvalue and reaction rates from intermediate transport simulation """ @@ -551,7 +523,7 @@ class SILEQIIntegrator(SIIntegrator): self, n_bos, bos_rates, dt, source_rate, i) prev_res = self.operator.prev_res[-2] prev_dt = self.timesteps[i] - prev_res.time[0] - self._prev_rates = prev_res.rates[0] + self._prev_rates = prev_res.rates else: prev_dt = self.timesteps[i - 1] @@ -584,7 +556,10 @@ class SILEQIIntegrator(SIIntegrator): n_inter, inputs, dt, i, matrix_func=leqi_f4) proc_time += time1 + time2 - return proc_time, [n_eos, n_inter], [res_bar] + # Store updated rates for next step + self._prev_rates = copy.deepcopy(bos_rates) + + return proc_time, n_inter, res_bar integrator_by_name = { diff --git a/openmc/deplete/results.py b/openmc/deplete/results.py index 7427abd735..e1fcb26b6d 100644 --- a/openmc/deplete/results.py +++ b/openmc/deplete/results.py @@ -203,7 +203,7 @@ class Results(list): # Evaluate value in each region for i, result in enumerate(self): times[i] = result.time[0] - concentrations[i] = result[0, mat_id, nuc] + concentrations[i] = result[mat_id, nuc] # Unit conversions times = _get_time_as(times, time_units) @@ -363,7 +363,7 @@ class Results(list): # Evaluate value in each region for i, result in enumerate(self): times[i] = result.time[0] - rates[i] = result.rates[0].get(mat_id, nuc, rx) * result[0, mat, nuc] + rates[i] = result.rates.get(mat_id, nuc, rx) * result[mat, nuc] return times, rates @@ -397,7 +397,7 @@ class Results(list): # Get time/eigenvalue at each point for i, result in enumerate(self): times[i] = result.time[0] - eigenvalues[i] = result.k[0] + eigenvalues[i] = result.k # Convert time units if necessary times = _get_time_as(times, time_units) @@ -630,7 +630,7 @@ class Results(list): for nuc in result.index_nuc: if nuc not in available_cross_sections: continue - atoms = result[0, mat_id, nuc] + atoms = result[mat_id, nuc] if atoms > 0.0: atoms_per_barn_cm = 1e-24 * atoms / mat.volume mat.remove_nuclide(nuc) # Replace if it's there diff --git a/openmc/deplete/stepresult.py b/openmc/deplete/stepresult.py index 1a26cbe346..ff39e9acb6 100644 --- a/openmc/deplete/stepresult.py +++ b/openmc/deplete/stepresult.py @@ -16,7 +16,7 @@ from openmc.mpi import comm, MPI from openmc.checkvalue import PathLike from .reaction_rates import ReactionRates -VERSION_RESULTS = (1, 1) +VERSION_RESULTS = (1, 2) __all__ = ["StepResult"] @@ -30,8 +30,8 @@ class StepResult: Attributes ---------- - k : list of (float, float) - Eigenvalue and uncertainty for each substep. + k : tuple of (float, float) + Eigenvalue and uncertainty at end of step. time : list of float Time at beginning, end of step, in seconds. source_rate : float @@ -40,8 +40,8 @@ class StepResult: Number of mats. n_nuc : int Number of nuclides. - rates : list of ReactionRates - The reaction rates for each substep. + rates : ReactionRates + The reaction rates at end of step. volume : dict of str to float Dictionary mapping mat id to volume. index_mat : dict of str to int @@ -52,10 +52,8 @@ class StepResult: A dictionary mapping mat ID as string to global index. n_hdf5_mats : int Number of materials in entire geometry. - n_stages : int - Number of stages in simulation. data : numpy.ndarray - Atom quantity, stored by stage, mat, then by nuclide. + Atom quantity, stored by mat, then by nuclide. proc_time : int Average time spent depleting a material across all materials and processes @@ -86,17 +84,17 @@ class StepResult: Parameters ---------- pos : tuple - A three-length tuple containing a stage index, mat index and a nuc - index. All can be integers or slices. The second two can be + A two-length tuple containing a mat index and a nuc + index. Both can be integers or slices, or can be strings corresponding to their respective dictionary. Returns ------- float - The atoms for stage, mat, nuc + The atoms for mat, nuc """ - stage, mat, nuc = pos + mat, nuc = pos if isinstance(mat, openmc.Material): mat = str(mat.id) if isinstance(mat, str): @@ -104,7 +102,7 @@ class StepResult: if isinstance(nuc, str): nuc = self.index_nuc[nuc] - return self.data[stage, mat, nuc] + return self.data[mat, nuc] def __setitem__(self, pos, val): """Sets an item from results. @@ -112,21 +110,21 @@ class StepResult: Parameters ---------- pos : tuple - A three-length tuple containing a stage index, mat index and a nuc - index. All can be integers or slices. The second two can be + A two-length tuple containing a mat index and a nuc + index. Both can be integers or slices, or can be strings corresponding to their respective dictionary. val : float The value to set data to. """ - stage, mat, nuc = pos + mat, nuc = pos if isinstance(mat, str): mat = self.index_mat[mat] if isinstance(nuc, str): nuc = self.index_nuc[nuc] - self.data[stage, mat, nuc] = val + self.data[mat, nuc] = val @property def n_mat(self): @@ -140,11 +138,7 @@ class StepResult: def n_hdf5_mats(self): return len(self.mat_to_hdf5_ind) - @property - def n_stages(self): - return self.data.shape[0] - - def allocate(self, volume, nuc_list, burn_list, full_burn_list, stages): + def allocate(self, volume, nuc_list, burn_list, full_burn_list): """Allocate memory for depletion step data Parameters @@ -157,8 +151,6 @@ class StepResult: A list of all mat IDs to be burned. Used for sorting the simulation. full_burn_list : list of str List of all burnable material IDs - stages : int - Number of stages in simulation. """ self.volume = copy.deepcopy(volume) @@ -167,7 +159,7 @@ class StepResult: self.mat_to_hdf5_ind = {mat: i for i, mat in enumerate(full_burn_list)} # Create storage array - self.data = np.zeros((stages, self.n_mat, self.n_nuc)) + self.data = np.zeros((self.n_mat, self.n_nuc)) def distribute(self, local_materials, ranges): """Create a new object containing data for distributed materials @@ -196,8 +188,8 @@ class StepResult: 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] + new.data = self.data[ranges] + new.rates = self.rates[ranges] return new def get_material(self, mat_id): @@ -232,7 +224,7 @@ class StepResult: f'values are {list(self.volume.keys())}' ) from e for nuc, _ in sorted(self.index_nuc.items(), key=lambda x: x[1]): - atoms = self[0, mat_id, nuc] + atoms = self[mat_id, nuc] if atoms <= 0.0: continue atom_per_bcm = atoms / vol * 1e-24 @@ -240,7 +232,7 @@ class StepResult: material.volume = vol return material - def export_to_hdf5(self, filename, step): + def export_to_hdf5(self, filename, step, write_rates: bool = False): """Export results to an HDF5 file Parameters @@ -249,6 +241,8 @@ class StepResult: The filename to write to step : int What step is this? + write_rates : bool, optional + Whether to include reaction rate datasets in the results file. """ # Write new file if first time step, else add to existing file @@ -259,7 +253,8 @@ class StepResult: kwargs['driver'] = 'mpio' kwargs['comm'] = comm with h5py.File(filename, **kwargs) as handle: - self._to_hdf5(handle, step, parallel=True) + self._to_hdf5(handle, step, parallel=True, + write_rates=write_rates) else: # Gather results at root process all_results = comm.gather(self) @@ -268,15 +263,18 @@ class StepResult: if comm.rank == 0: with h5py.File(filename, **kwargs) as handle: for res in all_results: - res._to_hdf5(handle, step, parallel=False) + res._to_hdf5(handle, step, parallel=False, + write_rates=write_rates) - def _write_hdf5_metadata(self, handle): + def _write_hdf5_metadata(self, handle, write_rates): """Writes result metadata in HDF5 file Parameters ---------- handle : h5py.File or h5py.Group An hdf5 file or group type to store this in. + write_rates : bool + Whether reaction rate datasets are being written. """ # Create and save the 5 dictionaries: @@ -284,8 +282,8 @@ class StepResult: # self.index_mat -> self.volume (TODO: support for changing volumes) # self.index_nuc # reactions - # self.rates[0].index_nuc (can be different from above, above is superset) - # self.rates[0].index_rx + # self.rates.index_nuc (can be different from above, above is superset) + # self.rates.index_rx # these are shared by every step of the simulation, and should be deduplicated. # Store concentration mat and nuclide dictionaries (along with volumes) @@ -295,13 +293,19 @@ class StepResult: mat_list = sorted(self.mat_to_hdf5_ind, key=int) nuc_list = sorted(self.index_nuc) - rxn_list = sorted(self.rates[0].index_rx) + + include_rates = ( + write_rates + and self.rates is not None + and bool(self.rates.index_nuc) + and bool(self.rates.index_rx) + ) + rxn_list = sorted(self.rates.index_rx) if include_rates else [] n_mats = self.n_hdf5_mats n_nuc_number = len(nuc_list) - n_nuc_rxn = len(self.rates[0].index_nuc) + n_nuc_rxn = len(self.rates.index_nuc) if include_rates else 0 n_rxn = len(rxn_list) - n_stages = self.n_stages mat_group = handle.create_group("materials") @@ -315,41 +319,44 @@ class StepResult: for nuc in nuc_list: nuc_single_group = nuc_group.create_group(nuc) nuc_single_group.attrs["atom number index"] = self.index_nuc[nuc] - if nuc in self.rates[0].index_nuc: - nuc_single_group.attrs["reaction rate index"] = self.rates[0].index_nuc[nuc] + if include_rates and nuc in self.rates.index_nuc: + nuc_single_group.attrs["reaction rate index"] = ( + self.rates.index_nuc[nuc]) - rxn_group = handle.create_group("reactions") + if include_rates: + rxn_group = handle.create_group("reactions") - for rxn in rxn_list: - rxn_single_group = rxn_group.create_group(rxn) - rxn_single_group.attrs["index"] = self.rates[0].index_rx[rxn] + for rxn in rxn_list: + rxn_single_group = rxn_group.create_group(rxn) + rxn_single_group.attrs["index"] = ( + self.rates.index_rx[rxn]) # Construct array storage - handle.create_dataset("number", (1, n_stages, n_mats, n_nuc_number), - maxshape=(None, n_stages, n_mats, n_nuc_number), + handle.create_dataset("number", (1, n_mats, n_nuc_number), + maxshape=(None, n_mats, n_nuc_number), chunks=True, dtype='float64') - if n_nuc_rxn > 0 and n_rxn > 0: - handle.create_dataset("reaction rates", (1, n_stages, n_mats, n_nuc_rxn, n_rxn), - maxshape=(None, n_stages, n_mats, n_nuc_rxn, n_rxn), - chunks=True, - dtype='float64') + if include_rates and n_nuc_rxn > 0 and n_rxn > 0: + handle.create_dataset( + "reaction rates", (1, n_mats, n_nuc_rxn, n_rxn), + maxshape=(None, n_mats, n_nuc_rxn, n_rxn), + chunks=True, dtype='float64') - handle.create_dataset("eigenvalues", (1, n_stages, 2), - maxshape=(None, n_stages, 2), dtype='float64') + handle.create_dataset("eigenvalues", (1, 2), + maxshape=(None, 2), dtype='float64') handle.create_dataset("time", (1, 2), maxshape=(None, 2), dtype='float64') - handle.create_dataset("source_rate", (1, n_stages), maxshape=(None, n_stages), + handle.create_dataset("source_rate", (1,), maxshape=(None,), dtype='float64') handle.create_dataset( "depletion time", (1,), maxshape=(None,), dtype="float64") - def _to_hdf5(self, handle, index, parallel=False): + def _to_hdf5(self, handle, index, parallel=False, write_rates: bool = False): """Converts results object into an hdf5 object. Parameters @@ -360,12 +367,14 @@ class StepResult: What step is this? parallel : bool Being called with parallel HDF5? + write_rates : bool, optional + Whether reaction rate datasets are being written. """ if "/number" not in handle: if parallel: comm.barrier() - self._write_hdf5_metadata(handle) + self._write_hdf5_metadata(handle, write_rates) if parallel: comm.barrier() @@ -417,18 +426,14 @@ class StepResult: return # Add data - # Note, for the last step, self.n_stages = 1, even if n_stages != 1. - n_stages = self.n_stages inds = [self.mat_to_hdf5_ind[mat] for mat in self.index_mat] low = min(inds) high = max(inds) - for i in range(n_stages): - number_dset[index, i, low:high+1] = self.data[i] - if has_reactions: - rxn_dset[index, i, low:high+1] = self.rates[i] - if comm.rank == 0: - eigenvalues_dset[index, i] = self.k[i] + number_dset[index, low:high+1] = self.data + if has_reactions: + rxn_dset[index, low:high+1] = self.rates if comm.rank == 0: + eigenvalues_dset[index] = self.k time_dset[index] = self.time source_rate_dset[index] = self.source_rate if self.proc_time is not None: @@ -459,10 +464,24 @@ class StepResult: # Older versions used "power" instead of "source_rate" source_rate_dset = handle["/power"] - results.data = number_dset[step, :, :, :] - results.k = eigenvalues_dset[step, :] + # Check if this is an old format file (with stages dimension) or new format + # Old format: number has shape (n_steps, n_stages, n_mats, n_nucs) + # New format: number has shape (n_steps, n_mats, n_nucs) + has_stages = len(number_dset.shape) == 4 + + if has_stages: + # Old format - extract data from first stage (index 0) + results.data = number_dset[step, 0, :, :] + results.k = eigenvalues_dset[step, 0, :] + # source_rate had shape (n_steps, n_stages) in old format + results.source_rate = source_rate_dset[step, 0] + else: + # New format - no stages dimension + results.data = number_dset[step, :, :] + results.k = eigenvalues_dset[step, :] + results.source_rate = source_rate_dset[step] + results.time = time_dset[step, :] - results.source_rate = source_rate_dset[step, 0] if "depletion time" in handle: proc_time_dset = handle["/depletion time"] @@ -493,33 +512,45 @@ class StepResult: if "reaction rate index" in nuc_handle.attrs: rxn_nuc_to_ind[nuc] = nuc_handle.attrs["reaction rate index"] - for rxn, rxn_handle in handle["/reactions"].items(): - rxn_to_ind[rxn] = rxn_handle.attrs["index"] + if "reactions" in handle: + for rxn, rxn_handle in handle["/reactions"].items(): + rxn_to_ind[rxn] = rxn_handle.attrs["index"] - results.rates = [] - # Reconstruct reactions - for i in range(results.n_stages): - rate = ReactionRates(results.index_mat, rxn_nuc_to_ind, rxn_to_ind, True) - - if "reaction rates" in handle: - rate[:] = handle["/reaction rates"][step, i, :, :, :] - results.rates.append(rate) + # Reconstruct reaction rates + rate = ReactionRates(results.index_mat, rxn_nuc_to_ind, rxn_to_ind, True) + if "reaction rates" in handle: + if has_stages: + # Old format: (n_steps, n_stages, n_mats, n_nucs, n_rxns) + rate[:] = handle["/reaction rates"][step, 0, :, :, :] + else: + # New format: (n_steps, n_mats, n_nucs, n_rxns) + rate[:] = handle["/reaction rates"][step, :, :, :] + results.rates = rate return results @staticmethod - def save(op, x, op_results, t, source_rate, step_ind, proc_time=None, - path: PathLike = "depletion_results.h5"): + def save( + op, + x, + op_results, + t, + source_rate, + step_ind, + proc_time=None, + write_rates: bool = False, + path: PathLike = "depletion_results.h5" + ): """Creates and writes depletion results to disk Parameters ---------- op : openmc.deplete.abc.TransportOperator The operator used to generate these results. - x : list of list of numpy.array - The prior x vectors. Indexed [i][cell] using the above equation. - op_results : list of openmc.deplete.OperatorResult - Results of applying transport operator + x : numpy.array + End-of-step concentrations for each material + op_results : openmc.deplete.OperatorResult + Result of applying transport operator at end of step t : list of float Time indices. source_rate : float @@ -530,7 +561,8 @@ class StepResult: Total process time spent depleting materials. This may be process-dependent and will be reduced across MPI processes. - + write_rates : bool, optional + Whether reaction rates should be written to the results file. path : PathLike Path to file to write. Defaults to 'depletion_results.h5'. @@ -539,26 +571,20 @@ class StepResult: # Get indexing terms vol_dict, nuc_list, burn_list, full_burn_list = op.get_results_info() - stages = len(x) - # Create results results = StepResult() - results.allocate(vol_dict, nuc_list, burn_list, full_burn_list, stages) + results.allocate(vol_dict, nuc_list, burn_list, full_burn_list) n_mat = len(burn_list) - for i in range(stages): - for mat_i in range(n_mat): - results[i, mat_i, :] = x[i][mat_i] + for mat_i in range(n_mat): + results[mat_i, :] = x[mat_i] - ks = [] - for r in op_results: - if isinstance(r.k, type(None)): - ks += [(None, None)] - else: - ks += [(r.k.nominal_value, r.k.std_dev)] - results.k = ks - results.rates = [r.rates for r in op_results] + if isinstance(op_results.k, type(None)): + results.k = (None, None) + else: + results.k = (op_results.k.nominal_value, op_results.k.std_dev) + results.rates = op_results.rates results.time = t results.source_rate = source_rate results.proc_time = proc_time @@ -567,7 +593,7 @@ class StepResult: if not Path(path).is_file(): Path(path).parent.mkdir(parents=True, exist_ok=True) - results.export_to_hdf5(path, step_ind) + results.export_to_hdf5(path, step_ind, write_rates) def transfer_volumes(self, model): """Transfers volumes from depletion results to geometry diff --git a/tests/unit_tests/test_deplete_continue.py b/tests/unit_tests/test_deplete_continue.py index 637c9d5e44..1b6eac2384 100644 --- a/tests/unit_tests/test_deplete_continue.py +++ b/tests/unit_tests/test_deplete_continue.py @@ -17,7 +17,7 @@ def test_continue(run_in_tmpdir): operator = dummy_operator.DummyOperator() # initial depletion - bundle.solver(operator, [1.0, 2.0], [1.0, 2.0]).integrate() + bundle.solver(operator, [1.0, 2.0], [1.0, 2.0]).integrate(write_rates=True) # set up continue run prev_res = openmc.deplete.Results(operator.output_dir / "depletion_results.h5") @@ -25,7 +25,7 @@ def test_continue(run_in_tmpdir): # if continue run happens, test passes bundle.solver(operator, [1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0], - continue_timesteps=True).integrate() + continue_timesteps=True).integrate(write_rates=True) final_res = openmc.deplete.Results(operator.output_dir / "depletion_results.h5") @@ -42,7 +42,7 @@ def test_continue_continue(run_in_tmpdir): operator = dummy_operator.DummyOperator() # initial depletion - bundle.solver(operator, [1.0, 2.0], [1.0, 2.0]).integrate() + bundle.solver(operator, [1.0, 2.0], [1.0, 2.0]).integrate(write_rates=True) # set up continue run prev_res = openmc.deplete.Results(operator.output_dir / "depletion_results.h5") @@ -50,7 +50,7 @@ def test_continue_continue(run_in_tmpdir): # first continue run bundle.solver(operator, [1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0], - continue_timesteps=True).integrate() + continue_timesteps=True).integrate(write_rates=True) prev_res = openmc.deplete.Results(operator.output_dir / "depletion_results.h5") # second continue run diff --git a/tests/unit_tests/test_deplete_integrator.py b/tests/unit_tests/test_deplete_integrator.py index b1d2cb950e..6463eaa208 100644 --- a/tests/unit_tests/test_deplete_integrator.py +++ b/tests/unit_tests/test_deplete_integrator.py @@ -10,6 +10,7 @@ import copy from random import uniform from unittest.mock import MagicMock +import h5py import numpy as np from uncertainties import ufloat import pytest @@ -38,8 +39,6 @@ INTEGRATORS = [ def test_results_save(run_in_tmpdir): """Test data save module""" - stages = 3 - rng = np.random.RandomState(comm.rank) # Mock geometry @@ -63,31 +62,22 @@ def test_results_save(run_in_tmpdir): op.get_results_info.return_value = ( vol_dict, nuc_list, burn_list, full_burn_list) - # Construct x - x1 = [] - x2 = [] + # Construct end-of-step concentrations + x1 = [rng.random(2), rng.random(2)] + x2 = [rng.random(2), rng.random(2)] - for i in range(stages): - x1.append([rng.random(2), rng.random(2)]) - x2.append([rng.random(2), rng.random(2)]) - - # Construct r + # Construct reaction rates r1 = ReactionRates(burn_list, ["na", "nb"], ["ra", "rb"]) r1[:] = rng.random((2, 2, 2)) + rate1 = copy.deepcopy(r1) - rate1 = [] - rate2 = [] + r2 = ReactionRates(burn_list, ["na", "nb"], ["ra", "rb"]) + r2[:] = rng.random((2, 2, 2)) + rate2 = copy.deepcopy(r2) - for i in range(stages): - rate1.append(copy.deepcopy(r1)) - r1[:] = rng.random((2, 2, 2)) - rate2.append(copy.deepcopy(r1)) - r1[:] = rng.random((2, 2, 2)) - - # Create global terms - # Col 0: eig, Col 1: uncertainty - eigvl1 = rng.random((stages, 2)) - eigvl2 = rng.random((stages, 2)) + # Create global terms (eigenvalue and uncertainty) + eigvl1 = rng.random(2) + eigvl2 = rng.random(2) eigvl1 = comm.bcast(eigvl1, root=0) eigvl2 = comm.bcast(eigvl2, root=0) @@ -95,29 +85,35 @@ def test_results_save(run_in_tmpdir): t1 = [0.0, 1.0] t2 = [1.0, 2.0] - op_result1 = [OperatorResult(ufloat(*k), rates) - for k, rates in zip(eigvl1, rate1)] - op_result2 = [OperatorResult(ufloat(*k), rates) - for k, rates in zip(eigvl2, rate2)] + op_result1 = OperatorResult(ufloat(*eigvl1), rate1) + op_result2 = OperatorResult(ufloat(*eigvl2), rate2) # saves within a subdirectory - StepResult.save(op, x1, op_result1, t1, 0, 0, path='out/put/depletion.h5') + StepResult.save( + op, + x1, + op_result1, + t1, + 0, + 0, + write_rates=True, + path='out/put/depletion.h5' + ) res = Results('out/put/depletion.h5') # saves with default filename - StepResult.save(op, x1, op_result1, t1, 0, 0) - StepResult.save(op, x2, op_result2, t2, 0, 1) + StepResult.save(op, x1, op_result1, t1, 0, 0, write_rates=True) + StepResult.save(op, x2, op_result2, t2, 0, 1, write_rates=True) # Load the files res = Results("depletion_results.h5") - for i in range(stages): - for mat_i, mat in enumerate(burn_list): - for nuc_i, nuc in enumerate(nuc_list): - assert res[0][i, mat, nuc] == x1[i][mat_i][nuc_i] - assert res[1][i, mat, nuc] == x2[i][mat_i][nuc_i] - np.testing.assert_array_equal(res[0].rates[i], rate1[i]) - np.testing.assert_array_equal(res[1].rates[i], rate2[i]) + for mat_i, mat in enumerate(burn_list): + for nuc_i, nuc in enumerate(nuc_list): + assert res[0][mat, nuc] == x1[mat_i][nuc_i] + assert res[1][mat, nuc] == x2[mat_i][nuc_i] + np.testing.assert_array_equal(res[0].rates, rate1) + np.testing.assert_array_equal(res[1].rates, rate2) np.testing.assert_array_equal(res[0].k, eigvl1) np.testing.assert_array_equal(res[0].time, t1) @@ -126,6 +122,31 @@ def test_results_save(run_in_tmpdir): np.testing.assert_array_equal(res[1].time, t2) +def test_results_save_without_rates(run_in_tmpdir): + """StepResult.save skips reaction-rate datasets by default""" + + op = MagicMock() + op.prev_res = None + vol_dict = {"0": 1.0} + nuc_list = ["na"] + burn_list = ["0"] + op.get_results_info.return_value = (vol_dict, nuc_list, burn_list, burn_list) + + x = [np.array([1.0])] + rates = ReactionRates(burn_list, nuc_list, ["ra"]) + rates[:] = np.array([[[2.0]]]) + op_result = OperatorResult(ufloat(1.0, 0.1), rates) + + StepResult.save(op, x, op_result, [0.0, 1.0], 0.0, 0) + + with h5py.File('depletion_results.h5', 'r') as handle: + assert 'reaction rates' not in handle + assert 'reactions' not in handle + + res = Results('depletion_results.h5') + assert res[0].rates.size == 0 + + def test_bad_integrator_inputs(): """Test failure modes for Integrator inputs""" diff --git a/tests/unit_tests/test_deplete_restart.py b/tests/unit_tests/test_deplete_restart.py index e8bfc062a0..1cbff30a5f 100644 --- a/tests/unit_tests/test_deplete_restart.py +++ b/tests/unit_tests/test_deplete_restart.py @@ -21,7 +21,7 @@ def test_restart_predictor_cecm(run_in_tmpdir): # Perform simulation using the predictor algorithm dt = [0.75] power = 1.0 - openmc.deplete.PredictorIntegrator(op, dt, power).integrate() + openmc.deplete.PredictorIntegrator(op, dt, power).integrate(write_rates=True) # Load the files prev_res = openmc.deplete.Results(op.output_dir / "depletion_results.h5") @@ -30,10 +30,6 @@ def test_restart_predictor_cecm(run_in_tmpdir): op = dummy_operator.DummyOperator(prev_res) op.output_dir = output_dir - # check ValueError is raised, indicating previous and current stages - with pytest.raises(ValueError, match="incompatible.* 1.*2"): - openmc.deplete.CECMIntegrator(op, dt, power) - def test_restart_cecm_predictor(run_in_tmpdir): """Integral regression test of integrator algorithm using CE/CM for the @@ -47,7 +43,7 @@ def test_restart_cecm_predictor(run_in_tmpdir): dt = [0.75] power = 1.0 cecm = openmc.deplete.CECMIntegrator(op, dt, power) - cecm.integrate() + cecm.integrate(write_rates=True) # Load the files prev_res = openmc.deplete.Results(op.output_dir / "depletion_results.h5") @@ -56,10 +52,6 @@ def test_restart_cecm_predictor(run_in_tmpdir): op = dummy_operator.DummyOperator(prev_res) op.output_dir = output_dir - # check ValueError is raised, indicating previous and current stages - with pytest.raises(ValueError, match="incompatible.* 2.*1"): - openmc.deplete.PredictorIntegrator(op, dt, power) - @pytest.mark.parametrize("scheme", dummy_operator.SCHEMES) def test_restart(run_in_tmpdir, scheme): @@ -70,7 +62,7 @@ def test_restart(run_in_tmpdir, scheme): operator = dummy_operator.DummyOperator() # take first step - bundle.solver(operator, [0.75], 1.0).integrate() + bundle.solver(operator, [0.75], 1.0).integrate(write_rates=True) # restart prev_res = openmc.deplete.Results( From d217efa007760dbe927af25063ab6d68990779cc Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 20 Nov 2025 12:10:04 -0600 Subject: [PATCH 55/76] Add two MPI barriers in R2S workflow (#3646) --- openmc/deplete/microxs.py | 3 ++- openmc/deplete/r2s.py | 1 + openmc/lib/core.py | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/openmc/deplete/microxs.py b/openmc/deplete/microxs.py index f4bdc67953..879a2d4ee9 100644 --- a/openmc/deplete/microxs.py +++ b/openmc/deplete/microxs.py @@ -177,8 +177,9 @@ def get_microxs_and_flux( if not openmc.lib.is_initialized: run_kwargs.setdefault('cwd', temp_dir) - # Run transport simulation + # Run transport simulation and synchronize statepoint_path = model.run(**run_kwargs) + comm.barrier() if comm.rank == 0: # Move the statepoint file if it is being saved to a specific path diff --git a/openmc/deplete/r2s.py b/openmc/deplete/r2s.py index 7f3e94edd9..97277cbda8 100644 --- a/openmc/deplete/r2s.py +++ b/openmc/deplete/r2s.py @@ -392,6 +392,7 @@ class R2SManager: ) output_path = output_dir / 'depletion_results.h5' integrator.integrate(final_step=False, path=output_path) + comm.barrier() # Get depletion results self.results['depletion_results'] = Results(output_path) diff --git a/openmc/lib/core.py b/openmc/lib/core.py index cfccecef2a..02c7784d1c 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -7,6 +7,7 @@ import os from pathlib import Path from random import getrandbits from tempfile import TemporaryDirectory +import traceback as tb import numpy as np from numpy.ctypeslib import as_array @@ -700,6 +701,15 @@ class TemporarySession: if self.already_initialized: return + # If an exception occurred, abort all ranks immediately + if exc_type is not None: + # Print exception info on the rank that failed + tb.print_exception(exc_type, exc_value, traceback) + sys.stdout.flush() + + # Abort all MPI processes + self.comm.Abort(1) + try: finalize() finally: From 27e38e894697bb32a1dac7848d2618818b6b8daf Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 22 Nov 2025 23:06:17 +0100 Subject: [PATCH 56/76] Add release notes for 0.15.3 (#3644) --- docs/source/releasenotes/0.15.3.rst | 226 ++++++++++++++++++ docs/source/releasenotes/index.rst | 1 + docs/source/usersguide/variance_reduction.rst | 4 +- openmc/model/model.py | 6 +- openmc/settings.py | 9 +- 5 files changed, 240 insertions(+), 6 deletions(-) create mode 100644 docs/source/releasenotes/0.15.3.rst diff --git a/docs/source/releasenotes/0.15.3.rst b/docs/source/releasenotes/0.15.3.rst new file mode 100644 index 0000000000..c509581047 --- /dev/null +++ b/docs/source/releasenotes/0.15.3.rst @@ -0,0 +1,226 @@ +==================== +What's New in 0.15.3 +==================== + +.. currentmodule:: openmc + +------- +Summary +------- + +This release of OpenMC includes many bug fixes, performance improvements, and +several notable new features. The major highlights of this release include a new +:class:`~openmc.deplete.R2SManager` class that automates the workflow for +rigorous 2-step (R2S) shutdown dose rate calculations, the ability to collect +higher moments for tally results that can be used to test normality, a new +uncertainty-aware criticality search method, a new collision tracking feature +that enables detailed tracking of particle interactions, support for distributed +cell densities, and several new tally filters. The random ray solver also +continues to receive significant updates, including automatic setup +capabilities, improved geometry handling, and better weight window support. +Depletion capabilities have been expanded with thermochemical redox control, +external transfer rates, and improved performance. + +------------------------------------ +Compatibility Notes and Deprecations +------------------------------------ + +MCPL has been changed from a build-time dependency to a runtime optional +dependency, which means OpenMC will attempt to load the MCPL library at +runtime when needed rather than requiring it at build time. + +The ``openmc.mgxs.Library.add_to_tallies_file`` method has been renamed to +:meth:`openmc.mgxs.Library.add_to_tallies`. + +------------ +New Features +------------ + +- A new collision tracking feature enables detailed tracking of particle + interactions (`#3417 `_) +- Added :meth:`~openmc.model.Model.keff_search` method for automated criticality + searches (`#3569 `_) +- Introduced automated workflow for mesh- or cell-based R2S calculations + (`#3508 `_) +- Ability to source electron/positrons directly for charged particle + simulations (`#3404 `_) +- Multi-group capability for kinetics parameter calculations with Iterated + Fission Probability (`#3425 + `_) +- Introduced a new :class:`openmc.MeshMaterialFilter` class (`#3406 + `_) +- Added support for distributed cell densities (`#3546 + `_) +- Implemented a :class:`openmc.WeightWindowsList` class that enables export to + HDF5 (`#3456 `_) +- Added :meth:`openmc.Material.mean_free_path` method (`#3469 + `_) +- Introduced :func:`openmc.lib.TemporarySession` context manager (`#3475 + `_) +- Added material depletion function for tracking individual material depletion + (`#3420 `_) +- Added methods on :class:`~openmc.Material` class for waste disposal rating / + classification (`#3366 `_, + `#3376 `_) +- Support for thermochemical redox control transfer rates in depletion + (`#2783 `_) +- Support for external transfer rates source term in depletion (`#3088 + `_) +- Added combing capability for fission site sampling and delayed neutron + emission time (`#2992 `_) +- Ability to specify reference direction for azimuthal angle in + :class:`~openmc.stats.PolarAzimuthal` distribution (`#3582 + `_) +- Allow spatial constraints on element sources within + :class:`~openmc.MeshSource` (`#3431 + `_) +- Added VTK HDF (.vtkhdf) format support for writing VTK data (`#3252 + `_) +- Implemented filter weight capability (`#3345 + `_) +- Optionally collect higher moments for tallies (`#3363 + `_) +- Several random ray solver enhancements: + + - Random Ray AutoMagic Setup for automatic configuration (`#3351 `_) + - Point source locator for random ray mode (`#3360 `_) + - Support for DAGMC geometries (`#3374 `_) + - Optimized mapping of source regions to tallies (`#3465 `_) + - Base source region refactor (`#3576 `_) + +--------------------------- +Bug Fixes and Small Changes +--------------------------- + +- Add two MPI barriers in R2S workflow (`#3646 `_) +- Fix a few warnings, rename add_to_tallies_file (`#3639 `_) +- Fix typo in DAGMC lost particle test (`#3634 `_) +- Avoid multiprocessing Pool when running depletion tests with MPI (`#3633 `_) +- Support MPI parallelism in R2SManager (`#3632 `_) +- Update documentation for particle tracks (`#3627 `_) +- Adding variance of variance and normality tests for tally statistics (`#3454 `_) +- Avoid divide-by-zero in ``from_multigroup_flux`` when flux is zero (`#3624 `_) +- Write particle states as separate lines in track VTK files (`#3628 `_) +- Reset DAGMC history when reviving from source (`#3601 `_) +- Add energy group structure: SCALE-999 (`#3564 `_) +- Fix bug in normalization of tally results with no_reduce (`#3619 `_) +- Enable nuclide filters with get_decay_photon_energy (`#3614 `_) +- Update ``check_type`` calls to accept both ``str`` and ``os.PathLike`` objects (`#3618 `_) +- Speed up ``apply_time_correction`` by reducing file I/O and deepcopies (`#3617 `_) +- FW-CADIS Disregard Max Realizations Setting (`#3616 `_) +- Random Ray Geometry Debug Mode Fix (`#3615 `_) +- Don't write reaction rates in depletion results by default (`#3609 `_) +- Allow Path objects in MGXSLibrary.export_to_hdf5 (`#3608 `_) +- Clip mixture distributions based on mean times integral (`#3603 `_) +- Allow V0 in atomic_mass function (for ENDF/B-VII.0 data) (`#3607 `_) +- Re-run flaky tests when needed (`#3604 `_) +- Ability to load mesh objects from weight_windows.h5 file (`#3598 `_) +- Switch to using coveralls github action for reporting (`#3594 `_) +- Add user setting for free gas threshold (`#3593 `_) +- Speed up time correction factors (`#3592 `_) +- Fix caching issue when using NCrystal materials (`#3538 `_) +- Fix random ray source region mesh export when using model.export_to_xml() (`#3579 `_) +- Ensure weight_windows_file information is read from XML (`#3587 `_) +- Add missing documentation on in depletion chain file format (`#3590 `_) +- Adding tally filter type option to statepoint get_tally (`#3584 `_) +- Optional separation of mesh-material-volume calc from get_homogenized_materials (`#3581 `_) +- Fix IFP implementation (`#3580 `_) +- Remove several TODOs related to C++17 support (`#3574 `_) +- Fix performance regression in libMesh unstructured mesh tallies (`#3577 `_) +- Update find_package calls in OpenMCConfig.cmake (`#3572 `_) +- Ensure ``n_dimension_`` attribute is set for unstructured meshes (`#3575 `_) +- Allow newer Sphinx version and fix docbuild warnings (`#3571 `_) +- Fixed a bug when combining TimeFilter, MeshFilter, and tracklength estimator (`#3525 `_) +- PowerLaw raises an error if sampling interval contains negative values (`#3542 `_) +- depletion: fix performance of chain matrix construction (`#3567 `_) +- Do not apply boundary conditions when initialized in volume calculation mode (`#3562 `_) +- Bump up tolerance for flaky activation test (`#3560 `_) +- Fixed a bug in plotting cross sections with S(a,b) data (`#3558 `_) +- Change test order to run unit tests first (`#3533 `_) +- adding ecco 33 (`#3556 `_) +- Refactor endf_data to be a fixture (`#3539 `_) +- Revert "fix broken CI" (`#3554 `_) +- fix broken CI (`#3551 `_) +- Leverage particle.move_distance in event advance (`#3544 `_) +- fix tests that accidentaly got broken (`#3543 `_) +- not printing nuclides with 0 percent to terminal (option 2 ) (`#3448 `_) +- Fix a bug in time cutoff behavior (`#3526 `_) +- Avoid duplicate materials written to XML (`#3536 `_) +- Use cached property for openmc.data.Decay.sources (`#3535 `_) +- more helpful error message for dose_coefficients (`#3534 `_) +- Adding 616 group structure (`#3531 `_) +- Remove unused special accessors for tallies (`#3527 `_) +- Consistent XML parsing using functions from _xml module (`#3517 `_) +- Add stat:sum field to MCPL files for proper weight normalization (`#3522 `_) +- Remove reorder_attributes from openmc._xml (`#3519 `_) +- fixed a bug in MeshMaterialFilter.from_volumes (`#3520 `_) +- Fixed a bug in distribcell offsets logic (`#3424 `_) +- Add test for FW-CADIS based WW generation on a DAGMC model (`#3504 `_) +- Fix for Weight Window Scaling Bug (`#3511 `_) +- Fix: ``materials``, ``plots``, and ``tallies`` cannot be passed as lists (`#3513 `_) +- Allow already-initialized openmc.lib in TemporarySession (`#3505 `_) +- Update DAGMC and libMesh precompiler definitions (`#3510 `_) +- Avoid adding ParentNuclideFilter twice when calling prepare_tallies (`#3506 `_) +- Enabling MCPL source files to be read when using surf_source_read (`#3472 `_) +- Boundary info accessors (`#3496 `_) +- automatically finding appropriate dimension when making regular mesh from domain (`#3468 `_) +- Add accessor methods for LocalCoord (`#3494 `_) +- Make MCPL a Runtime Optional Dependency (`#3429 `_) +- Use auto-chunking for StepResult HDF5 writing (`#3498 `_) +- Provide a way to get ID maps from plot parameters on the Model class (`#3481 `_) +- Update OSX install instructions to point to x64 platform (`#3501 `_) +- Update conda install instructions for macOS Apple silicon (`#3488 `_) +- Only show warning if in restart mode (`#3478 `_) +- Add flag to CMakeLists to use submodules instead of searching (`#3480 `_) +- Added citation metadata file (`#3409 `_) +- fix zam parsing (`#3484 `_) +- Support flux collapse method in ``get_microxs_and_flux`` (`#3466 `_) +- Stabilize Adjoint Source (`#3476 `_) +- Refactor and Harden Configuration Management (`#3461 `_) +- Updated Docs to Not Give Specific Python Version Requirement (`#3473 `_) +- Parallelization of Weight Window Update (`#3467 `_) +- Limit Random Ray Weight Window Generation to Final Batch (`#3464 `_) +- Fix Dockerfile DAGMC build (`#3463 `_) +- Fix Weight Window Infinite Loop Bug (`#3457 `_) +- Weight Window Birth Scaling (`#3459 `_) +- Adding checks to geometry.plot to avoid material name overlaps (`#3458 `_) +- Fixing crash when calling Geometry.plot when DAGMCUniverse in geometry (`#3455 `_) +- fixing expansion of elemental Ta bug (`#3443 `_) +- Prevent Adjoint Sources from Trending towards Infinity (`#3449 `_) +- adding plot function to DAGMCUnvierse (`#3451 `_) +- Allow specifying number of equiprobable angles for thermal scattering data generation (`#3346 `_) +- Change Dockerfile from debian:bookworm-slim to ubuntu:24.04 (`#3442 `_) +- Fix Resetting of Auto IDs When Generating MGXS (`#3437 `_) +- Allowing chain_file to be chain object to save reloading time (`#3436 `_) +- update units for flux (`#3441 `_) +- Fix raytrace infinite loop (`#3423 `_) +- Apply Max Number of Events Check to Random Rays (`#3438 `_) +- Add user setting for source rejection fraction (`#3433 `_) +- Adding fix and tests for spherical mesh as spatial distribution (`#3428 `_) +- Random Ray Missed Cell Policy Change for Adjoint Mode (`#3434 `_) +- Random Ray External Source Plotting Fix (`#3430 `_) +- Avoid negative heating values during pair production and bremsstrahlung (`#3426 `_) +- Fix no serialization of periodic_surface_id bug (`#3421 `_) +- Update _get_start_data to always grab the beginning of timestep time (`#3414 `_) +- Fixed a bug in charged particle energy deposition (`#3416 `_) +- Fix bug where the same mesh is written multiple times to settings.xml (`#3418 `_) +- small typo - spelling of Debian (`#3411 `_) +- added test for dagmc geometry plot (`#3375 `_) +- Random Ray Misc Memory Error Fixes (`#3405 `_) +- added type hints to model file (`#3399 `_) +- Apply resolve paths to path values in ``config`` (`#3400 `_) +- Fixing an incorrect computation of CDF of bremsstrahlung photons (`#3396 `_) +- Fix weight modification for uniform source sampling (`#3395 `_) +- Updates to VTK data checks (`#3371 `_) +- Map Compton subshell data to atomic relaxation data (`#3392 `_) +- Skip atomic relaxation if binding energy is larger than photon energy (`#3391 `_) +- Fix extremely large yields from Bremsstrahlung (`#3386 `_) +- corrected tally name in D1S example (`#3383 `_) +- Install MCPL using same build type as OpenMC in CI (`#3388 `_) +- using reduce chain level to remove need for reduce chain (`#3377 `_) +- Fix negative distances from bins_crossed for CylindricalMesh (`#3370 `_) +- Add check for equal value bins in an EnergyFilter (`#3372 `_) +- Fix for Issue Loading MGXS Data Files with LLVM 20 or Newer (`#3368 `_) +- Report plot ID instead of index for unsupported plot types in random ray mode (`#3361 `_) +- Handle Missing Tags in Versioning by Setting Default to 0 (`#3359 `_) +- added kg units to doc string in results class (`#3358 `_) diff --git a/docs/source/releasenotes/index.rst b/docs/source/releasenotes/index.rst index d24b83f9eb..1292599ba9 100644 --- a/docs/source/releasenotes/index.rst +++ b/docs/source/releasenotes/index.rst @@ -7,6 +7,7 @@ Release Notes .. toctree:: :maxdepth: 1 + 0.15.3 0.15.2 0.15.1 0.15.0 diff --git a/docs/source/usersguide/variance_reduction.rst b/docs/source/usersguide/variance_reduction.rst index 5c24851585..93321e1072 100644 --- a/docs/source/usersguide/variance_reduction.rst +++ b/docs/source/usersguide/variance_reduction.rst @@ -51,7 +51,7 @@ With the :class:`~openmc.WeightWindowGenerator` instance added to the :attr:`~openmc.Settings`, the rest of the problem can be defined as normal. When running, note that the second iteration and beyond may be several orders of magnitude slower than the first. As the weight windows are applied in each -iteration, particles may be agressively split, resulting in a large number of +iteration, particles may be aggressively split, resulting in a large number of secondary (split) particles being generated per initial source particle. This is not necessarily a bad thing, as the split particles are much more efficient at exploring low flux regions of phase space as compared to initial particles. @@ -161,7 +161,7 @@ solver, the Python input just needs to load the h5 file:: settings.weight_window_checkpoints = {'collision': True, 'surface': True} settings.survival_biasing = False - settings.weight_windows = openmc.WeightWindowsList.from_hdf5('weight_windows.h5') + settings.weight_windows_file = "weight_windows.h5" settings.weight_windows_on = True The :class:`~openmc.WeightWindowGenerator` instance is not needed to load an diff --git a/openmc/model/model.py b/openmc/model/model.py index 10e5cbfc74..48ae9f0b91 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -2112,8 +2112,12 @@ class Model: groups : openmc.mgxs.EnergyGroups or str, optional Energy group structure for the MGXS or the name of the group structure (based on keys from openmc.mgxs.GROUP_STRUCTURES). + nparticles : int, optional + Number of particles to simulate per batch when generating MGXS. + overwrite_mgxs_library : bool, optional + Whether to overwrite an existing MGXS library file. mgxs_path : str, optional - Filename of the mgxs.h5 library file. + Path to the mgxs.h5 library file. correction : str, optional Transport correction to apply to the MGXS. Options are None and "P0". diff --git a/openmc/settings.py b/openmc/settings.py index 43c1fe0698..289fb35b73 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -1278,9 +1278,12 @@ class Settings: return self._weight_windows_file @weight_windows_file.setter - def weight_windows_file(self, value: PathLike): - cv.check_type('weight windows file', value, PathLike) - self._weight_windows_file = input_path(value) + def weight_windows_file(self, value: PathLike | None): + if value is None: + self._weight_windows_file = None + else: + cv.check_type('weight windows file', value, PathLike) + self._weight_windows_file = input_path(value) @property def weight_window_generators(self) -> list[WeightWindowGenerator]: From dcb7443711a5ae761bcc686fdfa6703937d51ab1 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 27 Nov 2025 17:03:38 +0100 Subject: [PATCH 57/76] added test to check dagmc name is in xml (#3657) --- openmc/dagmc.py | 2 ++ tests/unit_tests/dagmc/test_model.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/openmc/dagmc.py b/openmc/dagmc.py index d1265be268..3cb48ddf17 100644 --- a/openmc/dagmc.py +++ b/openmc/dagmc.py @@ -302,6 +302,8 @@ class DAGMCUniverse(openmc.UniverseBase): dagmc_element = ET.Element('dagmc_universe') dagmc_element.set('id', str(self.id)) + if self.name: + dagmc_element.set('name', self.name) if self.auto_geom_ids: dagmc_element.set('auto_geom_ids', 'true') if self.auto_mat_ids: diff --git a/tests/unit_tests/dagmc/test_model.py b/tests/unit_tests/dagmc/test_model.py index 0de4f6092d..0917f5b237 100644 --- a/tests/unit_tests/dagmc/test_model.py +++ b/tests/unit_tests/dagmc/test_model.py @@ -31,7 +31,7 @@ def model(request): p = Path(request.fspath).parent / "dagmc.h5m" - daguniv = openmc.DAGMCUniverse(p, auto_geom_ids=True) + daguniv = openmc.DAGMCUniverse(p, name='simple-dagmc', auto_geom_ids=True) lattice = openmc.RectLattice() lattice.dimension = [2, 2] @@ -232,6 +232,7 @@ def test_dagmc_xml(model): dagmc_ele = root.find('dagmc_universe') assert dagmc_ele.get('id') == str(dag_univ.id) + assert dagmc_ele.get('name') == str(dag_univ.name) assert dagmc_ele.get('filename') == str(dag_univ.filename) assert dagmc_ele.get('auto_geom_ids') == str(dag_univ.auto_geom_ids).lower() From 7ab92ec142470da4cc1f685f0434777772c5343a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 28 Nov 2025 16:39:08 +0100 Subject: [PATCH 58/76] Fix typo in description of distance_inactive for random ray setting (#3663) --- openmc/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openmc/settings.py b/openmc/settings.py index 289fb35b73..76e191c5e0 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -182,7 +182,7 @@ class Settings: Options for configuring the random ray solver. Acceptable keys are: :distance_inactive: - Indicates the total active distance in [cm] a ray should travel + Indicates the total inactive distance in [cm] a ray should travel :distance_active: Indicates the total active distance in [cm] a ray should travel :ray_source: From ef22558f4a037585c4fdd96a1a64dd2781a72c37 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Sat, 29 Nov 2025 17:28:18 +0200 Subject: [PATCH 59/76] fix a bug in borated_water temperature assignment (#3662) --- openmc/model/funcs.py | 9 +++------ tests/unit_tests/test_material.py | 1 + 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/openmc/model/funcs.py b/openmc/model/funcs.py index 41aa920eae..e076b080a9 100644 --- a/openmc/model/funcs.py +++ b/openmc/model/funcs.py @@ -39,8 +39,8 @@ def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K', press_unit : {'MPa', 'psi'} The units used for the `pressure` argument. density : float - Water density in [g / cm^3]. If specified, this value overrides the - temperature and pressure arguments. + Water density in [g / cm^3]. If specified, this value overrides + the value that is computed from the temperature and pressure arguments. **kwargs All keyword arguments are passed to the created Material object. @@ -95,10 +95,7 @@ def borated_water(boron_ppm, temperature=293., pressure=0.1013, temp_unit='K', frac_B = boron_ppm * 1e-6 / M_B # Build the material. - if density is None: - out = openmc.Material(temperature=T, **kwargs) - else: - out = openmc.Material(**kwargs) + out = openmc.Material(temperature=T, **kwargs) out.add_element('H', frac_H, 'ao') out.add_element('O', frac_O, 'ao') out.add_element('B', frac_B, 'ao') diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 2e37242720..ce58339d7c 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -481,6 +481,7 @@ def test_borated_water(): # Test the density override m = openmc.model.borated_water(975, 566.5, 15.51, density=0.9) assert m.density == pytest.approx(0.9, 1e-3) + assert m.temperature == pytest.approx(566.5) def test_from_xml(run_in_tmpdir): From 9e9ab848337bc1ba208c72ecbb3fb548f19bb2a1 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 2 Dec 2025 10:11:56 -0600 Subject: [PATCH 60/76] Update C++/CMake policy based on Ubuntu 22.04 (#3666) --- docs/source/devguide/policies.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/devguide/policies.rst b/docs/source/devguide/policies.rst index 2cf3199876..3644ae8223 100644 --- a/docs/source/devguide/policies.rst +++ b/docs/source/devguide/policies.rst @@ -21,8 +21,8 @@ C++ code in OpenMC must conform to the most recent C++ standard that is fully supported in the `version of the gcc compiler `_ that is distributed with the oldest version of Ubuntu that is still within its `standard support period -`_. Ubuntu 20.04 LTS will be supported -through April 2025 and is distributed with gcc 9.3.0, which fully supports the +`_. Ubuntu 22.04 LTS will be supported +through April 2027 and is distributed with gcc 11.4.0, which fully supports the C++17 standard. -------------------- @@ -31,5 +31,5 @@ CMake Version Policy Similar to the C++ standard policy, the minimum supported version of CMake corresponds to whatever version is distributed with the oldest version of Ubuntu -still within its standard support period. Ubuntu 20.04 LTS is distributed with -CMake 3.16. +still within its standard support period. Ubuntu 22.04 LTS is distributed with +CMake 3.22. From 10706510bfb7e89555bb89bccc849bfde36be409 Mon Sep 17 00:00:00 2001 From: John Tramm Date: Tue, 2 Dec 2025 22:00:32 -0600 Subject: [PATCH 61/76] Random Ray Eigenvalue Flux Normalization Change (#3595) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../openmc/random_ray/flat_source_domain.h | 3 + src/eigenvalue.cpp | 10 + src/random_ray/flat_source_domain.cpp | 32 +- src/random_ray/linear_source_domain.cpp | 6 +- .../random_ray_adjoint_k_eff/results_true.dat | 244 +++++++-------- .../infinite_medium/results_true.dat | 2 +- .../material_wise/results_true.dat | 2 +- .../stochastic_slab/results_true.dat | 2 +- .../random_ray_auto_convert/test.py | 2 +- .../results_true.dat | 2 +- .../random_ray_diagonal_stabilization/test.py | 2 +- .../results_true.dat | 280 ++++++++--------- .../random_ray_k_eff/results_true.dat | 282 +++++++++--------- .../random_ray_k_eff_mesh/results_true.dat | 280 ++++++++--------- .../random_ray_linear/linear/results_true.dat | 280 ++++++++--------- .../linear_xy/results_true.dat | 280 ++++++++--------- 16 files changed, 874 insertions(+), 835 deletions(-) diff --git a/include/openmc/random_ray/flat_source_domain.h b/include/openmc/random_ray/flat_source_domain.h index d4e8027346..4df4e5d8d3 100644 --- a/include/openmc/random_ray/flat_source_domain.h +++ b/include/openmc/random_ray/flat_source_domain.h @@ -170,6 +170,9 @@ protected: simulation_volume_; // Total physical volume of the simulation domain, as // defined by the 3D box of the random ray source + double + fission_rate_; // The system's fission rate (per cm^3), in eigenvalue mode + // Volumes for each tally and bin/score combination. This intermediate data // structure is used when tallying quantities that must be normalized by // volume (i.e., flux). The vector is index by tally index, while the inner 2D diff --git a/src/eigenvalue.cpp b/src/eigenvalue.cpp index a2120a006d..8412cbd3b4 100644 --- a/src/eigenvalue.cpp +++ b/src/eigenvalue.cpp @@ -403,6 +403,16 @@ void calculate_average_keff() t_value * std::sqrt( (simulation::k_sum[1] / n - std::pow(simulation::keff, 2)) / (n - 1)); + + // In some cases (such as an infinite medium problem), random ray + // may estimate k exactly and in an unvarying manner between iterations. + // In this case, the floating point roundoff between the division and the + // power operations may cause an extremely small negative value to occur + // inside the sqrt operation, leading to NaN. If this occurs, we check for + // it and set the std dev to zero. + if (!std::isfinite(simulation::keff_std)) { + simulation::keff_std = 0.0; + } } } } diff --git a/src/random_ray/flat_source_domain.cpp b/src/random_ray/flat_source_domain.cpp index 1bf27e1eda..ec14795dd2 100644 --- a/src/random_ray/flat_source_domain.cpp +++ b/src/random_ray/flat_source_domain.cpp @@ -124,7 +124,9 @@ void FlatSourceDomain::update_single_neutron_source(SourceRegionHandle& srh) double chi = chi_[material * negroups_ + g_out]; scatter_source += sigma_s * scalar_flux; - fission_source += nu_sigma_f * scalar_flux * chi; + if (settings::create_fission_neutrons) { + fission_source += nu_sigma_f * scalar_flux * chi; + } } srh.source(g_out) = (scatter_source + fission_source * inverse_k_eff) / sigma_t; @@ -369,6 +371,7 @@ void FlatSourceDomain::compute_k_eff() // Adds entropy value to shared entropy vector in openmc namespace. simulation::entropy.push_back(H); + fission_rate_ = fission_rate_new; k_eff_ = k_eff_new; } @@ -519,12 +522,33 @@ void FlatSourceDomain::reset_tally_volumes() // simulation double FlatSourceDomain::compute_fixed_source_normalization_factor() const { - // If we are not in fixed source mode, then there are no external sources - // so no normalization is needed. - if (settings::run_mode != RunMode::FIXED_SOURCE || adjoint_) { + // Eigenvalue mode normalization + if (settings::run_mode == RunMode::EIGENVALUE) { + // Normalize fluxes by total number of fission neutrons produced. This + // ensures consistent scaling of the eigenvector such that its magnitude is + // comparable to the eigenvector produced by the Monte Carlo solver. + // Multiplying by the eigenvalue is unintuitive, but it is necessary. + // If the eigenvalue is 1.2, per starting source neutron, you will + // generate 1.2 neutrons. Thus if we normalize to generating only ONE + // neutron in total for the whole domain, then we don't actually have enough + // flux to generate the required 1.2 neutrons. We only know the flux + // required to generate 1 neutron (which would have required less than one + // starting neutron). Thus, you have to scale the flux up by the eigenvalue + // such that 1.2 neutrons are generated, so as to be consistent with the + // bookkeeping in MC which is all done per starting source neutron (not per + // neutron produced). + return k_eff_ / (fission_rate_ * simulation_volume_); + } + + // If we are in adjoint mode of a fixed source problem, the external + // source is already normalized, such that all resulting fluxes are + // also normalized. + if (adjoint_) { return 1.0; } + // Fixed source mode normalization + // Step 1 is to sum over all source regions and energy groups to get the // total external source strength in the simulation. double simulation_external_source_strength = 0.0; diff --git a/src/random_ray/linear_source_domain.cpp b/src/random_ray/linear_source_domain.cpp index e1ad68e3d8..47ffbb727b 100644 --- a/src/random_ray/linear_source_domain.cpp +++ b/src/random_ray/linear_source_domain.cpp @@ -68,9 +68,11 @@ void LinearSourceDomain::update_single_neutron_source(SourceRegionHandle& srh) // Compute source terms for flat and linear components of the flux scatter_flat += sigma_s * flux_flat; - fission_flat += nu_sigma_f * flux_flat * chi; scatter_linear += sigma_s * flux_linear; - fission_linear += nu_sigma_f * flux_linear * chi; + if (settings::create_fission_neutrons) { + fission_flat += nu_sigma_f * flux_flat * chi; + fission_linear += nu_sigma_f * flux_linear * chi; + } } // Compute the flat source term diff --git a/tests/regression_tests/random_ray_adjoint_k_eff/results_true.dat b/tests/regression_tests/random_ray_adjoint_k_eff/results_true.dat index 657c841b56..dfef53cd2f 100644 --- a/tests/regression_tests/random_ray_adjoint_k_eff/results_true.dat +++ b/tests/regression_tests/random_ray_adjoint_k_eff/results_true.dat @@ -1,171 +1,171 @@ k-combined: 1.006640E+00 1.812969E-03 tally 1: -6.684129E+00 -8.939821E+00 -2.685967E+00 -1.443592E+00 +1.208044E+00 +2.920182E-01 +4.854426E-01 +4.715453E-02 0.000000E+00 0.000000E+00 -6.358774E+00 -8.091444E+00 -9.687217E-01 -1.878029E-01 +1.149242E+00 +2.643067E-01 +1.750801E-01 +6.134563E-03 0.000000E+00 0.000000E+00 -5.963160E+00 -7.117108E+00 -1.932332E-01 -7.473914E-03 +1.077743E+00 +2.324814E-01 +3.492371E-02 +2.441363E-04 0.000000E+00 0.000000E+00 -5.137593E+00 -5.283310E+00 -1.714616E-01 -5.884834E-03 -1.086218E-06 -2.361752E-13 -4.857253E+00 -4.719856E+00 -5.689580E-02 -6.476286E-04 -2.989356E-03 -1.787808E-06 -4.830516E+00 -4.666801E+00 -7.203015E-03 -1.037676E-05 -3.620020E+00 -2.620927E+00 -5.161382E+00 -5.328124E+00 -6.786255E-02 -9.210763E-04 -5.531943E+00 -6.120553E+00 -5.414034E+00 -5.864661E+00 +9.285362E-01 +1.725808E-01 +3.098889E-02 +1.922297E-04 +1.963161E-07 +7.714727E-15 +8.778641E-01 +1.541719E-01 +1.028293E-02 +2.115448E-05 +5.402741E-04 +5.839789E-08 +8.730274E-01 +1.524358E-01 +1.301813E-03 +3.389450E-07 +6.542525E-01 +8.560964E-02 +9.328247E-01 +1.740366E-01 +1.226491E-02 +3.008584E-05 +9.997969E-01 +1.999204E-01 +9.784958E-01 +1.915688E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -5.632338E+00 -6.347626E+00 +1.017952E+00 +2.073461E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -5.682608E+00 -6.462382E+00 +1.027039E+00 +2.110955E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -5.310716E+00 -5.645180E+00 +9.598240E-01 +1.844004E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.945409E+00 -4.893171E+00 +8.937969E-01 +1.598332E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.842688E+00 -4.690352E+00 +8.752275E-01 +1.532052E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -5.117198E+00 -5.237280E+00 +9.248400E-01 +1.710699E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -6.938711E+00 -9.633345E+00 -2.835258E+00 -1.608212E+00 +1.254054E+00 +3.146708E-01 +5.124223E-01 +5.253093E-02 0.000000E+00 0.000000E+00 -6.549505E+00 -8.584036E+00 -1.015138E+00 -2.061993E-01 +1.183712E+00 +2.803961E-01 +1.834683E-01 +6.735381E-03 0.000000E+00 0.000000E+00 -6.050651E+00 -7.327711E+00 -1.992816E-01 -7.948424E-03 +1.093555E+00 +2.393604E-01 +3.601678E-02 +2.596341E-04 0.000000E+00 0.000000E+00 -5.113981E+00 -5.234801E+00 -1.732323E-01 -6.006619E-03 -1.097435E-06 -2.410627E-13 -4.837033E+00 -4.680541E+00 -5.760042E-02 -6.637112E-04 -3.026377E-03 -1.832205E-06 -4.827049E+00 -4.660105E+00 -7.319913E-03 -1.071647E-05 -3.678770E+00 -2.706730E+00 -5.175337E+00 -5.356957E+00 -6.923046E-02 -9.586177E-04 -5.643451E+00 -6.370016E+00 -6.693323E+00 -8.964322E+00 -2.753307E+00 -1.516683E+00 +9.242694E-01 +1.709967E-01 +3.130894E-02 +1.962084E-04 +1.983437E-07 +7.874400E-15 +8.742100E-01 +1.528879E-01 +1.041026E-02 +2.167970E-05 +5.469644E-04 +5.984780E-08 +8.724009E-01 +1.522171E-01 +1.322938E-03 +3.500386E-07 +6.648691E-01 +8.841161E-02 +9.353464E-01 +1.749781E-01 +1.251209E-02 +3.131171E-05 +1.019947E+00 +2.080664E-01 +1.209708E+00 +2.928214E-01 +4.976146E-01 +4.954258E-02 0.000000E+00 0.000000E+00 -6.358384E+00 -8.090233E+00 -9.912008E-01 -1.965868E-01 +1.149174E+00 +2.642694E-01 +1.791431E-01 +6.421530E-03 0.000000E+00 0.000000E+00 -5.957484E+00 -7.103246E+00 -1.974033E-01 -7.798286E-03 +1.076718E+00 +2.320295E-01 +3.567737E-02 +2.547314E-04 0.000000E+00 0.000000E+00 -5.130744E+00 -5.268844E+00 -1.749233E-01 -6.123348E-03 -1.108148E-06 -2.457474E-13 -4.857340E+00 -4.720019E+00 -5.816659E-02 -6.768049E-04 -3.056125E-03 -1.868351E-06 -4.830629E+00 -4.667018E+00 -7.366289E-03 -1.085264E-05 -3.702077E+00 -2.741125E+00 -5.164864E+00 -5.335279E+00 -6.947917E-02 -9.655086E-04 -5.663725E+00 -6.415806E+00 +9.272977E-01 +1.721077E-01 +3.161443E-02 +2.000179E-04 +2.002789E-07 +8.027290E-15 +8.778794E-01 +1.541769E-01 +1.051257E-02 +2.210729E-05 +5.523400E-04 +6.102818E-08 +8.730477E-01 +1.524429E-01 +1.331320E-03 +3.544869E-07 +6.690816E-01 +8.953516E-02 +9.334544E-01 +1.742707E-01 +1.255707E-02 +3.153710E-05 +1.023613E+00 +2.095641E-01 diff --git a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat index c7584ab647..ee396fa746 100644 --- a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.797820E-01 1.054725E-02 +7.797252E-01 1.055731E-02 diff --git a/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat b/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat index d544a27df6..3bade01e05 100644 --- a/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/material_wise/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.356667E-01 6.637270E-03 +7.372542E-01 6.967831E-03 diff --git a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat index 75a10a2247..86e08a710c 100644 --- a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.551716E-01 8.117378E-03 +7.496641E-01 8.282032E-03 diff --git a/tests/regression_tests/random_ray_auto_convert/test.py b/tests/regression_tests/random_ray_auto_convert/test.py index fa7f2f17f4..99a931dce8 100644 --- a/tests/regression_tests/random_ray_auto_convert/test.py +++ b/tests/regression_tests/random_ray_auto_convert/test.py @@ -27,7 +27,7 @@ def test_random_ray_auto_convert(method): # Convert to a multi-group model model.convert_to_multigroup( - method=method, groups='CASMO-2', nparticles=30, + method=method, groups='CASMO-2', nparticles=100, overwrite_mgxs_library=False, mgxs_path="mgxs.h5" ) diff --git a/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat b/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat index f27ad46b46..034d7f7c64 100644 --- a/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat +++ b/tests/regression_tests/random_ray_diagonal_stabilization/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.201808E-01 1.506596E-02 +7.134473E-01 1.422763E-02 diff --git a/tests/regression_tests/random_ray_diagonal_stabilization/test.py b/tests/regression_tests/random_ray_diagonal_stabilization/test.py index c7a1c9f7cd..8d36e1d258 100644 --- a/tests/regression_tests/random_ray_diagonal_stabilization/test.py +++ b/tests/regression_tests/random_ray_diagonal_stabilization/test.py @@ -23,7 +23,7 @@ def test_random_ray_diagonal_stabilization(): # MGXS data with some negatives on the diagonal, in order # to trigger diagonal correction. model.convert_to_multigroup( - method='material_wise', groups='CASMO-70', nparticles=30, + method='material_wise', groups='CASMO-70', nparticles=13, overwrite_mgxs_library=True, mgxs_path="mgxs.h5", correction='P0' ) diff --git a/tests/regression_tests/random_ray_halton_samples/results_true.dat b/tests/regression_tests/random_ray_halton_samples/results_true.dat index b62398935b..256f8a744a 100644 --- a/tests/regression_tests/random_ray_halton_samples/results_true.dat +++ b/tests/regression_tests/random_ray_halton_samples/results_true.dat @@ -1,171 +1,171 @@ k-combined: 8.388051E-01 7.383265E-03 tally 1: -5.033308E+00 -5.072162E+00 -1.917335E+00 -7.360725E-01 -4.666410E+00 -4.360038E+00 -2.851812E+00 -1.629362E+00 -4.365590E-01 -3.818884E-02 -1.062497E+00 -2.262071E-01 -1.697621E+00 -5.829333E-01 -5.639912E-02 -6.427568E-04 -1.372642E-01 -3.807294E-03 -2.376683E+00 -1.151027E+00 -8.060903E-02 -1.323179E-03 -1.961862E-01 -7.837693E-03 -7.145452E+00 -1.037540E+01 -8.551803E-02 -1.486269E-03 -2.081363E-01 -8.803955E-03 -2.053205E+01 -8.469498E+01 -3.235618E-02 -2.102891E-04 -8.006311E-02 -1.287559E-03 -1.326545E+01 -3.519484E+01 -1.867471E-01 -6.975133E-03 -5.194275E-01 -5.396284E-02 -7.558115E+00 -1.142535E+01 +1.065839E+00 +2.274384E-01 +4.060094E-01 +3.300592E-02 +9.881457E-01 +1.955066E-01 +6.038893E-01 +7.306038E-02 +9.244411E-02 +1.712380E-03 +2.249905E-01 +1.014308E-02 +3.594916E-01 +2.614145E-02 +1.194318E-02 +2.882412E-05 +2.906731E-02 +1.707363E-04 +5.032954E-01 +5.161897E-02 +1.707007E-02 +5.933921E-05 +4.154514E-02 +3.514889E-04 +1.513147E+00 +4.652938E-01 +1.810962E-02 +6.665306E-05 +4.407572E-02 +3.948212E-04 +4.347893E+00 +3.798064E+00 +6.851785E-03 +9.430195E-06 +1.695426E-02 +5.773923E-05 +2.809071E+00 +1.578195E+00 +3.954523E-02 +3.127754E-04 +1.099931E-01 +2.419775E-03 +1.600493E+00 +5.123291E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.386211E+00 -2.294414E+00 +7.170555E-01 +1.028835E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.827274E+00 -6.782305E-01 +3.869491E-01 +3.041553E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.702858E+00 -1.489752E+00 +5.723683E-01 +6.680970E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.475537E+00 -1.133971E+01 +1.583046E+00 +5.085372E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.828685E+01 -6.719606E+01 +3.872447E+00 +3.013344E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.143600E+01 -2.615734E+01 +2.421670E+00 +1.172938E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.590713E+00 -4.224107E+00 -1.705847E+00 -5.831967E-01 -4.151691E+00 -3.454497E+00 -2.730853E+00 -1.495413E+00 -4.072633E-01 -3.325944E-02 -9.911973E-01 -1.970084E-01 -1.664732E+00 -5.598668E-01 -5.385645E-02 -5.858353E-04 -1.310758E-01 -3.470126E-03 -2.312239E+00 -1.088485E+00 -7.662778E-02 -1.195422E-03 -1.864967E-01 -7.080943E-03 -7.105766E+00 -1.025960E+01 -8.287512E-02 -1.396474E-03 -2.017039E-01 -8.272053E-03 -2.099024E+01 -8.854251E+01 -3.191885E-02 -2.048368E-04 -7.898095E-02 -1.254175E-03 -1.355820E+01 -3.676862E+01 -1.815102E-01 -6.590727E-03 -5.048614E-01 -5.098890E-02 -5.093659E+00 -5.192360E+00 -1.874632E+00 -7.031793E-01 -4.562478E+00 -4.165199E+00 -2.870214E+00 -1.650126E+00 -4.244069E-01 -3.608745E-02 -1.032921E+00 -2.137598E-01 -1.703400E+00 -5.873029E-01 -5.464557E-02 -6.042855E-04 -1.329964E-01 -3.579413E-03 -2.389118E+00 -1.163674E+00 -7.832237E-02 -1.251254E-03 -1.906210E-01 -7.411654E-03 -7.162707E+00 -1.042515E+01 -8.273831E-02 -1.391799E-03 -2.013709E-01 -8.244359E-03 -2.043145E+01 -8.383557E+01 -3.096158E-02 -1.924116E-04 -7.661226E-02 -1.178098E-03 -1.314148E+01 -3.454143E+01 -1.771732E-01 -6.279887E-03 -4.927984E-01 -4.858410E-02 +9.721128E-01 +1.894086E-01 +3.612242E-01 +2.615053E-02 +8.791475E-01 +1.548996E-01 +5.782742E-01 +6.705354E-02 +8.624040E-02 +1.491336E-03 +2.098919E-01 +8.833753E-03 +3.525265E-01 +2.510689E-02 +1.140473E-02 +2.627142E-05 +2.775683E-02 +1.556157E-04 +4.896481E-01 +4.881407E-02 +1.622698E-02 +5.360976E-05 +3.949322E-02 +3.175511E-04 +1.504743E+00 +4.601003E-01 +1.754995E-02 +6.262618E-05 +4.271358E-02 +3.709679E-04 +4.444922E+00 +3.970609E+00 +6.759184E-03 +9.185746E-06 +1.672513E-02 +5.624252E-05 +2.871068E+00 +1.648778E+00 +3.843643E-02 +2.955428E-04 +1.069090E-01 +2.286455E-03 +1.078620E+00 +2.328291E-01 +3.969671E-01 +3.153110E-02 +9.661384E-01 +1.867708E-01 +6.077864E-01 +7.399164E-02 +8.987086E-02 +1.618157E-03 +2.187277E-01 +9.584966E-03 +3.607158E-01 +2.633746E-02 +1.157185E-02 +2.709895E-05 +2.816358E-02 +1.605174E-04 +5.059289E-01 +5.218618E-02 +1.658585E-02 +5.611375E-05 +4.036663E-02 +3.323832E-04 +1.516801E+00 +4.675245E-01 +1.752096E-02 +6.241641E-05 +4.264304E-02 +3.697253E-04 +4.326588E+00 +3.759517E+00 +6.556454E-03 +8.628460E-06 +1.622349E-02 +5.283037E-05 +2.782815E+00 +1.548888E+00 +3.751781E-02 +2.815972E-04 +1.043539E-01 +2.178566E-03 diff --git a/tests/regression_tests/random_ray_k_eff/results_true.dat b/tests/regression_tests/random_ray_k_eff/results_true.dat index 37eca77f3c..ace18df8cc 100644 --- a/tests/regression_tests/random_ray_k_eff/results_true.dat +++ b/tests/regression_tests/random_ray_k_eff/results_true.dat @@ -1,171 +1,171 @@ k-combined: -8.400321E-01 8.023358E-03 +8.400321E-01 8.023357E-03 tally 1: -5.086559E+00 -5.180935E+00 -1.885166E+00 -7.115503E-01 -4.588116E+00 -4.214784E+00 -2.860400E+00 -1.639328E+00 -4.245221E-01 -3.610929E-02 -1.033202E+00 -2.138892E-01 -1.692631E+00 -5.793966E-01 -5.445818E-02 -5.996625E-04 -1.325403E-01 -3.552030E-03 -2.372248E+00 -1.146944E+00 -7.808142E-02 -1.242278E-03 -1.900346E-01 -7.358491E-03 -7.134949E+00 -1.034824E+01 -8.272647E-02 -1.391871E-03 -2.013421E-01 -8.244788E-03 -2.043539E+01 -8.389902E+01 -3.099367E-02 -1.930673E-04 -7.669167E-02 -1.182113E-03 -1.313212E+01 -3.449537E+01 -1.764293E-01 -6.225586E-03 -4.907293E-01 -4.816400E-02 -7.567715E+00 -1.145439E+01 +1.075769E+00 +2.317354E-01 +3.986991E-01 +3.182682E-02 +9.703538E-01 +1.885224E-01 +6.049423E-01 +7.331941E-02 +8.978161E-02 +1.614997E-03 +2.185105E-01 +9.566247E-03 +3.579852E-01 +2.591721E-02 +1.151770E-02 +2.682363E-05 +2.803176E-02 +1.588866E-04 +5.017326E-01 +5.130808E-02 +1.651428E-02 +5.557274E-05 +4.019245E-02 +3.291786E-04 +1.509054E+00 +4.629325E-01 +1.749679E-02 +6.226587E-05 +4.258421E-02 +3.688336E-04 +4.322054E+00 +3.753085E+00 +6.555113E-03 +8.636537E-06 +1.622017E-02 +5.287982E-05 +2.777351E+00 +1.542942E+00 +3.731363E-02 +2.784662E-04 +1.037860E-01 +2.154343E-03 +1.600522E+00 +5.123477E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.383194E+00 -2.290468E+00 +7.155116E-01 +1.024445E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.819672E+00 -6.726158E-01 +3.848568E-01 +3.008769E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.693683E+00 -1.480961E+00 +5.697160E-01 +6.624996E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.453758E+00 -1.128171E+01 +1.576480E+00 +5.046890E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.823561E+01 -6.681652E+01 +3.856827E+00 +2.989000E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.137517E+01 -2.588512E+01 +2.405807E+00 +1.157889E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.601916E+00 -4.242624E+00 -1.719723E+00 -5.923465E-01 -4.185462E+00 -3.508695E+00 -2.730305E+00 -1.494324E+00 -4.108214E-01 -3.383938E-02 -9.998572E-01 -2.004436E-01 -1.660852E+00 -5.570432E-01 -5.428709E-02 -5.947848E-04 -1.321239E-01 -3.523137E-03 -2.306069E+00 -1.082855E+00 -7.697031E-02 -1.206036E-03 -1.873303E-01 -7.143815E-03 -7.075194E+00 -1.017519E+01 -8.322052E-02 -1.408294E-03 -2.025446E-01 -8.342071E-03 -2.094832E+01 -8.816715E+01 -3.234739E-02 -2.101889E-04 -8.004135E-02 -1.286945E-03 -1.357413E+01 -3.685983E+01 -1.861680E-01 -6.934827E-03 -5.178169E-01 -5.365102E-02 -5.072149E+00 -5.151429E+00 -1.916643E+00 -7.358710E-01 -4.664726E+00 -4.358845E+00 -2.859464E+00 -1.638250E+00 -4.332944E-01 -3.763170E-02 -1.054552E+00 -2.229070E-01 -1.693008E+00 -5.796671E-01 -5.561096E-02 -6.247543E-04 -1.353459E-01 -3.700658E-03 -2.368860E+00 -1.143296E+00 -7.951819E-02 -1.286690E-03 -1.935314E-01 -7.621557E-03 -7.119587E+00 -1.030023E+01 -8.428175E-02 -1.442931E-03 -2.051274E-01 -8.547243E-03 -2.046758E+01 -8.418768E+01 -3.181946E-02 -2.034766E-04 -7.873502E-02 -1.245847E-03 -1.325834E+01 -3.515919E+01 -1.832838E-01 -6.720555E-03 -5.097947E-01 -5.199331E-02 +9.732717E-01 +1.897670E-01 +3.637108E-01 +2.649544E-02 +8.851992E-01 +1.569426E-01 +5.774286E-01 +6.683395E-02 +8.688408E-02 +1.513473E-03 +2.114585E-01 +8.964883E-03 +3.512640E-01 +2.491729E-02 +1.148149E-02 +2.660532E-05 +2.794365E-02 +1.575935E-04 +4.877362E-01 +4.844138E-02 +1.627932E-02 +5.395212E-05 +3.962062E-02 +3.195790E-04 +1.496416E+00 +4.551920E-01 +1.760130E-02 +6.300084E-05 +4.283856E-02 +3.731872E-04 +4.430519E+00 +3.943947E+00 +6.841363E-03 +9.402132E-06 +1.692847E-02 +5.756741E-05 +2.870816E+00 +1.648662E+00 +3.937267E-02 +3.101707E-04 +1.095131E-01 +2.399624E-03 +1.072714E+00 +2.304093E-01 +4.053505E-01 +3.291277E-02 +9.865420E-01 +1.949549E-01 +6.047420E-01 +7.327008E-02 +9.163611E-02 +1.683034E-03 +2.230240E-01 +9.969255E-03 +3.580639E-01 +2.592902E-02 +1.176143E-02 +2.794541E-05 +2.862497E-02 +1.655313E-04 +5.010143E-01 +5.114429E-02 +1.681803E-02 +5.755790E-05 +4.093173E-02 +3.409375E-04 +1.505803E+00 +4.607828E-01 +1.782566E-02 +6.454911E-05 +4.338462E-02 +3.823584E-04 +4.328879E+00 +3.766055E+00 +6.729800E-03 +9.102372E-06 +1.665242E-02 +5.573204E-05 +2.804070E+00 +1.572690E+00 +3.876396E-02 +3.006259E-04 +1.078200E-01 +2.325780E-03 diff --git a/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat b/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat index 83209044ba..2ae8fad85f 100644 --- a/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat +++ b/tests/regression_tests/random_ray_k_eff_mesh/results_true.dat @@ -1,171 +1,171 @@ k-combined: 8.379203E-01 8.057199E-03 tally 1: -5.080172E+00 -5.167984E+00 -1.880341E+00 -7.079266E-01 -4.576373E+00 -4.193319E+00 -2.859914E+00 -1.638769E+00 -4.243332E-01 -3.607732E-02 -1.032742E+00 -2.136998E-01 -1.692643E+00 -5.794069E-01 -5.445214E-02 -5.995213E-04 -1.325256E-01 -3.551193E-03 -2.372336E+00 -1.147031E+00 -7.807378E-02 -1.242019E-03 -1.900160E-01 -7.356955E-03 -7.135636E+00 -1.035026E+01 -8.273225E-02 -1.392069E-03 -2.013562E-01 -8.245961E-03 -2.044034E+01 -8.394042E+01 -3.100485E-02 -1.932097E-04 -7.671934E-02 -1.182985E-03 -1.313652E+01 -3.451846E+01 -1.764978E-01 -6.230420E-03 -4.909196E-01 -4.820140E-02 -7.585874E+00 -1.150936E+01 +1.073897E+00 +2.309328E-01 +3.974859E-01 +3.163415E-02 +9.674011E-01 +1.873811E-01 +6.045463E-01 +7.322367E-02 +8.969819E-02 +1.612011E-03 +2.183075E-01 +9.548557E-03 +3.578121E-01 +2.589198E-02 +1.151076E-02 +2.679073E-05 +2.801489E-02 +1.586917E-04 +5.015038E-01 +5.126076E-02 +1.650453E-02 +5.550572E-05 +4.016872E-02 +3.287816E-04 +1.508456E+00 +4.625615E-01 +1.748939E-02 +6.221267E-05 +4.256620E-02 +3.685184E-04 +4.320984E+00 +3.751237E+00 +6.554265E-03 +8.634389E-06 +1.621807E-02 +5.286667E-05 +2.776930E+00 +1.542475E+00 +3.730995E-02 +2.784113E-04 +1.037757E-01 +2.153918E-03 +1.603583E+00 +5.143065E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -3.386790E+00 -2.295327E+00 +7.159242E-01 +1.025623E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.820058E+00 -6.729239E-01 +3.847488E-01 +3.007151E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.694013E+00 -1.481363E+00 +5.695050E-01 +6.620177E-02 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -7.453818E+00 -1.128202E+01 +1.575716E+00 +5.042003E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.823642E+01 -6.682239E+01 +3.855109E+00 +2.986316E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.137903E+01 -2.590265E+01 +2.405453E+00 +1.157547E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.589529E+00 -4.219985E+00 -1.712446E+00 -5.873675E-01 -4.167750E+00 -3.479202E+00 -2.728285E+00 -1.492132E+00 -4.104063E-01 -3.377132E-02 -9.988468E-01 -2.000405E-01 -1.660506E+00 -5.567967E-01 -5.427391E-02 -5.944708E-04 -1.320918E-01 -3.521277E-03 -2.305889E+00 -1.082691E+00 -7.695793E-02 -1.205644E-03 -1.873002E-01 -7.141490E-03 -7.076637E+00 -1.017946E+01 -8.323139E-02 -1.408687E-03 -2.025710E-01 -8.344398E-03 -2.095897E+01 -8.825741E+01 -3.236513E-02 -2.104220E-04 -8.008525E-02 -1.288373E-03 -1.358006E+01 -3.689205E+01 -1.862562E-01 -6.941428E-03 -5.180621E-01 -5.370209E-02 -5.067386E+00 -5.141748E+00 -1.912704E+00 -7.328484E-01 -4.655140E+00 -4.340941E+00 -2.858992E+00 -1.637705E+00 -4.331050E-01 -3.759875E-02 -1.054091E+00 -2.227118E-01 -1.692974E+00 -5.796396E-01 -5.560487E-02 -6.246120E-04 -1.353311E-01 -3.699815E-03 -2.368737E+00 -1.143184E+00 -7.950086E-02 -1.286135E-03 -1.934892E-01 -7.618269E-03 -7.119767E+00 -1.030095E+01 -8.427628E-02 -1.442764E-03 -2.051141E-01 -8.546249E-03 -2.047651E+01 -8.426275E+01 -3.183786E-02 -2.037156E-04 -7.878057E-02 -1.247311E-03 -1.326415E+01 -3.519010E+01 -1.833688E-01 -6.726832E-03 -5.100312E-01 -5.204188E-02 +9.701818E-01 +1.885724E-01 +3.619962E-01 +2.624740E-02 +8.810264E-01 +1.554734E-01 +5.767221E-01 +6.667165E-02 +8.675429E-02 +1.508976E-03 +2.111426E-01 +8.938242E-03 +3.510185E-01 +2.488161E-02 +1.147307E-02 +2.656498E-05 +2.792316E-02 +1.573545E-04 +4.874578E-01 +4.838573E-02 +1.626869E-02 +5.388082E-05 +3.959473E-02 +3.191567E-04 +1.495984E+00 +4.549294E-01 +1.759493E-02 +6.295564E-05 +4.282306E-02 +3.729194E-04 +4.430601E+00 +3.944093E+00 +6.841763E-03 +9.403281E-06 +1.692946E-02 +5.757445E-05 +2.870670E+00 +1.648496E+00 +3.937215E-02 +3.101637E-04 +1.095116E-01 +2.399569E-03 +1.071187E+00 +2.297540E-01 +4.043214E-01 +3.274592E-02 +9.840375E-01 +1.939666E-01 +6.043491E-01 +7.317500E-02 +9.155169E-02 +1.679939E-03 +2.228185E-01 +9.950920E-03 +3.578809E-01 +2.590208E-02 +1.175437E-02 +2.791136E-05 +2.860779E-02 +1.653296E-04 +5.007414E-01 +5.108824E-02 +1.680608E-02 +5.747571E-05 +4.090264E-02 +3.404506E-04 +1.505100E+00 +4.603562E-01 +1.781573E-02 +6.447733E-05 +4.336044E-02 +3.819332E-04 +4.328647E+00 +3.765700E+00 +6.730396E-03 +9.104085E-06 +1.665389E-02 +5.574253E-05 +2.803934E+00 +1.572540E+00 +3.876306E-02 +3.006136E-04 +1.078175E-01 +2.325685E-03 diff --git a/tests/regression_tests/random_ray_linear/linear/results_true.dat b/tests/regression_tests/random_ray_linear/linear/results_true.dat index 4c0e14370e..77d41f3732 100644 --- a/tests/regression_tests/random_ray_linear/linear/results_true.dat +++ b/tests/regression_tests/random_ray_linear/linear/results_true.dat @@ -1,171 +1,171 @@ k-combined: 1.095967E+00 1.543581E-02 tally 1: -2.548108E+01 -3.269093E+01 -9.271804E+00 -4.327275E+00 -2.256572E+01 -2.563210E+01 -1.816107E+01 -1.653421E+01 -2.659203E+00 -3.544951E-01 -6.471969E+00 -2.099810E+00 -1.364193E+01 -9.308675E+00 -4.362828E-01 -9.521133E-03 -1.061825E+00 -5.639730E-02 -1.746102E+01 -1.524680E+01 -5.733016E-01 -1.643671E-02 -1.395301E+00 -9.736092E-02 -4.539598E+01 -1.030472E+02 -5.263055E-01 -1.385088E-02 -1.280938E+00 -8.204609E-02 -9.945736E+01 -4.946716E+02 -1.505228E-01 -1.133424E-03 -3.724582E-01 -6.939732E-03 -5.324914E+01 -1.418809E+02 -7.219589E-01 -2.614875E-02 -2.008092E+00 -2.022988E-01 -4.188246E+01 -8.843469E+01 +5.425537E+00 +1.482137E+00 +1.974189E+00 +1.961888E-01 +4.804781E+00 +1.162101E+00 +3.866915E+00 +7.496163E-01 +5.662059E-01 +1.607180E-02 +1.378032E+00 +9.519943E-02 +2.904666E+00 +4.220197E-01 +9.289413E-02 +4.316514E-04 +2.260857E-01 +2.556836E-03 +3.717829E+00 +6.912286E-01 +1.220682E-01 +7.451721E-04 +2.970897E-01 +4.413940E-03 +9.665773E+00 +4.671720E+00 +1.120617E-01 +6.279393E-04 +2.727390E-01 +3.719615E-03 +2.117656E+01 +2.242614E+01 +3.204951E-02 +5.138445E-05 +7.930426E-02 +3.146169E-04 +1.133784E+01 +6.432186E+00 +1.537206E-01 +1.185474E-03 +4.275660E-01 +9.171376E-03 +8.917756E+00 +4.009380E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.224363E+01 -2.481131E+01 +4.736166E+00 +1.124858E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.436097E+01 -1.031496E+01 +3.057755E+00 +4.676344E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.901248E+01 -1.807657E+01 +4.048156E+00 +8.195089E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.559337E+01 -1.039424E+02 +9.707791E+00 +4.712281E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.802992E+01 -3.874925E+02 +1.874344E+01 +1.756722E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.506602E+01 -1.016497E+02 +9.595520E+00 +4.608366E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.207833E+01 -2.455068E+01 -8.139772E+00 -3.337974E+00 -1.981058E+01 -1.977210E+01 -1.710407E+01 -1.466648E+01 -2.542287E+00 -3.240467E-01 -6.187418E+00 -1.919453E+00 -1.342690E+01 -9.017908E+00 -4.362263E-01 -9.518695E-03 -1.061688E+00 -5.638286E-02 -1.713924E+01 -1.469065E+01 -5.714028E-01 -1.632839E-02 -1.390680E+00 -9.671931E-02 -4.539193E+01 -1.030326E+02 -5.345254E-01 -1.428719E-02 -1.300944E+00 -8.463057E-02 -1.013270E+02 -5.134168E+02 -1.555517E-01 -1.210145E-03 -3.849017E-01 -7.409480E-03 -5.377836E+01 -1.446537E+02 -7.374053E-01 -2.722908E-02 -2.051056E+00 -2.106567E-01 -2.522726E+01 -3.202007E+01 -9.366659E+00 -4.412278E+00 -2.279657E+01 -2.613561E+01 -1.803368E+01 -1.629756E+01 -2.696490E+00 -3.643066E-01 -6.562716E+00 -2.157928E+00 -1.357447E+01 -9.216150E+00 -4.437305E-01 -9.847287E-03 -1.079951E+00 -5.832923E-02 -1.735848E+01 -1.506775E+01 -5.825173E-01 -1.696803E-02 -1.417731E+00 -1.005081E-01 -4.519297E+01 -1.021280E+02 -5.357712E-01 -1.435322E-02 -1.303976E+00 -8.502167E-02 -9.934508E+01 -4.935314E+02 -1.538761E-01 -1.184229E-03 -3.807556E-01 -7.250804E-03 -5.335839E+01 -1.424221E+02 -7.404823E-01 -2.747396E-02 -2.059614E+00 -2.125512E-01 +4.701002E+00 +1.113069E+00 +1.733152E+00 +1.513360E-01 +4.218145E+00 +8.964208E-01 +3.641849E+00 +6.649342E-01 +5.413112E-01 +1.469131E-02 +1.317443E+00 +8.702223E-02 +2.858878E+00 +4.088359E-01 +9.288202E-02 +4.315389E-04 +2.260562E-01 +2.556170E-03 +3.649312E+00 +6.660131E-01 +1.216639E-01 +7.402611E-04 +2.961057E-01 +4.384849E-03 +9.664912E+00 +4.671059E+00 +1.138118E-01 +6.477188E-04 +2.769985E-01 +3.836780E-03 +2.157464E+01 +2.327600E+01 +3.312018E-02 +5.486221E-05 +8.195357E-02 +3.359106E-04 +1.145052E+01 +6.557893E+00 +1.570084E-01 +1.234420E-03 +4.367109E-01 +9.550040E-03 +5.371474E+00 +1.451702E+00 +1.994382E+00 +2.000414E-01 +4.853928E+00 +1.184921E+00 +3.839778E+00 +7.388780E-01 +5.741437E-01 +1.651648E-02 +1.397351E+00 +9.783345E-02 +2.890296E+00 +4.178220E-01 +9.447974E-02 +4.464346E-04 +2.299448E-01 +2.644403E-03 +3.695989E+00 +6.831063E-01 +1.240303E-01 +7.692555E-04 +3.018649E-01 +4.556594E-03 +9.622545E+00 +4.630042E+00 +1.140770E-01 +6.507108E-04 +2.776440E-01 +3.854503E-03 +2.115266E+01 +2.237450E+01 +3.276343E-02 +5.368742E-05 +8.107083E-02 +3.287176E-04 +1.136109E+01 +6.456700E+00 +1.576636E-01 +1.245524E-03 +4.385334E-01 +9.635950E-03 diff --git a/tests/regression_tests/random_ray_linear/linear_xy/results_true.dat b/tests/regression_tests/random_ray_linear/linear_xy/results_true.dat index abfd03c067..052608b425 100644 --- a/tests/regression_tests/random_ray_linear/linear_xy/results_true.dat +++ b/tests/regression_tests/random_ray_linear/linear_xy/results_true.dat @@ -1,171 +1,171 @@ k-combined: 1.104727E+00 1.593303E-02 tally 1: -2.566934E+01 -3.317503E+01 -9.417202E+00 -4.465518E+00 -2.291958E+01 -2.645097E+01 -1.823903E+01 -1.667438E+01 -2.679931E+00 -3.600420E-01 -6.522415E+00 -2.132667E+00 -1.365623E+01 -9.327448E+00 -4.370682E-01 -9.554968E-03 -1.063736E+00 -5.659772E-02 -1.750634E+01 -1.532609E+01 -5.762870E-01 -1.660889E-02 -1.402567E+00 -9.838082E-02 -4.543609E+01 -1.032286E+02 -5.271287E-01 -1.389456E-02 -1.282941E+00 -8.230483E-02 -9.881678E+01 -4.882586E+02 -1.487616E-01 -1.106634E-03 -3.681003E-01 -6.775702E-03 -5.260781E+01 -1.384126E+02 -7.018594E-01 -2.464953E-02 -1.952187E+00 -1.907001E-01 -4.184779E+01 -8.826530E+01 +5.465547E+00 +1.504031E+00 +2.005120E+00 +2.024490E-01 +4.880060E+00 +1.199182E+00 +3.883466E+00 +7.559482E-01 +5.706123E-01 +1.632280E-02 +1.388756E+00 +9.668619E-02 +2.907681E+00 +4.228621E-01 +9.306046E-02 +4.331768E-04 +2.264905E-01 +2.565871E-03 +3.727441E+00 +6.948089E-01 +1.227027E-01 +7.529631E-04 +2.986338E-01 +4.460088E-03 +9.674219E+00 +4.679846E+00 +1.122358E-01 +6.299070E-04 +2.731629E-01 +3.731271E-03 +2.103996E+01 +2.213497E+01 +3.167421E-02 +5.016895E-05 +7.837561E-02 +3.071747E-04 +1.120119E+01 +6.274853E+00 +1.494396E-01 +1.117486E-03 +4.156586E-01 +8.645390E-03 +8.910289E+00 +4.001626E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.226932E+01 -2.486554E+01 +4.741600E+00 +1.127303E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.441107E+01 -1.038682E+01 +3.068401E+00 +4.708885E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -1.909194E+01 -1.822767E+01 +4.065045E+00 +8.263510E-01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.579319E+01 -1.048559E+02 +9.750251E+00 +4.753623E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -8.833276E+01 -3.901410E+02 +1.880773E+01 +1.768690E+01 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -4.528911E+01 -1.025740E+02 +9.642921E+00 +4.650165E+00 0.000000E+00 0.000000E+00 0.000000E+00 0.000000E+00 -2.218278E+01 -2.477434E+01 -8.203467E+00 -3.389915E+00 -1.996560E+01 -2.007976E+01 -1.714818E+01 -1.473927E+01 -2.551034E+00 -3.262450E-01 -6.208707E+00 -1.932474E+00 -1.343470E+01 -9.027502E+00 -4.363259E-01 -9.522121E-03 -1.061930E+00 -5.640315E-02 -1.717034E+01 -1.474381E+01 -5.729720E-01 -1.641841E-02 -1.394499E+00 -9.725251E-02 -4.542715E+01 -1.031896E+02 -5.348128E-01 -1.430232E-02 -1.301643E+00 -8.472019E-02 -1.009076E+02 -5.091264E+02 -1.543547E-01 -1.191320E-03 -3.819398E-01 -7.294216E-03 -5.342751E+01 -1.427427E+02 -7.255554E-01 -2.633014E-02 -2.018096E+00 -2.037021E-01 -2.540053E+01 -3.247261E+01 -9.483956E+00 -4.526477E+00 -2.308205E+01 -2.681205E+01 -1.812760E+01 -1.646855E+01 -2.717374E+00 -3.700301E-01 -6.613545E+00 -2.191830E+00 -1.362672E+01 -9.286907E+00 -4.458292E-01 -9.940508E-03 -1.085059E+00 -5.888142E-02 -1.744511E+01 -1.521876E+01 -5.866632E-01 -1.721091E-02 -1.427821E+00 -1.019468E-01 -4.538426E+01 -1.029941E+02 -5.385934E-01 -1.450495E-02 -1.310845E+00 -8.592045E-02 -9.921424E+01 -4.921945E+02 -1.532444E-01 -1.174272E-03 -3.791926E-01 -7.189835E-03 -5.301633E+01 -1.405571E+02 -7.285745E-01 -2.655093E-02 -2.026493E+00 -2.054102E-01 +4.723189E+00 +1.123179E+00 +1.746692E+00 +1.536860E-01 +4.251098E+00 +9.103405E-01 +3.651202E+00 +6.682179E-01 +5.431675E-01 +1.479058E-02 +1.321961E+00 +8.761024E-02 +2.860513E+00 +4.092640E-01 +9.290237E-02 +4.316867E-04 +2.261058E-01 +2.557045E-03 +3.655900E+00 +6.684112E-01 +1.219969E-01 +7.443277E-04 +2.969160E-01 +4.408937E-03 +9.672316E+00 +4.678082E+00 +1.138719E-01 +6.483917E-04 +2.771448E-01 +3.840766E-03 +2.148514E+01 +2.308100E+01 +3.286501E-02 +5.400774E-05 +8.132216E-02 +3.306788E-04 +1.137571E+01 +6.471140E+00 +1.544841E-01 +1.193653E-03 +4.296897E-01 +9.234647E-03 +5.408307E+00 +1.472183E+00 +2.019332E+00 +2.052123E-01 +4.914651E+00 +1.215551E+00 +3.859737E+00 +7.466141E-01 +5.785840E-01 +1.677554E-02 +1.408158E+00 +9.936796E-02 +2.901397E+00 +4.210234E-01 +9.492573E-02 +4.506531E-04 +2.310302E-01 +2.669390E-03 +3.714401E+00 +6.899411E-01 +1.249118E-01 +7.802521E-04 +3.040104E-01 +4.621732E-03 +9.663183E+00 +4.669215E+00 +1.146768E-01 +6.575767E-04 +2.791038E-01 +3.895173E-03 +2.112461E+01 +2.231346E+01 +3.262864E-02 +5.323508E-05 +8.073730E-02 +3.259479E-04 +1.128817E+01 +6.372070E+00 +1.551272E-01 +1.203670E-03 +4.314785E-01 +9.312148E-03 From ad5a876bee9f3e3b96ddc28867fdec0028cb7587 Mon Sep 17 00:00:00 2001 From: John Tramm Date: Wed, 3 Dec 2025 01:48:38 -0600 Subject: [PATCH 62/76] Improved automatic MGXS generation for random ray (#3658) Co-authored-by: Paul Romano --- docs/source/usersguide/random_ray.rst | 28 ++- openmc/model/model.py | 186 +++++++++++++++--- .../infinite_medium/results_true.dat | 2 +- .../stochastic_slab/results_true.dat | 2 +- .../__init__.py | 0 .../infinite_medium/model/inputs_true.dat | 61 ++++++ .../infinite_medium/model/results_true.dat | 2 + .../infinite_medium/user/inputs_true.dat | 64 ++++++ .../infinite_medium/user/results_true.dat | 2 + .../stochastic_slab/model/inputs_true.dat | 61 ++++++ .../stochastic_slab/model/results_true.dat | 2 + .../stochastic_slab/user/inputs_true.dat | 64 ++++++ .../stochastic_slab/user/results_true.dat | 2 + .../test.py | 66 +++++++ 14 files changed, 511 insertions(+), 31 deletions(-) create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/__init__.py create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/results_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/results_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/results_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/results_true.dat create mode 100644 tests/regression_tests/random_ray_auto_convert_source_energy/test.py diff --git a/docs/source/usersguide/random_ray.rst b/docs/source/usersguide/random_ray.rst index d5d752a834..881498a0a7 100644 --- a/docs/source/usersguide/random_ray.rst +++ b/docs/source/usersguide/random_ray.rst @@ -644,7 +644,8 @@ model to use these multigroup cross sections. An example is given below:: nparticles=2000, overwrite_mgxs_library=False, mgxs_path="mgxs.h5", - correction=None + correction=None, + source_energy=None ) The most important parameter to set is the ``method`` parameter, which can be @@ -706,6 +707,31 @@ generation and use an existing library file. with a :math:`\rho` default value of 1.0, which can be adjusted with the ``settings.random_ray['diagonal_stabilization_rho']`` parameter. +When generating MGXS data with either the ``stochastic_slab`` or +``infinite_medium`` methods, by default the simulation will use a uniform source +distribution spread evenly over all energy groups. This ensures that all energy +groups receive tallies and therefore produce non-zero total multigroup cross +sections. Additionally, the function will convert any sources in the model into +simplified spatial sources that retain the original energy distributions. If +sources are present, they will be used 99% of the time to sample source energies +during MGXS generation. The other 1% of the time, energies will be sampled +uniformly over all energy groups to ensure that all groups receive some tallies. +However, the user may wish to specify a different source energy spectrum (for +instance, if they are using a FileSource, such that the energy distribution +cannot be extracted from the python source object). This can be done by +providing a :class:`openmc.stats.Univariate` distribution as the +``source_energy`` parameter of the :meth:`openmc.Model.convert_to_multigroup` +method. If provided, it will override any sources present in the model and will +be used 99% of the time to sample source energies during MGXS generation. The +other 1% of the time, energies will be sampled uniformly over all energy groups +to ensure that all groups receive some tallies. + +For instance, a D-D fusion simulation may involve a complex file source. In this +case, the user may wish to provide a discrete 2.45 MeV energy source +distribution for MGXS generation as:: + + source_energy = openmc.stats.delta_function(2.45e6) + Ultimately, the methods described above are all just approximations. Approximations in the generated MGXS data will fundamentally limit the potential accuracy of the random ray solver. However, the methods described above are all diff --git a/openmc/model/model.py b/openmc/model/model.py index 48ae9f0b91..2997247597 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1687,6 +1687,91 @@ class Model: self.geometry.get_all_materials().values() ) + def _create_mgxs_sources( + self, + groups: openmc.mgxs.EnergyGroups, + spatial_dist: openmc.stats.Spatial, + source_energy: openmc.stats.Univariate | None = None, + ) -> list[openmc.IndependentSource]: + """Create a list of independent sources to use with MGXS generation. + + Note that in all cases, a discrete source that is uniform over all + energy groups is created (strength = 0.01) to ensure that total cross + sections are generated for all energy groups. In the case that the user + has provided a source_energy distribution as an argument, an additional + source (strength = 0.99) is created using that energy distribution. If + the user has not provided a source_energy distribution, but the model + has sources defined, and all of those sources are of IndependentSource + type, then additional sources are created based on the model's existing + sources, keeping their energy distributions but replacing their + spatial/angular distributions, with their combined strength being 0.99. + If the user has not provided a source_energy distribution and no sources + are defined on the model and the run mode is 'eigenvalue', then a + default Watt spectrum source (strength = 0.99) is added. + + Parameters + ---------- + groups : openmc.mgxs.EnergyGroups + Energy group structure for the MGXS. + spatial_dist : openmc.stats.Spatial + Spatial distribution to use for all sources. + source_energy : openmc.stats.Univariate, optional + Energy distribution to use when generating MGXS data, replacing any + existing sources in the model. + + Returns + ------- + list[openmc.IndependentSource] + A list of independent sources to use for MGXS generation. + """ + # Make a discrete source that is uniform over the bins of the group structure + midpoints = [] + strengths = [] + for i in range(groups.num_groups): + bounds = groups.get_group_bounds(i+1) + midpoints.append((bounds[0] + bounds[1]) / 2.0) + strengths.append(1.0) + + uniform_energy = openmc.stats.Discrete(x=midpoints, p=strengths) + uniform_distribution = openmc.IndependentSource(spatial_dist, energy=uniform_energy, strength=0.01) + sources = [uniform_distribution] + + # If the user provided an energy distribution, use that + if source_energy is not None: + user_energy = openmc.IndependentSource( + space=spatial_dist, energy=source_energy, strength=0.99) + sources.append(user_energy) + + # If the user did not provide an energy distribution, create sources + # based on what is in their model, keeping the energy spectrum but + # replacing the spatial/angular distributions. We only do this if ALL + # sources are of IndependentSource type, as we can't pull the energy + # distribution from e.g. CompiledSource or FileSource types. + else: + if self.settings.source is not None: + for src in self.settings.source: + if not isinstance(src, openmc.IndependentSource): + break + else: + n_user_sources = len(self.settings.source) + for src in self.settings.source: + # Create a new IndependentSource with adjusted strength, space, and angle + user_source = openmc.IndependentSource( + space=spatial_dist, + energy=src.energy, + strength=0.99 / n_user_sources + ) + sources.append(user_source) + else: + # No user sources defined. If we are in eigenvalue mode, then use the default Watt spectrum. + if self.settings.run_mode == 'eigenvalue': + watt_energy = openmc.stats.Watt() + watt_source = openmc.IndependentSource( + space=spatial_dist, energy=watt_energy, strength=0.99) + sources.append(watt_source) + + return sources + def _generate_infinite_medium_mgxs( self, groups: openmc.mgxs.EnergyGroups, @@ -1694,6 +1779,7 @@ class Model: mgxs_path: PathLike, correction: str | None, directory: PathLike, + source_energy: openmc.stats.Univariate | None = None, ): """Generate a MGXS library by running multiple OpenMC simulations, each representing an infinite medium simulation of a single isolated @@ -1702,6 +1788,20 @@ class Model: method that ignores all spatial self shielding effects and all resonance shielding effects between materials. + Note that in all cases, a discrete source that is uniform over all + energy groups is created (strength = 0.01) to ensure that total cross + sections are generated for all energy groups. In the case that the user + has provided a source_energy distribution as an argument, an additional + source (strength = 0.99) is created using that energy distribution. If + the user has not provided a source_energy distribution, but the model + has sources defined, and all of those sources are of IndependentSource + type, then additional sources are created based on the model's existing + sources, keeping their energy distributions but replacing their + spatial/angular distributions, with their combined strength being 0.99. + If the user has not provided a source_energy distribution and no sources + are defined on the model and the run mode is 'eigenvalue', then a + default Watt spectrum source (strength = 0.99) is added. + Parameters ---------- groups : openmc.mgxs.EnergyGroups @@ -1715,9 +1815,10 @@ class Model: "P0". directory : str Directory to run the simulation in, so as to contain XML files. + source_energy : openmc.stats.Univariate, optional + Energy distribution to use when generating MGXS data, replacing any + existing sources in the model. """ - warnings.warn("The infinite medium method of generating MGXS may hang " - "if a material has a k-infinity > 1.0.") mgxs_sets = [] for material in self.materials: model = openmc.Model() @@ -1728,20 +1829,16 @@ class Model: # Settings model.settings.batches = 100 model.settings.particles = nparticles + + model.settings.source = self._create_mgxs_sources( + groups, + spatial_dist=openmc.stats.Point(), + source_energy=source_energy + ) + model.settings.run_mode = 'fixed source' + model.settings.create_fission_neutrons = False - # Make a discrete source that is uniform over the bins of the group structure - n_groups = groups.num_groups - midpoints = [] - strengths = [] - for i in range(n_groups): - bounds = groups.get_group_bounds(i+1) - midpoints.append((bounds[0] + bounds[1]) / 2.0) - strengths.append(1.0) - - energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths) - model.settings.source = openmc.IndependentSource( - space=openmc.stats.Point(), energy=energy_distribution) model.settings.output = {'summary': True, 'tallies': False} # Geometry @@ -1891,6 +1988,7 @@ class Model: mgxs_path: PathLike, correction: str | None, directory: PathLike, + source_energy: openmc.stats.Univariate | None = None, ) -> None: """Generate MGXS assuming a stochastic "sandwich" of materials in a layered slab geometry. While geometry-specific spatial shielding effects are not @@ -1915,6 +2013,23 @@ class Model: "P0". directory : str Directory to run the simulation in, so as to contain XML files. + source_energy : openmc.stats.Univariate, optional + Energy distribution to use when generating MGXS data, replacing any + existing sources in the model. In all cases, a discrete source that + is uniform over all energy groups is created (strength = 0.01) to + ensure that total cross sections are generated for all energy + groups. In the case that the user has provided a source_energy + distribution as an argument, an additional source (strength = 0.99) + is created using that energy distribution. If the user has not + provided a source_energy distribution, but the model has sources + defined, and all of those sources are of IndependentSource type, + then additional sources are created based on the model's existing + sources, keeping their energy distributions but replacing their + spatial/angular distributions, with their combined strength being + 0.99. If the user has not provided a source_energy distribution and + no sources are defined on the model and the run mode is + 'eigenvalue', then a default Watt spectrum source (strength = 0.99) + is added. """ model = openmc.Model() model.materials = self.materials @@ -1924,24 +2039,20 @@ class Model: model.settings.inactive = 100 model.settings.particles = nparticles model.settings.output = {'summary': True, 'tallies': False} - model.settings.run_mode = self.settings.run_mode # Stochastic slab geometry model.geometry, spatial_distribution = Model._create_stochastic_slab_geometry( model.materials) - # Make a discrete source that is uniform over the bins of the group structure - n_groups = groups.num_groups - midpoints = [] - strengths = [] - for i in range(n_groups): - bounds = groups.get_group_bounds(i+1) - midpoints.append((bounds[0] + bounds[1]) / 2.0) - strengths.append(1.0) + # Define the sources + model.settings.source = self._create_mgxs_sources( + groups, + spatial_dist=spatial_distribution, + source_energy=source_energy + ) - energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths) - model.settings.source = [openmc.IndependentSource( - space=spatial_distribution, energy=energy_distribution, strength=1.0)] + model.settings.run_mode = 'fixed source' + model.settings.create_fission_neutrons = False model.settings.output = {'summary': True, 'tallies': False} @@ -2099,6 +2210,7 @@ class Model: overwrite_mgxs_library: bool = False, mgxs_path: PathLike = "mgxs.h5", correction: str | None = None, + source_energy: openmc.stats.Univariate | None = None, ): """Convert all materials from continuous energy to multigroup. @@ -2121,6 +2233,24 @@ class Model: correction : str, optional Transport correction to apply to the MGXS. Options are None and "P0". + source_energy : openmc.stats.Univariate, optional + Energy distribution to use when generating MGXS data, replacing any + existing sources in the model. In all cases, a discrete source that + is uniform over all energy groups is created (strength = 0.01) to + ensure that total cross sections are generated for all energy + groups. In the case that the user has provided a source_energy + distribution as an argument, an additional source (strength = 0.99) + is created using that energy distribution. If the user has not + provided a source_energy distribution, but the model has sources + defined, and all of those sources are of IndependentSource type, + then additional sources are created based on the model's existing + sources, keeping their energy distributions but replacing their + spatial/angular distributions, with their combined strength being + 0.99. If the user has not provided a source_energy distribution and + no sources are defined on the model and the run mode is + 'eigenvalue', then a default Watt spectrum source (strength = 0.99) + is added. Note that this argument is only used when using the + "stochastic_slab" or "infinite_medium" MGXS generation methods. """ if isinstance(groups, str): groups = openmc.mgxs.EnergyGroups(groups) @@ -2150,13 +2280,13 @@ class Model: if not Path(mgxs_path).is_file() or overwrite_mgxs_library: if method == "infinite_medium": self._generate_infinite_medium_mgxs( - groups, nparticles, mgxs_path, correction, tmpdir) + groups, nparticles, mgxs_path, correction, tmpdir, source_energy) elif method == "material_wise": self._generate_material_wise_mgxs( groups, nparticles, mgxs_path, correction, tmpdir) elif method == "stochastic_slab": self._generate_stochastic_slab_mgxs( - groups, nparticles, mgxs_path, correction, tmpdir) + groups, nparticles, mgxs_path, correction, tmpdir, source_energy) else: raise ValueError( f'MGXS generation method "{method}" not recognized') diff --git a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat index ee396fa746..f984f37186 100644 --- a/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/infinite_medium/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.797252E-01 1.055731E-02 +7.479770E-01 1.624548E-02 diff --git a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat index 86e08a710c..674dee4aaf 100644 --- a/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat +++ b/tests/regression_tests/random_ray_auto_convert/stochastic_slab/results_true.dat @@ -1,2 +1,2 @@ k-combined: -7.496641E-01 8.282032E-03 +6.413334E-01 2.083132E-02 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/__init__.py b/tests/regression_tests/random_ray_auto_convert_source_energy/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/inputs_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/inputs_true.dat new file mode 100644 index 0000000000..80a166c678 --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/inputs_true.dat @@ -0,0 +1,61 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + 7000000.0 1.0 + + + multi-group + + + + -0.63 -0.63 -1.0 0.63 0.63 1.0 + + + 30.0 + 150.0 + + + + + + linear + + + 2 2 + -0.63 -0.63 + 0.63 0.63 + + + diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/results_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/results_true.dat new file mode 100644 index 0000000000..1fb09fd68a --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/model/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +7.657815E-01 2.317564E-02 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/inputs_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/inputs_true.dat new file mode 100644 index 0000000000..464c89a5df --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/inputs_true.dat @@ -0,0 +1,64 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + true + + + multi-group + + + + -0.63 -0.63 -1.0 0.63 0.63 1.0 + + + 30.0 + 150.0 + + + + + + linear + + + 2 2 + -0.63 -0.63 + 0.63 0.63 + + + diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/results_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/results_true.dat new file mode 100644 index 0000000000..073c5c99ff --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/infinite_medium/user/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +7.827784E-01 2.062954E-02 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/inputs_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/inputs_true.dat new file mode 100644 index 0000000000..80a166c678 --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/inputs_true.dat @@ -0,0 +1,61 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + 7000000.0 1.0 + + + multi-group + + + + -0.63 -0.63 -1.0 0.63 0.63 1.0 + + + 30.0 + 150.0 + + + + + + linear + + + 2 2 + -0.63 -0.63 + 0.63 0.63 + + + diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/results_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/results_true.dat new file mode 100644 index 0000000000..c5cdf8e29f --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/model/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +7.479571E-01 2.398563E-02 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/inputs_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/inputs_true.dat new file mode 100644 index 0000000000..464c89a5df --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/inputs_true.dat @@ -0,0 +1,64 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + eigenvalue + 100 + 10 + 5 + + + -0.63 -0.63 -1 0.63 0.63 1 + + + true + + + multi-group + + + + -0.63 -0.63 -1.0 0.63 0.63 1.0 + + + 30.0 + 150.0 + + + + + + linear + + + 2 2 + -0.63 -0.63 + 0.63 0.63 + + + diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/results_true.dat b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/results_true.dat new file mode 100644 index 0000000000..c6cce2e39c --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/stochastic_slab/user/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +7.620306E-01 2.175179E-02 diff --git a/tests/regression_tests/random_ray_auto_convert_source_energy/test.py b/tests/regression_tests/random_ray_auto_convert_source_energy/test.py new file mode 100644 index 0000000000..bb9119d895 --- /dev/null +++ b/tests/regression_tests/random_ray_auto_convert_source_energy/test.py @@ -0,0 +1,66 @@ +import os + +import openmc +from openmc.examples import pwr_pin_cell +from openmc import RegularMesh +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("source_type", ["model", "user"]) +@pytest.mark.parametrize("method", ["stochastic_slab", "infinite_medium"]) +def test_random_ray_auto_convert_source_energy(method, source_type): + dirname = f"{method}/{source_type}" + with change_directory(dirname): + openmc.reset_auto_ids() + + # Start with a normal continuous energy model + model = pwr_pin_cell() + + # Define the source energy distribution, using different methods + source_energy = None + if source_type == "model": + model.settings.source = openmc.IndependentSource( + energy=openmc.stats.delta_function(7.0e6) + ) + elif source_type == "user": + source_energy = openmc.stats.delta_function(1.0e4) + + # Convert to a multi-group model + model.convert_to_multigroup( + method=method, groups='CASMO-8', nparticles=100, + overwrite_mgxs_library=False, mgxs_path="mgxs.h5", + source_energy=source_energy + ) + + # Convert to a random ray model + model.convert_to_random_ray() + + # Set the number of particles + model.settings.particles = 100 + + # Overlay a basic 2x2 mesh + n = 2 + mesh = RegularMesh() + mesh.dimension = (n, n) + bbox = model.geometry.bounding_box + mesh.lower_left = (bbox.lower_left[0], bbox.lower_left[1]) + mesh.upper_right = (bbox.upper_right[0], bbox.upper_right[1]) + model.settings.random_ray['source_region_meshes'] = [ + (mesh, [model.geometry.root_universe])] + + # Set the source shape to linear + model.settings.random_ray['source_shape'] = 'linear' + + harness = MGXSTestHarness('statepoint.10.h5', model) + harness.main() From db8d4627386c5a5da94d7ddd953d57e93eaa10bb Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 4 Dec 2025 06:53:04 -0600 Subject: [PATCH 63/76] Allow DistribcellFilter to work with apply_tally_results=True (#3667) --- openmc/__init__.py | 2 +- openmc/data/decay.py | 16 ++----- openmc/data/neutron.py | 8 +--- openmc/filter.py | 19 ++++++-- openmc/model/model.py | 11 +++++ openmc/statepoint.py | 2 +- openmc/tallies.py | 37 ++++---------- tests/unit_tests/test_filter_distribcell.py | 53 +++++++++++++++++++++ 8 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 tests/unit_tests/test_filter_distribcell.py diff --git a/openmc/__init__.py b/openmc/__init__.py index bb972b4e6a..c204929c84 100644 --- a/openmc/__init__.py +++ b/openmc/__init__.py @@ -37,7 +37,7 @@ from openmc.tracks import * from .config import * # Import a few names from the model module -from openmc.model import Model +from openmc.model import Model, SearchResult from . import examples diff --git a/openmc/data/decay.py b/openmc/data/decay.py index c8a0bb5e7e..7cd4bf43d4 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -13,7 +13,7 @@ import openmc.checkvalue as cv from openmc.exceptions import DataError from openmc.mixin import EqualityMixin from openmc.stats import Discrete, Tabular, Univariate, combine_distributions -from .data import ATOMIC_SYMBOL, ATOMIC_NUMBER +from .data import ATOMIC_NUMBER, gnds_name from .function import INTERPOLATION_SCHEME from .endf import Evaluation, get_head_record, get_list_record, get_tab1_record @@ -126,9 +126,7 @@ class FissionProductYields(EqualityMixin): for j in range(n_products): Z, A = divmod(int(values[4*j]), 1000) isomeric_state = int(values[4*j + 1]) - name = ATOMIC_SYMBOL[Z] + str(A) - if isomeric_state > 0: - name += f'_m{isomeric_state}' + name = gnds_name(Z, A, isomeric_state) yield_j = ufloat(values[4*j + 2], values[4*j + 3]) yields[name] = yield_j @@ -256,10 +254,7 @@ class DecayMode(EqualityMixin): A += delta_A Z += delta_Z - if self._daughter_state > 0: - return f'{ATOMIC_SYMBOL[Z]}{A}_m{self._daughter_state}' - else: - return f'{ATOMIC_SYMBOL[Z]}{A}' + return gnds_name(Z, A, self._daughter_state) @property def parent(self): @@ -348,10 +343,7 @@ class Decay(EqualityMixin): self.nuclide['atomic_number'] = Z self.nuclide['mass_number'] = A self.nuclide['isomeric_state'] = metastable - if metastable > 0: - self.nuclide['name'] = f'{ATOMIC_SYMBOL[Z]}{A}_m{metastable}' - else: - self.nuclide['name'] = f'{ATOMIC_SYMBOL[Z]}{A}' + self.nuclide['name'] = gnds_name(Z, A, metastable) self.nuclide['mass'] = items[1] # AWR self.nuclide['excited_state'] = items[2] # State of the original nuclide self.nuclide['stable'] = (items[4] == 1) # Nucleus stability flag diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index 95a3424ea4..628801e5e9 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -11,7 +11,7 @@ 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 .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV, gnds_name from .endf import ( Evaluation, SUM_RULES, get_head_record, get_tab1_record, get_evaluations) from .fission_energy import FissionEnergyRelease @@ -678,11 +678,7 @@ class IncidentNeutron(EqualityMixin): temperature = ev.target['temperature'] # Determine name - element = ATOMIC_SYMBOL[atomic_number] - if metastable > 0: - name = f'{element}{mass_number}_m{metastable}' - else: - name = f'{element}{mass_number}' + name = gnds_name(atomic_number, mass_number, metastable) # Instantiate incident neutron data data = cls(name, atomic_number, mass_number, metastable, diff --git a/openmc/filter.py b/openmc/filter.py index 6a666d2a02..550146f85d 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -1839,12 +1839,21 @@ class DistribcellFilter(Filter): @property def paths(self): - return self._paths + if self._paths is None: + if not hasattr(self, '_geometry'): + raise ValueError( + "Model must be exported before the 'paths' attribute is" \ + "available for a DistribcellFilter.") - @paths.setter - def paths(self, paths): - cv.check_iterable_type('paths', paths, str) - self._paths = paths + # Determine paths for cell instances + self._geometry.determine_paths() + + # Get paths for the corresponding cell + cell_id = self.bins[0] + cell = self._geometry.get_all_cells()[cell_id] + self._paths = cell.paths + + return self._paths @Filter.bins.setter def bins(self, bins): diff --git a/openmc/model/model.py b/openmc/model/model.py index 2997247597..782725b78e 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -546,6 +546,13 @@ class Model: depletion_operator.cleanup_when_done = True depletion_operator.finalize() + def _link_geometry_to_filters(self): + """Establishes a link between distribcell filters and the geometry""" + for tally in self.tallies: + for f in tally.filters: + if isinstance(f, openmc.DistribcellFilter): + f._geometry = self.geometry + def export_to_xml(self, directory: PathLike = '.', remove_surfs: bool = False, nuclides_to_ignore: Iterable[str] | None = None): """Export model to separate XML files. @@ -587,6 +594,8 @@ class Model: if self.plots: self.plots.export_to_xml(d) + self._link_geometry_to_filters() + def export_to_model_xml(self, path: PathLike = 'model.xml', remove_surfs: bool = False, nuclides_to_ignore: Iterable[str] | None = None): """Export model to a single XML file. @@ -666,6 +675,8 @@ class Model: fh.write(ET.tostring(plots_element, encoding="unicode")) fh.write("\n") + self._link_geometry_to_filters() + def import_properties(self, filename: PathLike): """Import physical properties diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 11986841f0..a10ec3a839 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -723,7 +723,7 @@ class StatePoint: cell = cells[cell_id] if not cell._paths: summary.geometry.determine_paths() - tally_filter.paths = cell.paths + tally_filter._paths = cell.paths self._summary = summary diff --git a/openmc/tallies.py b/openmc/tallies.py index add3565798..09365e5257 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -290,7 +290,7 @@ class Tally(IDManagerMixin): @property def num_nuclides(self): - return len(self._nuclides) + return max(len(self._nuclides), 1) @property def scores(self): @@ -393,6 +393,11 @@ class Tally(IDManagerMixin): group = f[f'tallies/tally {self.id}'] self._num_realizations = int(group['n_realizations'][()]) + for filt in self.filters: + if isinstance(filt, openmc.DistribcellFilter): + filter_group = f[f'tallies/filters/filter {filt.id}'] + filt._num_bins = int(filter_group['n_bins'][()]) + # Update nuclides nuclide_names = group['nuclides'][()] self._nuclides = [name.decode().strip() for name in nuclide_names] @@ -3704,43 +3709,17 @@ class Tallies(cv.CheckedList): if possible. Defaults to False. """ - if not isinstance(tally, Tally): - msg = f'Unable to add a non-Tally "{tally}" to the Tallies instance' - raise TypeError(msg) - if merge: - merged = False - # Look for a tally to merge with this one for i, tally2 in enumerate(self): - # If a mergeable tally is found if tally2.can_merge(tally): # Replace tally2 with the merged tally merged_tally = tally2.merge(tally) self[i] = merged_tally - merged = True - break + return - # If no mergeable tally was found, simply add this tally - if not merged: - super().append(tally) - - else: - super().append(tally) - - def insert(self, index, item): - """Insert tally before index - - Parameters - ---------- - index : int - Index in list - item : openmc.Tally - Tally to insert - - """ - super().insert(index, item) + super().append(tally) def merge_tallies(self): """Merge any mergeable tallies together. Note that n-way merges are diff --git a/tests/unit_tests/test_filter_distribcell.py b/tests/unit_tests/test_filter_distribcell.py new file mode 100644 index 0000000000..d5734a2c07 --- /dev/null +++ b/tests/unit_tests/test_filter_distribcell.py @@ -0,0 +1,53 @@ +import openmc +import pandas as pd + + +def test_distribcell_filter_apply_tally_results(run_in_tmpdir): + # Reset IDs to ensure consistent paths + openmc.reset_auto_ids() + + mat = openmc.Material() + mat.add_nuclide("U235", 1.0) + mat.set_density("g/cm3", 1.0) + + # Define 2x2 lattice with a cylinder in each universe + cyl = openmc.ZCylinder(r=1.0) + cell1 = openmc.Cell(fill=mat, region=-cyl) + cell2 = openmc.Cell(fill=None, region=+cyl) + univ = openmc.Universe(cells=[cell1, cell2]) + lattice = openmc.RectLattice() + lattice.lower_left = (-3.0, -3.0) + lattice.pitch = (3.0, 3.0) + lattice.universes = [[univ, univ], [univ, univ]] + box = openmc.model.RectangularPrism(6., 6., boundary_type='reflective') + root_cell = openmc.Cell(region=-box, fill=lattice) + geometry = openmc.Geometry([root_cell]) + + # Create model and add tally with distribcell filter + model = openmc.Model(geometry) + model.settings.batches = 10 + model.settings.particles = 1000 + tally = openmc.Tally() + distribcell_filter = openmc.DistribcellFilter(cell1) + tally.filters = [distribcell_filter] + tally.scores = ['flux'] + model.tallies = [tally] + + # Run OpenMC and apply tally results + model.run(apply_tally_results=True) + + # Check that mean and standard deviation are available on tally + assert tally.mean.shape == (4, 1, 1) + assert tally.std_dev.shape == (4, 1, 1) + + # Make sure paths attribute on filter is correct + assert distribcell_filter.paths == [ + 'u3->c3->l2(0,0)->u1->c1', + 'u3->c3->l2(1,0)->u1->c1', + 'u3->c3->l2(0,1)->u1->c1', + 'u3->c3->l2(1,1)->u1->c1', + ] + + # Check that we can get a DataFrame from the tally + df = tally.get_pandas_dataframe() + assert isinstance(df, pd.DataFrame) From f28139250ac8dc7fdef3f8f13b8c65c5dbb82923 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 5 Dec 2025 18:02:26 +0100 Subject: [PATCH 64/76] Fixed plotting issue by scaling source locations with axis units (#3668) --- openmc/model/model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/model/model.py b/openmc/model/model.py index 782725b78e..538c64ff33 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1287,8 +1287,8 @@ class Model: tol = plane_tolerance for particle in particles: if (slice_value - tol < particle.r[z] < slice_value + tol): - xs.append(particle.r[x]) - ys.append(particle.r[y]) + xs.append(particle.r[x] * axis_scaling_factor[axis_units]) + ys.append(particle.r[y] * axis_scaling_factor[axis_units]) axes.scatter(xs, ys, **source_kwargs) return axes From 9b675adda5c64f8620c11e3d6723c598f443f982 Mon Sep 17 00:00:00 2001 From: Boris Polania Date: Fri, 5 Dec 2025 12:17:09 -0800 Subject: [PATCH 65/76] Introduce SlicePlot and VoxelPlot to replace the Plot class (#3528) Co-authored-by: Paul Romano --- docs/source/pythonapi/base.rst | 3 +- docs/source/usersguide/plots.rst | 46 ++- docs/source/usersguide/random_ray.rst | 6 +- examples/lattice/hexagonal/build_xml.py | 4 +- examples/lattice/nested/build_xml.py | 2 +- examples/lattice/simple/build_xml.py | 2 +- examples/pincell_random_ray/build_xml.py | 3 +- openmc/examples.py | 6 +- openmc/executor.py | 2 +- openmc/model/model.py | 2 +- openmc/plots.py | 324 ++++++++++++++++++--- src/mcpl_interface.cpp | 13 +- tests/regression_tests/distribmat/test.py | 4 +- tests/unit_tests/test_model.py | 6 +- tests/unit_tests/test_plots.py | 34 +-- tests/unit_tests/test_slice_voxel_plots.py | 273 +++++++++++++++++ 16 files changed, 618 insertions(+), 112 deletions(-) create mode 100644 tests/unit_tests/test_slice_voxel_plots.py diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index ce2f6f0f85..dea8c4427c 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -176,7 +176,8 @@ Geometry Plotting :nosignatures: :template: myclass.rst - openmc.Plot + openmc.SlicePlot + openmc.VoxelPlot openmc.WireframeRayTracePlot openmc.SolidRayTracePlot openmc.Plots diff --git a/docs/source/usersguide/plots.rst b/docs/source/usersguide/plots.rst index da0c69bdd8..b5c29a3e88 100644 --- a/docs/source/usersguide/plots.rst +++ b/docs/source/usersguide/plots.rst @@ -6,13 +6,14 @@ Geometry Visualization .. currentmodule:: openmc -OpenMC is capable of producing two-dimensional slice plots of a geometry as well -as three-dimensional voxel plots using the geometry plotting :ref:`run mode -`. The geometry plotting mode relies on the presence of a -:ref:`plots.xml ` file that indicates what plots should be created. To -create this file, one needs to create one or more :class:`openmc.Plot` -instances, add them to a :class:`openmc.Plots` collection, and then use the -:class:`Plots.export_to_xml` method to write the ``plots.xml`` file. +OpenMC is capable of producing two-dimensional slice plots of a geometry, +three-dimensional voxel plots, and three-dimensional raytrace plots using the +geometry plotting :ref:`run mode `. The geometry plotting +mode relies on the presence of a :ref:`plots.xml ` file that indicates +what plots should be created. To create this file, one needs to create one or +more instances of the various plot classes described below, add them to a +:class:`openmc.Plots` collection, and then use the :class:`Plots.export_to_xml` +method to write the ``plots.xml`` file. ----------- Slice Plots @@ -21,15 +22,14 @@ Slice Plots .. image:: ../_images/atr.png :width: 300px -By default, when an instance of :class:`openmc.Plot` is created, it indicates -that a 2D slice plot should be made. You can specify the origin of the plot -(:attr:`Plot.origin`), the width of the plot in each direction -(:attr:`Plot.width`), the number of pixels to use in each direction -(:attr:`Plot.pixels`), and the basis directions for the plot. For example, to -create a :math:`x` - :math:`z` plot centered at (5.0, 2.0, 3.0) with a width of -(50., 50.) and 400x400 pixels:: +The :class:`openmc.SlicePlot` class indicates that a 2D slice plot should be +made. You can specify the origin of the plot (:attr:`SlicePlot.origin`), the +width of the plot in each direction (:attr:`SlicePlot.width`), the number of +pixels to use in each direction (:attr:`SlicePlot.pixels`), and the basis +directions for the plot. For example, to create a :math:`x` - :math:`z` plot +centered at (5.0, 2.0, 3.0) with a width of (50., 50.) and 400x400 pixels:: - plot = openmc.Plot() + plot = openmc.SlicePlot() plot.basis = 'xz' plot.origin = (5.0, 2.0, 3.0) plot.width = (50., 50.) @@ -47,7 +47,7 @@ that location. By default, a unique color will be assigned to each cell in the geometry. If you want your plot to be colored by material instead, change the -:attr:`Plot.color_by` attribute:: +:attr:`SlicePlot.color_by` attribute:: plot.color_by = 'material' @@ -68,8 +68,8 @@ particular cells/materials should be given colors of your choosing:: Note that colors can be given as RGB tuples or by a string indicating a valid `SVG color `_. -When you're done creating your :class:`openmc.Plot` instances, you need to then -assign them to a :class:`openmc.Plots` collection and export it to XML:: +When you're done creating your :class:`openmc.SlicePlot` instances, you need to +then assign them to a :class:`openmc.Plots` collection and export it to XML:: plots = openmc.Plots([plot1, plot2, plot3]) plots.export_to_xml() @@ -97,13 +97,11 @@ Voxel Plots .. image:: ../_images/3dba.png :width: 200px -The :class:`openmc.Plot` class can also be told to generate a 3D voxel plot -instead of a 2D slice plot. Simply change the :attr:`Plot.type` attribute to -'voxel'. In this case, the :attr:`Plot.width` and :attr:`Plot.pixels` attributes -should be three items long, e.g.:: +The :class:`openmc.VoxelPlot` class enables the generation of a 3D voxel plot +instead of a 2D slice plot. In this case, the :attr:`VoxelPlot.width` and +:attr:`VoxelPlot.pixels` attributes should be three items long, e.g.:: - vox_plot = openmc.Plot() - vox_plot.type = 'voxel' + vox_plot = openmc.VoxelPlot() vox_plot.width = (100., 100., 50.) vox_plot.pixels = (400, 400, 200) diff --git a/docs/source/usersguide/random_ray.rst b/docs/source/usersguide/random_ray.rst index 881498a0a7..382381a9ee 100644 --- a/docs/source/usersguide/random_ray.rst +++ b/docs/source/usersguide/random_ray.rst @@ -1131,11 +1131,10 @@ given below: tallies.export_to_xml() # Create voxel plot - plot = openmc.Plot() + plot = openmc.VoxelPlot() 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 plots = openmc.Plots([plot]) @@ -1215,11 +1214,10 @@ given below: tallies.export_to_xml() # Create voxel plot - plot = openmc.Plot() + plot = openmc.VoxelPlot() 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 plots = openmc.Plots([plot]) diff --git a/examples/lattice/hexagonal/build_xml.py b/examples/lattice/hexagonal/build_xml.py index 9485d0aa45..2624e52b4d 100644 --- a/examples/lattice/hexagonal/build_xml.py +++ b/examples/lattice/hexagonal/build_xml.py @@ -128,14 +128,14 @@ settings_file.export_to_xml() # Exporting to OpenMC plots.xml file ############################################################################### -plot_xy = openmc.Plot(plot_id=1) +plot_xy = openmc.SlicePlot(plot_id=1) plot_xy.filename = 'plot_xy' plot_xy.origin = [0, 0, 0] plot_xy.width = [6, 6] plot_xy.pixels = [400, 400] plot_xy.color_by = 'material' -plot_yz = openmc.Plot(plot_id=2) +plot_yz = openmc.SlicePlot(plot_id=2) plot_yz.filename = 'plot_yz' plot_yz.basis = 'yz' plot_yz.origin = [0, 0, 0] diff --git a/examples/lattice/nested/build_xml.py b/examples/lattice/nested/build_xml.py index 2db23a46b3..a1d9c092dd 100644 --- a/examples/lattice/nested/build_xml.py +++ b/examples/lattice/nested/build_xml.py @@ -135,7 +135,7 @@ settings_file.export_to_xml() # Exporting to OpenMC plots.xml file ############################################################################### -plot = openmc.Plot(plot_id=1) +plot = openmc.SlicePlot(plot_id=1) plot.origin = [0, 0, 0] plot.width = [4, 4] plot.pixels = [400, 400] diff --git a/examples/lattice/simple/build_xml.py b/examples/lattice/simple/build_xml.py index 56c4661216..44531edd8a 100644 --- a/examples/lattice/simple/build_xml.py +++ b/examples/lattice/simple/build_xml.py @@ -128,7 +128,7 @@ settings_file.export_to_xml() # Exporting to OpenMC plots.xml file ############################################################################### -plot = openmc.Plot(plot_id=1) +plot = openmc.SlicePlot(plot_id=1) plot.origin = [0, 0, 0] plot.width = [4, 4] plot.pixels = [400, 400] diff --git a/examples/pincell_random_ray/build_xml.py b/examples/pincell_random_ray/build_xml.py index b3dd8020a5..5ff4c0082f 100644 --- a/examples/pincell_random_ray/build_xml.py +++ b/examples/pincell_random_ray/build_xml.py @@ -192,11 +192,10 @@ tallies.export_to_xml() # Exporting to OpenMC plots.xml file ############################################################################### -plot = openmc.Plot() +plot = openmc.VoxelPlot() plot.origin = [0, 0, 0] plot.width = [pitch, pitch, pitch] plot.pixels = [1000, 1000, 1] -plot.type = 'voxel' # Instantiate a Plots collection and export to XML plots = openmc.Plots([plot]) diff --git a/openmc/examples.py b/openmc/examples.py index 5578d513ea..01dd9d01f9 100644 --- a/openmc/examples.py +++ b/openmc/examples.py @@ -83,7 +83,7 @@ def pwr_pin_cell() -> openmc.Model: constraints={'fissionable': True} ) - plot = openmc.Plot.from_geometry(model.geometry) + plot = openmc.SlicePlot.from_geometry(model.geometry) plot.pixels = (300, 300) plot.color_by = 'material' model.plots.append(plot) @@ -429,7 +429,7 @@ def pwr_core() -> openmc.Model: model.settings.source = openmc.IndependentSource(space=openmc.stats.Box( [-160, -160, -183], [160, 160, 183])) - plot = openmc.Plot() + plot = openmc.SlicePlot() plot.origin = (125, 125, 0) plot.width = (250, 250) plot.pixels = (3000, 3000) @@ -544,7 +544,7 @@ def pwr_assembly() -> openmc.Model: constraints={'fissionable': True} ) - plot = openmc.Plot() + plot = openmc.SlicePlot() plot.origin = (0.0, 0.0, 0) plot.width = (21.42, 21.42) plot.pixels = (300, 300) diff --git a/openmc/executor.py b/openmc/executor.py index aacc48b3fa..9cd2993454 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -164,7 +164,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', path_input=None): Parameters ---------- - plots : Iterable of openmc.Plot + plots : Iterable of openmc.PlotBase Plots to display openmc_exec : str Path to OpenMC executable diff --git a/openmc/model/model.py b/openmc/model/model.py index 538c64ff33..e2ac57eba4 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1170,7 +1170,7 @@ class Model: self.settings.plot_seed = seed # Create plot object matching passed arguments - plot = openmc.Plot() + plot = openmc.SlicePlot() plot.origin = origin plot.width = width plot.pixels = pixels diff --git a/openmc/plots.py b/openmc/plots.py index a0bde3f007..cb722abc6e 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -2,6 +2,7 @@ from collections.abc import Iterable, Mapping from numbers import Integral, Real from pathlib import Path from textwrap import dedent +import warnings import h5py import lxml.etree as ET @@ -626,14 +627,15 @@ class PlotBase(IDManagerMixin): return element -class Plot(PlotBase): - """Definition of a finite region of space to be plotted. +class SlicePlot(PlotBase): + """Definition of a 2D slice plot of the geometry. - OpenMC is capable of generating two-dimensional slice plots, or - three-dimensional voxel or projection plots. Colors that are used in plots can be given as - RGB tuples, e.g. (255, 255, 255) would be white, or by a string indicating a + Colors that are used in plots can be given as RGB tuples, e.g. + (255, 255, 255) would be white, or by a string indicating a valid `SVG color `_. + .. versionadded:: 0.15.4 + Parameters ---------- plot_id : int @@ -648,7 +650,7 @@ class Plot(PlotBase): name : str Name of the plot pixels : Iterable of int - Number of pixels to use in each direction + Number of pixels to use in each direction (2 values) filename : str Path to write the plot to color_by : {'cell', 'material'} @@ -671,11 +673,9 @@ class Plot(PlotBase): level : int Universe depth to plot at width : Iterable of float - Width of the plot in each basis direction + Width of the plot in each basis direction (2 values) origin : tuple or list of ndarray - Origin (center) of the plot - type : {'slice', 'voxel'} - The type of the plot + Origin (center) of the plot (3 values) basis : {'xy', 'xz', 'yz'} The basis directions for the plot meshlines : dict @@ -688,10 +688,37 @@ class Plot(PlotBase): super().__init__(plot_id, name) self._width = [4.0, 4.0] self._origin = [0., 0., 0.] - self._type = 'slice' self._basis = 'xy' self._meshlines = None + @property + def type(self): + warnings.warn( + "The 'type' attribute is deprecated and will be removed in a future version. " + "This is a SlicePlot instance.", + FutureWarning, stacklevel=2 + ) + return 'slice' + + @type.setter + def type(self, value): + raise TypeError( + "Setting plot.type is no longer supported. " + "Use openmc.SlicePlot() for 2D slice plots or openmc.VoxelPlot() for 3D voxel plots." + ) + + @property + def pixels(self): + return self._pixels + + @pixels.setter + def pixels(self, pixels): + cv.check_type('plot pixels', pixels, Iterable, Integral) + cv.check_length('plot pixels', pixels, 2, 2) + for dim in pixels: + cv.check_greater_than('plot pixels', dim, 0) + self._pixels = pixels + @property def width(self): return self._width @@ -699,7 +726,7 @@ class Plot(PlotBase): @width.setter def width(self, width): cv.check_type('plot width', width, Iterable, Real) - cv.check_length('plot width', width, 2, 3) + cv.check_length('plot width', width, 2, 2) self._width = width @property @@ -712,15 +739,6 @@ class Plot(PlotBase): cv.check_length('plot origin', origin, 3) self._origin = origin - @property - def type(self): - return self._type - - @type.setter - def type(self, plottype): - cv.check_value('plot type', plottype, ['slice', 'voxel']) - self._type = plottype - @property def basis(self): return self._basis @@ -763,11 +781,10 @@ class Plot(PlotBase): self._meshlines = meshlines def __repr__(self): - string = 'Plot\n' + string = 'SlicePlot\n' string += '{: <16}=\t{}\n'.format('\tID', self._id) string += '{: <16}=\t{}\n'.format('\tName', self._name) string += '{: <16}=\t{}\n'.format('\tFilename', self._filename) - string += '{: <16}=\t{}\n'.format('\tType', self._type) string += '{: <16}=\t{}\n'.format('\tBasis', self._basis) string += '{: <16}=\t{}\n'.format('\tWidth', self._width) string += '{: <16}=\t{}\n'.format('\tOrigin', self._origin) @@ -883,7 +900,7 @@ class Plot(PlotBase): self._colors[domain] = (r, g, b) def to_xml_element(self): - """Return XML representation of the slice/voxel plot + """Return XML representation of the slice plot Returns ------- @@ -893,10 +910,8 @@ class Plot(PlotBase): """ element = super().to_xml_element() - element.set("type", self._type) - - if self._type == 'slice': - element.set("basis", self._basis) + element.set("type", "slice") + element.set("basis", self._basis) subelement = ET.SubElement(element, "origin") subelement.text = ' '.join(map(str, self._origin)) @@ -942,8 +957,8 @@ class Plot(PlotBase): Returns ------- - openmc.Plot - Plot object + openmc.SlicePlot + SlicePlot object """ plot_id = int(get_text(elem, "id")) @@ -952,9 +967,7 @@ class Plot(PlotBase): if "filename" in elem.keys(): plot.filename = get_text(elem, "filename") plot.color_by = get_text(elem, "color_by") - plot.type = get_text(elem, "type") - if plot.type == 'slice': - plot.basis = get_text(elem, "basis") + plot.basis = get_text(elem, "basis") plot.origin = tuple(get_elem_list(elem, "origin", float)) plot.width = tuple(get_elem_list(elem, "width", float)) @@ -1036,9 +1049,215 @@ class Plot(PlotBase): # Return produced image return _get_plot_image(self, cwd) + + +class VoxelPlot(PlotBase): + """Definition of a 3D voxel plot of the geometry. + + Colors that are used in plots can be given as RGB tuples, e.g. + (255, 255, 255) would be white, or by a string indicating a + valid `SVG color `_. + + .. versionadded:: 0.15.1 + + Parameters + ---------- + plot_id : int + Unique identifier for the plot + name : str + Name of the plot + + Attributes + ---------- + id : int + Unique identifier + name : str + Name of the plot + pixels : Iterable of int + Number of pixels to use in each direction (3 values) + filename : str + Path to write the plot to + color_by : {'cell', 'material'} + Indicate whether the plot should be colored by cell or by material + background : Iterable of int or str + Color of the background + mask_components : Iterable of openmc.Cell or openmc.Material or int + The cells or materials (or corresponding IDs) to mask + mask_background : Iterable of int or str + Color to apply to all cells/materials listed in mask_components + show_overlaps : bool + Indicate whether or not overlapping regions are shown + overlap_color : Iterable of int or str + Color to apply to overlapping regions + colors : dict + Dictionary indicating that certain cells/materials should be + displayed with a particular color. The keys can be of type + :class:`~openmc.Cell`, :class:`~openmc.Material`, or int (ID for a + cell/material). + level : int + Universe depth to plot at + width : Iterable of float + Width of the plot in each dimension (3 values) + origin : tuple or list of ndarray + Origin (center) of the plot (3 values) + + """ + + def __init__(self, plot_id=None, name=''): + super().__init__(plot_id, name) + self._width = [4.0, 4.0, 4.0] + self._origin = [0., 0., 0.] + self._pixels = [400, 400, 400] + + @property + def pixels(self): + return self._pixels + + @pixels.setter + def pixels(self, pixels): + cv.check_type('plot pixels', pixels, Iterable, Integral) + cv.check_length('plot pixels', pixels, 3, 3) + for dim in pixels: + cv.check_greater_than('plot pixels', dim, 0) + self._pixels = pixels + + @property + def width(self): + return self._width + + @width.setter + def width(self, width): + cv.check_type('plot width', width, Iterable, Real) + cv.check_length('plot width', width, 3, 3) + self._width = width + + @property + def origin(self): + return self._origin + + @origin.setter + def origin(self, origin): + cv.check_type('plot origin', origin, Iterable, Real) + cv.check_length('plot origin', origin, 3) + self._origin = origin + + def __repr__(self): + string = 'VoxelPlot\n' + string += '{: <16}=\t{}\n'.format('\tID', self._id) + string += '{: <16}=\t{}\n'.format('\tName', self._name) + string += '{: <16}=\t{}\n'.format('\tFilename', self._filename) + string += '{: <16}=\t{}\n'.format('\tWidth', self._width) + string += '{: <16}=\t{}\n'.format('\tOrigin', self._origin) + string += '{: <16}=\t{}\n'.format('\tPixels', self._pixels) + string += '{: <16}=\t{}\n'.format('\tColor by', self._color_by) + string += '{: <16}=\t{}\n'.format('\tBackground', self._background) + string += '{: <16}=\t{}\n'.format('\tMask components', + self._mask_components) + string += '{: <16}=\t{}\n'.format('\tMask background', + self._mask_background) + string += '{: <16}=\t{}\n'.format('\tOverlap Color', + self._overlap_color) + string += '{: <16}=\t{}\n'.format('\tColors', self._colors) + string += '{: <16}=\t{}\n'.format('\tLevel', self._level) + return string + + def to_xml_element(self): + """Return XML representation of the voxel plot + + Returns + ------- + element : lxml.etree._Element + XML element containing plot data + + """ + + element = super().to_xml_element() + element.set("type", "voxel") + + subelement = ET.SubElement(element, "origin") + subelement.text = ' '.join(map(str, self._origin)) + + subelement = ET.SubElement(element, "width") + subelement.text = ' '.join(map(str, self._width)) + + if self._colors: + self._colors_to_xml(element) + + if self._show_overlaps: + subelement = ET.SubElement(element, "show_overlaps") + subelement.text = "true" + + if self._overlap_color is not None: + color = self._overlap_color + if isinstance(color, str): + color = _SVG_COLORS[color.lower()] + subelement = ET.SubElement(element, "overlap_color") + subelement.text = ' '.join(str(x) for x in color) + + return element + + @classmethod + def from_xml_element(cls, elem): + """Generate plot object from an XML element + + Parameters + ---------- + elem : lxml.etree._Element + XML element + + Returns + ------- + openmc.VoxelPlot + VoxelPlot object + + """ + plot_id = int(get_text(elem, "id")) + name = get_text(elem, 'name', '') + plot = cls(plot_id, name) + if "filename" in elem.keys(): + plot.filename = get_text(elem, "filename") + plot.color_by = get_text(elem, "color_by") + + plot.origin = tuple(get_elem_list(elem, "origin", float)) + plot.width = tuple(get_elem_list(elem, "width", float)) + plot.pixels = tuple(get_elem_list(elem, "pixels")) + background = get_elem_list(elem, "background") + if background is not None: + plot._background = tuple(background) + + # Set plot colors + colors = {} + for color_elem in elem.findall("color"): + uid = int(get_text(color_elem, "id")) + colors[uid] = tuple(get_elem_list(color_elem, "rgb", int)) + plot.colors = colors + + # Set masking information + mask_elem = elem.find("mask") + if mask_elem is not None: + plot.mask_components = get_elem_list(mask_elem, "components", int) + background = get_elem_list(mask_elem, "background", int) + if background is not None: + plot.mask_background = tuple(background) + + # show overlaps + overlap = get_text(elem, "show_overlaps") + if overlap is not None: + plot.show_overlaps = (overlap in ('true', '1')) + overlap_color = get_elem_list(elem, "overlap_color", int) + if overlap_color is not None: + plot.overlap_color = tuple(overlap_color) + + # Set universe level + level = get_text(elem, "level") + if level is not None: + plot.level = int(level) + + return plot + def to_vtk(self, output: PathLike | None = None, openmc_exec: str = 'openmc', cwd: str = '.'): - """Render plot as an voxel image + """Render plot as a voxel image This method runs OpenMC in plotting mode to produce a .vti file. @@ -1059,10 +1278,6 @@ class Plot(PlotBase): Path of the .vti file produced """ - if self.type != 'voxel': - raise ValueError( - 'Generating a VTK file only works for voxel plots') - # Create plots.xml Plots([self]).export_to_xml(cwd) @@ -1082,6 +1297,20 @@ class Plot(PlotBase): return voxel_to_vtk(h5_voxel_file, output) +def Plot(plot_id=None, name=''): + """Legacy Plot class for backward compatibility. + + .. deprecated:: 0.15.4 + Use :class:`SlicePlot` for 2D slice plots or :class:`VoxelPlot` for 3D voxel plots. + + """ + warnings.warn( + "The Plot class is deprecated. Use SlicePlot for 2D slice plots " + "or VoxelPlot for 3D voxel plots.", FutureWarning + ) + return SlicePlot(plot_id, name) + + class RayTracePlot(PlotBase): """Definition of a camera's view of OpenMC geometry @@ -1737,16 +1966,16 @@ class SolidRayTracePlot(RayTracePlot): class Plots(cv.CheckedList): - """Collection of Plots used for an OpenMC simulation. + """Collection of plots used for an OpenMC simulation. This class corresponds directly to the plots.xml input file. It can be thought of as a normal Python list where each member is inherits from :class:`PlotBase`. It behaves like a list as the following example demonstrates: - >>> xz_plot = openmc.Plot() - >>> big_plot = openmc.Plot() - >>> small_plot = openmc.Plot() + >>> xz_plot = openmc.SlicePlot() + >>> big_plot = openmc.VoxelPlot() + >>> small_plot = openmc.SlicePlot() >>> p = openmc.Plots((xz_plot, big_plot)) >>> p.append(small_plot) >>> small_plot = p.pop() @@ -1782,7 +2011,7 @@ class Plots(cv.CheckedList): ---------- index : int Index in list - plot : openmc.Plot + plot : openmc.PlotBase Plot to insert """ @@ -1903,8 +2132,13 @@ class Plots(cv.CheckedList): plots.append(WireframeRayTracePlot.from_xml_element(e)) elif plot_type == 'solid_raytrace': plots.append(SolidRayTracePlot.from_xml_element(e)) - elif plot_type in ('slice', 'voxel'): - plots.append(Plot.from_xml_element(e)) + elif plot_type == 'slice': + plots.append(SlicePlot.from_xml_element(e)) + elif plot_type == 'voxel': + plots.append(VoxelPlot.from_xml_element(e)) + elif plot_type is None: + # For backward compatibility, assume slice if no type specified + plots.append(SlicePlot.from_xml_element(e)) else: raise ValueError("Unknown plot type: {}".format(plot_type)) return plots diff --git a/src/mcpl_interface.cpp b/src/mcpl_interface.cpp index 1294073019..256f3343fc 100644 --- a/src/mcpl_interface.cpp +++ b/src/mcpl_interface.cpp @@ -63,7 +63,7 @@ using mcpl_read_fpt = const mcpl_particle_repr_t* (*)(mcpl_file_t* file_handle); using mcpl_close_file_fpt = void (*)(mcpl_file_t* file_handle); using mcpl_hdr_add_data_fpt = void (*)(mcpl_outfile_t* file_handle, - const char* key, int32_t ldata, const char* data); + const char* key, uint32_t datalength, const char* data); using mcpl_create_outfile_fpt = mcpl_outfile_t* (*)(const char* filename); using mcpl_hdr_set_srcname_fpt = void (*)( mcpl_outfile_t* outfile_handle, const char* srcname); @@ -150,13 +150,20 @@ struct McplApi { load_symbol_platform("mcpl_create_outfile")); hdr_set_srcname = reinterpret_cast( load_symbol_platform("mcpl_hdr_set_srcname")); - hdr_add_data = reinterpret_cast( - load_symbol_platform("mcpl_hdr_add_data")); add_particle = reinterpret_cast( load_symbol_platform("mcpl_add_particle")); close_outfile = reinterpret_cast( load_symbol_platform("mcpl_close_outfile")); + // Try to load mcpl_hdr_add_data (available in MCPL >= 2.1.0) + // Set to nullptr if not available for graceful fallback + try { + hdr_add_data = reinterpret_cast( + load_symbol_platform("mcpl_hdr_add_data")); + } catch (const std::runtime_error&) { + hdr_add_data = nullptr; + } + // Try to load mcpl_hdr_add_stat_sum (available in MCPL >= 2.1.0) // Set to nullptr if not available for graceful fallback try { diff --git a/tests/regression_tests/distribmat/test.py b/tests/regression_tests/distribmat/test.py index 02f7e773e5..dd09eec36c 100644 --- a/tests/regression_tests/distribmat/test.py +++ b/tests/regression_tests/distribmat/test.py @@ -73,7 +73,7 @@ class DistribmatTestHarness(PyAPITestHarness): # Plots #################### - plot1 = openmc.Plot(plot_id=1) + plot1 = openmc.SlicePlot(plot_id=1) plot1.basis = 'xy' plot1.color_by = 'cell' plot1.filename = 'cellplot' @@ -81,7 +81,7 @@ class DistribmatTestHarness(PyAPITestHarness): plot1.width = (7, 7) plot1.pixels = (400, 400) - plot2 = openmc.Plot(plot_id=2) + plot2 = openmc.SlicePlot(plot_id=2) plot2.basis = 'xy' plot2.color_by = 'material' plot2.filename = 'matplot' diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index f4f94a47ca..9b28ff1c4d 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -73,13 +73,13 @@ def pin_model_attributes(): tal.scores = ['flux', 'fission'] tals.append(tal) - plot1 = openmc.Plot(plot_id=1) + plot1 = openmc.SlicePlot(plot_id=1) plot1.origin = (0., 0., 0.) plot1.width = (pitch, pitch) plot1.pixels = (300, 300) plot1.color_by = 'material' plot1.filename = 'test' - plot2 = openmc.Plot(plot_id=2) + plot2 = openmc.SlicePlot(plot_id=2) plot2.origin = (0., 0., 0.) plot2.width = (pitch, pitch) plot2.pixels = (300, 300) @@ -911,7 +911,7 @@ def test_setter_from_list(): model = openmc.Model(tallies=[tally]) assert isinstance(model.tallies, openmc.Tallies) - plot = openmc.Plot() + plot = openmc.SlicePlot() model = openmc.Model(plots=[plot]) assert isinstance(model.plots, openmc.Plots) diff --git a/tests/unit_tests/test_plots.py b/tests/unit_tests/test_plots.py index fad574ee69..98a93e44b5 100644 --- a/tests/unit_tests/test_plots.py +++ b/tests/unit_tests/test_plots.py @@ -9,12 +9,11 @@ from openmc.plots import _SVG_COLORS @pytest.fixture(scope='module') def myplot(): - plot = openmc.Plot(name='myplot') + plot = openmc.SlicePlot(name='myplot') plot.width = (100., 100.) plot.origin = (2., 3., -10.) plot.pixels = (500, 500) plot.filename = './not-a-dir/myplot' - plot.type = 'slice' plot.basis = 'yz' plot.background = 'black' plot.background = (0, 0, 0) @@ -80,8 +79,7 @@ def test_voxel_plot(run_in_tmpdir): geometry.export_to_xml() materials = openmc.Materials() materials.export_to_xml() - vox_plot = openmc.Plot() - vox_plot.type = 'voxel' + vox_plot = openmc.VoxelPlot() vox_plot.id = 12 vox_plot.width = (1500., 1500., 1500.) vox_plot.pixels = (200, 200, 200) @@ -97,8 +95,9 @@ def test_voxel_plot(run_in_tmpdir): assert Path('h5_voxel_plot.h5').is_file() assert Path('another_test_voxel_plot.vti').is_file() - slice_plot = openmc.Plot() - with pytest.raises(ValueError): + # SlicePlot should not have to_vtk method + slice_plot = openmc.SlicePlot() + with pytest.raises(AttributeError): slice_plot.to_vtk('shimmy.vti') @@ -153,14 +152,14 @@ def test_from_geometry(): geom = openmc.Geometry(univ) for basis in ('xy', 'yz', 'xz'): - plot = openmc.Plot.from_geometry(geom, basis) + plot = openmc.SlicePlot.from_geometry(geom, basis) assert plot.origin == pytest.approx((0., 0., 0.)) assert plot.width == pytest.approx((width, width)) assert plot.basis == basis def test_highlight_domains(): - plot = openmc.Plot() + plot = openmc.SlicePlot() plot.color_by = 'material' plots = openmc.Plots([plot]) @@ -179,8 +178,8 @@ def test_xml_element(myplot): assert elem.find('pixels') is not None assert elem.find('background').text == '0 0 0' - newplot = openmc.Plot.from_xml_element(elem) - attributes = ('id', 'color_by', 'filename', 'type', 'basis', 'level', + newplot = openmc.SlicePlot.from_xml_element(elem) + attributes = ('id', 'color_by', 'filename', 'basis', 'level', 'meshlines', 'show_overlaps', 'origin', 'width', 'pixels', 'background', 'mask_background') for attr in attributes: @@ -200,11 +199,11 @@ def test_to_xml_element_proj(myprojectionplot): def test_plots(run_in_tmpdir): - p1 = openmc.Plot(name='plot1') + p1 = openmc.SlicePlot(name='plot1') p1.origin = (5., 5., 5.) p1.colors = {10: (255, 100, 0)} p1.mask_components = [2, 4, 6] - p2 = openmc.Plot(name='plot2') + p2 = openmc.SlicePlot(name='plot2') p2.origin = (-3., -3., -3.) plots = openmc.Plots([p1, p2]) assert len(plots) == 2 @@ -213,7 +212,7 @@ def test_plots(run_in_tmpdir): plots = openmc.Plots([p1, p2, p3]) assert len(plots) == 3 - p4 = openmc.Plot(name='plot4') + p4 = openmc.VoxelPlot(name='plot4') plots.append(p4) assert len(plots) == 4 @@ -230,8 +229,7 @@ def test_plots(run_in_tmpdir): def test_voxel_plot_roundtrip(): # Define a voxel plot and create XML element - plot = openmc.Plot(name='my voxel plot') - plot.type = 'voxel' + plot = openmc.VoxelPlot(name='my voxel plot') plot.filename = 'voxel1' plot.pixels = (50, 50, 50) plot.origin = (0., 0., 0.) @@ -243,7 +241,6 @@ def test_voxel_plot_roundtrip(): new_plot = plot.from_xml_element(elem) assert new_plot.name == plot.name assert new_plot.filename == plot.filename - assert new_plot.type == plot.type assert new_plot.pixels == plot.pixels assert new_plot.origin == plot.origin assert new_plot.width == plot.width @@ -288,10 +285,9 @@ def test_phong_plot_roundtrip(): def test_plot_directory(run_in_tmpdir): pwr_pin = openmc.examples.pwr_pin_cell() - # create a standard plot, expected to work - plot = openmc.Plot() + # create a standard slice plot, expected to work + plot = openmc.SlicePlot() plot.filename = 'plot_1' - plot.type = 'slice' plot.pixels = (10, 10) plot.color_by = 'material' plot.width = (100., 100.) diff --git a/tests/unit_tests/test_slice_voxel_plots.py b/tests/unit_tests/test_slice_voxel_plots.py new file mode 100644 index 0000000000..48ca31b7a9 --- /dev/null +++ b/tests/unit_tests/test_slice_voxel_plots.py @@ -0,0 +1,273 @@ +"""Tests for SlicePlot and VoxelPlot classes + +This module tests the functionality of the new SlicePlot and VoxelPlot +classes that replace the legacy Plot class. +""" +import warnings + +import pytest +import openmc + + +def test_slice_plot_initialization(): + """Test SlicePlot initialization with defaults""" + plot = openmc.SlicePlot() + assert plot.width == [4.0, 4.0] + assert plot.pixels == [400, 400] + assert plot.basis == 'xy' + assert plot.origin == [0., 0., 0.] + + +def test_slice_plot_width_validation(): + """Test that SlicePlot only accepts 2 values for width""" + plot = openmc.SlicePlot() + + # Should accept 2 values + plot.width = [10.0, 20.0] + assert plot.width == [10.0, 20.0] + + # Should reject 1 value + with pytest.raises(ValueError, match='must be of length "2"'): + plot.width = [10.0] + + # Should reject 3 values + with pytest.raises(ValueError, match='must be of length "2"'): + plot.width = [10.0, 20.0, 30.0] + + +def test_slice_plot_pixels_validation(): + """Test that SlicePlot only accepts 2 values for pixels""" + plot = openmc.SlicePlot() + + # Should accept 2 values + plot.pixels = [100, 200] + assert plot.pixels == [100, 200] + + # Should reject 1 value + with pytest.raises(ValueError, match='must be of length "2"'): + plot.pixels = [100] + + # Should reject 3 values + with pytest.raises(ValueError, match='must be of length "2"'): + plot.pixels = [100, 200, 300] + + +def test_slice_plot_basis(): + """Test that SlicePlot has basis attribute""" + plot = openmc.SlicePlot() + + # Test all valid basis values + for basis in ['xy', 'xz', 'yz']: + plot.basis = basis + assert plot.basis == basis + + # Test invalid basis + with pytest.raises(ValueError): + plot.basis = 'invalid' + + +def test_slice_plot_meshlines(): + """Test that SlicePlot has meshlines attribute""" + plot = openmc.SlicePlot() + + meshlines = { + 'type': 'tally', + 'id': 1, + 'linewidth': 2, + 'color': (255, 0, 0) + } + plot.meshlines = meshlines + assert plot.meshlines == meshlines + + +def test_slice_plot_xml_roundtrip(): + """Test SlicePlot XML serialization and deserialization""" + plot = openmc.SlicePlot(name='test_slice') + plot.width = [15.0, 25.0] + plot.pixels = [150, 250] + plot.basis = 'xz' + plot.origin = [1.0, 2.0, 3.0] + plot.color_by = 'material' + plot.filename = 'test_plot' + + # Convert to XML and back + elem = plot.to_xml_element() + new_plot = openmc.SlicePlot.from_xml_element(elem) + + # Check all attributes preserved + assert new_plot.name == plot.name + assert new_plot.width == pytest.approx(plot.width) + assert new_plot.pixels == tuple(plot.pixels) + assert new_plot.basis == plot.basis + assert new_plot.origin == pytest.approx(plot.origin) + assert new_plot.color_by == plot.color_by + assert new_plot.filename == plot.filename + + +def test_slice_plot_from_geometry(): + """Test creating SlicePlot from geometry""" + # Create simple geometry + s = openmc.Sphere(r=10.0, boundary_type='vacuum') + c = openmc.Cell(region=-s) + univ = openmc.Universe(cells=[c]) + geom = openmc.Geometry(univ) + + # Test all basis options + for basis in ['xy', 'xz', 'yz']: + plot = openmc.SlicePlot.from_geometry(geom, basis=basis) + assert plot.basis == basis + assert plot.width == pytest.approx([20.0, 20.0]) + assert plot.origin == pytest.approx([0.0, 0.0, 0.0]) + + +def test_voxel_plot_initialization(): + """Test VoxelPlot initialization with defaults""" + plot = openmc.VoxelPlot() + assert plot.width == [4.0, 4.0, 4.0] + assert plot.pixels == [400, 400, 400] + assert plot.origin == [0., 0., 0.] + + +def test_voxel_plot_width_validation(): + """Test that VoxelPlot only accepts 3 values for width""" + plot = openmc.VoxelPlot() + + # Should accept 3 values + plot.width = [10.0, 20.0, 30.0] + assert plot.width == [10.0, 20.0, 30.0] + + # Should reject 2 values + with pytest.raises(ValueError, match='must be of length "3"'): + plot.width = [10.0, 20.0] + + # Should reject 1 value + with pytest.raises(ValueError, match='must be of length "3"'): + plot.width = [10.0] + + +def test_voxel_plot_pixels_validation(): + """Test that VoxelPlot only accepts 3 values for pixels""" + plot = openmc.VoxelPlot() + + # Should accept 3 values + plot.pixels = [100, 200, 300] + assert plot.pixels == [100, 200, 300] + + # Should reject 2 values + with pytest.raises(ValueError, match='must be of length "3"'): + plot.pixels = [100, 200] + + # Should reject 1 value + with pytest.raises(ValueError, match='must be of length "3"'): + plot.pixels = [100] + + +def test_voxel_plot_xml_roundtrip(): + """Test VoxelPlot XML serialization and deserialization""" + plot = openmc.VoxelPlot(name='test_voxel') + plot.width = [10.0, 20.0, 30.0] + plot.pixels = [100, 200, 300] + plot.origin = [1.0, 2.0, 3.0] + plot.color_by = 'cell' + plot.filename = 'voxel_plot' + + # Convert to XML and back + elem = plot.to_xml_element() + new_plot = openmc.VoxelPlot.from_xml_element(elem) + + # Check all attributes preserved + assert new_plot.name == plot.name + assert new_plot.width == pytest.approx(plot.width) + assert new_plot.pixels == tuple(plot.pixels) + assert new_plot.origin == pytest.approx(plot.origin) + assert new_plot.color_by == plot.color_by + assert new_plot.filename == plot.filename + + +def test_plot_deprecation_warning(): + """Test that Plot class raises deprecation warning""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + openmc.Plot() + + assert len(w) == 1 + assert issubclass(w[0].category, FutureWarning) + assert "deprecated" in str(w[0].message).lower() + + +def test_plot_returns_slice_plot(): + """Test that Plot() returns a SlicePlot instance""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + plot = openmc.Plot() + + # Should be an actual SlicePlot instance + assert isinstance(plot, openmc.SlicePlot) + + +def test_plot_type_setter_raises_error(): + """Test that setting plot.type raises a helpful error""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + plot = openmc.Plot() + + with pytest.raises(TypeError, match="no longer supported"): + plot.type = 'voxel' + + with pytest.raises(TypeError, match="no longer supported"): + plot.type = 'slice' + + +def test_plot_type_getter_warns(): + """Test that getting plot.type raises a deprecation warning""" + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + plot = openmc.Plot() + + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + plot_type = plot.type + + assert plot_type == 'slice' + assert len(w) == 1 + assert issubclass(w[0].category, FutureWarning) + assert "deprecated" in str(w[0].message).lower() + + +def test_plots_collection_mixed_types(): + """Test Plots collection with different plot types""" + slice_plot = openmc.SlicePlot(name='slice') + voxel_plot = openmc.VoxelPlot(name='voxel') + wireframe_plot = openmc.WireframeRayTracePlot(name='wireframe') + + plots = openmc.Plots([slice_plot, voxel_plot, wireframe_plot]) + + assert len(plots) == 3 + assert isinstance(plots[0], openmc.SlicePlot) + assert isinstance(plots[1], openmc.VoxelPlot) + assert isinstance(plots[2], openmc.WireframeRayTracePlot) + + +def test_plots_collection_xml_roundtrip(run_in_tmpdir): + """Test XML export and import with new plot types""" + s1 = openmc.SlicePlot(name='slice1') + s1.width = [10.0, 20.0] + s1.basis = 'xz' + + v1 = openmc.VoxelPlot(name='voxel1') + v1.width = [10.0, 20.0, 30.0] + + plots = openmc.Plots([s1, v1]) + plots.export_to_xml() + + # Read back + new_plots = openmc.Plots.from_xml() + + assert len(new_plots) == 2 + assert isinstance(new_plots[0], openmc.SlicePlot) + assert isinstance(new_plots[1], openmc.VoxelPlot) + assert new_plots[0].name == 'slice1' + assert new_plots[1].name == 'voxel1' + assert new_plots[0].basis == 'xz' + assert new_plots[0].width == pytest.approx([10.0, 20.0]) + assert new_plots[1].width == pytest.approx([10.0, 20.0, 30.0]) From f70febb05f5fc32925d08707db48ff2c33dfe493 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 6 Dec 2025 15:54:30 -0600 Subject: [PATCH 66/76] Update CITATION.cff file (#3671) --- CITATION.cff | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index 19b4213a15..ab27d89b83 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,9 +1,43 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +title: OpenMC +authors: +- family-names: Romano + given-names: Paul K. + orcid: "https://orcid.org/0000-0002-1147-045X" +- family-names: Shriwise + given-names: Patrick C. + orcid: "https://orcid.org/0000-0002-3979-7665" +- family-names: Shimwell + given-names: Jonathan + orcid: "https://orcid.org/0000-0001-6909-0946" +- family-names: Harper + given-names: Sterling +- family-names: Boyd + given-names: Will +- family-names: Nelson + given-names: Adam G. + orcid: "https://orcid.org/0000-0002-3614-0676" +- family-names: Tramm + given-names: John R. + orcid: "https://orcid.org/0000-0002-5397-4402" +- family-names: Ridley + given-names: Gavin + orcid: "https://orcid.org/0000-0003-1635-8042" +- family-names: Johnson + given-names: Andrew + orcid: "https://orcid.org/0000-0003-2125-8775" +- family-names: Peterson + given-names: Ethan E. + orcid: "https://orcid.org/0000-0002-5694-7194" +- family-names: Herman + given-names: Bryan R. preferred-citation: authors: - family-names: Romano given-names: Paul K. orcid: "https://orcid.org/0000-0002-1147-045X" - - final-names: Horelik + - family-names: Horelik given-names: Nicholas E. - family-names: Herman given-names: Bryan R. From 9b40ea008efb4ca48e51b5ab4569fb09c42c4380 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Mon, 8 Dec 2025 13:39:48 +0200 Subject: [PATCH 67/76] Read IFP settings only in source/eigenvalue run mode (#3673) --- src/settings.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/settings.cpp b/src/settings.cpp index 9dcf7c8dbc..d47e9b5e6b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -545,6 +545,20 @@ void read_settings_xml(pugi::xml_node root) } else if (rel_max_lost_particles <= 0.0 || rel_max_lost_particles >= 1.0) { fatal_error("Relative max lost particles must be between zero and one."); } + + // Check for user value for the number of generation of the Iterated Fission + // Probability (IFP) method + if (check_for_node(root, "ifp_n_generation")) { + ifp_n_generation = std::stoi(get_node_value(root, "ifp_n_generation")); + if (ifp_n_generation <= 0) { + fatal_error("'ifp_n_generation' must be greater than 0."); + } + // Avoid tallying 0 if IFP logs are not complete when active cycles start + if (ifp_n_generation > n_inactive) { + fatal_error("'ifp_n_generation' must be lower than or equal to the " + "number of inactive cycles."); + } + } } // Copy plotting random number seed if specified @@ -1130,20 +1144,6 @@ void read_settings_xml(pugi::xml_node root) temperature_range[1] = range.at(1); } - // Check for user value for the number of generation of the Iterated Fission - // Probability (IFP) method - if (check_for_node(root, "ifp_n_generation")) { - ifp_n_generation = std::stoi(get_node_value(root, "ifp_n_generation")); - if (ifp_n_generation <= 0) { - fatal_error("'ifp_n_generation' must be greater than 0."); - } - // Avoid tallying 0 if IFP logs are not complete when active cycles start - if (ifp_n_generation > n_inactive) { - fatal_error("'ifp_n_generation' must be lower than or equal to the " - "number of inactive cycles."); - } - } - // Check for tabular_legendre options if (check_for_node(root, "tabular_legendre")) { // Get pointer to tabular_legendre node From 8e06ed89986394ad46e6dccf7afc5157b6c9b870 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Dec 2025 16:54:37 +0100 Subject: [PATCH 68/76] Allowing model.id_map to return overlap ID values (#3669) Co-authored-by: Paul Romano --- openmc/lib/plot.py | 12 +++--------- openmc/model/model.py | 6 ++++++ tests/unit_tests/test_model.py | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/openmc/lib/plot.py b/openmc/lib/plot.py index f97348b20b..68f61821c5 100644 --- a/openmc/lib/plot.py +++ b/openmc/lib/plot.py @@ -52,7 +52,7 @@ class _PlotBase(Structure): C-Type Attributes ----------------- - origin : openmc.lib.plot._Position + origin_ : openmc.lib.plot._Position A position defining the origin of the plot. width_ : openmc.lib.plot._Position The width of the plot along the x, y, and z axes, respectively @@ -60,6 +60,8 @@ class _PlotBase(Structure): The axes basis of the plot view. pixels_ : c_size_t[3] The resolution of the plot in the horizontal and vertical dimensions + color_overlaps_ : c_bool + Whether to assign unique IDs (-3) to overlapping regions. level_ : c_int The universe level for the plot view @@ -187,14 +189,6 @@ class _PlotBase(Structure): def color_overlaps(self, color_overlaps): self.color_overlaps_ = color_overlaps - @property - def color_overlaps(self): - return self.color_overlaps_ - - @color_overlaps.setter - def color_overlaps(self, val): - self.color_overlaps_ = val - def __repr__(self): out_str = ["-----", "Plot:", diff --git a/openmc/model/model.py b/openmc/model/model.py index e2ac57eba4..a9aaa481d5 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -1037,6 +1037,7 @@ class Model: width: Sequence[float] | None = None, pixels: int | Sequence[int] = 40000, basis: str = 'xy', + color_overlaps: bool = False, **init_kwargs ) -> np.ndarray: """Generate an ID map for domains based on the plot parameters @@ -1065,6 +1066,10 @@ class Model: total and the image aspect ratio based on the width argument. basis : {'xy', 'yz', 'xz'}, optional Basis of the plot. + color_overlaps : bool, optional + Whether to assign unique IDs (-3) to overlapping regions. If False, + overlapping regions will be assigned the ID of the lowest-numbered + cell that occupies that region. Defaults to False. **init_kwargs Keyword arguments passed to :meth:`Model.init_lib`. @@ -1089,6 +1094,7 @@ class Model: plot_obj.h_res = pixels[0] plot_obj.v_res = pixels[1] plot_obj.basis = basis + plot_obj.color_overlaps = color_overlaps # Silence output by default. Also set arguments to start in volume # calculation mode to avoid loading cross sections diff --git a/tests/unit_tests/test_model.py b/tests/unit_tests/test_model.py index 9b28ff1c4d..d553af53c7 100644 --- a/tests/unit_tests/test_model.py +++ b/tests/unit_tests/test_model.py @@ -902,6 +902,32 @@ def test_id_map_aligned_model(): assert tr_material == 5, f"Expected material ID 5 at top-right corner, got {tr_material}" +def test_id_map_model_with_overlaps(): + """Test id_map with a model that has overlaps and color_overlaps option""" + surface1 = openmc.Sphere(r=50, boundary_type="vacuum") + surface2 = openmc.Sphere(r=30) + cell1 = openmc.Cell(region=-surface1) + cell2 = openmc.Cell(region=-surface2) + geometry = openmc.Geometry([cell1, cell2]) + settings = openmc.Settings() + model = openmc.Model(geometry=geometry, settings=settings) + id_slice = model.id_map( + pixels=(10, 10), + basis='xy', + origin=(0, 0, 0), + width=(100, 100), + ) + assert -3 not in id_slice # -3 indicates overlap region + id_slice = model.id_map( + pixels=(10, 10), + basis='xy', + origin=(0, 0, 0), + width=(100, 100), + color_overlaps=True, # enables id_map to return -3 for overlaps + ) + assert -3 in id_slice + + def test_setter_from_list(): mat = openmc.Material() model = openmc.Model(materials=[mat]) From a9dc84f75a8de4499c5bb04bede0f7a65eb844c5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Dec 2025 20:43:30 +0100 Subject: [PATCH 69/76] Allowing material making from class constructor (#3649) Co-authored-by: Jon Shimwell Co-authored-by: Paul Romano --- openmc/material.py | 48 ++++++++++++++++++++++++++--- tests/unit_tests/test_material.py | 51 +++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 1609da05a3..735a057432 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -60,6 +60,26 @@ class Material(IDManagerMixin): temperature : float, optional Temperature of the material in Kelvin. If not specified, the material inherits the default temperature applied to the model. + density : float, optional + Density of the material (units defined separately) + density_units : str + Units used for `density`. Can be one of 'g/cm3', 'g/cc', 'kg/m3', + 'atom/b-cm', 'atom/cm3', 'sum', or 'macro'. The 'macro' unit only + applies in the case of a multi-group calculation. Defaults to 'sum'. + depletable : bool, optional + Indicate whether the material is depletable. Defaults to False. + volume : float, optional + Volume of the material in cm^3. This can either be set manually or + calculated in a stochastic volume calculation and added via the + :meth:`Material.add_volume_information` method. + components : dict of str to float or dict + Dictionary mapping element or nuclide names to their atom or weight + percent. To specify enrichment of an element, the entry of + ``components`` for that element must instead be a dictionary containing + the keyword arguments as well as a value for ``'percent'`` + percent_type : {'ao', 'wo'} + Whether the values in `components` should be interpreted as atom percent + ('ao') or weight percent ('wo'). Attributes ---------- @@ -111,17 +131,28 @@ class Material(IDManagerMixin): next_id = 1 used_ids = set() - def __init__(self, material_id=None, name='', temperature=None): + def __init__( + self, + material_id: int | None = None, + name: str = "", + temperature: float | None = None, + density: float | None = None, + density_units: str = "sum", + depletable: bool | None = False, + volume: float | None = None, + components: dict | None = None, + percent_type: str = "ao", + ): # Initialize class attributes self.id = material_id self.name = name self.temperature = temperature self._density = None - self._density_units = 'sum' - self._depletable = False + self._density_units = density_units + self._depletable = depletable self._paths = None self._num_instances = None - self._volume = None + self._volume = volume self._atoms = {} self._isotropic = [] self._ncrystal_cfg = None @@ -136,6 +167,15 @@ class Material(IDManagerMixin): # If specified, a list of table names self._sab = [] + # Set density if provided + if density is not None: + self.set_density(density_units, density) + + # Add components if provided + if components is not None: + self.add_components(components, percent_type=percent_type) + + def __repr__(self) -> str: string = 'Material\n' string += '{: <16}=\t{}\n'.format('\tID', self._id) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index ce58339d7c..764c98d41a 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -768,3 +768,54 @@ def test_mean_free_path(): mat2.add_nuclide('Pb208', 1.0) mat2.set_density('g/cm3', 11.34) assert mat2.mean_free_path(energy=14e6) == pytest.approx(5.65, abs=1e-2) + + +def test_material_from_constructor(): + # Test that components and percent_type work in the constructor + components = { + 'Li': {'percent': 0.5, 'enrichment': 60.0, 'enrichment_target': 'Li7'}, + 'O16': 1.0, + 'Be': 0.5 + } + mat = openmc.Material( + material_id=123, + name="test-mat", + components=components, + percent_type="ao" + ) + # Check that nuclides were added + nuclide_names = [nuc.name for nuc in mat.nuclides] + assert 'O16' in nuclide_names + assert 'Be9' in nuclide_names + assert 'Li7' in nuclide_names + assert 'Li6' in nuclide_names + assert mat.id == 123 + assert mat.name == "test-mat" + + mat1 = openmc.Material( + **{ + "material_id": 1, + "name": "neutron_star", + "density": 1e17, + "density_units": "kg/m3", + } + ) + assert mat1.id == 1 + assert mat1.name == "neutron_star" + assert mat1._density == 1e17 + assert mat1._density_units == "kg/m3" + assert mat1.nuclides == [] + + mat2 = openmc.Material( + material_id=42, + name="plasma", + temperature=None, + density=1e-7, + density_units="g/cm3", + ) + assert mat2.id == 42 + assert mat2.name == "plasma" + assert mat2.temperature is None + assert mat2.density == 1e-7 + assert mat2.density_units == "g/cm3" + assert mat2.nuclides == [] From bc1348579f30281d1a84961389d87558d64cbaf6 Mon Sep 17 00:00:00 2001 From: Lewis Gross <43077972+lewisgross1296@users.noreply.github.com> Date: Wed, 10 Dec 2025 04:16:04 -0600 Subject: [PATCH 70/76] Generalize RotationalPeriodicBC for X-, Y-, or Z-axis (#3591) Co-authored-by: GuySten <62616591+GuySten@users.noreply.github.com> --- docs/source/io_formats/geometry.rst | 8 +- docs/source/usersguide/geometry.rst | 2 +- include/openmc/boundary_condition.h | 14 ++- openmc/surface.py | 14 +-- src/boundary_condition.cpp | 114 +++++++++--------- src/surface.cpp | 40 +++++- .../periodic_cyls/__init__.py | 0 tests/regression_tests/periodic_cyls/test.py | 91 ++++++++++++++ .../periodic_cyls/xcyl_model/inputs_true.dat | 29 +++++ .../periodic_cyls/xcyl_model/results_true.dat | 2 + .../periodic_cyls/ycyl_model/inputs_true.dat | 29 +++++ .../periodic_cyls/ycyl_model/results_true.dat | 2 + 12 files changed, 265 insertions(+), 80 deletions(-) create mode 100644 tests/regression_tests/periodic_cyls/__init__.py create mode 100644 tests/regression_tests/periodic_cyls/test.py create mode 100644 tests/regression_tests/periodic_cyls/xcyl_model/inputs_true.dat create mode 100644 tests/regression_tests/periodic_cyls/xcyl_model/results_true.dat create mode 100644 tests/regression_tests/periodic_cyls/ycyl_model/inputs_true.dat create mode 100644 tests/regression_tests/periodic_cyls/ycyl_model/results_true.dat diff --git a/docs/source/io_formats/geometry.rst b/docs/source/io_formats/geometry.rst index 6d0a37a24f..dda1efa9ae 100644 --- a/docs/source/io_formats/geometry.rst +++ b/docs/source/io_formats/geometry.rst @@ -38,11 +38,9 @@ Each ```` element can have the following attributes or sub-elements: :boundary: The boundary condition for the surface. This can be "transmission", - "vacuum", "reflective", or "periodic". Periodic boundary conditions can - only be applied to x-, y-, and z-planes. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. Specify which - planes are periodic and the code will automatically identify which planes - are paired together. + "vacuum", "reflective", or "periodic". Specify which planes are + periodic and the code will automatically identify which planes are + paired together. *Default*: "transmission" diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 6f14ebfa51..8c68e48516 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -192,7 +192,7 @@ Otherwise it is necessary to specify pairs explicitly using the Both rotational and translational periodic boundary conditions are specified in the same fashion. If both planes have the same normal vector, a translational periodicity is assumed; rotational periodicity is assumed otherwise. Currently, -only rotations about the :math:`z`-axis are supported. +rotations must be about the :math:`x`-, :math:`y`-, or :math:`z`-axis. For a rotational periodic BC, the normal vectors of each surface must point inwards---towards the valid geometry. For example, a :class:`XPlane` and diff --git a/include/openmc/boundary_condition.h b/include/openmc/boundary_condition.h index af40131f1c..5a14239e8b 100644 --- a/include/openmc/boundary_condition.h +++ b/include/openmc/boundary_condition.h @@ -138,18 +138,26 @@ protected: //============================================================================== //! A BC that rotates particles about a global axis. // -//! Currently only rotations about the z-axis are supported. +//! Only rotations about the x, y, and z axes are supported. //============================================================================== class RotationalPeriodicBC : public PeriodicBC { public: - RotationalPeriodicBC(int i_surf, int j_surf); - + enum PeriodicAxis { x, y, z }; + RotationalPeriodicBC(int i_surf, int j_surf, PeriodicAxis axis); + double compute_periodic_rotation( + double rise_1, double run_1, double rise_2, double run_2) const; void handle_particle(Particle& p, const Surface& surf) const override; protected: //! Angle about the axis by which particle coordinates will be rotated double angle_; + //! Ensure that choice of axes is right handed. axis_1_idx_ corresponds to the + //! independent axis and axis_2_idx_ corresponds to the dependent axis in the + //! 2D plane perpendicular to the planes' axis of rotation + int zero_axis_idx_; + int axis_1_idx_; + int axis_2_idx_; }; } // namespace openmc diff --git a/openmc/surface.py b/openmc/surface.py index 4839783ffa..1fe5fabdf7 100644 --- a/openmc/surface.py +++ b/openmc/surface.py @@ -123,9 +123,8 @@ class Surface(IDManagerMixin, ABC): boundary_type : {'transmission', 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Note that periodic boundary conditions - can only be applied to x-, y-, and z-planes, and only axis-aligned - periodicity is supported. + freely pass through the surface. Note that only axis-aligned + periodicity is supported around the x-, y-, and z-axes. albedo : float, optional Albedo of the surfaces as a ratio of particle weight after interaction with the surface to the initial weight. Values must be positive. Only @@ -822,8 +821,7 @@ class XPlane(PlaneMixin, Surface): boundary_type : {'transmission', 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., x-planes can only be paired with x-planes. + freely pass through the surface. albedo : float, optional Albedo of the surfaces as a ratio of particle weight after interaction with the surface to the initial weight. Values must be positive. Only @@ -887,8 +885,7 @@ class YPlane(PlaneMixin, Surface): boundary_type : {'transmission', 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., y-planes can only be paired with y-planes. + freely pass through the surface. albedo : float, optional Albedo of the surfaces as a ratio of particle weight after interaction with the surface to the initial weight. Values must be positive. Only @@ -952,8 +949,7 @@ class ZPlane(PlaneMixin, Surface): boundary_type : {'transmission', 'vacuum', 'reflective', 'periodic', 'white'}, optional Boundary condition that defines the behavior for particles hitting the surface. Defaults to transmissive boundary condition where particles - freely pass through the surface. Only axis-aligned periodicity is - supported, i.e., z-planes can only be paired with z-planes. + freely pass through the surface. albedo : float, optional Albedo of the surfaces as a ratio of particle weight after interaction with the surface to the initial weight. Values must be positive. Only diff --git a/src/boundary_condition.cpp b/src/boundary_condition.cpp index 7216ac8964..2840b3c7d5 100644 --- a/src/boundary_condition.cpp +++ b/src/boundary_condition.cpp @@ -158,63 +158,44 @@ void TranslationalPeriodicBC::handle_particle( // RotationalPeriodicBC implementation //============================================================================== -RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf) +RotationalPeriodicBC::RotationalPeriodicBC( + int i_surf, int j_surf, PeriodicAxis axis) : PeriodicBC(i_surf, j_surf) { Surface& surf1 {*model::surfaces[i_surf_]}; Surface& surf2 {*model::surfaces[j_surf_]}; - // Check the type of the first surface - bool surf1_is_xyplane; - if (const auto* ptr = dynamic_cast(&surf1)) { - surf1_is_xyplane = true; - } else if (const auto* ptr = dynamic_cast(&surf1)) { - surf1_is_xyplane = true; - } else if (const auto* ptr = dynamic_cast(&surf1)) { - surf1_is_xyplane = false; - } else { - throw std::invalid_argument(fmt::format( - "Surface {} is an invalid type for " - "rotational periodic BCs. Only x-planes, y-planes, or general planes " - "(that are perpendicular to z) are supported for these BCs.", - surf1.id_)); - } - - // Check the type of the second surface - bool surf2_is_xyplane; - if (const auto* ptr = dynamic_cast(&surf2)) { - surf2_is_xyplane = true; - } else if (const auto* ptr = dynamic_cast(&surf2)) { - surf2_is_xyplane = true; - } else if (const auto* ptr = dynamic_cast(&surf2)) { - surf2_is_xyplane = false; - } else { - throw std::invalid_argument(fmt::format( - "Surface {} is an invalid type for " - "rotational periodic BCs. Only x-planes, y-planes, or general planes " - "(that are perpendicular to z) are supported for these BCs.", - surf2.id_)); + // below convention for right handed coordinate system + switch (axis) { + case x: + zero_axis_idx_ = 0; // x component of plane must be zero + axis_1_idx_ = 1; // y component independent + axis_2_idx_ = 2; // z component dependent + break; + case y: + // for a right handed coordinate system, z should be the independent axis + // but this would cause the y-rotation case to be different than the other + // two. using a left handed coordinate system and a negative rotation the + // compute angle and rotation matrix behavior mimics that of the x and z + // cases + zero_axis_idx_ = 1; // y component of plane must be zero + axis_1_idx_ = 0; // x component independent + axis_2_idx_ = 2; // z component dependent + break; + case z: + zero_axis_idx_ = 2; // z component of plane must be zero + axis_1_idx_ = 0; // x component independent + axis_2_idx_ = 1; // y component dependent + break; + default: + throw std::invalid_argument( + fmt::format("You've specified an axis that is not x, y, or z.")); } // Compute the surface normal vectors and make sure they are perpendicular - // to the z-axis + // to the correct axis Direction norm1 = surf1.normal({0, 0, 0}); Direction norm2 = surf2.normal({0, 0, 0}); - if (std::abs(norm1.z) > FP_PRECISION) { - throw std::invalid_argument(fmt::format( - "Rotational periodic BCs are only " - "supported for rotations about the z-axis, but surface {} is not " - "perpendicular to the z-axis.", - surf1.id_)); - } - if (std::abs(norm2.z) > FP_PRECISION) { - throw std::invalid_argument(fmt::format( - "Rotational periodic BCs are only " - "supported for rotations about the z-axis, but surface {} is not " - "perpendicular to the z-axis.", - surf2.id_)); - } - // Make sure both surfaces intersect the origin if (std::abs(surf1.evaluate({0, 0, 0})) > FP_COINCIDENT) { throw std::invalid_argument(fmt::format( @@ -231,15 +212,8 @@ RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf) surf2.id_)); } - // Compute the BC rotation angle. Here it is assumed that both surface - // normal vectors point inwards---towards the valid geometry region. - // Consequently, the rotation angle is not the difference between the two - // normals, but is instead the difference between one normal and one - // anti-normal. (An incident ray on one surface must be an outgoing ray on - // the other surface after rotation hence the anti-normal.) - double theta1 = std::atan2(norm1.y, norm1.x); - double theta2 = std::atan2(norm2.y, norm2.x) + PI; - angle_ = theta2 - theta1; + angle_ = compute_periodic_rotation(norm1[axis_2_idx_], norm1[axis_1_idx_], + norm2[axis_2_idx_], norm2[axis_1_idx_]); // Warn the user if the angle does not evenly divide a circle double rem = std::abs(std::remainder((2 * PI / angle_), 1.0)); @@ -251,6 +225,20 @@ RotationalPeriodicBC::RotationalPeriodicBC(int i_surf, int j_surf) } } +double RotationalPeriodicBC::compute_periodic_rotation( + double rise_1, double run_1, double rise_2, double run_2) const +{ + // Compute the BC rotation angle. Here it is assumed that both surface + // normal vectors point inwards---towards the valid geometry region. + // Consequently, the rotation angle is not the difference between the two + // normals, but is instead the difference between one normal and one + // anti-normal. (An incident ray on one surface must be an outgoing ray on + // the other surface after rotation hence the anti-normal.) + double theta1 = std::atan2(rise_1, run_1); + double theta2 = std::atan2(rise_2, run_2) + PI; + return theta2 - theta1; +} + void RotationalPeriodicBC::handle_particle( Particle& p, const Surface& surf) const { @@ -278,10 +266,16 @@ void RotationalPeriodicBC::handle_particle( Direction u = p.u(); double cos_theta = std::cos(theta); double sin_theta = std::sin(theta); - Position new_r = { - cos_theta * r.x - sin_theta * r.y, sin_theta * r.x + cos_theta * r.y, r.z}; - Direction new_u = { - cos_theta * u.x - sin_theta * u.y, sin_theta * u.x + cos_theta * u.y, u.z}; + + Position new_r; + new_r[zero_axis_idx_] = r[zero_axis_idx_]; + new_r[axis_1_idx_] = cos_theta * r[axis_1_idx_] - sin_theta * r[axis_2_idx_]; + new_r[axis_2_idx_] = sin_theta * r[axis_1_idx_] + cos_theta * r[axis_2_idx_]; + + Direction new_u; + new_u[zero_axis_idx_] = u[zero_axis_idx_]; + new_u[axis_1_idx_] = cos_theta * u[axis_1_idx_] - sin_theta * u[axis_2_idx_]; + new_u[axis_2_idx_] = sin_theta * u[axis_1_idx_] + cos_theta * u[axis_2_idx_]; // Handle the effects of the surface albedo on the particle's weight. BoundaryCondition::handle_albedo(p, surf); diff --git a/src/surface.cpp b/src/surface.cpp index ea19514a31..09fc0f24f0 100644 --- a/src/surface.cpp +++ b/src/surface.cpp @@ -1334,8 +1334,44 @@ void read_surfaces(pugi::xml_node node) surf1.bc_ = make_unique(i_surf, j_surf); surf2.bc_ = make_unique(i_surf, j_surf); } else { - surf1.bc_ = make_unique(i_surf, j_surf); - surf2.bc_ = make_unique(i_surf, j_surf); + // check that both normals have at least one 0 component + if (std::abs(norm1.x) > FP_PRECISION && + std::abs(norm1.y) > FP_PRECISION && + std::abs(norm1.z) > FP_PRECISION) { + fatal_error(fmt::format( + "The normal ({}) of the periodic surface ({}) does not contain any " + "component with a zero value. A RotationalPeriodicBC requires one " + "component which is zero for both plane normals.", + norm1, i_surf)); + } + if (std::abs(norm2.x) > FP_PRECISION && + std::abs(norm2.y) > FP_PRECISION && + std::abs(norm2.z) > FP_PRECISION) { + fatal_error(fmt::format( + "The normal ({}) of the periodic surface ({}) does not contain any " + "component with a zero value. A RotationalPeriodicBC requires one " + "component which is zero for both plane normals.", + norm2, j_surf)); + } + // find common zero component, which indicates the periodic axis + RotationalPeriodicBC::PeriodicAxis axis; + if (std::abs(norm1.x) <= FP_PRECISION && + std::abs(norm2.x) <= FP_PRECISION) { + axis = RotationalPeriodicBC::PeriodicAxis::x; + } else if (std::abs(norm1.y) <= FP_PRECISION && + std::abs(norm2.y) <= FP_PRECISION) { + axis = RotationalPeriodicBC::PeriodicAxis::y; + } else if (std::abs(norm1.z) <= FP_PRECISION && + std::abs(norm2.z) <= FP_PRECISION) { + axis = RotationalPeriodicBC::PeriodicAxis::z; + } else { + fatal_error(fmt::format( + "There is no component which is 0.0 in both normal vectors. This " + "indicates that the two planes are not periodic about the X, Y, or Z " + "axis, which is not supported.")); + } + surf1.bc_ = make_unique(i_surf, j_surf, axis); + surf2.bc_ = make_unique(i_surf, j_surf, axis); } // If albedo data is present in albedo map, set the boundary albedo. diff --git a/tests/regression_tests/periodic_cyls/__init__.py b/tests/regression_tests/periodic_cyls/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/regression_tests/periodic_cyls/test.py b/tests/regression_tests/periodic_cyls/test.py new file mode 100644 index 0000000000..a341e37994 --- /dev/null +++ b/tests/regression_tests/periodic_cyls/test.py @@ -0,0 +1,91 @@ +import openmc +import numpy as np +import pytest +from openmc.utility_funcs import change_directory +from tests.testing_harness import PyAPITestHarness + + +@pytest.fixture +def xcyl_model(): + model = openmc.Model() + # Define materials + fuel = openmc.Material() + fuel.add_nuclide('U235', 0.2) + fuel.add_nuclide('U238', 0.8) + fuel.set_density('g/cc', 19.1) + model.materials = openmc.Materials([fuel]) + + # Define geometry + # finite cylinder + x_min = openmc.XPlane(x0=0.0, boundary_type='reflective') + x_max = openmc.XPlane(x0=20.0, boundary_type='reflective') + x_cyl = openmc.XCylinder(r=20.0,boundary_type='vacuum') + # slice cylinder for periodic BC + periodic_bounding_yplane = openmc.YPlane(y0=0, boundary_type='periodic') + periodic_bounding_plane = openmc.Plane( + a=0.0, b=-np.sqrt(3) / 3, c=1, boundary_type='periodic', + ) + sixth_cyl_cell = openmc.Cell(1, fill=fuel, region = + +x_min &- x_max & -x_cyl & +periodic_bounding_yplane & +periodic_bounding_plane) + periodic_bounding_yplane.periodic_surface = periodic_bounding_plane + periodic_bounding_plane.periodic_surface = periodic_bounding_yplane + + model.geometry = openmc.Geometry([sixth_cyl_cell]) + + + # Define settings + model.settings.particles = 1000 + model.settings.batches = 4 + model.settings.inactive = 0 + model.settings.source = openmc.IndependentSource(space=openmc.stats.Box( + (0, 0, 0), (20, 20, 20)) + ) + return model + +@pytest.fixture +def ycyl_model(): + model = openmc.Model() + # Define materials + fuel = openmc.Material() + fuel.add_nuclide('U235', 0.2) + fuel.add_nuclide('U238', 0.8) + fuel.set_density('g/cc', 19.1) + model.materials = openmc.Materials([fuel]) + + # Define geometry + # finite cylinder + y_min = openmc.YPlane(y0=0.0, boundary_type='reflective') + y_max = openmc.YPlane(y0=20.0, boundary_type='reflective') + y_cyl = openmc.YCylinder(r=20.0,boundary_type='vacuum') + # slice cylinder for periodic BC + periodic_bounding_xplane = openmc.XPlane(x0=0, boundary_type='periodic') + periodic_bounding_plane = openmc.Plane( + a=-np.sqrt(3) / 3, b=0.0, c=1, boundary_type='periodic', + ) + sixth_cyl_cell = openmc.Cell(1, fill=fuel, region = + +y_min &- y_max & -y_cyl & +periodic_bounding_xplane & +periodic_bounding_plane) + periodic_bounding_xplane.periodic_surface = periodic_bounding_plane + periodic_bounding_plane.periodic_surface = periodic_bounding_xplane + model.geometry = openmc.Geometry([sixth_cyl_cell]) + + + # Define settings + model.settings.particles = 1000 + model.settings.batches = 4 + model.settings.inactive = 0 + model.settings.source = openmc.IndependentSource(space=openmc.stats.Box( + (0, 0, 0), (20, 20, 20)) + ) + return model + +def test_xcyl(xcyl_model): + with change_directory("xcyl_model"): + openmc.reset_auto_ids() + harness = PyAPITestHarness('statepoint.4.h5', xcyl_model) + harness.main() + +def test_ycyl(ycyl_model): + with change_directory("ycyl_model"): + openmc.reset_auto_ids() + harness = PyAPITestHarness('statepoint.4.h5', ycyl_model) + harness.main() \ No newline at end of file diff --git a/tests/regression_tests/periodic_cyls/xcyl_model/inputs_true.dat b/tests/regression_tests/periodic_cyls/xcyl_model/inputs_true.dat new file mode 100644 index 0000000000..7d1ecf426a --- /dev/null +++ b/tests/regression_tests/periodic_cyls/xcyl_model/inputs_true.dat @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 4 + 0 + + + 0 0 0 20 20 20 + + + + diff --git a/tests/regression_tests/periodic_cyls/xcyl_model/results_true.dat b/tests/regression_tests/periodic_cyls/xcyl_model/results_true.dat new file mode 100644 index 0000000000..c7e3eb6703 --- /dev/null +++ b/tests/regression_tests/periodic_cyls/xcyl_model/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.082283E+00 6.676373E-02 diff --git a/tests/regression_tests/periodic_cyls/ycyl_model/inputs_true.dat b/tests/regression_tests/periodic_cyls/ycyl_model/inputs_true.dat new file mode 100644 index 0000000000..f3ca7e0f4a --- /dev/null +++ b/tests/regression_tests/periodic_cyls/ycyl_model/inputs_true.dat @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + eigenvalue + 1000 + 4 + 0 + + + 0 0 0 20 20 20 + + + + diff --git a/tests/regression_tests/periodic_cyls/ycyl_model/results_true.dat b/tests/regression_tests/periodic_cyls/ycyl_model/results_true.dat new file mode 100644 index 0000000000..562467f2cd --- /dev/null +++ b/tests/regression_tests/periodic_cyls/ycyl_model/results_true.dat @@ -0,0 +1,2 @@ +k-combined: +1.082652E+00 3.316031E-02 From d09fbc61b5e164e9a434de85358dfe48a3f1b0b9 Mon Sep 17 00:00:00 2001 From: John Tramm Date: Wed, 10 Dec 2025 09:26:26 -0600 Subject: [PATCH 71/76] Copilot Bot File (#3651) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Paul Romano Co-authored-by: Patrick Shriwise --- AGENTS.md | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..32e30213ae --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,280 @@ +# OpenMC AI Coding Agent Instructions + +## Project Overview + +OpenMC is a Monte Carlo particle transport code for simulating nuclear reactors, +fusion devices, or other systems with neutron/photon radiation. It's a hybrid +C++17/Python codebase where: +- **C++ core** (`src/`, `include/openmc/`) handles the computationally intensive transport simulation +- **Python API** (`openmc/`) provides user-facing model building, post-processing, and depletion capabilities +- **C API bindings** (`openmc/lib/`) wrap the C++ library via ctypes for runtime control + +## Architecture & Key Components + +### C++ Component Structure +- **Global vectors of unique_ptrs**: Core objects like `model::cells`, `model::universes`, `nuclides` are stored as `vector>` in nested namespaces (`openmc::model`, `openmc::simulation`, `openmc::settings`, `openmc::data`) +- **Custom container types**: OpenMC provides its own `vector`, `array`, `unique_ptr`, and `make_unique` in the `openmc::` namespace (defined in `vector.h`, `array.h`, `memory.h`). These are currently typedefs to `std::` equivalents but may become custom implementations for accelerator support. Always use `openmc::vector`, not `std::vector`. +- **Geometry systems**: + - **CSG (default)**: Arbitrarily complex Constructive Solid Geometry using `Surface`, `Region`, `Cell`, `Universe`, `Lattice` + - **DAGMC**: CAD-based geometry via Direct Accelerated Geometry Monte Carlo (optional, requires `OPENMC_USE_DAGMC`) + - **Unstructured mesh**: libMesh-based geometry (optional, requires `OPENMC_USE_LIBMESH`) +- **Particle tracking**: `Particle` class with `GeometryState` manages particle transport through geometry +- **Tallies**: Score quantities during simulation via `Filter` and `Tally` objects +- **Random ray solver**: Alternative deterministic method in `src/random_ray/` +- **Optional features**: DAGMC (CAD geometry), libMesh (unstructured mesh), MPI, all controlled by `#ifdef OPENMC_MPI`, etc. + +### Python Component Structure +- **ID management**: All geometry objects (Cell, Surface, Material, etc.) inherit from `IDManagerMixin` which auto-assigns unique integer IDs and tracks them via class-level `used_ids` and `next_id` +- **Input validation**: Extensive use of `openmc.checkvalue` module functions (`check_type`, `check_value`, `check_length`) for all setters +- **XML I/O**: Most classes implement `to_xml_element()` and `from_xml_element()` for serialization to OpenMC's XML input format +- **HDF5 output**: Post-simulation data in statepoint files read via `openmc.StatePoint` +- **Depletion**: `openmc.deplete` implements burnup via operator-splitting with various integrators (Predictor, CECM, etc.) +- **Nuclear Data**: `openmc.data` provides programmatic access to nuclear data files (ENDF, ACE, HDF5) + +## Critical Build & Test Workflows + +### Build Dependencies +- **C++17 compiler**: GCC, Clang, or Intel +- **CMake** (3.16+): Required for configuring and building the C++ library +- **HDF5**: Required for cross section data and output file formats +- **libpng**: Used for generating visualization when OpenMC is run in plotting mode + +Without CMake and HDF5, OpenMC cannot be compiled. + +### Building the C++ Library +```bash +# Configure with CMake (from build/ directory) +cmake .. -DOPENMC_USE_MPI=ON -DOPENMC_USE_OPENMP=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo + +# Available CMake options (all default OFF except OPENMC_USE_OPENMP and OPENMC_BUILD_TESTS): +# -DOPENMC_USE_OPENMP=ON/OFF # OpenMP parallelism +# -DOPENMC_USE_MPI=ON/OFF # MPI support +# -DOPENMC_USE_DAGMC=ON/OFF # CAD geometry support +# -DOPENMC_USE_LIBMESH=ON/OFF # Unstructured mesh +# -DOPENMC_ENABLE_PROFILE=ON/OFF # Profiling flags +# -DOPENMC_ENABLE_COVERAGE=ON/OFF # Coverage analysis + +# Build +make -j + +# C++ unit tests (uses Catch2) +ctest +``` + +### Python Development +```bash +# Install in development mode (requires building C++ library first) +pip install -e . + +# Python tests (uses pytest) +pytest tests/unit_tests/ # Fast unit tests +pytest tests/regression_tests/ # Full regression suite (requires nuclear data) +``` + +### Nuclear Data Setup (CRITICAL for Running OpenMC) +Most tests require the NNDC HDF5 nuclear cross-section library. + +**Important**: Check if `OPENMC_CROSS_SECTIONS` is already set in the user's +environment before downloading, as many users already have nuclear data +installed. Though do note that if this variable is present that it may point to +different cross section data and that the NNDC data is required for tests to +pass. + +**If not already configured, download and setup:** +```bash +# Download NNDC HDF5 cross section library (~800 MB compressed) +wget -q -O - https://anl.box.com/shared/static/teaup95cqv8s9nn56hfn7ku8mmelr95p.xz | tar -C $HOME -xJ + +# Set environment variable (add to ~/.bashrc or ~/.zshrc for persistence) +export OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml +``` + +**Alternative**: Use the provided download script (checks if data exists before downloading): +```bash +bash tools/ci/download-xs.sh # Downloads both NNDC HDF5 and ENDF/B-VII.1 data +``` + +Without this data, regression tests will fail with "No cross_sections.xml file +found" errors, or, in the case that alternative cross section data is configured +the tests will execute but will not pass. The `cross_sections.xml` file is an +index listing paths to individual HDF5 nuclear data files for each nuclide. + +## Testing Expectations + +### Environment Requirements + + - **Data**: As described above, OpenMC's test suite requires OpenMC to be configured with NNDC data. + - **OpenMP Settings**: OpenMC's tests may fail is more than two OpenMP threads are used. The environment variable `OMP_NUM_THREADS=2` should be set to avoid sporadic test failures. + - **Executable configuration**: The OpenMC executable should compiled with debug symbols enabled. + +### C++ Tests +Located in `tests/cpp_unit_tests/`, use Catch2 framework. Run via `ctest` after building with `-DOPENMC_BUILD_TESTS=ON`. + +### Python Unit Tests +Located in `tests/unit_tests/`, these are fast, standalone tests that verify Python API functionality without running full simulations. Use standard pytest patterns: + +**Categories**: +- **API validation**: Test object creation, property setters/getters, XML serialization (e.g., `test_material.py`, `test_cell.py`, `test_source.py`) +- **Data processing**: Test nuclear data handling, cross sections, depletion chains (e.g., `test_data_neutron.py`, `test_deplete_chain.py`) +- **Library bindings**: Test `openmc.lib` ctypes interface with `model.init_lib()`/`model.finalize_lib()` (e.g., `test_lib.py`) +- **Geometry operations**: Test bounding boxes, containment, lattice generation (e.g., `test_bounding_box.py`, `test_lattice.py`) + +**Common patterns**: +- Use fixtures from `tests/unit_tests/conftest.py` (e.g., `uo2`, `water`, `sphere_model`) +- Test invalid inputs with `pytest.raises(ValueError)` or `pytest.raises(TypeError)` +- Use `run_in_tmpdir` fixture for tests that create files +- Tests with `openmc.lib` require calling `model.init_lib()` in try/finally with `model.finalize_lib()` + +**Example**: +```python +def test_material_properties(): + m = openmc.Material() + m.add_nuclide('U235', 1.0) + assert 'U235' in m.nuclides + + with pytest.raises(TypeError): + m.add_nuclide('H1', '1.0') # Invalid type +``` + +Unit tests should be fast. For tests requiring simulation output, use regression tests instead. + +### Python Regression Tests +Regression tests compare OpenMC output against reference data. **Prefer using existing models from `openmc.examples` or those found in tests/unit_tests/conftest.py** (like `pwr_pin_cell()`, `pwr_assembly()`, `slab_mg()`) rather than building from scratch. + +**Test Harness Types** (in `tests/testing_harness.py`): +- **PyAPITestHarness**: Standard harness for Python API tests. Compares `inputs_true.dat` (XML hash) and `results_true.dat` (statepoint k-eff and tally values). Requires `model.xml` generation. +- **HashedPyAPITestHarness**: Like PyAPITestHarness but hashes the results for compact comparison +- **TolerantPyAPITestHarness**: For tests with floating-point non-associativity (e.g., random ray solver with single precision). Uses relative tolerance comparisons. +- **WeightWindowPyAPITestHarness**: Compares weight window bounds from `weight_windows.h5` +- **CollisionTrackTestHarness**: Compares collision track data from `collision_track.h5` against `collision_track_true.h5` +- **TestHarness**: Base harness for XML-based tests (no Python model building) +- **PlotTestHarness**: Compares plot output files (PNG or voxel HDF5) +- **CMFDTestHarness**: Specialized for CMFD acceleration tests +- **ParticleRestartTestHarness**: Tests particle restart functionality + +Almost all cases use either `PyAPITestHarness` or `HashedPyAPITestHarness` + +**Example Test**: +```python +from openmc.examples import pwr_pin_cell +from tests.testing_harness import PyAPITestHarness + +def test_my_feature(): + model = pwr_pin_cell() + model.settings.particles = 1000 # Modify to exercise feature + harness = PyAPITestHarness('statepoint.10.h5', model) + harness.main() +``` + +**Workflow**: Create `test.py` and `__init__.py` in `tests/regression_tests/my_test/`, run `pytest --update` to generate reference files (`inputs_true.dat`, `results_true.dat`, etc.), then verify with `pytest` without `--update`. Test results should be generated with a debug build (`-DCMAKE_BUILD_TYPE=Debug`) + +**Critical**: When modifying OpenMC code, regenerate affected test references with `pytest --update` and commit updated reference files. + +### Test Configuration + +`pytest.ini` sets: `python_files = test*.py`, `python_classes = NoThanks` (disables class-based test collection). + +### Testing Options + +For builds of OpenMC with MPI enabled, the `--mpi` flag should be passed to the test suite to ensure that appropriate tests are executed using two MPI processes. + +The entire test suite can be executed with OpenMC running in event-based mode (instead of the default history-based mode) by providing the `--event` flag to the `pytest` command. + +## Cross-Language Boundaries + +The C API (defined in `include/openmc/capi.h`) exposes C++ functionality to Python via ctypes bindings in `openmc/lib/`. Example: +```cpp +// C++ API in capi.h +extern "C" int openmc_run(); + +// Python binding in openmc/lib/core.py +_dll.openmc_run.restype = c_int +def run(): + _dll.openmc_run() +``` + +When modifying C++ public APIs, update corresponding ctypes signatures in `openmc/lib/*.py`. + +## Code Style & Conventions + +### C++ Style (enforced by .clang-format) + OpenMC generally tries to follow C++ core guidelines where possible + (https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) and follow + modern C++ practices (e.g. RAII) whenever possible. + +- **Naming**: + - Classes: `CamelCase` (e.g., `HexLattice`) + - Functions/methods: `snake_case` (e.g., `get_indices`) + - Variables: `snake_case` with trailing underscore for class members (e.g., `n_particles_`, `energy_`) + - Constants: `UPPER_SNAKE_CASE` (e.g., `SQRT_PI`) +- **Namespaces**: All code in `openmc::` namespace, global state in sub-namespaces +- **Include order**: Related header first, then C/C++ stdlib, third-party libs, local headers +- **Comments**: C++-style (`//`) only, never C-style (`/* */`) +- **Standard**: C++17 features allowed +- **Formatting**: Run `clang-format` (version 15) before committing; install via `tools/dev/install-commit-hooks.sh` + +### Python Style +- **PEP8** compliant +- **Docstrings**: numpydoc format for all public functions/methods +- **Type hints**: Use sparingly, primarily for complex signatures +- **Path handling**: Use `pathlib.Path` for filesystem operations, accept `str | os.PathLike` in function arguments +- **Dependencies**: Core dependencies only (numpy, scipy, h5py, pandas, matplotlib, lxml, ipython, uncertainties, setuptools, endf). Other packages must be optional +- **Python version**: Minimum 3.11 (as of Nov 2025) + +### ID Management Pattern (Python) +When creating geometry objects, IDs can be auto-assigned or explicit: +```python +# Auto-assigned ID +cell = openmc.Cell() # Gets next available ID + +# Explicit ID +cell = openmc.Cell(id=10) # Warning if ID already used + +# Reset all IDs (useful in test fixtures) +openmc.reset_auto_ids() +``` + +### Input Validation Pattern (Python) +All setters use checkvalue functions: +```python +import openmc.checkvalue as cv + +@property +def temperature(self): + return self._temperature + +@temperature.setter +def temperature(self, temp): + cv.check_type('temperature', temp, Real) + cv.check_greater_than('temperature', temp, 0.0) + self._temperature = temp +``` + +### Working with HDF5 Files +C++ uses custom HDF5 wrappers in `src/hdf5_interface.cpp`. Python uses h5py directly. Statepoint format version is `VERSION_STATEPOINT` in `include/openmc/constants.h`. + +### Conditional Compilation +Check for optional features: +```cpp +#ifdef OPENMC_MPI + // MPI-specific code +#endif + +#ifdef OPENMC_DAGMC + // DAGMC-specific code +#endif +``` + +## Documentation + +- **User docs**: Sphinx documentation in `docs/source/` hosted at https://docs.openmc.org +- **C++ docs**: Doxygen-style comments with `\brief`, `\param` tags +- **Python docs**: numpydoc format docstrings + +## Common Pitfalls + +1. **Forgetting nuclear data**: Tests fail without `OPENMC_CROSS_SECTIONS` environment variable +2. **ID conflicts**: Python objects with duplicate IDs trigger `IDWarning`, use `reset_auto_ids()` between tests +3. **MPI builds**: Code must work with and without MPI; use `#ifdef OPENMC_MPI` guards +4. **Path handling**: Use `pathlib.Path` in new Python code, not `os.path` +5. **Clang-format version**: CI uses version 15; other versions may produce different formatting From a62e754bbb77646a81bcbe2dd6bcb58e9686286d Mon Sep 17 00:00:00 2001 From: pranav Date: Thu, 11 Dec 2025 09:24:28 +0530 Subject: [PATCH 72/76] Add user documentation for DAGMCUniverse synchronization (#3674) Co-authored-by: Patrick Shriwise --- docs/source/usersguide/geometry.rst | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/docs/source/usersguide/geometry.rst b/docs/source/usersguide/geometry.rst index 8c68e48516..f51fbd73c0 100644 --- a/docs/source/usersguide/geometry.rst +++ b/docs/source/usersguide/geometry.rst @@ -182,6 +182,8 @@ boundary condition. Periodic boundary conditions can be applied to pairs of planar surfaces. If there are only two periodic surfaces they will be matched automatically. + + Otherwise it is necessary to specify pairs explicitly using the :attr:`Surface.periodic_surface` attribute as in the following example:: @@ -530,6 +532,89 @@ UWUW and OpenMC material ID space will cause an error. To automatically resolve these ID overlaps, ``auto_ids`` can be set to ``True`` to append the UWUW material IDs to the OpenMC material ID space. + +Material overrides and differentiation +-------------------------------------- + +Programmatic access to DAGMC cell information for material overrides +and differentiation requires synchronization of the DAGMC universe +representation across Python and C-API:: + + model.init_lib() + model.sync_dagmc_universes() + model.finalize_lib() + +Upon completion of these steps, the :attr:`DAGMCUniverse.cells` attribute will +be populated with :class:`DAGMCCell` proxy objects that represent the cells +defined in the DAGMC model. The :class:`DAGMCCell` objects will have +:class:`openmc.Material`'s' applied according to the assignments upon +initialization of the model. These materials can be replaced in the same manner +as :class:`openmc.Cell` objects to override material assignments in the DAGMC +model. + +Depletion with DAGMC geometry +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The synchronization of :class:`openmc.DAGMCUniverse`'s is important for +depletion calculations using DAGMC geometry when materials need to be +differentiated to perform material burnup independently in each DAGMC cell. See +:meth:`openmc.model.Model.differentiate_mats`. + +Material overrides +~~~~~~~~~~~~~~~~~~ + +OpenMC supports overriding material assignments defined inside a DAGMC HDF5 +model so that CAD-assigned materials can be replaced by :class:`openmc.Material` +objects. This is useful when the CAD geometry provides the shape but OpenMC +materials (specific nuclide content, densities, or depletion behavior) are +required. + + +Replacing materials by name +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a DAGMC file includes material name tags, you can replace all cells that +reference a particular name with an :class:`openmc.Material` using +:meth:`~openmc.DAGMCUniverse.replace_material_assignment`:: + + import openmc + + dag_univ = openmc.DAGMCUniverse('dagmc.h5m') + + fuel = openmc.Material(name='fuel') + fuel.add_nuclide('U235', 0.05) + fuel.add_nuclide('U238', 0.95) + fuel.set_density('g/cm3', 10.5) + + dag_univ.replace_material_assignment('Fuel', fuel) + +This lets you keep CAD geometry while adopting OpenMC material definitions. + +Per-cell material overrides +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To assign overrides without initializing :class:`openmc.Model`, the +:meth:`openmc.DAGMCUniverse.add_material_override` method can be used to assign +materials to particular DAGMC cells. The method accepts either an integer cell +ID:: + + dag_univ = openmc.DAGMCUniverse('dagmc.h5m') + + enriched = openmc.Material(name='fuel_enriched') + enriched.add_nuclide('U235', 0.10) + enriched.add_nuclide('U238', 0.90) + enriched.set_density('g/cm3', 10.5) + + dag_univ.add_material_override(1, enriched) + +In the case that the :class:`openmc.DAGMCUniverse` has already been synchronized, +a :class:`openmc.DAGMCCell` object can also be provide to assign the material. + +Overrides are written to the `` element of the +:ref:` ` XML element so the C++ core can apply +them on initialization. + + .. _Direct Accelerated Geometry Monte Carlo: https://svalinn.github.io/DAGMC/ .. _University of Wisconsin Unified Workflow: https://svalinn.github.io/DAGMC/usersguide/uw2.html From 5c4121efd2ad6f2ef2b3bc394157a4eb6d9a1a73 Mon Sep 17 00:00:00 2001 From: GuySten <62616591+GuySten@users.noreply.github.com> Date: Fri, 12 Dec 2025 06:01:10 +0200 Subject: [PATCH 73/76] Fix hdf5 source_bank struct size. (#3676) --- include/openmc/bank_io.h | 16 ++++++------ src/collision_track.cpp | 4 +-- src/state_point.cpp | 23 +++++++++++------- .../surface_source/surface_source_true.h5 | Bin 106144 -> 88096 bytes .../case-01/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-02/surface_source_true.h5 | Bin 13896 -> 13588 bytes .../case-03/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-04/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-05/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-06/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-07/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-08/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-09/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-10/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-11/surface_source_true.h5 | Bin 5160 -> 6532 bytes .../case-12/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-13/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-14/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-15/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-16/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-17/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-18/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-19/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-20/surface_source_true.h5 | Bin 33344 -> 29296 bytes .../case-21/surface_source_true.h5 | Bin 2144 -> 2144 bytes .../case-a01/surface_source_true.h5 | Bin 6720 -> 7792 bytes 26 files changed, 25 insertions(+), 18 deletions(-) diff --git a/include/openmc/bank_io.h b/include/openmc/bank_io.h index 90ffd820fa..418ec111f2 100644 --- a/include/openmc/bank_io.h +++ b/include/openmc/bank_io.h @@ -16,8 +16,9 @@ namespace openmc { template -void write_bank_dataset(const char* dataset_name, hid_t group_id, - span bank, const vector& bank_index, hid_t banktype +void write_bank_dataset( + const char* dataset_name, hid_t group_id, span bank, + const vector& bank_index, hid_t membanktype, hid_t filebanktype #ifdef OPENMC_MPI , MPI_Datatype mpi_dtype @@ -30,8 +31,8 @@ void write_bank_dataset(const char* dataset_name, hid_t group_id, #ifdef PHDF5 hsize_t dims[] {static_cast(dims_size)}; hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace, H5P_DEFAULT, - H5P_DEFAULT, H5P_DEFAULT); + hid_t dset = H5Dcreate(group_id, dataset_name, filebanktype, dspace, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); hsize_t count[] {static_cast(count_size)}; hid_t memspace = H5Screate_simple(1, count, nullptr); @@ -42,7 +43,7 @@ void write_bank_dataset(const char* dataset_name, hid_t group_id, hid_t plist = H5Pcreate(H5P_DATASET_XFER); H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); - H5Dwrite(dset, banktype, memspace, dspace, plist, bank.data()); + H5Dwrite(dset, membanktype, memspace, dspace, plist, bank.data()); H5Sclose(dspace); H5Sclose(memspace); @@ -52,7 +53,7 @@ void write_bank_dataset(const char* dataset_name, hid_t group_id, if (mpi::master) { hsize_t dims[] {static_cast(dims_size)}; hid_t dspace = H5Screate_simple(1, dims, nullptr); - hid_t dset = H5Dcreate(group_id, dataset_name, banktype, dspace, + hid_t dset = H5Dcreate(group_id, dataset_name, filebanktype, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); #ifdef OPENMC_MPI @@ -75,7 +76,8 @@ void write_bank_dataset(const char* dataset_name, hid_t group_id, H5Sselect_hyperslab( dspace_rank, H5S_SELECT_SET, start, nullptr, count, nullptr); - H5Dwrite(dset, banktype, memspace, dspace_rank, H5P_DEFAULT, bank.data()); + H5Dwrite( + dset, membanktype, memspace, dspace_rank, H5P_DEFAULT, bank.data()); H5Sclose(memspace); H5Sclose(dspace_rank); diff --git a/src/collision_track.cpp b/src/collision_track.cpp index 75e56574a6..03cbc32b7b 100644 --- a/src/collision_track.cpp +++ b/src/collision_track.cpp @@ -78,10 +78,10 @@ void write_collision_track_bank(hid_t group_id, hid_t banktype = h5_collision_track_banktype(); #ifdef OPENMC_MPI write_bank_dataset("collision_track_bank", group_id, collision_track_bank, - bank_index, banktype, mpi::collision_track_site); + bank_index, banktype, banktype, mpi::collision_track_site); #else write_bank_dataset("collision_track_bank", group_id, collision_track_bank, - bank_index, banktype); + bank_index, banktype, banktype); #endif H5Tclose(banktype); diff --git a/src/state_point.cpp b/src/state_point.cpp index 47296da3a5..8ccebeb05a 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -554,7 +554,7 @@ extern "C" int openmc_statepoint_load(const char* filename) return 0; } -hid_t h5banktype() +hid_t h5banktype(bool memory) { // Create compound type for position hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(struct Position)); @@ -569,7 +569,10 @@ hid_t h5banktype() // - openmc/statepoint.py // - docs/source/io_formats/statepoint.rst // - docs/source/io_formats/source.rst - hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct SourceSite)); + auto n = sizeof(SourceSite); + if (!memory) + n = 2 * sizeof(struct Position) + 3 * sizeof(double) + 3 * sizeof(int); + hid_t banktype = H5Tcreate(H5T_COMPOUND, n); H5Tinsert(banktype, "r", HOFFSET(SourceSite, r), postype); H5Tinsert(banktype, "u", HOFFSET(SourceSite, u), postype); H5Tinsert(banktype, "E", HOFFSET(SourceSite, E), H5T_NATIVE_DOUBLE); @@ -641,17 +644,19 @@ void write_h5_source_point(const char* filename, span source_bank, void write_source_bank(hid_t group_id, span source_bank, const vector& bank_index) { - hid_t banktype = h5banktype(); + hid_t membanktype = h5banktype(true); + hid_t filebanktype = h5banktype(false); #ifdef OPENMC_MPI - write_bank_dataset("source_bank", group_id, source_bank, bank_index, banktype, - mpi::source_site); + write_bank_dataset("source_bank", group_id, source_bank, bank_index, + membanktype, filebanktype, mpi::source_site); #else - write_bank_dataset( - "source_bank", group_id, source_bank, bank_index, banktype); + write_bank_dataset("source_bank", group_id, source_bank, bank_index, + membanktype, filebanktype); #endif - H5Tclose(banktype); + H5Tclose(membanktype); + H5Tclose(filebanktype); } // Determine member names of a compound HDF5 datatype @@ -672,7 +677,7 @@ std::string dtype_member_names(hid_t dtype_id) void read_source_bank( hid_t group_id, vector& sites, bool distribute) { - hid_t banktype = h5banktype(); + hid_t banktype = h5banktype(true); // Open the dataset hid_t dset = H5Dopen(group_id, "source_bank", H5P_DEFAULT); diff --git a/tests/regression_tests/surface_source/surface_source_true.h5 b/tests/regression_tests/surface_source/surface_source_true.h5 index 2c2a19038fc1b6d9c7785e8a7f591e9e5c7fd959..d343d12aed654f2da53310c5943c20d8bd85afb9 100644 GIT binary patch delta 4436 zcmY+Gd;C;$8pr!pGTo=5hHlfmjxIX%RR>*;QYIBsx{NMNQ6^ER`PT1D zg&mh=7TIZY8EnjA?O-uj{1(fwtifU|%PhIPAOEe_>+|k;o;mY5&-ZzbGr#PSR@wY9 zUZi>0IW%}niw1T0V2e>Lx;Hd$XvTkmW}#*hv}kA+l)PE9u%(Z-3bkx|r?K>K=vb@a zP_g=d(r!TMXls>jqjU_FQMRqpfp$taA+x>G!466%kkwJ?JW2+YwmT_ZK&j43*HE#G z(vjnot|Rw&rAsK&Ri(ROiHs1ICnz09=7~z@P@=oi6_oFxbf~A&Rb=;4I@}vu;>$^WhcnFgu5bdA-6&9BFrzv9K{yni?U1by^JRknK7QorT8N2 za(q!}8NSF~j_(S5k#hyU$h#6>REp!fQl(d6i;SzVMe)_xqTCv6*U~Do)?u08K}Yu0 zJm@I&EIG3OLXJ`;9(+`MjxjyYEs*;HxA-fqqu7hIj6 zz!y3H#20xV;)_Zj;rlOqQS4)UQMQWjC-jQUPwDkDd{N+A^6&7k0XS7j9i((@fEy|8$ zjHfVKWR7CAqZuu-PGw~%c^WH21%s81VZ6vWoe?8%EWW5T4&U)AJpo%}oPjNho7ke< znb=NbOURnUrY2*H?6a^%;j@*lA!iCtmxV2I&%qXDrmFNbIz`5GI-P;-4CW+9GS6i% zrxWA|@&tZpELmbEn$xb%2W@K(*&DSx1WL?kGgOXc$dQf2- zYrX+bv~^DETP9$bJmp$MHqZAMr)r5qweU34EVa=_0ns_!G7${uH(- z_cXT8&?>V2to-;^c@PBVHhB;P!5ctAP!U)ukQaougQTD;ux|tfL3jr+mp5>aobpqW zaXMX7WMFDYfn{G`-f zUhV0_e10PT3wac(RJHLS*HH0eQnKR`@&4EGhm>C?@XJy!P}jMKm7kTL1!Fe|$Ztb< zCH2Z9%vrLm)J^%hNJ%~PD3g%ijX)aIq*Qo}^Ghi%B};x!oK@6ok7FUFko>w7r4%_r z-;$Xc*nL6dD(dbNY(Po{DW&9x$dh{JN$$3XtR|(pl*&cC8>qHCxpo?$W(vQQ&go(C*L*)K~eNy*O+qF#MgHLfKI z3}(0EcM_}P@t~8=V?_kV;u-*fORtU(hImtDNp97sHb1# zro%`A2~d+OtEAd^iP1`_FdR7hKsZW0{xbLf^-?mwNL}a3G;+0EH3CHT3r12;yuy5? z?veSP)ZJ64=U=7O^<;G^m84XCjeez+86{U8;JF%2Is7`~m2!!SE(O?4Yle6W6>9?( z=M5TdOH=LmCROdd$4WPic1zEnDeoSM=_=w_e>pjdf6JLs?mN!SpNR=%{SRA| z{2p6W_yOCa^oE=t>FOtJk^3{YKdZewEsYJ*vcPB#vVwRE&;)d@J&!<3vfwdfl@6>^ zf>4kJwj!t!gpMT$cVce3qDJ|lZeK}M| z_PUrR`Z4(+9~es*-DR9nl30I^7~|>hM3NoA3768)K<>7TULxFRIc*H$9xJE~#{Wuc zL$Hoh8_H%^QX9r%S5X_z`((9BkKoO*h8vA!Cu_OcDcoZeds&D5XhxP`ey1_9^{m}s zU>mR+!@M?PHI~jdVKq*r`6DDV9-AcY6R_EgyNT5n?9asNI_xK6wH2Ff*iYi=;g68& zWNfw*pN$QFfE1_Tvx6te!sjLiF%_Sk9DN!-yEyf9d^}D)1CQODdL|xeVjGV=#OL9$ zmv(32(MY=rj|}ZzK&!Ly*{9MDHv7?q*c`y(R)%&PU*)fk@a=r%4lciw%kNU@ySeNh F^$W+aIS~K= delta 18335 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 t=VY&IRpL>aBOZm<#3OXmtQo0{@wrp delta 4990 zcmZXXOH7 zsql6)&+B=D*g$;3=?e5>l3nhSM-i8-<)T;6B!)yH6G~)4iA*RlWD*li;&vYTGilCu z$*Le*`Is@$B!*4mN&);#HU)_mx|(G{9u}fU*z`y;J?Lba&^a)nb6`T}kYo~*O=4*Y zCStN!g8s=y?LV5<%`&0>OsGE->Yri~Q%!%`5fe&eLWxW$G1VmQ6NyYHkqIR-p~QVA zalc4pLWxW$kqIU4H;HK?kqIR-p+qK>m}U~wP2x~B?vcq&LG}dcuW?=Lg6s-%qSkfY z5afv9icd04PI^0fWU9CBrFOh^b@4&tuzuIFmfTskTWgps9YIefKMGRW7KoZZR<2_&>uP*3#SxfF*;m)<)x*#`e$sG~yi0#$|xmio@ zJmJn$?#URgL>HgOaKfx5cfN4v+r4!W?0}oK{T(<*ChLMwheFYz(C(lM+8t}jU1YoU zZ8F*E#8XnF@=kSONM2s+I-3@MNEkfs!qiNtOR?QWKbXb#jJoLUMg!K8yF|E4Y_~3G zhpgQgz%-@C-O!8ulq&a!y|_PJOb(+rYspv6bs(b5MuYsp=L;S8G88T>MaSBNee&)`6sV2C-9d|X0g4`3N@T}`v5ae5*w3zOZ3C!N2W`B1Am5n>~B^^qjlAHV^kP<$gMcJ?P@( z8_*szQ8!-0d>uXsdrt)EdEM1q_sMg{wIfL9JY1}yxjOB+bU|}po z#hN8S=st0wev)QVqIvRYq3DP{!CDZ#MjOE*dDtoP=%BPj9?mjP z50zI$>u}Se_voch^vpfhhAZl=idN7^xJDj+hI~e%b@FJTm?aNugFM;@Hp#>G$fJYO z7I`>1evdB7+vMTykVg-vyP^$vd*snaxKAFwPu`d4fIM0#9+HQ3L>_GfdGfFehBFwtnsJ?~t@>(b`SIrlZWfB(LD`svxL zCU@@QQsSlQ8eLvA(`Lx+b{WN2g%K>h8K$dHvH!vNmb8AC2g|nOpGTL2hjOmhzCQ2Y z;%h%%idenA`~g{jxMf5!V~a`Y@k^_WG7s@k>{hu$@a6uSeAtmW;*g^bsif?kkniKA zWUCL#oI`dY4Qyos(rTp4LK2i6NQ%;NQd-v_Rn`oo8{)B2HIli@mM!-v)5r`^>`dMv zgARGNMi0UV zh+Z3iAiCr`jnb;&oc9o2=`To_nckSRbjb^l7&AX1_L2>&=d83^n3;#PQhq?%C^ybY zOMkfUAnnMQ)^|t;TU|}k(!=r=a)p^a$W=-y%7FTJ{k$ty#!z zW_BR`l#cV#(gQW)kgpC&HA_pkJPpx{{|iL7oJ>l~$EUx5R8zJgK}x(uS|Q4FhipOg zY{Xinr7{Jn=bTMQloDx^mR{JCkY;8!AbK{!DQW51n1JZs*CAQXscn~*Zh0Ki#mpMy kCM9q|S~r-d5Pw=)ni+xUWwVmbSC{_Y`QygCfBZk0r~m)} diff --git a/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-03/surface_source_true.h5 index 228f5a7d0a462f38a1cb0b4274dd40d4307b5a12..d14771f5a00887c16ca1399a629d0e2448430bda 100644 GIT binary patch delta 1272 zcmZ|LIc(EV9DwnpL14roi=!CI5hM;%E+dMt0HJW3a=G-Cn%k5DDQ8-)l%u4GA!FsY zFrrRbkf^$J%$N<29z8I4^yq~HK@<=f6jCYhg=G~U10@I^#jOmen zUp~(Cuud>Nw3Fl!!9K+qP^3ZOPM+EyedE{O4h~eBJ4}FL{61aEC!x$z%EWCT<;lsR79?Apq2v8`J zhdM$YA*_ewp*b`snHOE({{OYsIdcYn z=I_6Z-@bKRO>>k?F1RM0#?b9s&OB#~!(jyYUmF7=??9hG z(#+Y&TTOyUpskIQncLjp@?&$#PvxOwA^8nVp%Kn$0#16H~Lr zreR`gw%RmIvLbO6A*7kGk!2f6k6P~+$`*Sk3Q-!%| zigkxnYq8H-r0GKaJV>YQ=2NkYOCJB5id|fET)q#>XA+syB#X#fO|pr2(%{;!i6Le+ z$sx^Z8V0-N;F@#{&ZXm-bR6f(;}81y038>)Fd>h~v))&z-^{dg=qexkMrqv?M?*X-TOm$;rVYWpa_p99)Dd zR&sE`Wn_+Zqkp++{>BY+h4l_p%HnY@I#pSVYHLwrEo!Yroh%+5z%8tovwZR4;`dz4 zYOqQhW$`c%vzn|Y&DP?$wP=yWt^#;kttV}=xL<(FZl}w>eh6>I2_nY9^~BV4*fdPq zw5yXeH*I9iMw$yTtBYJWY{Z=IC5^cu6H{~2reRWj7_+)bGp|Vx5wlM(5pxz3Q{%H~ zn0SgXt50i!#jGZ$$hB%CMa6LSlg2+weUb*`oA;p@Z{7eM7aoOy$+RXMkzQ)zAXk0~ zTuvfWHu78(PCRZ8Rtb`;T=U=wQ^ji!_Tt2nbqo`jOxVb>CT6N}iu6*rIKzyWV&*0} z^UqSu+$@XSGR))*a;Xe%P8>^RaBr1{>~a`5eq1cav5E~V`gj}Nlh_IzZq)03 zF?t(^xMd?oJ!YzCajG6ORdKf-Gh^vm*0ffIjh+S^$J6nR2DDO%Be)T*RO0Argf@Y+ z*Bh}claGyXtHjaX1cS^M@@0tmCK#B!w~_K@Xp&*_zw>j=XsQCpr)D%wp<~Z+7*dJM zYO;^WswQcggo>gTxR}gn!kOh&3kIvqQqhXR8Ps&T6~`I!oqpGfXH^Cmk<*4}m9xuK z8^)QrBv3rp#I5@U3U@m+98SK|#LOds;#oUp=E<3dPGF^cT4~}0S`-jj)`SyEdIwsl zJaVN2EjW)n=|Br6DV;E=gmSraydMg^EjT^yFnu5{rBsqk{XD_mrH5i5#l z*D)^!6-)h7F9w<6#VMjrVzUx$aEcKdS=7WsO(VMDVsg40V~)u&kGe6Ylnh}#I4+gP z7kY49MlLo&YVNm&Hv=@d-ed-iN;+|;CzG;5kP5ozv6pJq)Aaibr5sW22gfK^(^ zP(J`eE0OD(v=RAeBh{b7#c63?6EiIt;=LxEgvtlu;v_UTh~>KETlZ-Y%W-(|d;tTK zRZTd&n1sVi(GZ&U$fiFGp(&@7S3_v(qw6a?4bn$sS`*GBFKr}$7_NSDO$}pkza0E# zxN)ohZ#51e?lU-5iRIcEtYwh-*%`EBl67`Hnb3q2%ko(?b;^+iBWTLeWPAkCU4GFb zR?E??xOV;T#Bm6LRq!dTfzfteis&jvKM( sVc>)@rU{3N2R0HlhNdcod^Luq{N=^s7@9JPxZn+!e;(7<8T#J-55UccTL1t6 diff --git a/tests/regression_tests/surface_source_write/case-04/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-04/surface_source_true.h5 index c276af40f4302f4e0feff883bc3c472bc4df7ca1..d2acc69910740026a283af0568d90370f9ff7065 100644 GIT binary patch delta 1271 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 JQSyjJ#UJ$40M-Bi delta 4948 zcmZXYTWC~Q6ozN!WTH_M6HUy`M8{kw8Z|Mu$#r6GlSwir=AM|CYc;mfD7D~&f}s`! zmBvjTQc&=r4+=`7C@5I;L8yX)Pz4KyT57?9q6JGWP21V~UuW%uGcUTnz5ajgv(F^I z+qb{k?|kX_I@{r$p3j*!?0c_WHVTYnhr@0QewNx2B3h#Ror=uN$B8S^fsdA}SNAL8fL~Bx5`)RP81#fOc}K*_ z#8ibdnOg>5}DO`i&i;~B; zkci`3$zz_cfoU|8y!emFi4gKE9;VUKv@{{0UXUuzBw#`e`#nj3-zp-8c$^6JYTA-g z$6AXxS>z|dca3!=UKT$kVMsg=aV5i2EeD@cStiQfr^zUitS-scVy!G5rJyZE7MWC} zT36Oti}lvRC5taoVX#3K4^pwgG}>Ueh*^gXrdx#>)*{ndWLb-BD%AJf&CeX+!olV+ z86dKW$vlx#Tm|Ssf&5NYGQ+Y^N5Rn9W8@joI>7HpbSi$-hVw-!y-qFEMaH{rlqs;4@4lT-+uy!aXqs=ow{VI*&2A zNj*B`A`79?DK<<*r`UBOI>jQ2@N?yqhrX`}hpq!`z6hpffEmJB459<9w-^=?(&APz z-smz}M3ul#$5v+vdRNHh8?>wwYq138QT&{39tc)S!Br2;RZN7J;;SiRLikFD)Q^~% z5H@k46jrO*>U}A!RAzLQ!AfPur84X@j(gvgp;raR&T=g4te7jua)R8|-{r7USrMo} zZxUP0R$wE^L>%H(1=K1v{FM--uwbSV%PKnlpyhSE?5V=C%8zfVFk9uvn<`kjxVO-Y z*_xd6Laj39cP|8H#@Iz(H3aEwae_z&lV?OSndEMVDvQZ+BH2Wu#gh=?u7OI&(a{=g zE=L~gLJb~mqb%}k@v>zsiO*~CvUMUotc8`CHete52a-n{2or~iuKTe~F9{40(F9V>76VPN*e)%; zZ^HZg_t4p-36Y1SJX6rjr-6tUC z9myuqzV_$iOBF$ACdPdR64y*5YhLnXGF{hvx(f#pz@N9 zO&lj;MwlU6RJ!NrB#uwT+`=S|Pu|1SM`Y}Wz|1`9N%)r3cF;?PKf=D0z^RE2zf3NmsptX{&7z4$b#RH!+ zX<7P_8OaQ%2hu4%T1roaUoz=bHXNr?#c}m}t-j{hcWY`%UuUNmYt01ZX`+6@92E6+ zQ2h0x3J9mI4apj8jKEee{5_KRY4oxR^nj}5kDmUHsVo-rAI%jZ5LHU z@V8cXh{_I&Dxm>;XSA;G5;cb=oZX_9(R(gFAJ_Jt?z*{`c=YbK_9e&Rx%_@nRfM%< zB**c5T$c}u${i9_M!4TS{O|qoxwu+KM16yHl>dPM;kY_N|HsHj1NL!I3(!x{KbmkX z`bX|0`DnpCC8`GFG}n(dyfa)s%u)Iu75^;Pk2R>}mF{}wI*r4-LF4GH z1((iY-K2A9x037e{?cuFhka-Dx^tK25&mx3i>iCCyRR}%KD_(n!g9uZc$k_8T4^dWm>6;k+dtxp%~)1@}GiFg_5EHoT9-!<;34 TR{T%IqYi71cxdy)Bbb*zT`c@f delta 4999 zcmZXYO-xi*6vyX-Z$uenR6a%+D&iPv+bSo!RL7{r=~i``$bf z4!{56{q{58mwSB2ZY}P;<@b&~dg!nA7x;W$PvVp2*&+V%_`UHo`5({EGtS>BJCc5i zd_VSRM{28gKD#&T-^548Ma1dIj=9JJBkve#3&fITpSi`L^B~ZP3uj}?sBGrL^hEnN zISBg5`I+;ROCon?E9#QSC6lYqg-a%vLQc<1A(u*SHi)`Za_T8r=S(A)PIbCxI=Kwy zGRS2zmq~6DbDPLzk-M3Puf&jbMoRPDnHff&F%m9tSKVObJ4Ql;{ z)BQ|_P;bae2LR9#ZC%WC*w$gDON5@^hohB{ez6bF@jXRSobqxv zN!*=$OLkG!bCoefKY>#F6s1(4^=@15X1dJQWlZm}^&X}pwvO0Z9)B;9wF=yjA$gS` z`zSNX$ciH6lnGX$$`IY>eabAWj3I$){AhlV$T;z8`~->%@$ouOs_`!E7k86igD-49 zY@%Se1~V&&JZ2>QfIBn9$l?KvsT5;!YB8pgnhw-LR|)-8=_=CRgP2fFq>qvNiquf% zA4a;P7*i|8EJbmOS}OQ6iZKU?bkw=YLLFK}MGM~{w1`qcLp^kz&<~WZBfW75{SGOT z>@**Cle>x>rpy~g^q6{kOg)X!`iQNMke)k&nMW1b?7U_qdK8&sDwFKYGV)T92FlbN zLzN-=D2?_}8dZVEsc1mKacXg!5#6Fmw5V&uFHrL03;W_#Bfg9#Y92X`=FQanCL_9e zi)dcigcdE-LhBRu@lTKrH{t;^sRP zNq3eR(Z}z!TXa$jt-Ea9MS8d$H-B2_)pp$cY0|p7+pg|r`i!m5Fx_M89;SPR9_hgB zUZ(r(>ORulojCbfp_e*QeU|h>7arX?A{~tAOh3yQqB8@Oxpx|!4cSoSJY|}@kul^h zBX1bdvtraopV<(d8DtqlbY_S$uX}JFL!!MP7br8!i0*TdGWtA*=uDht45>JaS;H!m z;@oCL_Zgu+<>ydkh|Y{s=DErkqBEB$qt9%}dOtdQDN{P&CNqloDD#Yw@Of1EDRYC7 z=@>FelnF7SGiK#mQyD|@2JyP5h}Zp-LA>r}4_q07mCw1&$O}cxl2tx|DnmYGe*KwXdxG{TT}RLNM8Ing??eG4t<1vhD<9`LYXy2@}^N`GLwv~ QFcSPYmMi`QKvinOe;dR{8vp~{on{b6IB#44C@-!(U zDjFoBG%2@C>4L(g3ksJmT~P4M?rMct>C$Y6~~NHb#Su%Q@JRnzLz`7 zZN*Ztz)vY?h5VshEU5XuP^k9G-?Oz@KfhZ2Q`#J-I9W^nA$>*28JKg09B-)16EZ}; zpP1h|Z@$l0b%BsWh~X?0@&`0kNMosx39GwE$Z6<{h5UjP-je$J{7x=wtTW5#FaLWM ztY}@aH1f#TCVQoj-=Ma&&YJJ?bz~KJxU0!SUqc=#JYC2djI~0JA%nk;@ln~pnCnHr zl0W9GjpU(hs_!FKdoy{c2Gb)(ephS%-}IK&S-Q3LoZlVWR^R*E$v2FfBG|#_&^(&h zNq$#rZ+DP~y1RZBvpReD^P%l!dL(cyriZ?d>5;3P>(V_VmQahLpx3$3EUIpp?8r-3hyL&7!G-4@K2G4*-gG%1gFU( zgms2Il(Xa!!9GVG>Ur{r;ke|XT_BGH?nUy@FOf$IPmqUknLIN1SIEQcA>Shck32$H zSII-UMjjFD>*S%{Am8BJBoFNtc_eUelZWn;M+)x_c^JLqk-@)99%di;J`vm_j}X>< z@=zX-M+Cb<9%?^%#Bd&xhxUj(61b1aLw`aZDZHoTVLT&`41Se7%mMNPA{Zo(5Y}_@ zP+pKn1p6g1qX63g delta 4948 zcmZXYTWC~Q6ozN!WTH_M6HUy`M8{kw8Z|Mu$#r6GlSwir=AM|CYc;mfD7D~&f}s`! zmBvjTQc&=r4+=`7C@5I;L8yX)Pz4KyT57?9q6JGWP21V~UuW%uGcUTnz5ajgv(F^I z+qb{k?|kX_I@{r$p3j*!?0c_WHVTYnhr@0QewNx2B3h#Ror=uN$B8S^fsdA}SNAL8fL~Bx5`)RP81#fOc}K*_ z#8ibdnOg>5}DO`i&i;~B; zkci`3$zz_cfoU|8y!emFi4gKE9;VUKv@{{0UXUuzBw#`e`#nj3-zp-8c$^6JYTA-g z$6AXxS>z|dca3!=UKT$kVMsg=aV5i2EeD@cStiQfr^zUitS-scVy!G5rJyZE7MWC} zT36Oti}lvRC5taoVX#3K4^pwgG}>Ueh*^gXrdx#>)*{ndWLb-BD%AJf&CeX+!olV+ z86dKW$vlx#Tm|Ssf&5NYGQ+Y^N5Rn9W8@joI>7HpbSi$-hVw-!y-qFEMaH{rlqs;4@4lT-+uy!aXqs=ow{VI*&2A zNj*B`A`79?DK<<*r`UBOI>jQ2@N?yqhrX`}hpq!`z6hpffEmJB459<9w-^=?(&APz z-smz}M3ul#$5v+vdRNHh8?>wwYq138QT&{39tc)S!Br2;RZN7J;;SiRLikFD)Q^~% z5H@k46jrO*>U}A!RAzLQ!AfPur84X@j(gvgp;raR&T=g4te7jua)R8|-{r7USrMo} zZxUP0R$wE^L>%H(1=K1v{FM--uwbSV%PKnlpyhSE?5V=C%8zfVFk9uvn<`kjxVO-Y z*_xd6Laj39cP|8H#@Iz(H3aEwae_z&lV?OSndEMVDvQZ+BH2Wu#gh=?u7OI&(a{=g zE=L~gLJb~mqb%}k@v>zsiO*~CvUMUotc8`CHete52a-n{2or~iuKTe~F9{40(F9V>76VPN*e)%; zZ^HZg_t4p-36Y1SJX6rjr-6tUC z9myuqzV_$iOBF$ACdPdR64y*5YhLnXGF{hvx(f#pz@N9 zO&lj;MwlU6RJ!NrB#uwT+`=S|Pu|1SM`Y}Wz|1?37F6fJc#Kg1h`Nyp&czGh#_O-w`4?2 zEJ#FIGTwNjC*<)429F*+Fz{LCbRbUp=@nb|>F@fdQu4DnW|XRf6PrGki(>Lyxud+S zSSl9yDFv;NZOX-hnw<-UYOnk?U7Pmfi`74=&2Wkn_4pssSA=Z9oGIk^AC*}`hRDvJ zXSeTL&$CsXBV-LtICF*k4owwu7%|*=LQX-SFXSi^cnk7p+4D@gFkc&s@^yT1`?<12 zNJ|qkTU#Rb_EI6gqILK8sx7CF814%C&{xt&0#6sR4r7&&V@TnzW`0!GGUpl*uw>he zwT|(jtk2I8tG$6dRDJ|YkOF?l5Lo{)#}lsr=SRq`+g$Pb8MkUTm^_pb I@`y&nZ^?BCC;$Ke delta 4980 zcmZXYTTE0}6o%)*peQKn3@{)lcZP}zGIGBu*MS-C$X!5C&|<~JCO+5%Q=8DlMBMR# zrZ(}x2Td@d(ZnVuzR<)bnA+5&K4>HtAb~eGdE{ z-~DEN@}=!cmaX#QLiRQ;Svso>{YojGj{$a6Ohc>FeSl*l$|Axnf9j*9f z{C?bqdh6Bbj;Q~FmnxSf!XMq|P-J$&CGJEA)}^a<^eJLPzo5V%b|%-ip(c#U8W9H* zLlw?sZaY*Pm>4y*yJ=QLNX@1YvN?oAGMRN^Ruq$!5K`n?UvoKxEQb(p%zD*K3=VXQ zJkZx}9OzaaoEr;4G?PoQ5JXGC@38^(I8;y^2lY0tosR31bXggF6%y%fOZaVF?Kxq9FtCT4|7oZ_|g=+f+tE zb$;bMq$U$vRS?-C=7>}hafr8>=vNgavY%>kh|(5uEekCUvtTs~H&!iY`aIaLngz2S z2x?fc;(?&ne0Oy+_%j>#U2hH=%z@7wG@64Z8IOPgg- zoP${{=1i+OXfp@xGWdEgG#%zlrwsD;;l8{0zNd0=-$z17H1VP?(+8Ni^Dt|WiJ>|gLWY>Q4nQ?bBwS1o8R448M2;~rI*&3L%SRvWXpe|! z%Zl=%MqAb}5p7uyym)sU^3Y=r;?T8Q4ID%Z!>#OMfrxf1M*&(y$QH*7@I*Js;QIpf z(;j6lL~W!@j}#)U?det_#%M0v(z`faRDrZ|ly54aPUiG-1;%OOtprKonwb#t zsuE3=8I@O|sbNM|aj6O|(zwM-BI!(W4xuK4$uyBnCNGF&G4ULR${^9=LI`+`~u(UPtF5M~i*EFeLYzmyI!P}!P?r9B{FzhQ#B-Vl$_7x_k zh~)8#%6PT=ZET7WHxqS3Lv=nM@GT*7mp_EtIt-HK0Wi3&t9d zR%Z7@171aCcJV$0C35y@AAWw6&)xOm1j@KeL?gPC%i5ETsFgk^UU_c<9GSX?$vAWB?-#-?NC;07lmG$eRJQQ|1@m zjFYM39sSJ^)U)6Qkp?F3iTIc_w4kYS$J;Gv+QjL#7BrO>sV-5|3KC#4N2Hm_TOut? zs@m|1wg!o~(uU_D19@4+Y8$ptChBX)7VXFe1+(p#*}-ImNGFq`4%BE*y-dXLRI6Af zqCM5y36=KLnNF4*uUl18) z;^{_>_RS03XnIUGecg?hX;cPzJ(yr+_4yvCwOcOrKy8bhRZmjA4Sd#Op+~C9VJ@q_sg_p1=hC4Y*9i z_y)8H?@81cCTbBgL<|$Ph*v}m6Sa%nQ`qZ(9DMZ@25bL(c?wOnW#)VeqAhcpNFhJR z7eus6dM2UL8GJ8;hOX7NVr%cB8^pDBKb3@w7Z@oqCX{{5|I`QRpJ?_ xG?^k&NhKDsNW^emyKqlIrOD(J4)l;b&}UOPP~&scB3x(tobvxxq|utM{{gElbWQ*O diff --git a/tests/regression_tests/surface_source_write/case-09/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-09/surface_source_true.h5 index ebce87b36aff8050b2b6b9df2bf4292296045da5..d62363f97fd4cdbacfd65b2dd99605721d60f03f 100644 GIT binary patch delta 1273 zcmb8sH*C~U9DwmF2+RTogk*sL(@hbWZc4y(6Pkesm~KLV3-uD((ZU5W+<5X^GDexQ zAQ5G`F=NIXJ>J0J(W3_jKFdU=WFgW||K}oq_g*Hyl;ZEjrctU6jBos0E{ch-<(=iF z#Zs}rpHk2Y>7raLsOfc~Q0_I;>I<`V%=8vz>*?pyb87Lw_bpAxnb=EazCZnLeHq_EI$O)>uMo0< z7@jWVB#f0pHj%(z#r{!Q!*5?L0!F$_S!;zHfwC^U4u8$D^+Kvf{+_deBlwHEDZkg) zoUea>FWEwRYi`&S!M6M|eKfK?zYcfg>-1S|7pD(rHz&U*Q)fnSEq0H_-b~E&_OW{y z``JAb_y_nV%r17{C4z(O3T;@2$V0J(tRjScSjaJ`N64cC=P3VtXva8oL~xIjhkk-Q zVt6OX!*IwWfq#lT%x?1CA~;PRZCGc>Lpe(xA?$PHp`Is?4jh*}v6RCh+gkhuKTNR|NOTqYdi;c_+9{M}-h~d2_ f590%QB=A3yhdD@oPz0aIqYbN09?B4TghS#d{mBeO delta 5311 zcmZYDKTMQ&9LMqJ{voI+ww{8DZvHGh$#4{N?Y1u!oXlsOdT9Z zioY;0IM9TFqzuG3IGEJIfx)CEb)bn!Ny^|rQwEZf)U@|J-_P&+A^dJ=pT7Kko;&V< zx9Q)1hJN`W{NuK8{loE!hmp{|XJe7Qk@ewl$jd%*y+Z$AUL@3>8(esQ^qPNj3Zpmb ze!KUqaLLKglY*xF|FVzZxPQcC3R)M*a6xM z<>}Q@y;`PM%l)h1mE_Ay&%UNWBeW6#2s0)P=e2A?Z9~4{J!pN zaMQI5|2U8$N7gyA-jNL|-5caBDt2U}BcC}^;z+`gQkBk)@?4uBImSNwW<6u2%#kgQ zY;|OtBjt`%sEjA%^=wyZgH)>6GdombrSj45%!+9$l}~$@{_$9;+_Xw1v}v(4Lw4(# zQOF*ZkC448jhp2@)hZ*9eJb;i{VJI?UyWBYg$usu3&gvN}=Ts^yWp!S~o@sRCf+H6lX>z1l zrEI4>*Cmz2E|JTQTydmDr3b64Die;_JGbf?E7u%pQz_alujjgoUEOe`T_wIpRvnNW zV^=rzjFnrC+*Y}>SMI}@zJP@FOn$YTiKuiyqK?E=@@iz2qtaF*zfqQC#r#|&zflnR zti<-oAWsKlkfn|+Qwi;t)pC_)2#Y%kVKF~KSj@(x+=qP}f!G>G%{;`fVel}S1G1tF zL)gVRN74sn#Zo?nu#~e9ma^fHtQf~3i2RKy`-;pAgt<)B%8I!hgxFk$%?Ai`S$kMk z%;f-txtxYDm&rO=mB_o3eLekk^0$_R|NHE(I{AIZc2?KRfbD$j$a_bsQu2M|_tku# zlJ6s?buuM4Wm+qbh%l{v5T^AVglR25Dl01m=7A$`AtF4w%l})r~S{xaJFxsJvtZcMB)9lD-M!rM+a+`lL@*QfU?U}~2atlU#1j1;~FOrDK zoRbwZJ`7>T=OE1Z)AO=o#;q{pvp8cj?wN*0Sux{75N3P^!i=Xb$jW9sWCk7i0Abi` zFUpExAAm6I(-4L|*(585y&q!39x_u9hP}F3Rt)=N2*ds!!i-m4k`*&^E+<)YnZU|fc8e&@>HbvKD#g=zL*z#8pwmjY@E4I87!j`{;u;r_+%Ze?( z1FJd0jnj8z#Tq|_ zu*S0x*0|vdS=sh_W(dO4&Nz~~E48WcYxC1xsSQK?;jY}2QhRT)3_uv`X^2g;XOf+= zVw(FQJM@j1g6veO{!&&p-=294vHAAQdx*_<#8iDHE1Pf6Jc2OalMu$b@@rW!)_oAB z`5lBcF7J{R}Qx_e|njS+U_g5H@@QVjJ$6;_qZd>4wzn j`}`VWs~#~$-Lj%|L0I)y5LP{Yzjd|$zrOs2FMRwDQPTh6 diff --git a/tests/regression_tests/surface_source_write/case-10/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-10/surface_source_true.h5 index fded9d987e392214edeb3fccd50c3ecc5f8a7728..acaf39cb485cef41a634a2e980fe160b4bcc1316 100644 GIT binary patch delta 1273 zcmZ9{H*C~U7{Kwn90CIZOt%z@sj@;d5WtjxDFG9jfd`mwLVyeP5?W{>K@1rqzlAYk z%7R3cCF6}5Jz7j27(9CPz`)GON$aoA|8^p3TBDiy`}w^D1V zx!6=J@TU~CLjF-I7S#M)C{#M-ubJA6A78ERac!1U9IGb(kiH`1B)-g^63h{@jQnWL z{c~M^o|>ccgjDAX*@qa;0wKRcQ-vHr0(W8UK7Y%li)ypFxHgBEG~Oqd3TZCm-(c2- z%js)Ej-Y<`_f(tdBZjkrKD3qek-%LgXMY=gOuq-)$sJ zP9ZCZV7Cf63UwFjBZjk^^`Y%yeI#%#^3eCPK2mu5gsj5Y&-%#VA0Q92jrH3^aF9Gg zSck|%vB@KXeV9DdBjgdoIZ7VdG4e>@wv&f`oIFx^C&ppoX z56B~eT_z8;n>=DT56MG&L>>v;$K;_uA&(T^Q}QsLkw*r57NW}{IP6V2vevTDxRXrehMn{3XTlQ|zvVh)=ao2ZGV(2HCsRoaUd z6qBKXr74YIsTUSfv5-Qg7Q9eUuvAc?r7877L1+aFg4*uP`~BbiuzRE5GxNUR%3&$K)s6eoQ#Vmz%?feI6JX0@uv$4gpuV3pjbEgcK1A`&T9h*T4Ch*#;u%Cjaw zRFinOvTJuHc302SFJ)r7&vbl4^Bb%?Y?Q^9Zfv*7S~OdW z7He_9TC~cdAsa{3CVPDt7bCuMV{Pr$sU5PY-Gg48){!o2(QPeyWU;gtnqKQjpDa8% z*mgf}`%DfFdmxA$Wa7@noIxh1hzv0?eTIX`Atnp^;4{MH9+6Qdrq5Uq8E0~5KYaW| z!h|aiWP<0+6PaXUIv-||kPnp#BT2<95gjPEi0D9Z7C@x~Wu^c>42L}8y9GF6oh8wQ z5SUqF7gI!ZmaG-RB3xSRD8l!*NfvWO@Y4x$qX=`i$l=&x4D0Y1DMq_U-sfsD1Y4zG zTM5k7oBv1&9z^-(7vGeOtDlhh(l>;y6higVpD2Y;z4X5?MO!B~c}sKEn}4(n!}`sC zr3_Z_at&b~SgAMvkOy;ju+@qOJ4hrFB3^l*RvFM=4uOjW%jFnWLGX@-ck!^V0>df| zzOH~enTKCgpq(Z)UIhJ;N#^Folu7T!vbbS8^LGMGFilF6j33aTt3QQ{mC zogV8|SW31$x7uo)+a6h5tj2dIQ$#$f#&@R!B(DbMW;le3kBQ__yHN3%NIowqrxq$R zCPKxTS}dSY_WZLJXHmogcO3-9OimHe!SSFD7AiRM>tRvGf`xhvt0;L=k1eVw$@QTq zm%Y#WuwNA;7qVi+BOhM*UUqUdz^PKsKiz;vW{lXy?FOv1ngn){&P?>>a6IY1nzG{v?qX6(OJaFM9FB>ug!?g~JA6a|GTGeX!8E@<|_hns<~C@f#6+N6G7l z$7Z>TrG8lG>&fGOSm=bw8Gt}tJvp@j(pBgi#-H>LC1d%se2no#&(v zVonT`1tL0d?h(-$lRN|!Zj}M4_<%?P``jU-)5bLnm6k38)N9{mTh9k(MDfSM#eF$BIhOz@8LZ-{21OV)kpkL>)g5K#{%@l#Wn$AUR(^( zN5sq~LtG_dW|JY_5;3#MF1jYsxIi}kZW4|4?dA0(+URU*I}D<;X@y8B@8%T|9Y@Vm zP8 zG+CU+(WumVIgO){7a#QzWit?%(PfBpM09km6KNokT@)RKsk-xAJc>tC-FcoyGOr{8S#DJ_!q*N4IJC iknE5#k6|;4>|%Bv9rU&577?9C&i997@34xHw4M6+?hyw&eChq`Z1)-419YFj6h$DnU JCLa(E0RVxPKIZ@c delta 545 zcmZoMUZF8TgGobVqgE3$W5(vS%qGmzOiYXnK)}Hu0iqa~8520b42BcjlmD zm9bfZ-GgzGKnU-DAOI@|DVgjm5DgaLg=heZEW{A`3KbE6tML?!W(AoeFma>khYr5^lyIj+F#Ntt(t@qXa~42uS)7R5}bU PttlBT0*V5-W1%ttGbq0H diff --git a/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-12/surface_source_true.h5 index 6c6925daba145c5db52a281023dd017f066e0732..4b830d057dee2d3175982058352b5aae3fbb2e45 100644 GIT binary patch delta 1337 zcmY+@OKc2r9KiA2Ru~ctA{nn3B#e5ED#mlid(>;_A4`={udPRIJ?q^f9=B%ym!70t z?14n};?})sdRiCRn@Kp#aTCHEM0_{X$+F2O|M}1C=KK3kvW3Sr0Uzqa$-kZvA5r6;R)zXCQ zgECFXEJ`Et(}h%L2-yiA&P*ZSq4KbuW%P}CdB*lVt&7*y6;&kWC(9rbk8(}>@`JhxsVwY zVbybdC@VNVO0XMv{ZLnuhYx2J$A`9><0F7;k%zv9bA% z5V?)yQG}Hu55*>r66{Unp>8G*AI=u?(6*9C0CyXC=-bJojPwrjFdXs-;q4?3vyptG z$n7GJBCOryq3j`#670R?q3$COAC5~N+J5o~;2t0ky@`C2NJW1I#cl~Fe&4$-9DLK& z;=lUwXYg~O>G|m9AZ5I$|J3>NYwA~i_3QUPhg19A;g9W4Hrr1hIhl>Oy5*ocRi*{w z!#K$J2;m)Ke3*wB|FFoV86QPhM;ITx z%1ECi52KYlLU^ah!#qtMnKO|ht93S_oMQ%*U}xwED1@67P$m<0JR6yV&YEq)n=9X=>bmg+m zEj+WWHe0s!;vcru*=9@2HrH~?&8^yUv#FI!w_db#*0Q?K`99}4zm5BkKA-3LKF>Ml zUeDL_`;WfQUQBp(aYAVS$%6fU-;UEK{44#l6B2w*{4>!>r#~FOFE&yC#ksy${S!!c zV^v@8IGsMB-gkIfXYzmXk1nSYb!=L%CJ7LDh+oKku5pDlq(GG@#PkUWxyv;ZgqRv$ zoM%?jxSC1h$mDV4F(J2SU_Hq~DpEnF2r<*Ajw92A1k<2O5psyhbS8;%Vl$*B-Z_y@ zHFfM{nyQ=?)j=8scV;4(>CMdY1{oCGVojzuGus=?@dk4#D9u3YdEQKxH<<4YvMD%_ z2~7?KS2Lsfn_s~Da8>av>?7AJ%<~2dy}=?5beF|)8W-oFOFpF+&c(z63ZCU)2?duq zSW3b9Y?Kvppj$4JmgnZ-Ygx`@vP#M7ok&Ms6elW{71M%ZPA93eSrC*+i{$xO)e4%h zYd*%U@{TK&+N5l#%a{aIACuKWPG+ND(7XI{3byA&_0rbFYt>u9RP{+tvj%Gkv@M9~ zpGO6iPFa9;RCENr*JpJ5p6Fw^{Eo90&ACSH1;ULBuPrrl2PeZEL)lS_%>t zB2(whtn&u--k`x7G@pFoG61Xo!U-Wjic2U{}vAP#sAT22xp7%(P{|w?cX1S zP~ZNif~cJ*wSNV%zbqjw{pQE)2^webr_ z6-J;Avf8iqMWEKEaWew-8d8^5BUnqpE7fRKAq%-u4WV|8k{YC|B)zu==@6-}aylaE z>{=|OTF9Q--X!wU8Y1dq?SQ^PwOqClF}~tg$&FB1Um0w~m<}5Ac_YSH zOG#>ipi9Q|H9@d}1m~L|u$Ge841uu}zv^y=pqm6AH{;vwi3ckth6Wx^{UciY@Y547 z^j&}Z&woF?`dP=pK=030*>9FydFI#;RlmJo_TH%nm#U&|m%i9_AQF06gpSm6k&aP1(26AvQqa?iTI)8)T2VVh>4Y|wv)cjH7~`5Lll%)Cs{968zeULz+rKqzl0`3SQ$N zg@QXAXiur!fU+5sIn05!lUo}wp6o<_RN+R9w?49OBgShVxw#R746b)o{w4@AnK zCe~4|FqtDYdEIELZRJ2W)~DYQS2@uBv8)Ff{f^k*gW1+P=JsN?wGKmaWzs0u80&CU z#%8Fjbr@o;;{w+h>u{7I);iMq(8pTGFq0)R{TvhPA1VFVx%Q8z`>`eCAC5Z9>E-lY zWe#BbMHK8BK&|zWGXq$Fd2jetQVe8;ETE5xb(E7aEI>a)rVpa2eTH-oqD2|EaMcMW z)>eF5P-ASxQC&>RW$(=-YY+J&NcU0t zl@aVpJHz)QsI|_Jw+qc<@}2EvGAQILCe|aecSAKKHG6hrrhbupyBlMyM~prNf%OPO pj7P-(Z^AX!BQi$ORC~m;qu5A*c6FJ92^8c!9Ze-?Fpm+_;D5%jpD6$U diff --git a/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-13/surface_source_true.h5 index 6c6925daba145c5db52a281023dd017f066e0732..f53e2c3a2b0b5d0a55456dd2c6ab1ea3d7ca01af 100644 GIT binary patch delta 1337 zcmY+@OKc2r9KiA2Ru~ct(qt$xNEr1RRXUzK-s3&=kEP0}*Vd!9p7m}Kk6W||?)lEM6&wpk&-`{_d%|EUxeNXlnRoN^3bq}kP zV&GkMLv?MkDw*J;B(y~NqB@yS%lkwk+baKz)y8~%ZM6+(s3XYEKlh5AoigB&0LBvi~?m$Uqgcyq4)xE7#?He%k20SHo`+fB*m0(u8~o zWx9}A6i4*U5K^rbvJ*a>nL@rt`FYnY`iQ@)&ld6-(t3q4N5~$;_lD+1*S+&9_u^;q znw?*H*0+F09epEOorTe=aj$&8%w5Ep5bsNi`Tdg0zGtbBA-rYLJ<}Aj*A%(sLS|5a zRnPIEtl;=4!fxR8LtRN8KAcq?A6g^FM*!C%4}CSqM+xaQynYyKIX*&o>v;Vz*OOl_ zavR8_04qfvicKCx*c-`1-9#QfoXzB+Z6S{U?pE^9w~FwlUIOGw++d&@YPVzfN zZWnnJVC^OkWe<52Vecgmbsu^7a9r}x_LD~d_W*h5P2`(ID*7uZc1t+<$KI{s;M=Yi z|MkzmgJ1GZ&&M_gDdR=`=gwE(Qos8e-+cHroZ9aWe` z;~?WBgm;MXVIF4u!y=bvd=y|EVSFe@86QR1&5RHA7~{i-)57@Bjx#<2xF;ANy2tn^ zA$^iOj8^gp;hiE6^E7#6&O{2V*4c=1ju}vdouLo4jXr!h=jlVcKpz3zi}ayiqK^{N z?et+>rjHO_mOji5`W+&7g*>dQk(aE>HI9!W?Ca#A-XISj&Q0>rI>{q|dy72u+vHI~ i`VM&*cgZ7!caJ>G`{eJ7+yn9>tS;U@ly34Uc8h-=b1uvP delta 4944 zcmZXXeN5F=7{`B?`{ODaDhdktf*`1%D4>ED1@67P$m<0JR6yV&YEq)n=9X=>bmg+m zEj+WWHe0s!;vcru*=9@2HrH~?&8^yUv#FI!w_db#*0Q?K`99}4zm5BkKA-3LKF>Ml zUeDL_`;WfQUQBp(aYAVS$%6fU-;UEK{44#l6B2w*{4>!>r#~FOFE&yC#ksy${S!!c zV^v@8IGsMB-gkIfXYzmXk1nSYb!=L%CJ7LDh+oKku5pDlq(GG@#PkUWxyv;ZgqRv$ zoM%?jxSC1h$mDV4F(J2SU_Hq~DpEnF2r<*Ajw92A1k<2O5psyhbS8;%Vl$*B-Z_y@ zHFfM{nyQ=?)j=8scV;4(>CMdY1{oCGVojzuGus=?@dk4#D9u3YdEQKxH<<4YvMD%_ z2~7?KS2Lsfn_s~Da8>av>?7AJ%<~2dy}=?5beF|)8W-oFOFpF+&c(z63ZCU)2?duq zSW3b9Y?Kvppj$4JmgnZ-Ygx`@vP#M7ok&Ms6elW{71M%ZPA93eSrC*+i{$xO)e4%h zYd*%U@{TK&+N5l#%a{aIACuKWPG+ND(7XI{3byA&_0rbFYt>u9RP{+tvj%Gkv@M9~ zpGO6iPFa9;RCENr*JpJ5p6Fw^{Eo90&ACSH1;ULBuPrrl2PeZEL)lS_%>t zB2(whtn&u--k`x7G@pFoG61Xo!U-Wjic2U{}vAP#sAT22xp7%(P{|w?cX1S zP~ZNif~cJ*wSNV%zbqjw{pQE)2^webr_ z6-J;Avf8iqMWEKEaWew-8d8^5BUnqpE7fRKAq%-u4WV|8k{YC|B)zu==@6-}aylaE z>{=|OTF9Q--X!wU8Y1dq?SQ^PwOqClF}~tg$&FB1Um0w~m<}5Ac_YSH zOG#>ipi9Q|H9@d}1m~L|u$Ge841uu}zv^y=pqm6AH{;vwi3ckth6Wx^{UciY@Y547 z^j&}Z&woF?`dP=pK=030*>9FydFI#;RlmJo_TH%nm#U&|m%i9_AQF06gpSm6k&aP1(26AvQqa?iTI)8)T2VVh>4Y|wv)cjH7~`5Lll%)Cs{968zeULz+rKqzl0`3SQ$N zg@QXAXiur!fU+5sIn05!lUo}wp6o<_RN+R9w?49OBgShVxw#R746b)o{w4@AnK zCe~4|FqtDYdEIELZRJ2W)~DYQS2@uBv8)Ff{f^k*gW1+P=JsN?wGKmaWzs0u80&CU z#%8Fjbr@o;;{w+h>u{7I);iMq(8pTGFq0)R{TvhPA1VFVx%Q8z`>`eCAC5Z9>E-lY zWe#BbMHK8BK&|zWGXq$Fd2jetQVe8;ETE5xb(E7aEI>a)rVpa2eTH-oqD2|EaMcMW z)>eF5P-ASxQC&>RW$(=-YY+J&NcU0t zl@aVpJHz)QsI|_Jw+qc<@}2EvGAQILCe|aecSAKKHG6hrrhbupyBlMyM~prNf%OPO pj7P-(Z^AX!BQi$ORC~m;qu5A*c6FJ92^8c!9Ze-?Fpm+_;D5%jpD6$U diff --git a/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-14/surface_source_true.h5 index 6c6925daba145c5db52a281023dd017f066e0732..ec049fec48a990387c41b36f590e7ee85eb667eb 100644 GIT binary patch delta 1337 zcmY+@Ic(EV9DwnpMPQJi283iTVL$>?E>kXZHKttVDuzC2pcKpB%ljhvw=E=1!c5U29J?I-~l1N$h88IetLd(qVNAKrSPPt{4LpQ)MT%|uYXjV z6oYSTSJlo;)+7^rl!TV3T+}8LYGt2DWKYW9W3@3O1J?OLZJd*QUkLsqJw?dRqx!~+ z+=OUb99`o_@oG;LGLLxgPZH9ptL{He7BWzUtgIFKlF*8$PnK0=$>f`*=LH}3L!Hn z!fN37P*!q$lwhyo^+R1v9zL8k93R?Rj*kGYMIQP(j*l|Z>v{b!HgJ4|@HX=LVQwP7 zN#q*IqX;WS9*RvKCD@zELv11tAI=u?(6*9C0CyXC=-bJojPwrjFdXs-;q4?3a~Jtt zBDb47im>*Ohq9MEO0b*BL)}LnJ{*@kwEg4}z&$`7dJFj$k&6BbirpU8eQ(|t4!!Aa z_XmFb8Twjic`>#vNEt61zI44BN&U*Nef{C*aB9Ch{Hfz5l#!2!B;hiE6^E7#6&P0l=*4c=1ju}vbouLo)Jbn0ZF3^W|kv;;rm*_*kOdn;W zJLto>LLVW#EPa@r^gBiFDtTDfBK@q&b&ih`>>K2v-Xsqn&MorLy2vAddz(D;JLFMD i`Yw4G_sAoJcb`1W2jm}!+(YuCtZv>ulpgXZ^@zVHcP`EV delta 4944 zcmZXXeN5F=7{`B?`{ODaDhdktf*`1%D4>ED1@67P$m<0JR6yV&YEq)n=9X=>bmg+m zEj+WWHe0s!;vcru*=9@2HrH~?&8^yUv#FI!w_db#*0Q?K`99}4zm5BkKA-3LKF>Ml zUeDL_`;WfQUQBp(aYAVS$%6fU-;UEK{44#l6B2w*{4>!>r#~FOFE&yC#ksy${S!!c zV^v@8IGsMB-gkIfXYzmXk1nSYb!=L%CJ7LDh+oKku5pDlq(GG@#PkUWxyv;ZgqRv$ zoM%?jxSC1h$mDV4F(J2SU_Hq~DpEnF2r<*Ajw92A1k<2O5psyhbS8;%Vl$*B-Z_y@ zHFfM{nyQ=?)j=8scV;4(>CMdY1{oCGVojzuGus=?@dk4#D9u3YdEQKxH<<4YvMD%_ z2~7?KS2Lsfn_s~Da8>av>?7AJ%<~2dy}=?5beF|)8W-oFOFpF+&c(z63ZCU)2?duq zSW3b9Y?Kvppj$4JmgnZ-Ygx`@vP#M7ok&Ms6elW{71M%ZPA93eSrC*+i{$xO)e4%h zYd*%U@{TK&+N5l#%a{aIACuKWPG+ND(7XI{3byA&_0rbFYt>u9RP{+tvj%Gkv@M9~ zpGO6iPFa9;RCENr*JpJ5p6Fw^{Eo90&ACSH1;ULBuPrrl2PeZEL)lS_%>t zB2(whtn&u--k`x7G@pFoG61Xo!U-Wjic2U{}vAP#sAT22xp7%(P{|w?cX1S zP~ZNif~cJ*wSNV%zbqjw{pQE)2^webr_ z6-J;Avf8iqMWEKEaWew-8d8^5BUnqpE7fRKAq%-u4WV|8k{YC|B)zu==@6-}aylaE z>{=|OTF9Q--X!wU8Y1dq?SQ^PwOqClF}~tg$&FB1Um0w~m<}5Ac_YSH zOG#>ipi9Q|H9@d}1m~L|u$Ge841uu}zv^y=pqm6AH{;vwi3ckth6Wx^{UciY@Y547 z^j&}Z&woF?`dP=pK=030*>9FydFI#;RlmJo_TH%nm#U&|m%i9_AQF06gpSm6k&aP1(26AvQqa?iTI)8)T2VVh>4Y|wv)cjH7~`5Lll%)Cs{968zeULz+rKqzl0`3SQ$N zg@QXAXiur!fU+5sIn05!lUo}wp6o<_RN+R9w?49OBgShVxw#R746b)o{w4@AnK zCe~4|FqtDYdEIELZRJ2W)~DYQS2@uBv8)Ff{f^k*gW1+P=JsN?wGKmaWzs0u80&CU z#%8Fjbr@o;;{w+h>u{7I);iMq(8pTGFq0)R{TvhPA1VFVx%Q8z`>`eCAC5Z9>E-lY zWe#BbMHK8BK&|zWGXq$Fd2jetQVe8;ETE5xb(E7aEI>a)rVpa2eTH-oqD2|EaMcMW z)>eF5P-ASxQC&>RW$(=-YY+J&NcU0t zl@aVpJHz)QsI|_Jw+qc<@}2EvGAQILCe|aecSAKKHG6hrrhbupyBlMyM~prNf%OPO pj7P-(Z^AX!BQi$ORC~m;qu5A*c6FJ92^8c!9Ze-?Fpm+_;D5%jpD6$U diff --git a/tests/regression_tests/surface_source_write/case-15/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-15/surface_source_true.h5 index 5bdb39b2a703fa7cdb17a153a688cb0ea7664f1c..fd5892096c58be336ca5c9fea4b7afc60dd66dbb 100644 GIT binary patch delta 30 mcmaDL@IYY08fM0j&1;!Wm>C%-KVmatdA7(RbF&1y2O|Ki$_gd` delta 30 mcmaDL@IYY08fM0f&1;!Wm>HQSKVmatxuw3WrHw1^ml1Um% z$I8YT85+x5Ql9dZ#~F*1DNkYHL+Lm3%zSV4TR*up{4+k4Ev+3nz4fQ%aX9nG^0wto z;&Xd6THD|Kdwz0W|68$oCb?i`e0shApYC9^(w&V$mv0E&FB?L8 zVdxGqrMM_`zY<*>x;17@E(zW5#FvKdD09loLiZ<09J=H5RF{YDFVZVQ_cH_am7!ZF zyDD_2SkPP@y0hdP zE>FH)etT%2kY`Hqq&(3?o*9#;&Z^@IqEl*GNjy!22&p`dIJlTGE7Buh4lOK>j5Zd?U znNl2-C;C918Iwcu#H;eFd%M3^_jKil@+2S0(^GvcPx^^G1NEo!WS_~ipjneAKP-PZ zv`6HbQhY8?^o2Y#CSS@EeCnqp4o};AC~9`mjD0& delta 4944 zcmZXXZ%EZ=6vw^SKc%Jl@2b~->CJ0i>)JH6tkkr$Zp~X(T56VBEp=H_C@?5cR!~sP zE(HYz1_lO=N%W$?n1O=^?VUk^vc?L0Va%XGV{P;KeJ{^*c8+iIe9rlPzvn#SCI9%{ z_T#tq@AB-M2gmXULv5W8AA}Z%rrGVbkcF?sAt~ygkWgFOV(XibU;6`pN2G+!cz*7D zn6k)k3q-{FqyJs_vgXxHpf0wBkzqkT3gV07s@sCh3sMu`5^kjrjX47M;`u6bwCzvu zo7uYwe0Da0FHoLH%TPUEW6f;<-_Bb}^r zKAo>JN!z&@yxo%lb(lKjmtZ?gzl9?cD;d%y$ap5P$Xt#DBRIC4TRavdI*ZS=XA#q9 zS==--n+sY6851Pj#Z^r%67$5xV{9wX4p*$RI{W_zx9hHOMENk{q4rU|t>_`r* zB9v8xo44!SSj`BA-9%u|q4{7ybu(~BoeJ~FF zkQ8_)x?V4KHuD35OnH$Xsh+5`00EKuP0tmO_DlipvSy3c@Y((~WcKwMGF$KkDF$ir zk{0=e+_JY27np@61#uSfnI1tVipXlNwb&*~oqT33GNbg#<7?q(NL(?<5UzNNXtsOO^T4QkYvs{5qJM*`{@5_Q^WTMk`^= zddx=aq=xlKGGtVc&w|vKan*<*pUSXBj0$evfZ!M%JiGxGhI|ynw-GbTwCc7X^BWPf zOvUWkgk!DZ-X>%k_1q>h>n}$;R-0chN1P$Ef|OVAnV|}p#;OHARB+R>O47bn$=h!# zxnId|wA&AalhytoU{w_C`gj@7LhxVnWQqi zcOug&p6*1ZnGOFE35GNY@<0$<9aPCWvq6wiK|Tvo@8>=vf_w@R{B^Mq7^vHY`%=_> z-|xbGR$<>wibh)8r^P?J@eIbYrXGtJa#N5wL8|s})pbE;_mE|G?B&5jd%4A1LCW^= znJfE<>HB@;=;{WZaH#=mr~X+@H$d%F?^n?XwN+eegxbu$YUFC~eoh7inc7bhN)PA8q_`L?($v`NCb*>QGqRiElCIi=&Ak1*8G9N*Mhg*~Z{dPT z+RiR28W;6Akc4khnuoXDW5ypwG)dc?O4F_i|HUmM+Y|_?I6Oa zBfMRIgeQ$0A%cjb5M=A?>W)HS$gm(E1@Rr@s@sCh3sUnHSKSN}m)>VikgDTQnVIXy zags~D|DVTkl4+NBlJ=cW-hNBlwOx2^%j#AapMBHCvrD>(`HgM}R_OJoyCE>7@M}&k z2=XdOaC%-KVmatdA-OYbF&1y2O|Ki_X;Zj delta 30 mcmaDL@IYY08fM0f&1;!Wm>HQSKVmatxvzODW3vRi2O|Kkf(lFk diff --git a/tests/regression_tests/surface_source_write/case-18/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-18/surface_source_true.h5 index e5a7619c552c4321cdcaa3710363e430fa57516b..436063aee23677c481b9cec5ff8e6c8791d021b7 100644 GIT binary patch delta 30 mcmaDL@IYY08fM0j&1;!Wm>C%-KVmatdA-OYbF&1y2O|Ki_X;Zj delta 30 mcmaDL@IYY08fM0f&1;!Wm>HQSKVmatd7ybJW3vRi2O|KkiwaEu diff --git a/tests/regression_tests/surface_source_write/case-19/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-19/surface_source_true.h5 index db8a49dceeb20ebdc3e0c1b8db765cafed5a4052..eda3e030bda7d7bc798329e59061173d516ec10c 100644 GIT binary patch delta 30 mcmaDL@IYY08fM0j&1;!Wm>C%-KVmatdArCWbF&1y2O|Kj2?{L$ delta 30 mcmaDL@IYY08fM0f&1;!Wm>HQSKVmatd8m0RW3vRi2O|KklnPD& diff --git a/tests/regression_tests/surface_source_write/case-20/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-20/surface_source_true.h5 index 01d2abf61cf8a41876d664d1aa505a967e7559cb..083ce90c8964c549b597eceef343401fe63fd70d 100644 GIT binary patch delta 1270 zcmY+ls^*pfT-a5zzsJ9$HJ0H8cWB@ z#u*tJ%U4pSOnD27+j+}dSol$TX1!sPfuhkYlly6`*C#|PW`dEeRb1x zWjZm@B$=F9R;QEr%srW`?d$(NJ2~s0--?5$l5?u*$@TgF^lcRS)8rdM|I3EZog4ZC z3>4>u{#T;&L%+sIc|quZC%!QBN0?Dv6#73&;?N&sPJMCc|02C4^gpwpxis|aWS52h z1WVe><;ge7Zw%cP@(dJ-Jkgc%jFeZ&6K|4dMs>A3$u;uKsjrnMy-uD5O)5{eS)S$Q z-TmGzyZX~xSlS8ZSu^iZ;>axRh|XSZSrKd z%d@1t!}sL5d>*H4=Jag(N8CXF>C{JXs~rlJ*&S z@}2TKL-(va1I2UlM9<4JQobNh{GvQFs#>1pC3)u5FUynel4n5^2@*6TK$SNcp-v@f-5YsNR$(c}t!-_1p5Ktvm~wz4B!HY1ib*56K@2-C=nK ziqGVUK9^^t{6e1iOL=BgU&)gkk!Mc*wLIxJ@+@e+l_&d7o+a(~^5jS5kB06Cc?ODO M@a{)f)KgDA_0&_(7WK3gQLv?jwzQ=Q0|Nu5 z3=AZt|1dBxFfcGM5W~PgQU(T^FfcGMkd&kh3?yY>ASr1N-|yZ_|34PYC-3|I|C59~ z{rfNH_g{R!p7h;#Gk)q#q0{nqtnhqcwa@1iH$WEP!`=v7JBUvVi?ekW>BugaG{obkvvP<7*5rQ9Q?r$Sf zDOHKibVJ@#Ss)2lNwr&Nx=7|Br8*NjAeBic$s9?r+FNx%KG4mxB!PoceW)|-ki9B1 zkP3+7Rt2OoX(O42_;ru}kW?nEBvT~ihrLxZWS?%Hgd9*QJtCD!6Qo*aCLjTolAu(F zR2m>hRK`h)j!I=SbtGeupzd*wNoA5H870|*9MwIwHL}NKq~^u$+%KDBIbX{ZkUEuRlGqKYY^E1duhkMsG%1zM z^gv!}wFr5o61gdrNjJ#?q*1HzEvcGRx=7|pLbs)QtyL$)QJI6-nHfw;Wzs=1OA@#v zRgrFPhuA4PR` zmfrt=<+x1{J4Gi*N*+jMGYur;Bt;LUvU9bLWDHWKpTfyVWs)TsCE0?MV~@|ReI$EK zMj(6iS(^|$X)~WnWikxOpR@(;21)uescdElVyEajNvc*Vn;9foBS}7%YQKJp0g_dc z#1n7TPqG4$f3)V-yYZ(|Rq3<(NR}aXP{*=Tne>t@L8^6g^qEv9JtT`Hk>^q!)IHrK z3lKZ!!=FoK(nT^4v6DYkCzVMjB&biHBME*Xm7U=oko+C)xU(dIdZ}!ton(fj>V>yz zgB-^jI_@-yzdXh+XEBB&DyUvRl0gVwd>@NlBwrc851W><%9% zDQc3+?(jNDRDWJ$kaH@|YpLwY%|h~5uH%kE?55o!sr^#+*vtsYCd97X%vVxf()SsL z*iE|uv70vCEY%gQhDg>ScEP5;mda!ha!vQFktDy7%4P;gR!I^q-l`vB*YXNUyj7~3 z`aXRm%OtUHrMjh6FUb-~^gD0W1G%kx79nC%-KVmat`LxI)bF&1y2O|KjHVQHT delta 30 mcmaDL@IYY08fM0f&1;!Wm>HQSKVmatd8BzNW3vRi2O|KkoeEC? diff --git a/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 b/tests/regression_tests/surface_source_write/case-a01/surface_source_true.h5 index da36fc505eb67f3da0ce48511464b699a4fb16e3..807211e3ac16e7c7c452f6fd43079e2a4cfa71ea 100644 GIT binary patch delta 252 zcmY+-FAM=;7zXg~bH@39{+-WkCYmH%xFCq4@B~q$T@+0c&09p16dO~-i=rrs;srqv zJfe5|?RnnxgkIEJwPQi^)LB>>=Y!>04IR^pXDg$A#nQ_8{YnLS`6NvIwezQElN{(% z`1~Vd8*-&?3bILIorX;4Mt%ljXCZgmviEb4fPK$&@{k!lXi$J0$vBWXJ!x2kT&Puo nEGeQ<84^;v0$I_x3VAcH%&yCM7wa15=|;ZcEZKF=(!Gu^BJ)*K delta 850 zcmexhbHHSR29tx-My)1h#*EEtnN66bnV1+EfPjNR0z@$|GbV6=84M2uC;wrSU`evS zlCfEW-GgzGKnU-DAOI@|DVgjm5DgaLg=heZEW{A`iXq}D7|j7PM+juZ48a7j5m9g> zJ_ Date: Fri, 12 Dec 2025 08:21:46 +0200 Subject: [PATCH 74/76] IFP creates fatal error in all run modes except eigenvalue. (#3681) --- src/tallies/tally.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index 9daeb1d69f..6eef1da9cf 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -215,7 +215,7 @@ Tally::Tally(pugi::xml_node node) "number of inactive cycles."); } settings::ifp_on = true; - } else { + } else if (settings::run_mode == RunMode::FIXED_SOURCE) { fatal_error( "Iterated Fission Probability can only be used in an eigenvalue " "calculation."); From bbfa18d72c34d8710b5f4f3fa1fff54f5248fcc5 Mon Sep 17 00:00:00 2001 From: Kevin Sawatzky <66632997+nuclearkevin@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:29:43 -0600 Subject: [PATCH 75/76] Add a command-line argument for output verbosity (#3680) Co-authored-by: Paul Romano --- docs/source/usersguide/scripts.rst | 1 + man/man1/openmc.1 | 3 +++ src/finalize.cpp | 2 +- src/initialize.cpp | 13 ++++++++++++- src/output.cpp | 1 + src/settings.cpp | 6 ++++-- 6 files changed, 22 insertions(+), 4 deletions(-) diff --git a/docs/source/usersguide/scripts.rst b/docs/source/usersguide/scripts.rst index 0879d63efd..eb0abeb0dd 100644 --- a/docs/source/usersguide/scripts.rst +++ b/docs/source/usersguide/scripts.rst @@ -48,6 +48,7 @@ flags: restart file -s, --threads N Run with *N* OpenMP threads -t, --track Write tracks for all particles (up to max_tracks) +-q, --verbosity V Set the output verbosity to *V* -v, --version Show version information -h, --help Show help message diff --git a/man/man1/openmc.1 b/man/man1/openmc.1 index 7826a759a1..30e8b2ce47 100644 --- a/man/man1/openmc.1 +++ b/man/man1/openmc.1 @@ -39,6 +39,9 @@ Use \fIN\fP OpenMP threads. .B "\-t\fR, \fP\-\-track" Write tracks for all particles (up to max_tracks). .TP +.BI \-q " V" "\fR,\fP \-\-verbosity" " V" +Set the output verbosity to \fIV\fP. +.TP .B "\-v\fR, \fP\-\-version" Show version information. .TP diff --git a/src/finalize.cpp b/src/finalize.cpp index 9ee9434099..344eaa1a0a 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -142,7 +142,7 @@ int openmc_finalize() settings::uniform_source_sampling = false; settings::ufs_on = false; settings::urr_ptables_on = true; - settings::verbosity = 7; + settings::verbosity = -1; settings::weight_cutoff = 0.25; settings::weight_survive = 1.0; settings::weight_windows_file.clear(); diff --git a/src/initialize.cpp b/src/initialize.cpp index e2a5b97433..a2269ed1ea 100644 --- a/src/initialize.cpp +++ b/src/initialize.cpp @@ -226,6 +226,15 @@ int parse_command_line(int argc, char* argv[]) i += 1; settings::n_particles = std::stoll(argv[i]); + } else if (arg == "-q" || arg == "--verbosity") { + i += 1; + settings::verbosity = std::stoi(argv[i]); + if (settings::verbosity > 10 || settings::verbosity < 1) { + auto msg = fmt::format("Invalid verbosity: {}.", settings::verbosity); + strcpy(openmc_err_msg, msg.c_str()); + return OPENMC_E_INVALID_ARGUMENT; + } + } else if (arg == "-e" || arg == "--event") { settings::event_based = true; } else if (arg == "-r" || arg == "--restart") { @@ -376,8 +385,10 @@ bool read_model_xml() auto settings_root = root.child("settings"); // Verbosity - if (check_for_node(settings_root, "verbosity")) { + if (check_for_node(settings_root, "verbosity") && settings::verbosity == -1) { settings::verbosity = std::stoi(get_node_value(settings_root, "verbosity")); + } else if (settings::verbosity == -1) { + settings::verbosity = 7; } // To this point, we haven't displayed any output since we didn't know what diff --git a/src/output.cpp b/src/output.cpp index 0a14e8843d..80e2b10ab8 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -281,6 +281,7 @@ void print_usage() " -t, --track Write tracks for all particles (up to " "max_tracks)\n" " -e, --event Run using event-based parallelism\n" + " -q, --verbosity Output verbosity\n" " -v, --version Show version information\n" " -h, --help Show this message\n"); } diff --git a/src/settings.cpp b/src/settings.cpp index d47e9b5e6b..5b472468fc 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -145,7 +145,7 @@ int trace_gen; int64_t trace_particle; vector> track_identifiers; int trigger_batch_interval {1}; -int verbosity {7}; +int verbosity {-1}; double weight_cutoff {0.25}; double weight_survive {1.0}; @@ -396,8 +396,10 @@ void read_settings_xml() xml_node root = doc.document_element(); // Verbosity - if (check_for_node(root, "verbosity")) { + if (check_for_node(root, "verbosity") && verbosity == -1) { verbosity = std::stoi(get_node_value(root, "verbosity")); + } else if (verbosity == -1) { + verbosity = 7; } // To this point, we haven't displayed any output since we didn't know what From d1183566383e38e96c97db195613c407f9a5c091 Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Wed, 17 Dec 2025 00:10:07 -0600 Subject: [PATCH 76/76] Use MeshBase method to check replicated. Add header for replicated mesh (#3689) --- src/mesh.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mesh.cpp b/src/mesh.cpp index 610d057cf0..c3a2d45818 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -51,6 +51,7 @@ #include "libmesh/mesh_modification.h" #include "libmesh/mesh_tools.h" #include "libmesh/numeric_vector.h" +#include "libmesh/replicated_mesh.h" #endif #ifdef OPENMC_DAGMC_ENABLED @@ -3435,7 +3436,7 @@ LibMesh::LibMesh(hid_t group) : UnstructuredMesh(group) // create the mesh from a pointer to a libMesh Mesh LibMesh::LibMesh(libMesh::MeshBase& input_mesh, double length_multiplier) { - if (!dynamic_cast(&input_mesh)) { + if (!input_mesh.is_replicated()) { fatal_error("At present LibMesh tallies require a replicated mesh. Please " "ensure 'input_mesh' is a libMesh::ReplicatedMesh."); }