Merge pull request #1706 from paulromano/sourcefile-improve

Refactoring of source classes
This commit is contained in:
Patrick Shriwise 2020-11-09 15:14:58 -06:00 committed by GitHub
commit bf1c35e23e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 250 additions and 260 deletions

View file

@ -465,7 +465,7 @@ attributes/sub-elements:
as complex as is required to define the source for your problem. The library
has a few basic requirements:
* It must contain a class that inherits from ``openmc::CustomSource``;
* It must contain a class that inherits from ``openmc::Source``;
* The class must implement a function called ``sample()``;
* There must be an ``openmc_create_source()`` function that creates the source
as a unique pointer. This function can be used to pass parameters through to

View file

@ -194,9 +194,9 @@ below.
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : public openmc::CustomSource
class CustomSource : public openmc::Source
{
openmc::Particle::Bank sample(uint64_t* seed)
openmc::Particle::Bank sample(uint64_t* seed) const
{
openmc::Particle::Bank particle;
// weight
@ -216,16 +216,16 @@ below.
}
};
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameters)
extern "C" std::unique_ptr<CustomSource> openmc_create_source(std::string parameters)
{
return std::make_unique<Source>();
return std::make_unique<CustomSource>();
}
The above source creates monodirectional 14.08 MeV neutrons that are distributed
in a ring with a 3 cm radius. This routine is not particularly complex, but
should serve as an example upon which to build more complicated sources.
.. note:: The source class must inherit from ``openmc::CustomSource`` and
.. note:: The source class must inherit from ``openmc::Source`` and
implement a ``sample()`` function.
.. note:: The ``openmc_create_source()`` function signature must be declared
@ -266,12 +266,12 @@ the source class when it is created:
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : public openmc::CustomSource {
class CustomSource : public openmc::Source {
public:
Source(double energy) : energy_{energy} { }
CustomSource(double energy) : energy_{energy} { }
// Samples from an instance of this class.
openmc::Particle::Bank sample(uint64_t* seed)
openmc::Particle::Bank sample(uint64_t* seed) const
{
openmc::Particle::Bank particle;
// weight
@ -293,9 +293,9 @@ the source class when it is created:
double energy_;
};
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameter) {
extern "C" std::unique_ptr<CustomSource> openmc_create_source(std::string parameter) {
double energy = std::stod(parameter);
return std::make_unique<Source>(energy);
return std::make_unique<CustomSource>(energy);
}
As with the basic custom source functionality, the custom source library

View file

@ -5,9 +5,9 @@
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : public openmc::CustomSource
class RingSource : public openmc::Source
{
openmc::Particle::Bank sample(uint64_t* seed)
openmc::Particle::Bank sample(uint64_t* seed) const
{
openmc::Particle::Bank particle;
// wgt
@ -30,7 +30,7 @@ class Source : public openmc::CustomSource
// A function to create a unique pointer to an instance of this class when generated
// via a plugin call using dlopen/dlsym.
// You must have external C linkage here otherwise dlopen will not find the file
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameters)
extern "C" std::unique_ptr<RingSource> openmc_create_source(std::string parameters)
{
return std::make_unique<Source>();
return std::make_unique<RingSource>();
}

View file

@ -6,14 +6,13 @@
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : public openmc::CustomSource
{
class RingSource : public openmc::Source {
public:
Source(double radius, double energy) : radius_(radius), energy_(energy) { }
RingSource(double radius, double energy) : radius_(radius), energy_(energy) { }
// Defines a function that can create a unique pointer to a new instance of this class
// by extracting the parameters from the provided string.
static std::unique_ptr<Source> from_string(std::string parameters)
static std::unique_ptr<RingSource> from_string(std::string parameters)
{
std::unordered_map<std::string, std::string> parameter_mapping;
@ -28,11 +27,11 @@ class Source : public openmc::CustomSource
double radius = std::stod(parameter_mapping["radius"]);
double energy = std::stod(parameter_mapping["energy"]);
return std::make_unique<Source>(radius, energy);
return std::make_unique<RingSource>(radius, energy);
}
// Samples from an instance of this class.
openmc::Particle::Bank sample(uint64_t* seed)
openmc::Particle::Bank sample(uint64_t* seed) const
{
openmc::Particle::Bank particle;
// wgt
@ -60,7 +59,7 @@ class Source : public openmc::CustomSource
// A function to create a unique pointer to an instance of this class when generated
// via a plugin call using dlopen/dlsym.
// You must have external C linkage here otherwise dlopen will not find the file
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameters)
extern "C" std::unique_ptr<RingSource> openmc_create_source(std::string parameters)
{
return Source::from_string(parameters);
return RingSource::from_string(parameters);
}

View file

@ -59,8 +59,6 @@ extern std::string path_cross_sections; //!< path to cross_sections.xml
extern std::string path_input; //!< directory where main .xml files resides
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

View file

@ -19,32 +19,47 @@ namespace openmc {
// Global variables
//==============================================================================
class SourceDistribution;
class Source;
namespace model {
extern std::vector<SourceDistribution> external_sources;
extern std::vector<std::unique_ptr<Source>> external_sources;
} // namespace model
//==============================================================================
//! External source distribution
//! Abstract source interface
//==============================================================================
class SourceDistribution {
class Source {
public:
virtual ~Source() = default;
// Methods that must be implemented
virtual Particle::Bank sample(uint64_t* seed) const = 0;
// Methods that can be overridden
virtual double strength() const { return 1.0; }
};
//==============================================================================
//! Source composed of independent spatial, angle, and energy distributions
//==============================================================================
class IndependentSource : public Source {
public:
// Constructors
SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy);
explicit SourceDistribution(pugi::xml_node node);
IndependentSource(UPtrSpace space, UPtrAngle angle, UPtrDist energy);
explicit IndependentSource(pugi::xml_node node);
//! Sample from the external source distribution
//! \param[inout] seed Pseudorandom seed pointer
//! \return Sampled site
Particle::Bank sample(uint64_t* seed) const;
Particle::Bank sample(uint64_t* seed) const override;
// Properties
Particle::Type particle_type() const { return particle_; }
double strength() const { return strength_; }
double strength() const override { return strength_; }
// Make observing pointers available
SpatialDistribution* space() const { return space_.get(); }
@ -59,14 +74,45 @@ private:
UPtrDist energy_; //!< Energy distribution
};
class CustomSource {
public:
virtual ~CustomSource() {}
//==============================================================================
//! Source composed of particles read from a file
//==============================================================================
virtual Particle::Bank sample(uint64_t* seed) = 0;
class FileSource : public Source {
public:
// Constructors
explicit FileSource(std::string path);
// Methods
Particle::Bank sample(uint64_t* seed) const override;
private:
std::vector<Particle::Bank> sites_; //!< Source sites from a file
};
typedef std::unique_ptr<CustomSource> create_custom_source_t(std::string parameters);
//==============================================================================
//! Wrapper for custom sources that manages opening/closing shared library
//==============================================================================
class CustomSourceWrapper : public Source {
public:
// Constructors, destructors
CustomSourceWrapper(std::string path, std::string parameters);
~CustomSourceWrapper();
// Defer implementation to custom source library
Particle::Bank sample(uint64_t* seed) const override
{
return custom_source_->sample(seed);
}
double strength() const override { return custom_source_->strength(); }
private:
void* shared_library_; //!< library from dlopen
std::unique_ptr<Source> custom_source_;
};
typedef std::unique_ptr<Source> create_custom_source_t(std::string parameters);
//==============================================================================
// Functions
@ -81,18 +127,6 @@ extern "C" void initialize_source();
//! \return Sampled source site
Particle::Bank sample_external_source(uint64_t* seed);
//! Sample a site from custom source library
Particle::Bank sample_custom_source_library(uint64_t* seed);
//! Load custom source library
void load_custom_source_library();
//! Release 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();
void free_memory_source();
} // namespace openmc

View file

@ -2,17 +2,19 @@
#define OPENMC_STATE_POINT_H
#include <cstdint>
#include <vector>
#include "hdf5.h"
#include "openmc/capi.h"
#include "openmc/particle.h"
namespace openmc {
void load_state_point();
void write_source_point(const char* filename);
void write_source_bank(hid_t group_id);
void read_source_bank(hid_t group_id);
void read_source_bank(hid_t group_id, std::vector<Particle::Bank>& sites, bool distribute);
void write_tally_results_nr(hid_t file_id);
void restart_set_keff();

View file

@ -73,8 +73,6 @@ std::string path_cross_sections;
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;
@ -421,17 +419,31 @@ void read_settings_xml()
// Get point to list of <source> elements and make sure there is at least one
for (pugi::xml_node node : root.children("source")) {
model::external_sources.emplace_back(node);
if (check_for_node(node, "file")) {
auto path = get_node_value(node, "file", false, true);
model::external_sources.push_back(std::make_unique<FileSource>(path));
} else if (check_for_node(node, "library")) {
// Get shared library path and parameters
auto path = get_node_value(node, "library", false, true);
std::string parameters;
if (check_for_node(node, "parameters")) {
parameters = get_node_value(node, "parameters", false, true);
}
// Create custom source
model::external_sources.push_back(std::make_unique<CustomSourceWrapper>(path, parameters));
} else {
model::external_sources.push_back(std::make_unique<IndependentSource>(node));
}
}
// If no source specified, default to isotropic point source at origin with Watt spectrum
if (model::external_sources.empty()) {
SourceDistribution source {
model::external_sources.push_back(std::make_unique<IndependentSource>(
UPtrSpace{new SpatialPoint({0.0, 0.0, 0.0})},
UPtrAngle{new Isotropic()},
UPtrDist{new Watt(0.988e6, 2.249e-6)}
};
model::external_sources.push_back(std::move(source));
));
}
// Check if we want to write out source

View file

@ -121,12 +121,6 @@ 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) {
@ -173,12 +167,6 @@ 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();

View file

@ -39,27 +39,18 @@ namespace openmc {
namespace model {
std::vector<SourceDistribution> external_sources;
std::vector<std::unique_ptr<Source>> external_sources;
}
namespace {
void* custom_source_library;
std::string custom_source_parameters;
std::unique_ptr<CustomSource> custom_source;
}
//==============================================================================
// SourceDistribution implementation
// IndependentSource implementation
//==============================================================================
SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
IndependentSource::IndependentSource(UPtrSpace space, UPtrAngle angle, UPtrDist energy)
: space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { }
SourceDistribution::SourceDistribution(pugi::xml_node node)
IndependentSource::IndependentSource(pugi::xml_node node)
{
// Check for particle type
if (check_for_node(node, "particle")) {
@ -81,24 +72,7 @@ SourceDistribution::SourceDistribution(pugi::xml_node node)
// Check for external source file
if (check_for_node(node, "file")) {
// Copy path of source file
settings::path_source = get_node_value(node, "file", false, true);
// Check if source file exists
if (!file_exists(settings::path_source)) {
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);
if (!file_exists(settings::path_source_library)) {
fatal_error(fmt::format("Source library '{}' does not exist.",
settings::path_source_library));
}
if (check_for_node(node, "parameters")) {
custom_source_parameters = get_node_value(node, "parameters", false, true);
}
} else {
// Spatial distribution for external source
@ -167,8 +141,7 @@ SourceDistribution::SourceDistribution(pugi::xml_node node)
}
}
Particle::Bank SourceDistribution::sample(uint64_t* seed) const
Particle::Bank IndependentSource::sample(uint64_t* seed) const
{
Particle::Bank site;
@ -185,10 +158,10 @@ Particle::Bank SourceDistribution::sample(uint64_t* seed) const
// Sample spatial distribution
site.r = space_->sample(seed);
double xyz[] {site.r.x, site.r.y, site.r.z};
// Now search to see if location exists in geometry
int32_t cell_index, instance;
double xyz[] {site.r.x, site.r.y, site.r.z};
int err = openmc_find_cell(xyz, &cell_index, &instance);
found = (err != OPENMC_E_GEOMETRY);
@ -256,6 +229,94 @@ Particle::Bank SourceDistribution::sample(uint64_t* seed) const
return site;
}
//==============================================================================
// FileSource implementation
//==============================================================================
FileSource::FileSource(std::string path)
{
// Check if source file exists
if (!file_exists(path)) {
fatal_error(fmt::format("Source file '{}' does not exist.", path));
}
// Read the source from a binary file instead of sampling from some
// assumed source distribution
write_message(6, "Reading source file from {}...", path);
// Open the binary file
hid_t file_id = file_open(path, 'r', true);
// Check to make sure this is a source file
std::string filetype;
read_attribute(file_id, "filetype", filetype);
if (filetype != "source" && filetype != "statepoint") {
fatal_error("Specified starting source file not a source file type.");
}
// Read in the source particles
read_source_bank(file_id, sites_, false);
// Close file
file_close(file_id);
}
Particle::Bank FileSource::sample(uint64_t* seed) const
{
size_t i_site = sites_.size()*prn(seed);
return sites_[i_site];
}
//==============================================================================
// CustomSourceWrapper implementation
//==============================================================================
CustomSourceWrapper::CustomSourceWrapper(std::string path, std::string parameters)
{
#ifdef HAS_DYNAMIC_LINKING
// Open the library
shared_library_ = dlopen(path.c_str(), RTLD_LAZY);
if (!shared_library_) {
fatal_error("Couldn't open source library " + path);
}
// reset errors
dlerror();
// get the function to create the custom source from the library
auto create_custom_source = reinterpret_cast<create_custom_source_t*>(
dlsym(shared_library_, "openmc_create_source"));
// check for any dlsym errors
auto dlsym_error = dlerror();
if (dlsym_error) {
std::string error_msg = fmt::format("Couldn't open the openmc_create_source symbol: {}", dlsym_error);
dlclose(shared_library_);
fatal_error(error_msg);
}
// create a pointer to an instance of the custom source
custom_source_ = create_custom_source(parameters);
#else
fatal_error("Custom source libraries have not yet been implemented for "
"non-POSIX systems");
#endif
}
CustomSourceWrapper::~CustomSourceWrapper()
{
// Make sure custom source is cleared before closing shared library
if (custom_source_.get()) custom_source_.reset();
#ifdef HAS_DYNAMIC_LINKING
dlclose(shared_library_);
#else
fatal_error("Custom source libraries have not yet been implemented for "
"non-POSIX systems");
#endif
}
//==============================================================================
// Non-member functions
//==============================================================================
@ -264,47 +325,16 @@ void initialize_source()
{
write_message("Initializing source particles...", 5);
if (!settings::path_source.empty()) {
// Read the source from a binary file instead of sampling from some
// assumed source distribution
// Generation source sites from specified distribution in user input
#pragma omp parallel for
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;
uint64_t seed = init_seed(id, STREAM_SOURCE);
write_message(6, "Reading source file from {}...", settings::path_source);
// Open the binary file
hid_t file_id = file_open(settings::path_source, 'r', true);
// Read the file type
std::string filetype;
read_attribute(file_id, "filetype", filetype);
// Check to make sure this is a source file
if (filetype != "source" && filetype != "statepoint") {
fatal_error("Specified starting source file not a source file type.");
}
// Read in the source bank
read_source_bank(file_id);
// Close file
file_close(file_id);
} else if (!settings::path_source_library.empty()) {
write_message(6, "Sampling library source {}...", settings::path_source);
fill_source_bank_custom_source();
} else {
// Generation source sites from specified distribution in user input
#pragma omp parallel for
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;
uint64_t seed = init_seed(id, STREAM_SOURCE);
// sample external source distribution
simulation::source_bank[i] = sample_external_source(&seed);
}
// sample external source distribution
simulation::source_bank[i] = sample_external_source(&seed);
}
// Write out initial source
@ -319,15 +349,10 @@ void initialize_source()
Particle::Bank sample_external_source(uint64_t* seed)
{
// return values from custom source if using
if (!settings::path_source_library.empty()) {
return sample_custom_source_library(seed);
}
// Determine total source strength
double total_strength = 0.0;
for (auto& s : model::external_sources)
total_strength += s.strength();
total_strength += s->strength();
// Sample from among multiple source distributions
int i = 0;
@ -335,13 +360,13 @@ Particle::Bank sample_external_source(uint64_t* seed)
double xi = prn(seed)*total_strength;
double c = 0.0;
for (; i < model::external_sources.size(); ++i) {
c += model::external_sources[i].strength();
c += model::external_sources[i]->strength();
if (xi < c) break;
}
}
// Sample source site from i-th source distribution
Particle::Bank site {model::external_sources[i].sample(seed)};
Particle::Bank site {model::external_sources[i]->sample(seed)};
// If running in MG, convert site.E to group
if (!settings::run_CE) {
@ -358,80 +383,4 @@ void free_memory_source()
model::external_sources.clear();
}
void load_custom_source_library()
{
#ifdef HAS_DYNAMIC_LINKING
// Open the library
custom_source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY);
if (!custom_source_library) {
fatal_error("Couldn't open source library " + settings::path_source_library);
}
// reset errors
dlerror();
// get the function to create the CustomSource from the library
auto create_custom_source = reinterpret_cast<create_custom_source_t*>(
dlsym(custom_source_library, "openmc_create_source"));
// check for any dlsym errors
auto dlsym_error = dlerror();
if (dlsym_error) {
std::string error_msg = fmt::format("Couldn't open the openmc_create_source symbol: {}", dlsym_error);
dlclose(custom_source_library);
fatal_error(error_msg);
}
// create a pointer to an instance of the CustomSource
custom_source = create_custom_source(custom_source_parameters);
#else
fatal_error("Custom source libraries have not yet been implemented for "
"non-POSIX systems");
#endif
}
void close_custom_source_library()
{
if (custom_source.get()) {
// Make sure the custom source is destroyed before we close it's libary.
custom_source.reset();
}
#ifdef HAS_DYNAMIC_LINKING
dlclose(custom_source_library);
#else
fatal_error("Custom source libraries have not yet been implemented for "
"non-POSIX systems");
#endif
}
Particle::Bank sample_custom_source_library(uint64_t* seed)
{
// sample from the instance of the CustomSource
return custom_source->sample(seed);
}
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) {
// initialize random number seed
int64_t id = (simulation::total_gen + overall_generation()) *
settings::n_particles + simulation::work_index[mpi::rank] + i + 1;
uint64_t seed = init_seed(id, STREAM_SOURCE);
// sample custom library source
simulation::source_bank[i] = sample_custom_source_library(&seed);
}
// release the library
close_custom_source_library();
}
} // namespace openmc

View file

@ -485,11 +485,11 @@ void load_state_point()
+ "...", 5);
// Open source file
file_id = file_open(settings::path_source.c_str(), 'r', true);
file_id = file_open(settings::path_sourcepoint.c_str(), 'r', true);
}
// Read source
read_source_bank(file_id);
read_source_bank(file_id, simulation::source_bank, true);
}
@ -653,43 +653,51 @@ write_source_bank(hid_t group_id)
}
void read_source_bank(hid_t group_id)
void read_source_bank(hid_t group_id, std::vector<Particle::Bank>& sites, bool distribute)
{
hid_t banktype = h5banktype();
// Open the dataset
hid_t dset = H5Dopen(group_id, "source_bank", H5P_DEFAULT);
// Create another data space but for each proc individually
hsize_t dims[] {static_cast<hsize_t>(simulation::work_per_rank)};
hid_t memspace = H5Screate_simple(1, dims, nullptr);
// Make sure source bank is big enough
hid_t dspace = H5Dget_space(dset);
hsize_t dims_all[1];
H5Sget_simple_extent_dims(dspace, dims_all, nullptr);
if (simulation::work_index[mpi::n_procs] > dims_all[0]) {
fatal_error("Number of source sites in source file is less "
"than number of source particles per generation.");
}
hsize_t n_sites;
H5Sget_simple_extent_dims(dspace, &n_sites, nullptr);
// Select hyperslab for each process
hsize_t start[] {static_cast<hsize_t>(simulation::work_index[mpi::rank])};
H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, dims, nullptr);
// Make sure vector is big enough in case where we're reading entire source on
// each process
if (!distribute) sites.resize(n_sites);
hid_t memspace;
if (distribute) {
if (simulation::work_index[mpi::n_procs] > n_sites) {
fatal_error("Number of source sites in source file is less "
"than number of source particles per generation.");
}
// Create another data space but for each proc individually
hsize_t n_sites_local = simulation::work_per_rank;
memspace = H5Screate_simple(1, &n_sites_local, nullptr);
// Select hyperslab for each process
hsize_t offset = simulation::work_index[mpi::rank];
H5Sselect_hyperslab(dspace, H5S_SELECT_SET, &offset, nullptr, &n_sites_local, nullptr);
} else {
memspace = H5S_ALL;
}
#ifdef PHDF5
// Read data in parallel
hid_t plist = H5Pcreate(H5P_DATASET_XFER);
H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE);
H5Dread(dset, banktype, memspace, dspace, plist, simulation::source_bank.data());
H5Dread(dset, banktype, memspace, dspace, plist, sites.data());
H5Pclose(plist);
#else
H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, simulation::source_bank.data());
H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, sites.data());
#endif
// Close all ids
H5Sclose(dspace);
H5Sclose(memspace);
if (distribute) H5Sclose(memspace);
H5Dclose(dset);
H5Tclose(banktype);
}

