Changed thread_safe_append() to optionally accept an element to append. Also changed some TODO discussion comment text in event.h

This commit is contained in:
John Tramm 2020-01-28 15:57:01 +00:00
parent 958a77f103
commit fbc241765b
3 changed files with 48 additions and 45 deletions

View file

@ -29,10 +29,18 @@ struct EventQueueItem{
int64_t material; //!< material that particle is in
double E; //!< particle energy
// Compare by particle type, then by material type, then by energy
// TODO: Currently, material IDs are not usually unique to material
// types. When unique material type IDs are available, we can alter the
// material field in this struct to contain the material type instead.
// Constructors
EventQueueItem() = default;
EventQueueItem(const Particle& p, int64_t buffer_idx) :
idx(buffer_idx), type(p.type_), material(p.material_), E(p.E_) {}
// Compare by particle type, then by material type (4.5% fuel/7.0% fuel/cladding/etc),
// then by energy.
// TODO: Currently in OpenMC, the material ID corresponds not only to a general
// type, but also specific isotopic densities. Ideally we would
// like to be able to just sort by general material type, regardless of densities.
// A more general material type ID may be added in the future, in which case we
// can update the material field of this struct to contain the more general id.
bool operator<(const EventQueueItem& rhs) const
{
return std::tie(type, material, E) < std::tie(rhs.type, rhs.material, rhs.E);

View file

@ -59,15 +59,17 @@ public:
capacity_ = capacity;
}
//! Increase the size of the container by one and returns an index to the
//! last element of the array. Also tests to enforce that the append
//! operation does not read off the end of the array. In the event that this
//! does happen, set the size to be equal to the capacity and return -1.
//! Increase the size of the container by one and append value to the
//! array. Returns an index to the element of the array written to. Also
//! tests to enforce that the append operation does not read off the end
//! of the array. In the event that this does happen, set the size to be
//! equal to the capacity and return -1.
//
//! \return The last index in the array, which is safe to write to. In the
//! event that this index would be greater than what was allocated for the
//! container, return -1.
int64_t thread_safe_append()
//! \value The value of the element to append
//! \return The index in the array written to. In the event that this
//! index would be greater than what was allocated for the container,
//! return -1.
int64_t thread_safe_append(const T& value = {})
{
// Atomically capture the index we want to write to
int64_t idx;
@ -81,6 +83,9 @@ public:
return -1;
}
// Copy element value to the array
data_[idx] = value;
return idx;
}

View file

@ -47,23 +47,13 @@ void free_event_queues(void)
simulation::particles.clear();
}
void enqueue_particle(SharedArray<EventQueueItem>& queue, const Particle* p, int64_t buffer_idx)
{
int64_t idx = queue.thread_safe_append();
queue[idx].idx = buffer_idx;
queue[idx].E = p->E_;
queue[idx].material = p->material_;
queue[idx].type = p->type_;
}
void dispatch_xs_event(int64_t buffer_idx)
{
Particle* p = &simulation::particles[buffer_idx];
if (p->material_ == MATERIAL_VOID || !model::materials[p->material_]->fissionable_) {
enqueue_particle(simulation::calculate_nonfuel_xs_queue, p, buffer_idx);
Particle& p = simulation::particles[buffer_idx];
if (p.material_ == MATERIAL_VOID || !model::materials[p.material_]->fissionable_) {
simulation::calculate_nonfuel_xs_queue.thread_safe_append({p, buffer_idx});
} else {
enqueue_particle(simulation::calculate_fuel_xs_queue, p, buffer_idx);
simulation::calculate_fuel_xs_queue.thread_safe_append({p, buffer_idx});
}
}
@ -117,12 +107,12 @@ void process_advance_particle_events()
#pragma omp parallel for schedule(runtime)
for (int64_t i = 0; i < simulation::advance_particle_queue.size(); i++) {
int64_t buffer_idx = simulation::advance_particle_queue[i].idx;
Particle* p = &simulation::particles[buffer_idx];
p->event_advance();
if (p->collision_distance_ > p->boundary_.distance) {
enqueue_particle(simulation::surface_crossing_queue, p, buffer_idx);
Particle& p = simulation::particles[buffer_idx];
p.event_advance();
if (p.collision_distance_ > p.boundary_.distance) {
simulation::surface_crossing_queue.thread_safe_append({p, buffer_idx});
} else {
enqueue_particle(simulation::collision_queue, p, buffer_idx);
simulation::collision_queue.thread_safe_append({p, buffer_idx});
}
}
@ -137,12 +127,12 @@ void process_surface_crossing_events()
#pragma omp parallel for schedule(runtime)
for (int64_t i = 0; i < simulation::surface_crossing_queue.size(); i++) {
int64_t buffer_index = simulation::surface_crossing_queue[i].idx;
Particle* p = &simulation::particles[buffer_index];
p->event_cross_surface();
p->event_revive_from_secondary();
if (p->alive_)
dispatch_xs_event(buffer_index);
int64_t buffer_idx = simulation::surface_crossing_queue[i].idx;
Particle& p = simulation::particles[buffer_idx];
p.event_cross_surface();
p.event_revive_from_secondary();
if (p.alive_)
dispatch_xs_event(buffer_idx);
}
simulation::surface_crossing_queue.resize(0);
@ -156,12 +146,12 @@ void process_collision_events()
#pragma omp parallel for schedule(runtime)
for (int64_t i = 0; i < simulation::collision_queue.size(); i++) {
int64_t buffer_index = simulation::collision_queue[i].idx;
Particle* p = &simulation::particles[buffer_index];
p->event_collide();
p->event_revive_from_secondary();
if (p->alive_)
dispatch_xs_event(buffer_index);
int64_t buffer_idx = simulation::collision_queue[i].idx;
Particle& p = simulation::particles[buffer_idx];
p.event_collide();
p.event_revive_from_secondary();
if (p.alive_)
dispatch_xs_event(buffer_idx);
}
simulation::collision_queue.resize(0);
@ -174,8 +164,8 @@ void process_death_events(int64_t n_particles)
simulation::time_event_death.start();
#pragma omp parallel for schedule(runtime)
for (int64_t i = 0; i < n_particles; i++) {
Particle* p = &simulation::particles[i];
p->event_death();
Particle& p = simulation::particles[i];
p.event_death();
}
simulation::time_event_death.stop();
}