C-API bindings for key random ray functions (#3749)

This commit is contained in:
Kevin Sawatzky 2026-02-06 10:42:32 -06:00 committed by GitHub
parent 8a62a97115
commit 14acc762bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 107 additions and 57 deletions

View file

@ -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

View file

@ -40,6 +40,7 @@ Functions
reset_timers
run
run_in_memory
run_random_ray
sample_external_source
simulation_finalize
simulation_init

View file

@ -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);

View file

@ -66,10 +66,9 @@ private:
//! 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

View file

@ -82,6 +82,7 @@ _dll.openmc_properties_import.restype = c_int
_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

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -5,6 +5,7 @@ import os
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()