diff --git a/include/openmc/settings.h b/include/openmc/settings.h index cbc0c488b..689e22283 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -60,6 +60,7 @@ extern std::string path_input; //!< directory where main .xml files r extern std::string path_output; //!< directory where output files are written extern std::string path_particle_restart; //!< path to a particle restart file extern std::string path_source; +extern std::string path_source_library; //!< path to the source shared object extern std::string path_sourcepoint; //!< path to a source file extern "C" std::string path_statepoint; //!< path to a statepoint file diff --git a/include/openmc/source.h b/include/openmc/source.h index a177995ea..0a73260fd 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -59,6 +59,10 @@ private: //! Initialize source bank from file/distribution extern "C" void initialize_source(); +// as yet uncreated function to sample a source from a shared object +// +// extern "C" Particle::Bank sample_source(); + //! Sample a site from all external source distributions in proportion to their //! source strength //! \param[inout] seed Pseudorandom seed pointer diff --git a/src/settings.cpp b/src/settings.cpp index 5bd53de25..6419e4691 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -74,6 +74,7 @@ std::string path_input; std::string path_output; std::string path_particle_restart; std::string path_source; +std::string path_source_library; std::string path_sourcepoint; std::string path_statepoint; diff --git a/src/source.cpp b/src/source.cpp index b15a15d23..4666783d4 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -1,6 +1,8 @@ #include "openmc/source.h" #include // for move +#include // for stringstream +#include // for dlopen #include #include "xtensor/xadapt.hpp" @@ -71,7 +73,14 @@ SourceDistribution::SourceDistribution(pugi::xml_node node) fatal_error(fmt::format("Source file '{}' does not exist.", settings::path_source)); } - + } else if (check_for_node(node, "library")) { + settings::path_source_library = get_node_value(node, "library", false, true); + // check if it exists + if (!file_exists(settings::path_source_library)) { + std::stringstream msg; + msg << "Library file " << settings::path_source_library << "' does not exist."; + fatal_error(msg); + } } else { // Spatial distribution for external source @@ -261,7 +270,50 @@ void initialize_source() // Close file file_close(file_id); + } else if ( settings::path_source_library != "" ) { + // Get the source from a library object + std::stringstream msg; + msg << "Sampling from library source " << settings::path_source << "..."; + write_message(msg, 6); + + // Open the library + void* source_library = dlopen(settings::path_source_library.c_str(),RTLD_LAZY); + if(!source_library) { + std::stringstream msg("Couldnt open source library " + settings::path_source_library); + fatal_error(msg); + } + + // load the symbol + typedef Particle::Bank (*sample_t)(); + + // reset errors + dlerror(); + + // get the function from the library + sample_t sample_source = (sample_t) dlsym(source_library, "sample_source"); + const char *dlsym_error = dlerror(); + + if (dlsym_error) { + dlclose(source_library); + fatal_error(dlsym_error); + } + + // Generation source sites from specified distribution in the + // library source + for (int64_t i = 0; i < simulation::work_per_rank; ++i) { + // initialize random number seed + int64_t id = simulation::total_gen*settings::n_particles + + simulation::work_index[mpi::rank] + i + 1; + set_particle_seed(id); + + // sample external source distribution + simulation::source_bank[i] = sample_source(); + } + + // release the library + dlclose(source_library); + } else { // Generation source sites from specified distribution in user input for (int64_t i = 0; i < simulation::work_per_rank; ++i) {