View file

@ -632,7 +632,7 @@ void Tally::accumulate()
double total_source = 0.0;
if (settings::run_mode == RunMode::FIXED_SOURCE) {
for (const auto& s : model::external_sources) {
total_source += s.strength();
total_source += s->strength();
}
} else {
total_source = 1.0;

View file

@ -5,16 +5,16 @@
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : openmc::CustomSource
class CustomSource : public openmc::Source
{
openmc::Particle::Bank sample(uint64_t *seed)
openmc::Particle::Bank sample(uint64_t *seed) const
{
openmc::Particle::Bank particle;
// wgt
particle.particle = openmc::Particle::Type::neutron;
particle.wgt = 1.0;
// position
particle.r.x = 0.;
particle.r.y = 0.;
particle.r.z = 0.;
@ -22,14 +22,14 @@ class Source : openmc::CustomSource
particle.u = {1.0, 0.0, 0.0};
particle.E = 14.08e6;
particle.delayed_group = 0;
return particle;
return particle;
}
};
// A function to create a unique pointer to an instance of this class when generated
// via a plugin call using dlopen/dlsym.
// You must have external C linkage here otherwise dlopen will not find the file
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameters)
extern "C" std::unique_ptr<CustomSource> openmc_create_source(std::string parameters)
{
return std::make_unique<Source>();
return std::make_unique<CustomSource>();
}

View file

@ -1,2 +1,2 @@
k-combined:
2.939525E-01 6.311780E-03
3.080726E-01 9.554124E-03

View file

@ -1,12 +1,12 @@
#include "openmc/source.h"
#include "openmc/particle.h"
class Source : public openmc::CustomSource {
class CustomSource : public openmc::Source {
public:
Source(double energy) : energy_(energy) { }
CustomSource(double energy) : energy_(energy) { }
// Samples from an instance of this class.
openmc::Particle::Bank sample(uint64_t* seed)
openmc::Particle::Bank sample(uint64_t* seed) const
{
openmc::Particle::Bank particle;
// wgt
@ -31,8 +31,8 @@ class Source : public openmc::CustomSource {
// A function to create a unique pointer to an instance of this class when generated
// via a plugin call using dlopen/dlsym.
// You must have external C linkage here otherwise dlopen will not find the file
extern "C" std::unique_ptr<Source> openmc_create_source(std::string parameter)
extern "C" std::unique_ptr<CustomSource> openmc_create_source(std::string parameter)
{
double energy = std::stod(parameter);
return std::make_unique<Source>(energy);
return std::make_unique<CustomSource>(energy);
}