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

openmc-dev / openmc / 26675018610

30 May 2026 04:53AM UTC coverage: 81.343% (+0.006%) from 81.337%
26675018610

Pull #3915

github

web-flow
Merge b70d83d50 into 46d889613
Pull Request #3915: Allow tracklength estimator for neutron heating

18010 of 26105 branches covered (68.99%)

Branch coverage included in aggregate %.

9 of 9 new or added lines in 1 file covered. (100.0%)

1782 existing lines in 46 files now uncovered.

59130 of 68728 relevant lines covered (86.03%)

48511807.72 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)
255✔
33
{
34
  simulation::calculate_fuel_xs_queue.reserve(n_particles);
255✔
35
  simulation::calculate_nonfuel_xs_queue.reserve(n_particles);
255✔
36
  simulation::advance_particle_queue.reserve(n_particles);
255✔
37
  simulation::surface_crossing_queue.reserve(n_particles);
255✔
38
  simulation::collision_queue.reserve(n_particles);
255✔
39

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

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

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

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

65
void process_init_events(int64_t n_particles, int64_t source_offset)
3,221✔
66
{
67
  simulation::time_event_init.start();
3,221✔
68
#pragma omp parallel for schedule(runtime)
3,221✔
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,221✔
75
}
3,221✔
76

77
void process_calculate_xs_events(SharedArray<EventQueueItem>& queue)
1,275,058✔
78
{
79
  simulation::time_event_calculate_xs.start();
1,275,058✔
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,275,058✔
92

93
#pragma omp parallel for schedule(runtime)
1,275,058✔
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,275,058✔
105

106
  queue.resize(0);
1,275,058✔
107

108
  simulation::time_event_calculate_xs.stop();
1,275,058✔
109
}
1,275,058✔
110

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

115
#pragma omp parallel for schedule(runtime)
1,269,775✔
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,775✔
130

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

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

138
#pragma omp parallel for schedule(runtime)
265,885✔
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,885✔
149

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

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

157
#pragma omp parallel for schedule(runtime)
1,022,593✔
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,593✔
168

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

172
void process_death_events(int64_t n_particles)
3,616✔
173
{
174
  simulation::time_event_death.start();
3,616✔
175
#pragma omp parallel for schedule(runtime)
3,616✔
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,616✔
181
}
3,616✔
182

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

192
    if (max == 0) {
3,836,927✔
193
      break;
194
    } else if (max == simulation::calculate_fuel_xs_queue.size()) {
3,833,311✔
195
      process_calculate_xs_events(simulation::calculate_fuel_xs_queue);
466,161✔
196
    } else if (max == simulation::calculate_nonfuel_xs_queue.size()) {
3,367,150✔
197
      process_calculate_xs_events(simulation::calculate_nonfuel_xs_queue);
808,897✔
198
    } else if (max == simulation::advance_particle_queue.size()) {
2,558,253✔
199
      process_advance_particle_events();
1,269,775✔
200
    } else if (max == simulation::surface_crossing_queue.size()) {
1,288,478✔
201
      process_surface_crossing_events();
265,885✔
202
    } else if (max == simulation::collision_queue.size()) {
1,022,593!
203
      process_collision_events();
1,022,593✔
204
    }
205
  }
206
}
3,616✔
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