• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

openmc-dev / openmc / 26245425348

21 May 2026 06:30PM UTC coverage: 81.319% (-0.06%) from 81.382%
26245425348

Pull #3553

github

web-flow
Merge f76231f92 into 7d09a1260
Pull Request #3553: adding mesh tally amalgamation algorithm

17993 of 26103 branches covered (68.93%)

Branch coverage included in aggregate %.

59110 of 68712 relevant lines covered (86.03%)

48523054.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.42
/src/event.cpp
1
#include "openmc/event.h"
2

3
#include "openmc/bank.h"
4
#include "openmc/error.h"
5
#include "openmc/material.h"
6
#include "openmc/settings.h"
7
#include "openmc/simulation.h"
8
#include "openmc/timer.h"
9

10
namespace openmc {
11

12
//==============================================================================
13
// Global variables
14
//==============================================================================
15

16
namespace simulation {
17

18
SharedArray<EventQueueItem> calculate_fuel_xs_queue;
19
SharedArray<EventQueueItem> calculate_nonfuel_xs_queue;
20
SharedArray<EventQueueItem> advance_particle_queue;
21
SharedArray<EventQueueItem> surface_crossing_queue;
22
SharedArray<EventQueueItem> collision_queue;
23

24
vector<Particle> particles;
25

26
} // namespace simulation
27

28
//==============================================================================
29
// Non-member functions
30
//==============================================================================
31

32
void init_event_queues(int64_t n_particles)
253✔
33
{
34
  simulation::calculate_fuel_xs_queue.reserve(n_particles);
253✔
35
  simulation::calculate_nonfuel_xs_queue.reserve(n_particles);
253✔
36
  simulation::advance_particle_queue.reserve(n_particles);
253✔
37
  simulation::surface_crossing_queue.reserve(n_particles);
253✔
38
  simulation::collision_queue.reserve(n_particles);
253✔
39

40
  simulation::particles.resize(n_particles);
253✔
41
}
253✔
42

43
void free_event_queues(void)
×
44
{
45
  simulation::calculate_fuel_xs_queue.clear();
×
46
  simulation::calculate_nonfuel_xs_queue.clear();
×
47
  simulation::advance_particle_queue.clear();
×
48
  simulation::surface_crossing_queue.clear();
×
49
  simulation::collision_queue.clear();
×
50

51
  simulation::particles.clear();
×
52
}
×
53

54
void dispatch_xs_event(int64_t buffer_idx)
231,373,849✔
55
{
56
  Particle& p = simulation::particles[buffer_idx];
231,373,849✔
57
  if (p.material() == MATERIAL_VOID ||
231,373,849✔
58
      !model::materials[p.material()]->fissionable()) {
213,704,614✔
59
    simulation::calculate_nonfuel_xs_queue.thread_safe_append({p, buffer_idx});
52,406,633✔
60
  } else {
61
    simulation::calculate_fuel_xs_queue.thread_safe_append({p, buffer_idx});
178,967,216✔
62
  }
63
}
231,373,849✔
64

65
void process_init_events(int64_t n_particles, int64_t source_offset)
3,211✔
66
{
67
  simulation::time_event_init.start();
3,211✔
68
#pragma omp parallel for schedule(runtime)
3,211✔
69
  for (int64_t i = 0; i < n_particles; i++) {
×
70
    initialize_particle_track(
71
      simulation::particles[i], source_offset + i + 1, false);
72
    dispatch_xs_event(i);
73
  }
74
  simulation::time_event_init.stop();
3,211✔
75
}
3,211✔
76

77
void process_calculate_xs_events(SharedArray<EventQueueItem>& queue)
1,274,750✔
78
{
79
  simulation::time_event_calculate_xs.start();
1,274,750✔
80

81
  // TODO: If using C++17, we could perform a parallel sort of the queue by
82
  // particle type, material type, and then energy, in order to improve cache
83
  // locality and reduce thread divergence on GPU. However, the parallel
84
  // algorithms typically require linking against an additional library (Intel
85
  // TBB). Prior to C++17, std::sort is a serial only operation, which in this
86
  // case makes it too slow to be practical for most test problems.
87
  //
88
  // std::sort(std::execution::par_unseq, queue.data(), queue.data() +
89
  // queue.size());
90

91
  int64_t offset = simulation::advance_particle_queue.size();
1,274,750✔
92

93
#pragma omp parallel for schedule(runtime)
1,274,750✔
94
  for (int64_t i = 0; i < queue.size(); i++) {
×
95
    Particle* p = &simulation::particles[queue[i].idx];
96
    p->event_calculate_xs();
97

98
    // After executing a calculate_xs event, particles will
99
    // always require an advance event. Therefore, we don't need to use
100
    // the protected enqueuing function.
101
    simulation::advance_particle_queue[offset + i] = queue[i];
102
  }
103

104
  simulation::advance_particle_queue.resize(offset + queue.size());
1,274,750✔
105

106
  queue.resize(0);
1,274,750✔
107

108
  simulation::time_event_calculate_xs.stop();
1,274,750✔
109
}
1,274,750✔
110

111
void process_advance_particle_events()
1,269,467✔
112
{
113
  simulation::time_event_advance_particle.start();
1,269,467✔
114

115
#pragma omp parallel for schedule(runtime)
1,269,467✔
116
  for (int64_t i = 0; i < simulation::advance_particle_queue.size(); i++) {
×
117
    int64_t buffer_idx = simulation::advance_particle_queue[i].idx;
118
    Particle& p = simulation::particles[buffer_idx];
119
    p.event_advance();
120
    if (!p.alive())
×
121
      continue;
122
    if (p.collision_distance() > p.boundary().distance()) {
×
123
      simulation::surface_crossing_queue.thread_safe_append({p, buffer_idx});
124
    } else {
125
      simulation::collision_queue.thread_safe_append({p, buffer_idx});
126
    }
127
  }
128

129
  simulation::advance_particle_queue.resize(0);
1,269,467✔
130

131
  simulation::time_event_advance_particle.stop();
1,269,467✔
132
}
1,269,467✔
133

134
void process_surface_crossing_events()
265,809✔
135
{
136
  simulation::time_event_surface_crossing.start();
265,809✔
137

138
#pragma omp parallel for schedule(runtime)
265,809✔
139
  for (int64_t i = 0; i < simulation::surface_crossing_queue.size(); i++) {
×
140
    int64_t buffer_idx = simulation::surface_crossing_queue[i].idx;
141
    Particle& p = simulation::particles[buffer_idx];
142
    p.event_cross_surface();
143
    p.event_check_limit_and_revive();
144
    if (p.alive())
×
145
      dispatch_xs_event(buffer_idx);
146
  }
147

148
  simulation::surface_crossing_queue.resize(0);
265,809✔
149

150
  simulation::time_event_surface_crossing.stop();
265,809✔
151
}
265,809✔
152

153
void process_collision_events()
1,022,345✔
154
{
155
  simulation::time_event_collision.start();
1,022,345✔
156

157
#pragma omp parallel for schedule(runtime)
1,022,345✔
158
  for (int64_t i = 0; i < simulation::collision_queue.size(); i++) {
×
159
    int64_t buffer_idx = simulation::collision_queue[i].idx;
160
    Particle& p = simulation::particles[buffer_idx];
161
    p.event_collide();
162
    p.event_check_limit_and_revive();
163
    if (p.alive())
×
164
      dispatch_xs_event(buffer_idx);
165
  }
166

167
  simulation::collision_queue.resize(0);
1,022,345✔
168

169
  simulation::time_event_collision.stop();
1,022,345✔
170
}
1,022,345✔
171

172
void process_death_events(int64_t n_particles)
3,606✔
173
{
174
  simulation::time_event_death.start();
3,606✔
175
#pragma omp parallel for schedule(runtime)
3,606✔
176
  for (int64_t i = 0; i < n_particles; i++) {
×
177
    Particle& p = simulation::particles[i];
178
    p.event_death();
179
  }
180
  simulation::time_event_death.stop();
3,606✔
181
}
3,606✔
182

183
void process_transport_events()
3,606✔
184
{
185
  while (true) {
3,835,977✔
186
    int64_t max = std::max({simulation::calculate_fuel_xs_queue.size(),
3,835,977✔
187
      simulation::calculate_nonfuel_xs_queue.size(),
3,835,977✔
188
      simulation::advance_particle_queue.size(),
3,835,977✔
189
      simulation::surface_crossing_queue.size(),
3,835,977✔
190
      simulation::collision_queue.size()});
3,835,977✔
191

192
    if (max == 0) {
3,835,977✔
193
      break;
194
    } else if (max == simulation::calculate_fuel_xs_queue.size()) {
3,832,371✔
195
      process_calculate_xs_events(simulation::calculate_fuel_xs_queue);
466,161✔
196
    } else if (max == simulation::calculate_nonfuel_xs_queue.size()) {
3,366,210✔
197
      process_calculate_xs_events(simulation::calculate_nonfuel_xs_queue);
808,589✔
198
    } else if (max == simulation::advance_particle_queue.size()) {
2,557,621✔
199
      process_advance_particle_events();
1,269,467✔
200
    } else if (max == simulation::surface_crossing_queue.size()) {
1,288,154✔
201
      process_surface_crossing_events();
265,809✔
202
    } else if (max == simulation::collision_queue.size()) {
1,022,345!
203
      process_collision_events();
1,022,345✔
204
    }
205
  }
206
}
3,606✔
207

208
void process_init_secondary_events(int64_t n_particles, int64_t offset,
395✔
209
  const SharedArray<SourceSite>& shared_secondary_bank)
210
{
211
  simulation::time_event_init.start();
395✔
212
#pragma omp parallel for schedule(runtime)
395✔
213
  for (int64_t i = 0; i < n_particles; i++) {
×
214
    initialize_particle_track(simulation::particles[i], offset + i + 1, true);
215
    const SourceSite& site = shared_secondary_bank[offset + i];
216
    simulation::particles[i].event_revive_from_secondary(site);
217
    if (simulation::particles[i].alive()) {
×
218
      dispatch_xs_event(i);
219
    }
220
  }
221
  simulation::time_event_init.stop();
395✔
222
}
395✔
223

224
} // namespace openmc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc