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

openmc-dev / openmc / 30024940656

23 Jul 2026 04:24PM UTC coverage: 81.335% (-0.08%) from 81.413%
30024940656

Pull #4026

github

web-flow
Merge f173173d6 into a533fcd7f
Pull Request #4026: Add domain decomposition for random ray solver

19250 of 28006 branches covered (68.74%)

Branch coverage included in aggregate %.

1183 of 1206 new or added lines in 12 files covered. (98.09%)

4 existing lines in 1 file now uncovered.

61107 of 70791 relevant lines covered (86.32%)

49020891.15 hits per line

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

76.94
/src/random_ray/source_region.cpp
1
#include "openmc/random_ray/source_region.h"
2

3
#include "openmc/error.h"
4
#include "openmc/message_passing.h"
5
#include "openmc/simulation.h"
6

7
namespace openmc {
8

9
//==============================================================================
10
// SourceRegionHandle implementation
11
//==============================================================================
12
SourceRegionHandle::SourceRegionHandle(SourceRegion& sr)
51,900,781✔
13
  : negroups_(sr.scalar_flux_old_.size()), material_(&sr.scalars_.material_),
51,900,781✔
14
    temperature_idx_(&sr.scalars_.temperature_idx_),
51,900,781✔
15
    density_mult_(&sr.scalars_.density_mult_),
51,900,781✔
16
    is_small_(&sr.scalars_.is_small_), n_hits_(&sr.scalars_.n_hits_),
51,900,781✔
17
    is_linear_(sr.source_gradients_.size() > 0), lock_(&sr.lock_),
51,900,781✔
18
    volume_(&sr.scalars_.volume_), volume_t_(&sr.scalars_.volume_t_),
51,900,781✔
19
    volume_sq_(&sr.scalars_.volume_sq_),
51,900,781✔
20
    volume_sq_t_(&sr.scalars_.volume_sq_t_),
51,900,781✔
21
    volume_naive_(&sr.scalars_.volume_naive_),
51,900,781✔
22
    position_recorded_(&sr.scalars_.position_recorded_),
51,900,781✔
23
    external_source_present_(&sr.scalars_.external_source_present_),
51,900,781✔
24
    position_(&sr.scalars_.position_), centroid_(&sr.scalars_.centroid_),
51,900,781✔
25
    centroid_iteration_(&sr.scalars_.centroid_iteration_),
51,900,781✔
26
    centroid_t_(&sr.scalars_.centroid_t_),
51,900,781✔
27
    mom_matrix_(&sr.scalars_.mom_matrix_),
51,900,781✔
28
    mom_matrix_t_(&sr.scalars_.mom_matrix_t_), volume_task_(&sr.volume_task_),
51,900,781✔
29
    mesh_(&sr.scalars_.mesh_), parent_sr_(&sr.scalars_.parent_sr_),
51,900,781✔
30
    scalar_flux_old_(sr.scalar_flux_old_.data()),
51,900,781✔
31
    scalar_flux_new_(sr.scalar_flux_new_.data()), source_(sr.source_.data()),
51,900,781✔
32
    external_source_(sr.external_source_.data()),
51,900,781✔
33
    scalar_flux_final_(sr.scalar_flux_final_.data()),
51,900,781✔
34
    source_gradients_(sr.source_gradients_.data()),
51,900,781✔
35
    flux_moments_old_(sr.flux_moments_old_.data()),
51,900,781✔
36
    flux_moments_new_(sr.flux_moments_new_.data()),
51,900,781✔
37
    flux_moments_t_(sr.flux_moments_t_.data()),
51,900,781✔
38
    tally_task_(sr.tally_task_.data()), key_(&sr.scalars_.key_)
51,900,781✔
39
{}
51,900,781✔
40

41
//==============================================================================
42
// SourceRegion implementation
43
//==============================================================================
44
SourceRegion::SourceRegion(int negroups, bool is_linear)
7,306,970✔
45
{
46
  if (settings::run_mode == RunMode::EIGENVALUE) {
7,306,970✔
47
    // If in eigenvalue mode, set starting flux to guess of 1
48
    scalar_flux_old_.assign(negroups, 1.0);
163,679✔
49
  } else {
50
    // If in fixed source mode, set starting flux to guess of zero
51
    // and initialize external source arrays
52
    scalar_flux_old_.assign(negroups, 0.0);
7,143,291✔
53
    external_source_.assign(negroups, 0.0);
7,143,291✔
54
  }
55

56
  scalar_flux_new_.assign(negroups, 0.0);
7,306,970✔
57
  source_.assign(negroups, 0.0);
7,306,970✔
58
  scalar_flux_final_.assign(negroups, 0.0);
7,306,970✔
59

60
  tally_task_.resize(negroups);
7,306,970✔
61
  if (is_linear) {
7,306,970✔
62
    source_gradients_.resize(negroups);
2,497,704✔
63
    flux_moments_old_.resize(negroups);
2,497,704✔
64
    flux_moments_new_.resize(negroups);
2,497,704✔
65
    flux_moments_t_.resize(negroups);
2,497,704✔
66
  }
67
}
7,306,970✔
68

69
SourceRegion::SourceRegion(const SourceRegionHandle& handle)
4,753,882✔
70
  : SourceRegion(handle.negroups_, handle.is_linear_)
4,753,882✔
71
{
72
  scalars_.material_ = handle.material();
4,753,882✔
73
  scalars_.is_small_ = handle.is_small();
4,753,882✔
74
  scalars_.temperature_idx_ = handle.temperature_idx();
4,753,882✔
75
  scalars_.density_mult_ = handle.density_mult();
4,753,882✔
76
  scalars_.n_hits_ = handle.n_hits();
4,753,882✔
77
  scalars_.volume_ = handle.volume();
4,753,882✔
78
  scalars_.volume_t_ = handle.volume_t();
4,753,882✔
79
  scalars_.volume_sq_ = handle.volume_sq();
4,753,882✔
80
  scalars_.volume_sq_t_ = handle.volume_sq_t();
4,753,882✔
81
  scalars_.volume_naive_ = handle.volume_naive();
4,753,882✔
82
  scalars_.position_recorded_ = handle.position_recorded();
4,753,882✔
83
  scalars_.position_ = handle.position();
4,753,882✔
84
  scalars_.centroid_ = handle.centroid();
4,753,882✔
85
  scalars_.centroid_iteration_ = handle.centroid_iteration();
4,753,882✔
86
  scalars_.centroid_t_ = handle.centroid_t();
4,753,882✔
87
  scalars_.key_ = handle.key();
4,753,882✔
88
  scalars_.mesh_ = handle.mesh();
4,753,882✔
89
  scalars_.parent_sr_ = handle.parent_sr();
4,753,882✔
90

91
  if (handle.is_linear_) {
4,753,882✔
92
    scalars_.mom_matrix_ = handle.mom_matrix();
1,661,316✔
93
    scalars_.mom_matrix_t_ = handle.mom_matrix_t();
1,661,316✔
94
  }
95

96
  for (int g = 0; g < scalar_flux_new_.size(); g++) {
10,168,316✔
97
    scalar_flux_old_[g] = handle.scalar_flux_old(g);
5,414,434✔
98
    scalar_flux_new_[g] = handle.scalar_flux_new(g);
5,414,434✔
99
    source_[g] = handle.source(g);
5,414,434✔
100
    scalar_flux_final_[g] = handle.scalar_flux_final(g);
5,414,434✔
101
    if (handle.is_linear_) {
5,414,434✔
102
      source_gradients_[g] = handle.source_gradients(g);
1,785,756✔
103
      flux_moments_old_[g] = handle.flux_moments_old(g);
1,785,756✔
104
      flux_moments_new_[g] = handle.flux_moments_new(g);
1,785,756✔
105
      flux_moments_t_[g] = handle.flux_moments_t(g);
1,785,756✔
106
    }
107
    tally_task_[g] = handle.tally_task(g);
5,414,434!
108
  }
109
  if (settings::run_mode == RunMode::FIXED_SOURCE) {
4,753,882✔
110
    scalars_.external_source_present_ = handle.external_source_present();
4,648,442✔
111
    for (int g = 0; g < scalar_flux_new_.size(); g++) {
9,380,404✔
112
      external_source_[g] = handle.external_source(g);
4,731,962✔
113
    }
114
  }
115

116
  volume_task_ = handle.volume_task();
4,753,882!
117
}
4,753,882✔
118

119
// combine two source regions from different ranks together
120
void SourceRegion::merge(SourceRegion& sr_add, bool is_linear)
549✔
121
{
122

123
  // scalar fields
124
  scalars_.volume_ += sr_add.scalars_.volume_;
549✔
125
  scalars_.volume_sq_ += sr_add.scalars_.volume_sq_;
549✔
126
  scalars_.volume_naive_ += sr_add.scalars_.volume_naive_;
549✔
127
  scalars_.n_hits_ += sr_add.scalars_.n_hits_;
549✔
128
  scalars_.external_source_present_ =
1,098✔
129
    std::max(scalars_.external_source_present_,
1,098✔
130
      sr_add.scalars_.external_source_present_);
549!
131
  scalars_.centroid_iteration_ += sr_add.scalars_.centroid_iteration_;
549✔
132
  if (is_linear) {
549✔
133
    scalars_.mom_matrix_ += sr_add.scalars_.mom_matrix_;
217✔
134
  }
135

136
// vector fields
137
#pragma omp simd
423✔
138
  for (int g = 0; g < scalar_flux_new_.size(); g++) {
675✔
139
    scalar_flux_new_[g] += sr_add.scalar_flux_new_[g];
549!
140
    scalar_flux_final_[g] += sr_add.scalar_flux_final_[g];
549✔
141

142
    if (settings::run_mode == RunMode::FIXED_SOURCE) {
549!
143
      external_source_[g] += sr_add.external_source_[g];
549✔
144
    }
145
    if (is_linear) {
549✔
146
      flux_moments_new_[g] += sr_add.flux_moments_new_[g];
217✔
147
    }
148
  }
149
}
549✔
150

151
//==============================================================================
152
// SourceRegionContainer implementation
153
//==============================================================================
154

155
void SourceRegionContainer::push_back(const SourceRegion& sr)
7,158,195✔
156
{
157
  n_source_regions_++;
7,158,195✔
158

159
  // Scalar fields
160
  material_.push_back(sr.scalars_.material_);
7,158,195✔
161
  temperature_idx_.push_back(sr.scalars_.temperature_idx_);
7,158,195✔
162
  density_mult_.push_back(sr.scalars_.density_mult_);
7,158,195✔
163
  is_small_.push_back(sr.scalars_.is_small_);
7,158,195✔
164
  n_hits_.push_back(sr.scalars_.n_hits_);
7,158,195✔
165
  lock_.push_back(sr.lock_);
7,158,195✔
166
  volume_.push_back(sr.scalars_.volume_);
7,158,195✔
167
  volume_t_.push_back(sr.scalars_.volume_t_);
7,158,195✔
168
  volume_sq_.push_back(sr.scalars_.volume_sq_);
7,158,195✔
169
  volume_sq_t_.push_back(sr.scalars_.volume_sq_t_);
7,158,195✔
170
  volume_naive_.push_back(sr.scalars_.volume_naive_);
7,158,195✔
171
  position_recorded_.push_back(sr.scalars_.position_recorded_);
7,158,195✔
172
  external_source_present_.push_back(sr.scalars_.external_source_present_);
7,158,195✔
173
  position_.push_back(sr.scalars_.position_);
7,158,195✔
174
  volume_task_.push_back(sr.volume_task_);
7,158,195✔
175
  mesh_.push_back(sr.scalars_.mesh_);
7,158,195✔
176
  parent_sr_.push_back(sr.scalars_.parent_sr_);
7,158,195✔
177
  key_.push_back(sr.scalars_.key_);
7,158,195✔
178
  centroid_.push_back(sr.scalars_.centroid_);
7,158,195✔
179
  centroid_iteration_.push_back(sr.scalars_.centroid_iteration_);
7,158,195✔
180
  centroid_t_.push_back(sr.scalars_.centroid_t_);
7,158,195✔
181

182
  // Only store these fields if is_linear_ is true
183
  if (is_linear_) {
7,158,195✔
184
    mom_matrix_.push_back(sr.scalars_.mom_matrix_);
2,450,016✔
185
    mom_matrix_t_.push_back(sr.scalars_.mom_matrix_t_);
2,450,016✔
186
  }
187

188
  // Energy-dependent fields
189
  for (int g = 0; g < negroups_; ++g) {
15,563,637✔
190
    scalar_flux_old_.push_back(sr.scalar_flux_old_[g]);
8,405,442✔
191
    scalar_flux_new_.push_back(sr.scalar_flux_new_[g]);
8,405,442✔
192
    scalar_flux_final_.push_back(sr.scalar_flux_final_[g]);
8,405,442✔
193
    source_.push_back(sr.source_[g]);
8,405,442✔
194
    if (settings::run_mode == RunMode::FIXED_SOURCE) {
8,405,442✔
195
      external_source_.push_back(sr.external_source_[g]);
7,361,774✔
196
    }
197

198
    // Only store these fields if is_linear_ is true
199
    if (is_linear_) {
8,405,442✔
200
      source_gradients_.push_back(sr.source_gradients_[g]);
2,643,624✔
201
      flux_moments_old_.push_back(sr.flux_moments_old_[g]);
2,643,624✔
202
      flux_moments_new_.push_back(sr.flux_moments_new_[g]);
2,643,624✔
203
      flux_moments_t_.push_back(sr.flux_moments_t_[g]);
2,643,624✔
204
    }
205

206
    // Tally tasks
207
    tally_task_.emplace_back(sr.tally_task_[g]);
8,405,442✔
208
  }
209
}
7,158,195✔
210

211
void SourceRegionContainer::assign(
×
212
  int n_source_regions, const SourceRegion& source_region)
213
{
214
  // Clear existing data
215
  n_source_regions_ = 0;
×
216
  material_.clear();
×
217
  temperature_idx_.clear();
×
218
  density_mult_.clear();
×
219
  is_small_.clear();
×
220
  n_hits_.clear();
×
221
  lock_.clear();
×
222
  volume_.clear();
×
223
  volume_t_.clear();
×
224
  volume_sq_.clear();
×
225
  volume_sq_t_.clear();
×
226
  volume_naive_.clear();
×
227
  position_recorded_.clear();
×
228
  external_source_present_.clear();
×
229
  position_.clear();
×
230
  mesh_.clear();
×
231
  parent_sr_.clear();
×
NEW
232
  centroid_.clear();
×
NEW
233
  centroid_iteration_.clear();
×
NEW
234
  centroid_t_.clear();
×
NEW
235
  key_.clear();
×
236

237
  if (is_linear_) {
×
238
    mom_matrix_.clear();
×
239
    mom_matrix_t_.clear();
×
240
  }
241

242
  scalar_flux_old_.clear();
×
243
  scalar_flux_new_.clear();
×
244
  scalar_flux_final_.clear();
×
245
  source_.clear();
×
246
  external_source_.clear();
×
247

248
  if (is_linear_) {
×
249
    source_gradients_.clear();
×
250
    flux_moments_old_.clear();
×
251
    flux_moments_new_.clear();
×
252
    flux_moments_t_.clear();
×
253
  }
254

255
  tally_task_.clear();
×
256
  volume_task_.clear();
×
257

258
  // Fill with copies of source_region
259
  for (int i = 0; i < n_source_regions; ++i) {
×
260
    push_back(source_region);
×
261
  }
262
}
×
263

264
void SourceRegionContainer::flux_swap()
21,842✔
265
{
266
  scalar_flux_old_.swap(scalar_flux_new_);
21,842✔
267
  if (is_linear_) {
21,842✔
268
    flux_moments_old_.swap(flux_moments_new_);
10,275✔
269
  }
270
}
21,842✔
271

272
SourceRegionHandle SourceRegionContainer::get_source_region_handle(int64_t sr)
1,606,497,187✔
273
{
274
  SourceRegionHandle handle;
1,606,497,187✔
275
  handle.negroups_ = negroups();
1,606,497,187✔
276
  handle.material_ = &material(sr);
1,606,497,187✔
277
  handle.temperature_idx_ = &temperature_idx(sr);
1,606,497,187✔
278
  handle.density_mult_ = &density_mult(sr);
1,606,497,187✔
279
  handle.is_small_ = &is_small(sr);
1,606,497,187✔
280
  handle.n_hits_ = &n_hits(sr);
1,606,497,187✔
281
  handle.is_linear_ = is_linear();
1,606,497,187✔
282
  handle.lock_ = &lock(sr);
1,606,497,187✔
283
  handle.volume_ = &volume(sr);
1,606,497,187✔
284
  handle.volume_t_ = &volume_t(sr);
1,606,497,187✔
285
  handle.volume_sq_ = &volume_sq(sr);
1,606,497,187✔
286
  handle.volume_sq_t_ = &volume_sq_t(sr);
1,606,497,187✔
287
  handle.volume_naive_ = &volume_naive(sr);
1,606,497,187✔
288
  handle.position_recorded_ = &position_recorded(sr);
1,606,497,187✔
289
  handle.external_source_present_ = &external_source_present(sr);
1,606,497,187✔
290
  handle.position_ = &position(sr);
1,606,497,187✔
291
  handle.volume_task_ = &volume_task(sr);
1,606,497,187✔
292
  handle.mesh_ = &mesh(sr);
1,606,497,187✔
293
  handle.parent_sr_ = &parent_sr(sr);
1,606,497,187✔
294
  handle.scalar_flux_old_ = &scalar_flux_old(sr, 0);
1,606,497,187✔
295
  handle.scalar_flux_new_ = &scalar_flux_new(sr, 0);
1,606,497,187✔
296
  handle.source_ = &source(sr, 0);
1,606,497,187✔
297
  if (settings::run_mode == RunMode::FIXED_SOURCE) {
1,606,497,187✔
298
    handle.external_source_ = &external_source(sr, 0);
1,270,515,503✔
299
  } else {
300
    handle.external_source_ = nullptr;
335,981,684✔
301
  }
302
  handle.scalar_flux_final_ = &scalar_flux_final(sr, 0);
1,606,497,187✔
303
  handle.tally_task_ = &tally_task(sr, 0);
1,606,497,187✔
304
  handle.centroid_ = &centroid(sr);
1,606,497,187✔
305
  handle.centroid_iteration_ = &centroid_iteration(sr);
1,606,497,187✔
306
  handle.centroid_t_ = &centroid_t(sr);
1,606,497,187✔
307
  handle.key_ = &key(sr);
1,606,497,187✔
308

309
  if (handle.is_linear_) {
1,606,497,187✔
310
    handle.mom_matrix_ = &mom_matrix(sr);
686,466,569✔
311
    handle.mom_matrix_t_ = &mom_matrix_t(sr);
686,466,569✔
312
    handle.source_gradients_ = &source_gradients(sr, 0);
686,466,569✔
313
    handle.flux_moments_old_ = &flux_moments_old(sr, 0);
686,466,569✔
314
    handle.flux_moments_new_ = &flux_moments_new(sr, 0);
686,466,569✔
315
    handle.flux_moments_t_ = &flux_moments_t(sr, 0);
686,466,569✔
316
  }
317

318
  return handle;
1,606,497,187✔
319
}
320

321
void SourceRegionContainer::adjoint_reset()
113✔
322
{
323
  // Note: key_ must NOT be reset here. Source region keys are permanent
324
  // identifiers and required under domain decomposition to rebuild
325
  // source_region_map_ during load balancing and to exchange source region data
326
  // between ranks.
327
  std::fill(n_hits_.begin(), n_hits_.end(), 0);
113✔
328
  std::fill(volume_.begin(), volume_.end(), 0.0);
113✔
329
  std::fill(volume_t_.begin(), volume_t_.end(), 0.0);
113✔
330
  std::fill(volume_sq_.begin(), volume_sq_.end(), 0.0);
113✔
331
  std::fill(volume_sq_t_.begin(), volume_sq_t_.end(), 0.0);
113✔
332
  std::fill(volume_naive_.begin(), volume_naive_.end(), 0.0);
113✔
333
  std::fill(
113✔
334
    external_source_present_.begin(), external_source_present_.end(), 0);
335
  std::fill(external_source_.begin(), external_source_.end(), 0.0);
113✔
336
  std::fill(centroid_.begin(), centroid_.end(), Position {0.0, 0.0, 0.0});
113✔
337
  std::fill(centroid_iteration_.begin(), centroid_iteration_.end(),
113✔
338
    Position {0.0, 0.0, 0.0});
113✔
339
  std::fill(centroid_t_.begin(), centroid_t_.end(), Position {0.0, 0.0, 0.0});
113✔
340
  std::fill(mom_matrix_.begin(), mom_matrix_.end(),
113✔
341
    MomentMatrix {0.0, 0.0, 0.0, 0.0, 0.0, 0.0});
113✔
342
  std::fill(mom_matrix_t_.begin(), mom_matrix_t_.end(),
113✔
343
    MomentMatrix {0.0, 0.0, 0.0, 0.0, 0.0, 0.0});
113✔
344
  if (settings::run_mode == RunMode::FIXED_SOURCE) {
113✔
345
    std::fill(scalar_flux_old_.begin(), scalar_flux_old_.end(), 0.0);
98✔
346
  } else {
347
    std::fill(scalar_flux_old_.begin(), scalar_flux_old_.end(), 1.0);
15✔
348
  }
349
  std::fill(scalar_flux_new_.begin(), scalar_flux_new_.end(), 0.0);
113✔
350
  std::fill(source_.begin(), source_.end(), 0.0f);
686,712✔
351
  std::fill(external_source_.begin(), external_source_.end(), 0.0f);
113✔
352
  std::fill(source_gradients_.begin(), source_gradients_.end(),
113✔
353
    MomentArray {0.0, 0.0, 0.0});
113✔
354
  std::fill(flux_moments_old_.begin(), flux_moments_old_.end(),
113✔
355
    MomentArray {0.0, 0.0, 0.0});
113✔
356
  std::fill(flux_moments_new_.begin(), flux_moments_new_.end(),
113✔
357
    MomentArray {0.0, 0.0, 0.0});
113✔
358
  std::fill(flux_moments_t_.begin(), flux_moments_t_.end(),
113✔
359
    MomentArray {0.0, 0.0, 0.0});
113✔
360
}
113✔
361

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

© 2026 Coveralls, Inc