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

openmc-dev / openmc / 30025709467

23 Jul 2026 04:34PM UTC coverage: 81.336% (-0.08%) from 81.413%
30025709467

Pull #4026

github

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

19250 of 28006 branches covered (68.74%)

Branch coverage included in aggregate %.

1186 of 1209 new or added lines in 12 files covered. (98.1%)

61110 of 70794 relevant lines covered (86.32%)

49022453.97 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,363,351✔
45
{
46
  if (settings::run_mode == RunMode::EIGENVALUE) {
7,363,351✔
47
    // If in eigenvalue mode, set starting flux to guess of 1
48
    scalar_flux_old_.assign(negroups, 1.0);
164,968✔
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,198,383✔
53
    external_source_.assign(negroups, 0.0);
7,198,383✔
54
  }
55

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

60
  tally_task_.resize(negroups);
7,363,351✔
61
  if (is_linear) {
7,363,351✔
62
    source_gradients_.resize(negroups);
2,520,195✔
63
    flux_moments_old_.resize(negroups);
2,520,195✔
64
    flux_moments_new_.resize(negroups);
2,520,195✔
65
    flux_moments_t_.resize(negroups);
2,520,195✔
66
  }
67
}
7,363,351✔
68

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

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

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

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

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

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

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

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

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

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

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

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

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

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

206
    // Tally tasks
207
    tally_task_.emplace_back(sr.tally_task_[g]);
8,405,212✔
208
  }
209
}
7,158,313✔
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,305✔
273
{
274
  SourceRegionHandle handle;
1,606,497,305✔
275
  handle.negroups_ = negroups();
1,606,497,305✔
276
  handle.material_ = &material(sr);
1,606,497,305✔
277
  handle.temperature_idx_ = &temperature_idx(sr);
1,606,497,305✔
278
  handle.density_mult_ = &density_mult(sr);
1,606,497,305✔
279
  handle.is_small_ = &is_small(sr);
1,606,497,305✔
280
  handle.n_hits_ = &n_hits(sr);
1,606,497,305✔
281
  handle.is_linear_ = is_linear();
1,606,497,305✔
282
  handle.lock_ = &lock(sr);
1,606,497,305✔
283
  handle.volume_ = &volume(sr);
1,606,497,305✔
284
  handle.volume_t_ = &volume_t(sr);
1,606,497,305✔
285
  handle.volume_sq_ = &volume_sq(sr);
1,606,497,305✔
286
  handle.volume_sq_t_ = &volume_sq_t(sr);
1,606,497,305✔
287
  handle.volume_naive_ = &volume_naive(sr);
1,606,497,305✔
288
  handle.position_recorded_ = &position_recorded(sr);
1,606,497,305✔
289
  handle.external_source_present_ = &external_source_present(sr);
1,606,497,305✔
290
  handle.position_ = &position(sr);
1,606,497,305✔
291
  handle.volume_task_ = &volume_task(sr);
1,606,497,305✔
292
  handle.mesh_ = &mesh(sr);
1,606,497,305✔
293
  handle.parent_sr_ = &parent_sr(sr);
1,606,497,305✔
294
  handle.scalar_flux_old_ = &scalar_flux_old(sr, 0);
1,606,497,305✔
295
  handle.scalar_flux_new_ = &scalar_flux_new(sr, 0);
1,606,497,305✔
296
  handle.source_ = &source(sr, 0);
1,606,497,305✔
297
  if (settings::run_mode == RunMode::FIXED_SOURCE) {
1,606,497,305✔
298
    handle.external_source_ = &external_source(sr, 0);
1,270,515,513✔
299
  } else {
300
    handle.external_source_ = nullptr;
335,981,792✔
301
  }
302
  handle.scalar_flux_final_ = &scalar_flux_final(sr, 0);
1,606,497,305✔
303
  handle.tally_task_ = &tally_task(sr, 0);
1,606,497,305✔
304
  handle.centroid_ = &centroid(sr);
1,606,497,305✔
305
  handle.centroid_iteration_ = &centroid_iteration(sr);
1,606,497,305✔
306
  handle.centroid_t_ = &centroid_t(sr);
1,606,497,305✔
307
  handle.key_ = &key(sr);
1,606,497,305✔
308

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

318
  return handle;
1,606,497,305✔
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