From 62d1771e5f5d965e706792f6546c909223db0002 Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:04:25 -0600 Subject: [PATCH 1/6] Move random ray run and reset functions to the C-API. --- include/openmc/capi.h | 2 + .../openmc/random_ray/random_ray_simulation.h | 2 - src/random_ray/random_ray_simulation.cpp | 113 +++++++++--------- 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/include/openmc/capi.h b/include/openmc/capi.h index d8041ef4149..22c0fd8f6c6 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -140,6 +140,8 @@ int openmc_remove_tally(int32_t index); int openmc_reset(); int openmc_reset_timers(); int openmc_run(); +void openmc_run_random_ray(); +void openmc_reset_random_ray(); int openmc_sample_external_source(size_t n, uint64_t* seed, void* sites); void openmc_set_seed(int64_t new_seed); void openmc_set_stride(uint64_t new_stride); diff --git a/include/openmc/random_ray/random_ray_simulation.h b/include/openmc/random_ray/random_ray_simulation.h index 3db6510697c..711ad37dbfe 100644 --- a/include/openmc/random_ray/random_ray_simulation.h +++ b/include/openmc/random_ray/random_ray_simulation.h @@ -66,9 +66,7 @@ class RandomRaySimulation { //! Non-member functions //============================================================================ -void openmc_run_random_ray(); void validate_random_ray_inputs(); -void openmc_reset_random_ray(); void print_adjoint_header(); } // namespace openmc diff --git a/src/random_ray/random_ray_simulation.cpp b/src/random_ray/random_ray_simulation.cpp index 7bab3a9b1b6..863e012eb62 100644 --- a/src/random_ray/random_ray_simulation.cpp +++ b/src/random_ray/random_ray_simulation.cpp @@ -1,5 +1,6 @@ #include "openmc/random_ray/random_ray_simulation.h" +#include "openmc/capi.h" #include "openmc/eigenvalue.h" #include "openmc/geometry.h" #include "openmc/message_passing.h" @@ -22,49 +23,6 @@ namespace openmc { // Non-member functions //============================================================================== -void openmc_run_random_ray() -{ - ////////////////////////////////////////////////////////// - // Run forward simulation - ////////////////////////////////////////////////////////// - - if (mpi::master) { - if (FlatSourceDomain::adjoint_) { - FlatSourceDomain::adjoint_ = false; - openmc::print_adjoint_header(); - FlatSourceDomain::adjoint_ = true; - } - } - - // Initialize OpenMC general data structures - openmc_simulation_init(); - - // Validate that inputs meet requirements for random ray mode - if (mpi::master) - validate_random_ray_inputs(); - - // Initialize Random Ray Simulation Object - RandomRaySimulation sim; - - // Initialize fixed sources, if present - sim.apply_fixed_sources_and_mesh_domains(); - - // Run initial random ray simulation - sim.simulate(); - - ////////////////////////////////////////////////////////// - // Run adjoint simulation (if enabled) - ////////////////////////////////////////////////////////// - - if (sim.adjoint_needed_) { - // Setup for adjoint simulation - sim.prepare_adjoint_simulation(); - - // Run adjoint simulation - sim.simulate(); - } -} - // Enforces restrictions on inputs in random ray mode. While there are // many features that don't make sense in random ray mode, and are therefore // unsupported, we limit our testing/enforcement operations only to inputs @@ -283,17 +241,6 @@ void validate_random_ray_inputs() } } -void openmc_reset_random_ray() -{ - FlatSourceDomain::volume_estimator_ = RandomRayVolumeEstimator::HYBRID; - FlatSourceDomain::volume_normalized_flux_tallies_ = false; - FlatSourceDomain::adjoint_ = false; - FlatSourceDomain::mesh_domain_map_.clear(); - RandomRay::ray_source_.reset(); - RandomRay::source_shape_ = RandomRaySourceShape::FLAT; - RandomRay::sample_method_ = RandomRaySampleMethod::PRNG; -} - void print_adjoint_header() { if (!FlatSourceDomain::adjoint_) @@ -671,3 +618,61 @@ void RandomRaySimulation::print_results_random_ray( } } // namespace openmc + +//============================================================================== +// C API functions +//============================================================================== + +void openmc_run_random_ray() +{ + ////////////////////////////////////////////////////////// + // Run forward simulation + ////////////////////////////////////////////////////////// + + if (openmc::mpi::master) { + if (openmc::FlatSourceDomain::adjoint_) { + openmc::FlatSourceDomain::adjoint_ = false; + openmc::print_adjoint_header(); + openmc::FlatSourceDomain::adjoint_ = true; + } + } + + // Initialize OpenMC general data structures + openmc_simulation_init(); + + // Validate that inputs meet requirements for random ray mode + if (openmc::mpi::master) + openmc::validate_random_ray_inputs(); + + // Initialize Random Ray Simulation Object + openmc::RandomRaySimulation sim; + + // Initialize fixed sources, if present + sim.apply_fixed_sources_and_mesh_domains(); + + // Run initial random ray simulation + sim.simulate(); + + ////////////////////////////////////////////////////////// + // Run adjoint simulation (if enabled) + ////////////////////////////////////////////////////////// + + if (sim.adjoint_needed_) { + // Setup for adjoint simulation + sim.prepare_adjoint_simulation(); + + // Run adjoint simulation + sim.simulate(); + } +} + +void openmc_reset_random_ray() +{ + openmc::FlatSourceDomain::volume_estimator_ = openmc::RandomRayVolumeEstimator::HYBRID; + openmc::FlatSourceDomain::volume_normalized_flux_tallies_ = false; + openmc::FlatSourceDomain::adjoint_ = false; + openmc::FlatSourceDomain::mesh_domain_map_.clear(); + openmc::RandomRay::ray_source_.reset(); + openmc::RandomRay::source_shape_ = openmc::RandomRaySourceShape::FLAT; + openmc::RandomRay::sample_method_ = openmc::RandomRaySampleMethod::PRNG; +} From 313b218ef8728d6f809d51c3cd460871f1372456 Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Fri, 23 Jan 2026 14:24:24 -0600 Subject: [PATCH 2/6] Python bindings and docs. --- docs/source/capi/index.rst | 8 ++++++++ docs/source/pythonapi/capi.rst | 1 + openmc/lib/core.py | 21 +++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index 2583d51dff2..efd3c11ddd9 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -587,6 +587,10 @@ Functions :return: Return status (negative if an error occurs) :rtype: int +.. c:function:: void openmc_reset_random_ray() + + Reset the random ray solver + .. c:function:: int openmc_remove_tally(int32_t index); Given an index of a tally, remove it from the tallies array @@ -601,6 +605,10 @@ Functions :return: Return status (negative if an error occurs) :rtype: int +.. c:function:: void openmc_run_random_ray() + + Run a random ray simulation + .. c:function:: int openmc_set_n_batches(int32_t n_batches, bool set_max_batches, bool add_statepoint_batch) Set number of batches and number of max batches diff --git a/docs/source/pythonapi/capi.rst b/docs/source/pythonapi/capi.rst index 67eca009471..772523356e4 100644 --- a/docs/source/pythonapi/capi.rst +++ b/docs/source/pythonapi/capi.rst @@ -38,6 +38,7 @@ Functions property_map reset reset_timers + reset_random_ray run run_in_memory sample_external_source diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 02c7784d1cc..c354e560ce2 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -82,8 +82,12 @@ class _SourceSite(Structure): _dll.openmc_properties_import.errcheck = _error_handler _dll.openmc_run.restype = c_int _dll.openmc_run.errcheck = _error_handler +_dll.openmc_run_random_ray.restype = None +_dll.openmc_run_random_ray.errcheck = _error_handler _dll.openmc_reset.restype = c_int _dll.openmc_reset.errcheck = _error_handler +_dll.openmc_reset_random_ray.restype = None +_dll.openmc_reset_random_ray.errcheck = _error_handler _dll.openmc_reset_timers.restype = c_int _dll.openmc_reset_timers.errcheck = _error_handler _run_linsolver_argtypes = [_array_1d_dble, _array_1d_dble, _array_1d_dble, @@ -458,6 +462,11 @@ def reset(): _dll.openmc_reset() +def reset_random_ray(): + """Reset the random ray solver""" + _dll.openmc_reset_random_ray() + + def reset_timers(): """Reset timers.""" _dll.openmc_reset_timers() @@ -479,6 +488,18 @@ def run(output=True): _dll.openmc_run() +def run_random_ray(output=True): + """Run a random ray simulation + + Parameters + ---------- + output : bool, optional + Whether or not to show output. Defaults to showing output + """ + + with quiet_dll(output): + _dll.openmc_run_random_ray() + def sample_external_source( n_samples: int = 1000, prn_seed: int | None = None From 225283da388dbd34325aca2d6398ab8e2073635c Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Fri, 23 Jan 2026 15:39:37 -0600 Subject: [PATCH 3/6] Style changes. --- src/random_ray/random_ray_simulation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/random_ray/random_ray_simulation.cpp b/src/random_ray/random_ray_simulation.cpp index 863e012eb62..4a2afdb9893 100644 --- a/src/random_ray/random_ray_simulation.cpp +++ b/src/random_ray/random_ray_simulation.cpp @@ -668,7 +668,8 @@ void openmc_run_random_ray() void openmc_reset_random_ray() { - openmc::FlatSourceDomain::volume_estimator_ = openmc::RandomRayVolumeEstimator::HYBRID; + openmc::FlatSourceDomain::volume_estimator_ = + openmc::RandomRayVolumeEstimator::HYBRID; openmc::FlatSourceDomain::volume_normalized_flux_tallies_ = false; openmc::FlatSourceDomain::adjoint_ = false; openmc::FlatSourceDomain::mesh_domain_map_.clear(); From cc88df6db8573f5ad02962088063ad59a43d5f62 Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Sat, 24 Jan 2026 12:17:01 -0600 Subject: [PATCH 4/6] Remove openmc_reset_random_ray from the C-API - This is handled in openmc_finalize - Also rename openmc_reset_random_ray to openmc_finalize_random_ray (more clear IMO) --- docs/source/capi/index.rst | 4 ---- docs/source/pythonapi/capi.rst | 2 +- include/openmc/capi.h | 1 - .../openmc/random_ray/random_ray_simulation.h | 1 + openmc/lib/core.py | 8 ------- src/finalize.cpp | 2 +- src/random_ray/random_ray_simulation.cpp | 23 +++++++++---------- 7 files changed, 14 insertions(+), 27 deletions(-) diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index efd3c11ddd9..0a1962f7722 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -587,10 +587,6 @@ Functions :return: Return status (negative if an error occurs) :rtype: int -.. c:function:: void openmc_reset_random_ray() - - Reset the random ray solver - .. c:function:: int openmc_remove_tally(int32_t index); Given an index of a tally, remove it from the tallies array diff --git a/docs/source/pythonapi/capi.rst b/docs/source/pythonapi/capi.rst index 772523356e4..6f18db56f36 100644 --- a/docs/source/pythonapi/capi.rst +++ b/docs/source/pythonapi/capi.rst @@ -38,9 +38,9 @@ Functions property_map reset reset_timers - reset_random_ray run run_in_memory + run_random_ray sample_external_source simulation_finalize simulation_init diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 22c0fd8f6c6..868cca8f491 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -141,7 +141,6 @@ int openmc_reset(); int openmc_reset_timers(); int openmc_run(); void openmc_run_random_ray(); -void openmc_reset_random_ray(); int openmc_sample_external_source(size_t n, uint64_t* seed, void* sites); void openmc_set_seed(int64_t new_seed); void openmc_set_stride(uint64_t new_stride); diff --git a/include/openmc/random_ray/random_ray_simulation.h b/include/openmc/random_ray/random_ray_simulation.h index 711ad37dbfe..68c7779edad 100644 --- a/include/openmc/random_ray/random_ray_simulation.h +++ b/include/openmc/random_ray/random_ray_simulation.h @@ -68,6 +68,7 @@ class RandomRaySimulation { void validate_random_ray_inputs(); void print_adjoint_header(); +void openmc_finalize_random_ray(); } // namespace openmc diff --git a/openmc/lib/core.py b/openmc/lib/core.py index c354e560ce2..9eba337b4a9 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -83,11 +83,8 @@ class _SourceSite(Structure): _dll.openmc_run.restype = c_int _dll.openmc_run.errcheck = _error_handler _dll.openmc_run_random_ray.restype = None -_dll.openmc_run_random_ray.errcheck = _error_handler _dll.openmc_reset.restype = c_int _dll.openmc_reset.errcheck = _error_handler -_dll.openmc_reset_random_ray.restype = None -_dll.openmc_reset_random_ray.errcheck = _error_handler _dll.openmc_reset_timers.restype = c_int _dll.openmc_reset_timers.errcheck = _error_handler _run_linsolver_argtypes = [_array_1d_dble, _array_1d_dble, _array_1d_dble, @@ -462,11 +459,6 @@ def reset(): _dll.openmc_reset() -def reset_random_ray(): - """Reset the random ray solver""" - _dll.openmc_reset_random_ray() - - def reset_timers(): """Reset timers.""" _dll.openmc_reset_timers() diff --git a/src/finalize.cpp b/src/finalize.cpp index 344eaa1a0a7..8eb37bb8650 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -184,7 +184,7 @@ int openmc_finalize() } #endif - openmc_reset_random_ray(); + openmc_finalize_random_ray(); return 0; } diff --git a/src/random_ray/random_ray_simulation.cpp b/src/random_ray/random_ray_simulation.cpp index 4a2afdb9893..af3916e3f13 100644 --- a/src/random_ray/random_ray_simulation.cpp +++ b/src/random_ray/random_ray_simulation.cpp @@ -617,6 +617,17 @@ void RandomRaySimulation::print_results_random_ray( } } +void openmc_finalize_random_ray() +{ + FlatSourceDomain::volume_estimator_ = RandomRayVolumeEstimator::HYBRID; + FlatSourceDomain::volume_normalized_flux_tallies_ = false; + FlatSourceDomain::adjoint_ = false; + FlatSourceDomain::mesh_domain_map_.clear(); + RandomRay::ray_source_.reset(); + RandomRay::source_shape_ = RandomRaySourceShape::FLAT; + RandomRay::sample_method_ = RandomRaySampleMethod::PRNG; +} + } // namespace openmc //============================================================================== @@ -665,15 +676,3 @@ void openmc_run_random_ray() sim.simulate(); } } - -void openmc_reset_random_ray() -{ - openmc::FlatSourceDomain::volume_estimator_ = - openmc::RandomRayVolumeEstimator::HYBRID; - openmc::FlatSourceDomain::volume_normalized_flux_tallies_ = false; - openmc::FlatSourceDomain::adjoint_ = false; - openmc::FlatSourceDomain::mesh_domain_map_.clear(); - openmc::RandomRay::ray_source_.reset(); - openmc::RandomRay::source_shape_ = openmc::RandomRaySourceShape::FLAT; - openmc::RandomRay::sample_method_ = openmc::RandomRaySampleMethod::PRNG; -} From 943f5c05108e515a367f5c28800296d70b46c79a Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Sat, 24 Jan 2026 13:07:30 -0600 Subject: [PATCH 5/6] Add a test for run_random_ray. --- tests/unit_tests/test_lib.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/unit_tests/test_lib.py b/tests/unit_tests/test_lib.py index e5a4d198e88..3ec2a9ae444 100644 --- a/tests/unit_tests/test_lib.py +++ b/tests/unit_tests/test_lib.py @@ -5,6 +5,7 @@ import numpy as np import pytest import openmc +from openmc.examples import random_ray_pin_cell import openmc.exceptions as exc import openmc.lib @@ -83,6 +84,19 @@ def uo2_trigger_model(): yield +@pytest.fixture(scope='module') +def random_ray_pincell_model(): + """Set up a random ray model to test with and delete files when done""" + openmc.reset_auto_ids() + # Write XML and MGXS files in tmpdir + with cdtemp(): + model = random_ray_pin_cell() + model.settings.batches = 200 + model.settings.inactive = 50 + model.settings.particles = 50 + model.export_to_xml() + yield + @pytest.fixture(scope='module') def lib_init(pincell_model, mpi_intracomm): openmc.lib.init(intracomm=mpi_intracomm) @@ -1052,3 +1066,15 @@ def test_sample_external_source(run_in_tmpdir, mpi_intracomm): openmc.lib.init(["-c"]) openmc.lib.sample_external_source(100) openmc.lib.finalize() + + +def test_random_ray(random_ray_pincell_model, mpi_intracomm): + openmc.lib.finalize() + openmc.lib.init(intracomm=mpi_intracomm) + openmc.lib.simulation_init() + openmc.lib.run_random_ray() + keff = openmc.lib.keff() + + assert keff[0]==pytest.approx(1.3236826574065745) + + openmc.lib.finalize() From 8cb47b957cbd3ee7a85931947bf1821eda56ccbc Mon Sep 17 00:00:00 2001 From: nuclearkevin <66632997+nuclearkevin@users.noreply.github.com> Date: Sun, 25 Jan 2026 10:52:42 -0600 Subject: [PATCH 6/6] Reset the solver type to Monte Carlo. --- src/finalize.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/finalize.cpp b/src/finalize.cpp index 8eb37bb8650..ff5d79cb0c3 100644 --- a/src/finalize.cpp +++ b/src/finalize.cpp @@ -122,6 +122,7 @@ int openmc_finalize() settings::restart_run = false; settings::run_CE = true; settings::run_mode = RunMode::UNSET; + settings::solver_type = SolverType::MONTE_CARLO; settings::source_latest = false; settings::source_rejection_fraction = 0.05; settings::source_separate = false;