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

openmc-dev / openmc / 18199783194

02 Oct 2025 04:51PM UTC coverage: 85.122% (-0.08%) from 85.199%
18199783194

Pull #3587

github

web-flow
Merge 775bbd9ec into 1dacf4fd2
Pull Request #3587: Ensure weight_windows_file information is read from XML

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

263 existing lines in 10 files now uncovered.

53128 of 62414 relevant lines covered (85.12%)

38859371.13 hits per line

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

86.25
/include/openmc/random_ray/source_region.h
1
#ifndef OPENMC_RANDOM_RAY_SOURCE_REGION_H
2
#define OPENMC_RANDOM_RAY_SOURCE_REGION_H
3

4
#include "openmc/openmp_interface.h"
5
#include "openmc/position.h"
6
#include "openmc/random_ray/moment_matrix.h"
7
#include "openmc/settings.h"
8

9
namespace openmc {
10

11
//----------------------------------------------------------------------------
12
// Helper Functions
13

14
// The hash_combine function is the standard hash combine function from boost
15
// that is typically used for combining multiple hash values into a single hash
16
// as is needed for larger objects being stored in a hash map. The function is
17
// taken from:
18
// https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine
19
// which carries the following license:
20
//
21
// Boost Software License - Version 1.0 - August 17th, 2003
22
// Permission is hereby granted, free of charge, to any person or organization
23
// obtaining a copy of the software and accompanying documentation covered by
24
// this license (the "Software") to use, reproduce, display, distribute,
25
// execute, and transmit the Software, and to prepare derivative works of the
26
// Software, and to permit third-parties to whom the Software is furnished to
27
// do so, all subject to the following:
28
// The copyright notices in the Software and this entire statement, including
29
// the above license grant, this restriction and the following disclaimer,
30
// must be included in all copies of the Software, in whole or in part, and
31
// all derivative works of the Software, unless such copies or derivative
32
// works are solely in the form of machine-executable object code generated by
33
// a source language processor.
34
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
37
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
38
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
39
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
40
// DEALINGS IN THE SOFTWARE.
41
inline void hash_combine(size_t& seed, const size_t v)
2,147,483,647✔
42
{
43
  seed ^= (v + 0x9e3779b9 + (seed << 6) + (seed >> 2));
2,147,483,647✔
44
}
2,147,483,647✔
45

46
//----------------------------------------------------------------------------
47
// Helper Structs and Classes
48

49
// A mapping object that is used to map between a specific random ray
50
// source region and an OpenMC native tally bin that it should score to
51
// every iteration.
52
struct TallyTask {
53
  int tally_idx;
54
  int filter_idx;
55
  int score_idx;
56
  int score_type;
57
  TallyTask(int tally_idx, int filter_idx, int score_idx, int score_type)
3,562,018✔
58
    : tally_idx(tally_idx), filter_idx(filter_idx), score_idx(score_idx),
3,562,018✔
59
      score_type(score_type)
3,562,018✔
60
  {}
3,562,018✔
61
  TallyTask() = default;
62

63
  // Comparison and Hash operators are defined to allow usage of the
64
  // TallyTask struct as a key in an unordered_set
65
  bool operator==(const TallyTask& other) const
87✔
66
  {
67
    return tally_idx == other.tally_idx && filter_idx == other.filter_idx &&
87✔
68
           score_idx == other.score_idx && score_type == other.score_type;
174✔
69
  }
70

71
  struct HashFunctor {
72
    size_t operator()(const TallyTask& task) const
3,562,018✔
73
    {
74
      size_t seed = 0;
3,562,018✔
75
      hash_combine(seed, task.tally_idx);
3,562,018✔
76
      hash_combine(seed, task.filter_idx);
3,562,018✔
77
      hash_combine(seed, task.score_idx);
3,562,018✔
78
      hash_combine(seed, task.score_type);
3,562,018✔
79
      return seed;
3,562,018✔
80
    }
81
  };
82
};
83

84
// The SourceRegionKey combines a base source region (i.e., a material
85
// filled cell instance) with a mesh bin. This key is used as a handle
86
// for dynamically discovered source regions when subdividing source
87
// regions with meshes.
88
class SourceRegionKey {
89
public:
90
  int64_t base_source_region_id;
91
  int64_t mesh_bin;
92
  SourceRegionKey() = default;
UNCOV
93
  SourceRegionKey(int64_t source_region, int64_t bin)
×
UNCOV
94
    : base_source_region_id(source_region), mesh_bin(bin)
×
UNCOV
95
  {}
×
96

97
  // Equality operator required by the unordered_map
98
  bool operator==(const SourceRegionKey& other) const
1,284,114,296✔
99
  {
100
    return base_source_region_id == other.base_source_region_id &&
2,147,483,647✔
101
           mesh_bin == other.mesh_bin;
2,147,483,647✔
102
  }
103

104
  // Less than operator required by std::sort
105
  bool operator<(const SourceRegionKey& other) const
36,886,700✔
106
  {
107
    if (base_source_region_id < other.base_source_region_id) {
36,886,700✔
108
      return true;
18,388,981✔
109
    } else if (base_source_region_id > other.base_source_region_id) {
18,497,719✔
110
      return false;
10,912,796✔
111
    } else {
112
      return mesh_bin < other.mesh_bin;
7,584,923✔
113
    }
114
  }
115

116
  // Hashing functor required by the unordered_map
117
  struct HashFunctor {
118
    size_t operator()(const SourceRegionKey& key) const
1,435,292,349✔
119
    {
120
      size_t seed = 0;
1,435,292,349✔
121
      hash_combine(seed, key.base_source_region_id);
1,435,292,349✔
122
      hash_combine(seed, key.mesh_bin);
1,435,292,349✔
123
      return seed;
1,435,292,349✔
124
    }
125
  };
126
};
127

128
// Forward declaration of SourceRegion
129
class SourceRegion;
130

131
class SourceRegionHandle {
132
public:
133
  //----------------------------------------------------------------------------
134
  // Constructors
135
  SourceRegionHandle(SourceRegion& sr);
136
  SourceRegionHandle() = default;
×
137

138
  // All fields are commented/described in the SourceRegion class definition
139
  // below
140

141
  //----------------------------------------------------------------------------
142
  // Public Data members
143
  int negroups_;
144
  bool is_numerical_fp_artifact_ {false};
145
  bool is_linear_ {false};
146

147
  // Scalar fields
148
  int* material_;
149
  int* is_small_;
150
  int* n_hits_;
151
  int* birthday_;
152
  OpenMPMutex* lock_;
153
  double* volume_;
154
  double* volume_t_;
155
  double* volume_sq_;
156
  double* volume_sq_t_;
157
  double* volume_naive_;
158
  int* position_recorded_;
159
  int* external_source_present_;
160
  Position* position_;
161
  Position* centroid_;
162
  Position* centroid_iteration_;
163
  Position* centroid_t_;
164
  MomentMatrix* mom_matrix_;
165
  MomentMatrix* mom_matrix_t_;
166
  // A set of volume tally tasks. This more complicated data structure is
167
  // convenient for ensuring that volumes are only tallied once per source
168
  // region, regardless of how many energy groups are used for tallying.
169
  std::unordered_set<TallyTask, TallyTask::HashFunctor>* volume_task_;
170

171
  // Mesh that subdivides this source region
172
  int* mesh_;
173
  int64_t* parent_sr_;
174

175
  // Energy group-wise 1D arrays
176
  double* scalar_flux_old_;
177
  double* scalar_flux_new_;
178
  float* source_;
179
  float* external_source_;
180
  double* scalar_flux_final_;
181

182
  MomentArray* source_gradients_;
183
  MomentArray* flux_moments_old_;
184
  MomentArray* flux_moments_new_;
185
  MomentArray* flux_moments_t_;
186

187
  // 2D array representing values for all energy groups x tally
188
  // tasks. Each group may have a different number of tally tasks
189
  // associated with it, necessitating the use of a jagged array.
190
  vector<TallyTask>* tally_task_;
191

192
  //----------------------------------------------------------------------------
193
  // Public Accessors
194

UNCOV
195
  int& material() { return *material_; }
×
196
  const int material() const { return *material_; }
197

198
  int& is_small() { return *is_small_; }
199
  const int is_small() const { return *is_small_; }
200

201
  int& n_hits() { return *n_hits_; }
202
  const int n_hits() const { return *n_hits_; }
203

204
  void lock() { lock_->lock(); }
205
  void unlock() { lock_->unlock(); }
206

207
  double& volume() { return *volume_; }
208
  const double volume() const { return *volume_; }
209

210
  double& volume_t() { return *volume_t_; }
211
  const double volume_t() const { return *volume_t_; }
212

213
  double& volume_sq() { return *volume_sq_; }
214
  const double volume_sq() const { return *volume_sq_; }
215

216
  double& volume_sq_t() { return *volume_sq_t_; }
217
  const double volume_sq_t() const { return *volume_sq_t_; }
218

219
  double& volume_naive() { return *volume_naive_; }
220
  const double volume_naive() const { return *volume_naive_; }
221

222
  int& position_recorded() { return *position_recorded_; }
223
  const int position_recorded() const { return *position_recorded_; }
224

225
  int& external_source_present() { return *external_source_present_; }
4,500✔
226
  const int external_source_present() const
227
  {
228
    return *external_source_present_;
229
  }
230

231
  Position& position() { return *position_; }
232
  const Position position() const { return *position_; }
233

234
  Position& centroid() { return *centroid_; }
235
  const Position centroid() const { return *centroid_; }
236

237
  Position& centroid_iteration() { return *centroid_iteration_; }
238
  const Position centroid_iteration() const { return *centroid_iteration_; }
239

240
  Position& centroid_t() { return *centroid_t_; }
241
  const Position centroid_t() const { return *centroid_t_; }
242

243
  MomentMatrix& mom_matrix() { return *mom_matrix_; }
244
  const MomentMatrix mom_matrix() const { return *mom_matrix_; }
245

246
  MomentMatrix& mom_matrix_t() { return *mom_matrix_t_; }
247
  const MomentMatrix mom_matrix_t() const { return *mom_matrix_t_; }
248

249
  std::unordered_set<TallyTask, TallyTask::HashFunctor>& volume_task()
250
  {
251
    return *volume_task_;
252
  }
253
  const std::unordered_set<TallyTask, TallyTask::HashFunctor>& volume_task()
254
    const
255
  {
256
    return *volume_task_;
257
  }
258

259
  int& mesh() { return *mesh_; }
2,340,557✔
260
  const int mesh() const { return *mesh_; }
261

262
  int64_t& parent_sr() { return *parent_sr_; }
263
  const int64_t parent_sr() const { return *parent_sr_; }
264

265
  double& scalar_flux_old(int g) { return scalar_flux_old_[g]; }
160,920,775✔
266
  const double scalar_flux_old(int g) const { return scalar_flux_old_[g]; }
267

268
  double& scalar_flux_new(int g) { return scalar_flux_new_[g]; }
269
  const double scalar_flux_new(int g) const { return scalar_flux_new_[g]; }
270

271
  double& scalar_flux_final(int g) { return scalar_flux_final_[g]; }
272
  const double scalar_flux_final(int g) const { return scalar_flux_final_[g]; }
273

UNCOV
274
  float& source(int g) { return source_[g]; }
×
275
  const float source(int g) const { return source_[g]; }
276

277
  float& external_source(int g) { return external_source_[g]; }
×
278
  const float external_source(int g) const { return external_source_[g]; }
279

280
  MomentArray& source_gradients(int g) { return source_gradients_[g]; }
281
  const MomentArray source_gradients(int g) const
282
  {
283
    return source_gradients_[g];
284
  }
285

286
  MomentArray& flux_moments_old(int g) { return flux_moments_old_[g]; }
287
  const MomentArray flux_moments_old(int g) const
288
  {
289
    return flux_moments_old_[g];
290
  }
291

292
  MomentArray& flux_moments_new(int g) { return flux_moments_new_[g]; }
293
  const MomentArray flux_moments_new(int g) const
294
  {
295
    return flux_moments_new_[g];
296
  }
297

298
  MomentArray& flux_moments_t(int g) { return flux_moments_t_[g]; }
299
  const MomentArray flux_moments_t(int g) const { return flux_moments_t_[g]; }
300

301
  vector<TallyTask>& tally_task(int g) { return tally_task_[g]; }
302
  const vector<TallyTask>& tally_task(int g) const { return tally_task_[g]; }
303

304
}; // class SourceRegionHandle
305

306
class SourceRegion {
307
public:
308
  //----------------------------------------------------------------------------
309
  // Constructors
310
  SourceRegion(int negroups, bool is_linear);
311
  SourceRegion() = default;
312

313
  //----------------------------------------------------------------------------
314
  // Public Data members
315

316
  //---------------------------------------
317
  // Scalar fields
318

319
  int material_ {0}; //!< Index in openmc::model::materials array
320
  OpenMPMutex lock_;
321
  double volume_ {
322
    0.0}; //!< Volume (computed from the sum of ray crossing lengths)
323
  double volume_t_ {0.0};     //!< Volume totaled over all iterations
324
  double volume_sq_ {0.0};    //!< Volume squared
325
  double volume_sq_t_ {0.0};  //!< Volume squared totaled over all iterations
326
  double volume_naive_ {0.0}; //!< Volume as integrated from this iteration only
327
  int position_recorded_ {0}; //!< Has the position been recorded yet?
328
  int external_source_present_ {
329
    0};               //!< Is an external source present in this region?
330
  int is_small_ {0};  //!< Is it "small", receiving < 1.5 hits per iteration?
331
  int n_hits_ {0};    //!< Number of total hits (ray crossings)
332
                      // Mesh that subdivides this source region
333
  int mesh_ {C_NONE}; //!< Index in openmc::model::meshes array that subdivides
334
                      //!< this source region
335
  int64_t parent_sr_ {C_NONE}; //!< Index of a parent source region
336
  Position position_ {
337
    0.0, 0.0, 0.0}; //!< A position somewhere inside the region
338
  Position centroid_ {0.0, 0.0, 0.0}; //!< The centroid
339
  Position centroid_iteration_ {
340
    0.0, 0.0, 0.0}; //!< The centroid integrated from this iteration only
341
  Position centroid_t_ {
342
    0.0, 0.0, 0.0}; //!< The centroid accumulated over all iterations
343
  MomentMatrix mom_matrix_ {
344
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; //!< The spatial moment matrix
345
  MomentMatrix mom_matrix_t_ {0.0, 0.0, 0.0, 0.0, 0.0,
346
    0.0}; //!< The spatial moment matrix accumulated over all iterations
347

348
  // A set of volume tally tasks. This more complicated data structure is
349
  // convenient for ensuring that volumes are only tallied once per source
350
  // region, regardless of how many energy groups are used for tallying.
351
  std::unordered_set<TallyTask, TallyTask::HashFunctor> volume_task_;
352

353
  //---------------------------------------
354
  // Energy group-wise 1D arrays
355

356
  vector<double>
357
    scalar_flux_old_; //!< The scalar flux from the previous iteration
358
  vector<double>
359
    scalar_flux_new_; //!< The scalar flux from the current iteration
360
  vector<float>
361
    source_; //!< The total source term (fission + scattering + external)
362
  vector<float> external_source_;    //!< The external source term
363
  vector<double> scalar_flux_final_; //!< The scalar flux accumulated over all
364
                                     //!< active iterations (used for plotting,
365
                                     //!< or computing adjoint sources)
366

367
  vector<MomentArray> source_gradients_; //!< The linear source gradients
368
  vector<MomentArray>
369
    flux_moments_old_; //!< The linear flux moments from the previous iteration
370
  vector<MomentArray>
371
    flux_moments_new_; //!< The linear flux moments from the current iteration
372
  vector<MomentArray>
373
    flux_moments_t_; //!< The linear flux moments accumulated over all active
374
                     //!< iterations (used for plotting)
375

376
  //---------------------------------------
377
  // 2D array representing values for all energy groups x tally
378
  // tasks. Each group may have a different number of tally tasks
379
  // associated with it, necessitating the use of a jagged array.
380
  vector<vector<TallyTask>> tally_task_;
381
}; // class SourceRegion
382

383
class SourceRegionContainer {
384
public:
385
  //----------------------------------------------------------------------------
386
  // Constructors
387
  SourceRegionContainer(int negroups, bool is_linear)
577✔
388
    : negroups_(negroups), is_linear_(is_linear)
577✔
389
  {}
577✔
390
  SourceRegionContainer() = default;
577✔
391

392
  //----------------------------------------------------------------------------
393
  // Public Accessors
394
  int& material(int64_t sr) { return material_[sr]; }
1,407,588,131✔
395
  const int material(int64_t sr) const { return material_[sr]; }
32,174,380✔
396

397
  int& is_small(int64_t sr) { return is_small_[sr]; }
1,422,208,827✔
398
  const int is_small(int64_t sr) const { return is_small_[sr]; }
399

400
  int& n_hits(int64_t sr) { return n_hits_[sr]; }
1,329,358,730✔
401
  const int n_hits(int64_t sr) const { return n_hits_[sr]; }
402

403
  OpenMPMutex& lock(int64_t sr) { return lock_[sr]; }
404
  const OpenMPMutex& lock(int64_t sr) const { return lock_[sr]; }
405

406
  double& volume(int64_t sr) { return volume_[sr]; }
1,654,694,039✔
407
  const double volume(int64_t sr) const { return volume_[sr]; }
32,174,380✔
408

409
  double& volume_t(int64_t sr) { return volume_t_[sr]; }
1,535,224,487✔
410
  const double volume_t(int64_t sr) const { return volume_t_[sr]; }
411

412
  double& volume_sq(int64_t sr) { return volume_sq_[sr]; }
1,474,673,873✔
413
  const double volume_sq(int64_t sr) const { return volume_sq_[sr]; }
414

415
  double& volume_sq_t(int64_t sr) { return volume_sq_t_[sr]; }
1,402,694,651✔
416
  const double volume_sq_t(int64_t sr) const { return volume_sq_t_[sr]; }
417

418
  double& volume_naive(int64_t sr) { return volume_naive_[sr]; }
1,402,694,651✔
419
  const double volume_naive(int64_t sr) const { return volume_naive_[sr]; }
420

421
  int& position_recorded(int64_t sr) { return position_recorded_[sr]; }
1,258,261,924✔
422
  const int position_recorded(int64_t sr) const
423
  {
424
    return position_recorded_[sr];
425
  }
426

427
  int& external_source_present(int64_t sr)
1,338,552,652✔
428
  {
429
    return external_source_present_[sr];
1,338,552,652✔
430
  }
431
  const int external_source_present(int64_t sr) const
432
  {
433
    return external_source_present_[sr];
434
  }
435

436
  Position& position(int64_t sr) { return position_[sr]; }
1,260,501,039✔
437
  const Position position(int64_t sr) const { return position_[sr]; }
438

439
  Position& centroid(int64_t sr) { return centroid_[sr]; }
440
  const Position centroid(int64_t sr) const { return centroid_[sr]; }
441

442
  Position& centroid_iteration(int64_t sr) { return centroid_iteration_[sr]; }
443
  const Position centroid_iteration(int64_t sr) const
444
  {
445
    return centroid_iteration_[sr];
446
  }
447

448
  Position& centroid_t(int64_t sr) { return centroid_t_[sr]; }
449
  const Position centroid_t(int64_t sr) const { return centroid_t_[sr]; }
450

451
  MomentMatrix& mom_matrix(int64_t sr) { return mom_matrix_[sr]; }
452
  const MomentMatrix mom_matrix(int64_t sr) const { return mom_matrix_[sr]; }
453

454
  MomentMatrix& mom_matrix_t(int64_t sr) { return mom_matrix_t_[sr]; }
455
  const MomentMatrix mom_matrix_t(int64_t sr) const
456
  {
457
    return mom_matrix_t_[sr];
458
  }
459

460
  MomentArray& source_gradients(int64_t sr, int g)
461
  {
462
    return source_gradients_[index(sr, g)];
463
  }
464
  const MomentArray source_gradients(int64_t sr, int g) const
465
  {
466
    return source_gradients_[index(sr, g)];
467
  }
468
  MomentArray& source_gradients(int64_t se) { return source_gradients_[se]; }
469
  const MomentArray source_gradients(int64_t se) const
470
  {
471
    return source_gradients_[se];
472
  }
473

474
  MomentArray& flux_moments_old(int64_t sr, int g)
475
  {
476
    return flux_moments_old_[index(sr, g)];
477
  }
478
  const MomentArray flux_moments_old(int64_t sr, int g) const
479
  {
480
    return flux_moments_old_[index(sr, g)];
481
  }
482
  MomentArray& flux_moments_old(int64_t se) { return flux_moments_old_[se]; }
483
  const MomentArray flux_moments_old(int64_t se) const
484
  {
485
    return flux_moments_old_[se];
486
  }
487

488
  MomentArray& flux_moments_new(int64_t sr, int g)
489
  {
490
    return flux_moments_new_[index(sr, g)];
491
  }
492
  const MomentArray flux_moments_new(int64_t sr, int g) const
493
  {
494
    return flux_moments_new_[index(sr, g)];
495
  }
496
  MomentArray& flux_moments_new(int64_t se) { return flux_moments_new_[se]; }
497
  const MomentArray flux_moments_new(int64_t se) const
498
  {
499
    return flux_moments_new_[se];
500
  }
501

502
  MomentArray& flux_moments_t(int64_t sr, int g)
503
  {
504
    return flux_moments_t_[index(sr, g)];
505
  }
506
  const MomentArray flux_moments_t(int64_t sr, int g) const
507
  {
508
    return flux_moments_t_[index(sr, g)];
509
  }
510
  MomentArray& flux_moments_t(int64_t se) { return flux_moments_t_[se]; }
511
  const MomentArray flux_moments_t(int64_t se) const
512
  {
513
    return flux_moments_t_[se];
514
  }
515

516
  double& scalar_flux_old(int64_t sr, int g)
1,260,620,921✔
517
  {
518
    return scalar_flux_old_[index(sr, g)];
1,260,620,921✔
519
  }
520
  const double scalar_flux_old(int64_t sr, int g) const
521
  {
522
    return scalar_flux_old_[index(sr, g)];
523
  }
524
  double& scalar_flux_old(int64_t se) { return scalar_flux_old_[se]; }
525
  const double scalar_flux_old(int64_t se) const
526
  {
527
    return scalar_flux_old_[se];
528
  }
529

530
  double& scalar_flux_new(int64_t sr, int g)
1,537,178,101✔
531
  {
532
    return scalar_flux_new_[index(sr, g)];
1,537,178,101✔
533
  }
534
  const double scalar_flux_new(int64_t sr, int g) const
535
  {
536
    return scalar_flux_new_[index(sr, g)];
537
  }
538
  double& scalar_flux_new(int64_t se) { return scalar_flux_new_[se]; }
199,943,092✔
539
  const double scalar_flux_new(int64_t se) const
540
  {
541
    return scalar_flux_new_[se];
542
  }
543

544
  double& scalar_flux_final(int64_t sr, int g)
1,256,707,445✔
545
  {
546
    return scalar_flux_final_[index(sr, g)];
1,256,707,445✔
547
  }
UNCOV
548
  const double scalar_flux_final(int64_t sr, int g) const
×
549
  {
UNCOV
550
    return scalar_flux_final_[index(sr, g)];
×
551
  }
UNCOV
552
  double& scalar_flux_final(int64_t se) { return scalar_flux_final_[se]; }
×
553
  const double scalar_flux_final(int64_t se) const
554
  {
555
    return scalar_flux_final_[se];
556
  }
557

558
  float& source(int64_t sr, int g) { return source_[index(sr, g)]; }
1,338,087,858✔
559
  const float source(int64_t sr, int g) const { return source_[index(sr, g)]; }
560
  float& source(int64_t se) { return source_[se]; }
561
  const float source(int64_t se) const { return source_[se]; }
562

563
  float& external_source(int64_t sr, int g)
1,091,549,661✔
564
  {
565
    return external_source_[index(sr, g)];
1,091,549,661✔
566
  }
567
  const float external_source(int64_t sr, int g) const
33,369,064✔
568
  {
569
    return external_source_[index(sr, g)];
33,369,064✔
570
  }
571
  float& external_source(int64_t se) { return external_source_[se]; }
572
  const float external_source(int64_t se) const { return external_source_[se]; }
573

574
  vector<TallyTask>& tally_task(int64_t sr, int g)
1,298,728,049✔
575
  {
576
    return tally_task_[index(sr, g)];
1,298,728,049✔
577
  }
578
  const vector<TallyTask>& tally_task(int64_t sr, int g) const
579
  {
580
    return tally_task_[index(sr, g)];
581
  }
582
  vector<TallyTask>& tally_task(int64_t se) { return tally_task_[se]; }
583
  const vector<TallyTask>& tally_task(int64_t se) const
584
  {
585
    return tally_task_[se];
586
  }
587

588
  std::unordered_set<TallyTask, TallyTask::HashFunctor>& volume_task(int64_t sr)
1,292,820,667✔
589
  {
590
    return volume_task_[sr];
1,292,820,667✔
591
  }
592
  const std::unordered_set<TallyTask, TallyTask::HashFunctor>& volume_task(
593
    int64_t sr) const
594
  {
595
    return volume_task_[sr];
596
  }
597

598
  int& mesh(int64_t sr) { return mesh_[sr]; }
599
  const int mesh(int64_t sr) const { return mesh_[sr]; }
600

601
  int64_t& parent_sr(int64_t sr) { return parent_sr_[sr]; }
602
  const int64_t parent_sr(int64_t sr) const { return parent_sr_[sr]; }
603

604
  //----------------------------------------------------------------------------
605
  // Public Methods
606

607
  void push_back(const SourceRegion& sr);
608
  void assign(int n_source_regions, const SourceRegion& source_region);
609
  void flux_swap();
UNCOV
610
  int64_t n_source_regions() const { return n_source_regions_; }
×
611
  int64_t n_source_elements() const { return n_source_regions_ * negroups_; }
612
  int& negroups() { return negroups_; }
613
  const int negroups() const { return negroups_; }
614
  bool& is_linear() { return is_linear_; }
615
  const bool is_linear() const { return is_linear_; }
616
  SourceRegionHandle get_source_region_handle(int64_t sr);
617
  void adjoint_reset();
618

619
private:
620
  //----------------------------------------------------------------------------
621
  // Private Data Members
622
  int64_t n_source_regions_ {0};
623
  int negroups_ {0};
624
  bool is_linear_ {false};
625

626
  // SoA storage for scalar fields (one item per source region)
627
  vector<int> material_;
628
  vector<int> is_small_;
629
  vector<int> n_hits_;
630
  vector<int> mesh_;
631
  vector<int64_t> parent_sr_;
632
  vector<OpenMPMutex> lock_;
633
  vector<double> volume_;
634
  vector<double> volume_t_;
635
  vector<double> volume_sq_;
636
  vector<double> volume_sq_t_;
637
  vector<double> volume_naive_;
638
  vector<int> position_recorded_;
639
  vector<int> external_source_present_;
640
  vector<Position> position_;
641
  vector<Position> centroid_;
642
  vector<Position> centroid_iteration_;
643
  vector<Position> centroid_t_;
644
  vector<MomentMatrix> mom_matrix_;
645
  vector<MomentMatrix> mom_matrix_t_;
646
  // A set of volume tally tasks. This more complicated data structure is
647
  // convenient for ensuring that volumes are only tallied once per source
648
  // region, regardless of how many energy groups are used for tallying.
649
  vector<std::unordered_set<TallyTask, TallyTask::HashFunctor>> volume_task_;
650

651
  // SoA energy group-wise 2D arrays flattened to 1D
652
  vector<double> scalar_flux_old_;
653
  vector<double> scalar_flux_new_;
654
  vector<double> scalar_flux_final_;
655
  vector<float> source_;
656
  vector<float> external_source_;
657

658
  vector<MomentArray> source_gradients_;
659
  vector<MomentArray> flux_moments_old_;
660
  vector<MomentArray> flux_moments_new_;
661
  vector<MomentArray> flux_moments_t_;
662

663
  // SoA 3D array representing values for all source regions x energy groups x
664
  // tally tasks. The outer two dimensions (source regions and energy groups)
665
  // are flattened to 1D. Each group may have a different number of tally tasks
666
  // associated with it, necessitating the use of a jagged array for the inner
667
  // dimension.
668
  vector<vector<TallyTask>> tally_task_;
669

670
  //----------------------------------------------------------------------------
671
  // Private Methods
672

673
  // Helper function for indexing
674
  inline int index(int64_t sr, int g) const { return sr * negroups_ + g; }
2,147,483,647✔
675
};
676

677
} // namespace openmc
678

679
#endif // OPENMC_RANDOM_RAY_SOURCE_REGION_H
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