diff --git a/docs/source/capi/index.rst b/docs/source/capi/index.rst index 2583d51dff2..0a1962f7722 100644 --- a/docs/source/capi/index.rst +++ b/docs/source/capi/index.rst @@ -601,6 +601,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..6f18db56f36 100644 --- a/docs/source/pythonapi/capi.rst +++ b/docs/source/pythonapi/capi.rst @@ -40,6 +40,7 @@ Functions reset_timers 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 d8041ef4149..868cca8f491 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -140,6 +140,7 @@ int openmc_remove_tally(int32_t index); int openmc_reset(); int openmc_reset_timers(); int openmc_run(); +void openmc_run_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..68c7779edad 100644 --- a/include/openmc/random_ray/random_ray_simulation.h +++ b/include/openmc/random_ray/random_ray_simulation.h @@ -66,10 +66,9 @@ class RandomRaySimulation { //! Non-member functions //============================================================================ -void openmc_run_random_ray(); void validate_random_ray_inputs(); -void openmc_reset_random_ray(); void print_adjoint_header(); +void openmc_finalize_random_ray(); } // namespace openmc diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 02c7784d1cc..9eba337b4a9 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -82,6 +82,7 @@ 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_reset.restype = c_int _dll.openmc_reset.errcheck = _error_handler _dll.openmc_reset_timers.restype = c_int @@ -479,6 +480,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 diff --git a/src/finalize.cpp b/src/finalize.cpp index 344eaa1a0a7..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; @@ -184,7 +185,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 7bab3a9b1b6..af3916e3f13 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_) @@ -670,4 +617,62 @@ 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 + +//============================================================================== +// 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(); + } +} 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()