diff --git a/include/openmc/source.h b/include/openmc/source.h index 4db17f241..34183e0b0 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -65,8 +65,11 @@ extern "C" void initialize_source(); //! \return Sampled source site Particle::Bank sample_external_source(uint64_t* seed); -//! Fill source bank at end of generation for fixed source simulations -void fill_source_bank_fixedsource(); +//! Sample a site from custom source library +Particle::Bank sample_custom_source_library(uint64_t* seed); + +void load_custom_source_library(); +void close_custom_source_library(); //! Fill source bank at the end of a generation for dlopen based source simulation void fill_source_bank_custom_source(); diff --git a/src/simulation.cpp b/src/simulation.cpp index 2176e7d5c..4115e8a34 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -112,6 +112,12 @@ int openmc_simulation_init() } } + // If fixed source and using custom source library then need to load + if (settings::run_mode == RunMode::FIXED_SOURCE && + !settings::path_source_library.empty()) { + load_custom_source_library(); + } + // Display header if (mpi::master) { if (settings::run_mode == RunMode::FIXED_SOURCE) { @@ -158,6 +164,12 @@ int openmc_simulation_finalize() t->active_ = false; } + // If fixed source and using custom source library then need to close + if (settings::run_mode == RunMode::FIXED_SOURCE && + !settings::path_source_library.empty()) { + close_custom_source_library(); + } + // Stop timers and show timing statistics simulation::time_finalize.stop(); simulation::time_total.stop(); @@ -444,8 +456,13 @@ void initialize_history(Particle* p, int64_t index_source) int64_t id = (simulation::total_gen + overall_generation() - 1)*settings::n_particles + simulation::work_index[mpi::rank] + index_source; uint64_t seed = init_seed(id, STREAM_SOURCE); - // sample external source distribution then set - Particle::Bank site = sample_external_source(&seed); + // sample from external source distribution or custom library then set + Particle::Bank site; + if (!settings::path_source_library.empty()) { + site = sample_custom_source_library(&seed); + } else { + site = sample_external_source(&seed); + } p->from_source(&site); } else if (settings::run_mode == RunMode::EIGENVALUE) { // set defaults for eigenvalue simulations from primary bank diff --git a/src/source.cpp b/src/source.cpp index c0ee6a853..9f97c829e 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -38,6 +38,10 @@ namespace openmc { namespace model { +typedef Particle::Bank (*sample_t)(uint64_t &seed); +sample_t sample_source; +void* source_library; + std::vector external_sources; } @@ -276,25 +280,10 @@ void initialize_source() file_close(file_id); } else if (!settings::path_source_library.empty()) { - #ifdef HAS_DYNAMIC_LINKING - // Get the source from a library object write_message(fmt::format("Sampling from library source {}...", settings::path_source), 6); - // Open the library - auto source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY); - if (!source_library) { - fatal_error("Couldn't open source library " + settings::path_source_library); - } - - // reset errors - dlerror(); - fill_source_bank_custom_source(); - #else - fatal_error("Custom source libraries have not yet been implemented for " - "non-POSIX systems"); - #endif } else { // Generation source sites from specified distribution in user input @@ -355,13 +344,14 @@ void free_memory_source() model::external_sources.clear(); } -// fill the source bank from the external source -void fill_source_bank_custom_source() +//Load custom source library +void load_custom_source_library() { #ifdef HAS_DYNAMIC_LINKING + // Open the library - auto source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY); - if (!source_library) { + model::source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY); + if (!model::source_library) { fatal_error("Couldn't open source library " + settings::path_source_library); } @@ -369,16 +359,42 @@ void fill_source_bank_custom_source() dlerror(); // get the function from the library - using sample_t = Particle::Bank (*)(uint64_t* seed); - auto sample_source = reinterpret_cast(dlsym(source_library, "sample_source")); + //using sample_t = Particle::Bank (*)(uint64_t* seed); + model::sample_source = reinterpret_cast(dlsym(model::source_library, "sample_source")); // check for any dlsym errors auto dlsym_error = dlerror(); if (dlsym_error) { - dlclose(source_library); + dlclose(model::source_library); fatal_error(fmt::format("Couldn't open the sample_source symbol: {}", dlsym_error)); } +#else + fatal_error("Custom source libraries have not yet been implemented for " + "non-POSIX systems"); +#endif + +} + +//Release custom source library +void close_custom_source_library() +{ + dlclose(model::source_library); +} + +//Sample source particle from custom library +Particle::Bank sample_custom_source_library(uint64_t* seed) +{ + Particle::Bank site = model::sample_source(*seed); + return site; +} + +// fill the source bank from the external source +void fill_source_bank_custom_source() +{ + // Load the custom library + load_custom_source_library(); + // Generation source sites from specified distribution in the // library source for (int64_t i = 0; i < simulation::work_per_rank; ++i) { @@ -387,13 +403,12 @@ void fill_source_bank_custom_source() settings::n_particles + simulation::work_index[mpi::rank] + i + 1; uint64_t seed = init_seed(id, STREAM_SOURCE); - // sample external source distribution - simulation::source_bank[i] = sample_source(&seed); + // sample custom library source + simulation::source_bank[i] = sample_custom_source_library(&seed); } // release the library - dlclose(source_library); -#endif + close_custom_source_library(); } } // namespace openmc