diff --git a/include/openmc/event.h b/include/openmc/event.h index 3bf6473656..90bf0dc439 100644 --- a/include/openmc/event.h +++ b/include/openmc/event.h @@ -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); diff --git a/include/openmc/shared_array.h b/include/openmc/shared_array.h index be09ef6d3d..dac7edc63a 100644 --- a/include/openmc/shared_array.h +++ b/include/openmc/shared_array.h @@ -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; } diff --git a/src/event.cpp b/src/event.cpp index 01a61e06fd..2f22d09542 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -47,23 +47,13 @@ void free_event_queues(void) simulation::particles.clear(); } -void enqueue_particle(SharedArray& 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(); }