Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions include/openmc/particle_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,8 @@ class ParticleData : public GeometryState {
// Methods and accessors

// Cross section caches
NuclideMicroXS& neutron_xs(int i)
{
return neutron_xs_[i];
} // Microscopic neutron cross sections
// Microscopic neutron cross sections
NuclideMicroXS& neutron_xs(int i) { return neutron_xs_[i]; }
const NuclideMicroXS& neutron_xs(int i) const { return neutron_xs_[i]; }

// Microscopic photon cross sections
Expand Down
25 changes: 20 additions & 5 deletions src/particle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,15 +554,30 @@ void Particle::event_death()
finalize_particle_track(*this);
}

// Contribute tally reduction variables to global accumulator
// Contribute tally reduction variables to global accumulator
const auto k_absorption = keff_tally_absorption();
const auto k_collision = keff_tally_collision();
const auto k_tracklength = keff_tally_tracklength();
const auto leakage = keff_tally_leakage();

if (settings::run_mode == RunMode::EIGENVALUE) {
if (k_absorption != 0.0) {
#pragma omp atomic
global_tally_absorption += keff_tally_absorption();
global_tally_absorption += k_absorption;
}
if (k_collision != 0.0) {
#pragma omp atomic
global_tally_collision += keff_tally_collision();
global_tally_collision += k_collision;
}
if (k_tracklength != 0.0) {
#pragma omp atomic
global_tally_tracklength += keff_tally_tracklength();
global_tally_tracklength += k_tracklength;
}
}
if (leakage != 0.0) {
#pragma omp atomic
global_tally_leakage += keff_tally_leakage();
global_tally_leakage += leakage;
}

// Reset particle tallies once accumulated
keff_tally_absorption() = 0.0;
Expand Down
72 changes: 44 additions & 28 deletions src/random_lcg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,45 @@ constexpr uint64_t prn_mult {6364136223846793005ULL}; // multiplication
constexpr uint64_t prn_add {1442695040888963407ULL}; // additive factor, c
uint64_t prn_stride {DEFAULT_STRIDE}; // stride between particles

namespace {

struct SkipAheadCoefficients {
uint64_t multiplier;
uint64_t increment;
};

SkipAheadCoefficients future_seed_coefficients(uint64_t n)
{
// The algorithm here to determine the parameters used to skip ahead is
// described in F. Brown, "Random Number Generation with Arbitrary Stride,"
// Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
// O(log2(N)) operations instead of O(N). Basically, it computes parameters G
// and C which can then be used to find x_N = G*x_0 + C mod 2^M.

// Initialize constants
uint64_t g {prn_mult};
uint64_t c {prn_add};
uint64_t g_new {1};
uint64_t c_new {0};

while (n > 0) {
// Check if the least significant bit is 1.
if (n & 1) {
g_new *= g;
c_new = c_new * g + c;
}
c *= (g + 1);
g *= g;

// Move bits right, dropping least significant bit.
n >>= 1;
}

return {g_new, c_new};
}

} // namespace

//==============================================================================
// PRN
//==============================================================================
Expand Down Expand Up @@ -69,9 +108,10 @@ uint64_t init_seed(int64_t id, int offset)

void init_particle_seeds(int64_t id, uint64_t* seeds)
{
auto [multiplier, increment] =
future_seed_coefficients(static_cast<uint64_t>(id) * prn_stride);
for (int i = 0; i < N_STREAMS; i++) {
seeds[i] =
future_seed(static_cast<uint64_t>(id) * prn_stride, master_seed + i);
seeds[i] = multiplier * (master_seed + i) + increment;
}
}

Expand All @@ -90,33 +130,9 @@ void advance_prn_seed(int64_t n, uint64_t* seed)

uint64_t future_seed(uint64_t n, uint64_t seed)
{
// The algorithm here to determine the parameters used to skip ahead is
// described in F. Brown, "Random Number Generation with Arbitrary Stride,"
// Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
// O(log2(N)) operations instead of O(N). Basically, it computes parameters G
// and C which can then be used to find x_N = G*x_0 + C mod 2^M.

// Initialize constants
uint64_t g {prn_mult};
uint64_t c {prn_add};
uint64_t g_new {1};
uint64_t c_new {0};

while (n > 0) {
// Check if the least significant bit is 1.
if (n & 1) {
g_new *= g;
c_new = c_new * g + c;
}
c *= (g + 1);
g *= g;

// Move bits right, dropping least significant bit.
n >>= 1;
}

// With G and C, we can now find the new seed.
return g_new * seed + c_new;
auto [multiplier, increment] = future_seed_coefficients(n);
return multiplier * seed + increment;
}

//==============================================================================
Expand Down
6 changes: 4 additions & 2 deletions src/simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -923,15 +923,16 @@ void transport_history_based_shared_secondary()
#pragma omp parallel
{
vector<SourceSite> thread_bank;
Particle p;

#pragma omp for schedule(runtime)
for (int64_t i = 1; i <= simulation::work_per_rank; i++) {
Particle p;
initialize_particle_track(p, i, false);
transport_history_based_single_particle(p);
for (auto& site : p.local_secondary_bank()) {
thread_bank.push_back(site);
}
p.local_secondary_bank().clear();
}

// Drain thread-local bank into the shared secondary bank (once per thread)
Expand Down Expand Up @@ -988,18 +989,19 @@ void transport_history_based_shared_secondary()
#pragma omp parallel
{
vector<SourceSite> thread_bank;
Particle p;

#pragma omp for schedule(runtime)
for (int64_t i = 1; i <= simulation::shared_secondary_bank_read.size();
i++) {
Particle p;
initialize_particle_track(p, i, true);
SourceSite& site = simulation::shared_secondary_bank_read[i - 1];
p.event_revive_from_secondary(site);
transport_history_based_single_particle(p);
for (auto& secondary_site : p.local_secondary_bank()) {
thread_bank.push_back(secondary_site);
}
p.local_secondary_bank().clear();
}

// Drain thread-local bank into the shared secondary bank (once per
Expand Down
Loading