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

openmc-dev / openmc / 19918574733

04 Dec 2025 05:19AM UTC coverage: 82.123% (+0.07%) from 82.055%
19918574733

Pull #3667

github

web-flow
Merge 3127c6bd7 into ad5a876be
Pull Request #3667: Allow DistribcellFilter to work with apply_tally_results=True

16952 of 23523 branches covered (72.07%)

Branch coverage included in aggregate %.

29 of 30 new or added lines in 7 files covered. (96.67%)

139 existing lines in 6 files now uncovered.

54963 of 64047 relevant lines covered (85.82%)

43580650.96 hits per line

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

98.48
/include/openmc/particle_data.h
1
#ifndef OPENMC_PARTICLE_DATA_H
2
#define OPENMC_PARTICLE_DATA_H
3

4
#include "openmc/array.h"
5
#include "openmc/constants.h"
6
#include "openmc/position.h"
7
#include "openmc/random_lcg.h"
8
#include "openmc/tallies/filter_match.h"
9
#include "openmc/vector.h"
10

11
#ifdef OPENMC_DAGMC_ENABLED
12
#include "DagMC.hpp"
13
#endif
14

15
namespace openmc {
16

17
//==============================================================================
18
// Constants
19
//==============================================================================
20

21
// Since cross section libraries come with different numbers of delayed groups
22
// (e.g. ENDF/B-VII.1 has 6 and JEFF 3.1.1 has 8 delayed groups) and we don't
23
// yet know what cross section library is being used when the tallies.xml file
24
// is read in, we want to have an upper bound on the size of the array we
25
// use to store the bins for delayed group tallies.
26
constexpr int MAX_DELAYED_GROUPS {8};
27

28
constexpr double CACHE_INVALID {-1.0};
29

30
//==========================================================================
31
// Aliases and type definitions
32

33
//! Particle types
34
enum class ParticleType { neutron, photon, electron, positron };
35

36
//! Saved ("banked") state of a particle
37
//! NOTE: This structure's MPI type is built in initialize_mpi() of
38
//! initialize.cpp. Any changes made to the struct here must also be
39
//! made when building the Bank MPI type in initialize_mpi().
40
//! NOTE: This structure is also used on the python side, and is defined
41
//! in lib/core.py. Changes made to the type here must also be made to the
42
//! python defintion.
43
struct SourceSite {
44
  Position r;
45
  Direction u;
46
  double E;
47
  double time {0.0};
48
  double wgt {1.0};
49
  int delayed_group {0};
50
  int surf_id {SURFACE_NONE};
51
  ParticleType particle;
52

53
  // Extra attributes that don't show up in source written to file
54
  int parent_nuclide {-1};
55
  int64_t parent_id;
56
  int64_t progeny_id;
57
};
58

59
struct CollisionTrackSite {
60
  Position r;
61
  Direction u;
62
  double E;
63
  double dE;
64
  double time {0.0};
65
  double wgt {1.0};
66
  int event_mt {0};
67
  int delayed_group {0};
68
  int cell_id {0};
69
  int nuclide_id;
70
  int material_id {0};
71
  int universe_id {0};
72
  int n_collision {0};
73
  ParticleType particle;
74
  int64_t parent_id;
75
  int64_t progeny_id;
76
};
77

78
//! State of a particle used for particle track files
79
struct TrackState {
80
  Position r;           //!< Position in [cm]
81
  Direction u;          //!< Direction
82
  double E;             //!< Energy in [eV]
83
  double time {0.0};    //!< Time in [s]
84
  double wgt {1.0};     //!< Weight
85
  int cell_id;          //!< Cell ID
86
  int cell_instance;    //!< Cell instance
87
  int material_id {-1}; //!< Material ID (default value indicates void)
88
};
89

90
//! Full history of a single particle's track states
91
struct TrackStateHistory {
92
  ParticleType particle;
93
  std::vector<TrackState> states;
94
};
95

96
//! Saved ("banked") state of a particle, for nu-fission tallying
97
struct NuBank {
98
  double E;          //!< particle energy
99
  double wgt;        //!< particle weight
100
  int delayed_group; //!< particle delayed group
101
};
102

103
class LocalCoord {
104
public:
105
  void rotate(const vector<double>& rotation);
106

107
  //! clear data from a single coordinate level
108
  void reset();
109

110
  // accessors
111
  Position& r() { return r_; }
2,147,483,647✔
112
  const Position& r() const { return r_; }
2,147,483,647✔
113

114
  Direction& u() { return u_; }
2,147,483,647✔
115
  const Direction& u() const { return u_; }
2,147,483,647✔
116

117
  int& cell() { return cell_; }
2,147,483,647✔
118
  const int& cell() const { return cell_; }
2,147,483,647✔
119

120
  int& universe() { return universe_; }
2,147,483,647✔
121
  const int& universe() const { return universe_; }
9,540,949✔
122

123
  int& lattice() { return lattice_; }
862,194,789✔
124
  int lattice() const { return lattice_; }
2,147,483,647✔
125

126
  array<int, 3>& lattice_index() { return lattice_index_; }
2,147,483,647✔
127
  const array<int, 3>& lattice_index() const { return lattice_index_; }
2,147,483,647✔
128

129
  bool& rotated() { return rotated_; }
134,221,794✔
130
  const bool& rotated() const { return rotated_; }
85,503,297✔
131

132
private:
133
  // Data members
134
  Position r_;  //!< particle position
135
  Direction u_; //!< particle direction
136
  int cell_ {-1};
137
  int universe_ {-1};
138
  int lattice_ {-1};
139
  array<int, 3> lattice_index_ {{-1, -1, -1}};
140
  bool rotated_ {false}; //!< Is the level rotated?
141
};
142

143
//==============================================================================
144
//! Cached microscopic cross sections for a particular nuclide at the current
145
//! energy
146
//==============================================================================
147

148
struct NuclideMicroXS {
149
  // Microscopic cross sections in barns
150
  double total;      //!< total cross section
151
  double absorption; //!< absorption (disappearance)
152
  double fission;    //!< fission
153
  double nu_fission; //!< neutron production from fission
154

155
  double elastic;         //!< If sab_frac is not 1 or 0, then this value is
156
                          //!<   averaged over bound and non-bound nuclei
157
  double thermal;         //!< Bound thermal elastic & inelastic scattering
158
  double thermal_elastic; //!< Bound thermal elastic scattering
159
  double photon_prod;     //!< microscopic photon production xs
160

161
  // Cross sections for depletion reactions (note that these are not stored in
162
  // macroscopic cache)
163
  double reaction[DEPLETION_RX.size()];
164

165
  // Indicies and factors needed to compute cross sections from the data tables
166
  int index_grid;       //!< Index on nuclide energy grid
167
  int index_temp;       //!< Temperature index for nuclide
168
  double interp_factor; //!< Interpolation factor on nuc. energy grid
169
  int index_sab {-1};   //!< Index in sab_tables
170
  int index_temp_sab;   //!< Temperature index for sab_tables
171
  double sab_frac;      //!< Fraction of atoms affected by S(a,b)
172
  bool use_ptable;      //!< In URR range with probability tables?
173

174
  // Energy and temperature last used to evaluate these cross sections.  If
175
  // these values have changed, then the cross sections must be re-evaluated.
176
  double last_E {0.0};       //!< Last evaluated energy
177
  double last_sqrtkT {0.0};  //!< Last temperature in sqrt(Boltzmann constant
178
                             //!< * temperature (eV))
179
  double ncrystal_xs {-1.0}; //!< NCrystal cross section
180
};
181

182
//==============================================================================
183
//! Cached microscopic photon cross sections for a particular element at the
184
//! current energy
185
//==============================================================================
186

187
struct ElementMicroXS {
188
  int index_grid;         //!< index on element energy grid
189
  double last_E {0.0};    //!< last evaluated energy in [eV]
190
  double interp_factor;   //!< interpolation factor on energy grid
191
  double total;           //!< microscopic total photon xs
192
  double coherent;        //!< microscopic coherent xs
193
  double incoherent;      //!< microscopic incoherent xs
194
  double photoelectric;   //!< microscopic photoelectric xs
195
  double pair_production; //!< microscopic pair production xs
196
};
197

198
//==============================================================================
199
// MacroXS contains cached macroscopic cross sections for the material a
200
// particle is traveling through
201
//==============================================================================
202

203
struct MacroXS {
204
  double total;       //!< macroscopic total xs
205
  double absorption;  //!< macroscopic absorption xs
206
  double fission;     //!< macroscopic fission xs
207
  double nu_fission;  //!< macroscopic production xs
208
  double photon_prod; //!< macroscopic photon production xs
209

210
  // Photon cross sections
211
  double coherent;        //!< macroscopic coherent xs
212
  double incoherent;      //!< macroscopic incoherent xs
213
  double photoelectric;   //!< macroscopic photoelectric xs
214
  double pair_production; //!< macroscopic pair production xs
215
};
216

217
//==============================================================================
218
// Cache contains the cached data for an MGXS object
219
//==============================================================================
220

221
struct CacheDataMG {
222
  int material {-1}; //!< material index
223
  double sqrtkT;     //!< last temperature corresponding to t
224
  int t {0};         //!< temperature index
225
  int a {0};         //!< angle index
226
  Direction u;       //!< angle that corresponds to a
227
};
228

229
//==============================================================================
230
// Information about nearest boundary crossing
231
//==============================================================================
232

233
class BoundaryInfo {
234
public:
235
  void reset()
15,616,590✔
236
  {
237
    distance_ = INFINITY;
15,616,590✔
238
    surface_ = SURFACE_NONE;
15,616,590✔
239
    coord_level_ = 0;
15,616,590✔
240
    lattice_translation_ = {0, 0, 0};
15,616,590✔
241
  }
15,616,590✔
242
  double& distance() { return distance_; }
2,147,483,647✔
243
  const double& distance() const { return distance_; }
244

245
  int& surface() { return surface_; }
2,147,483,647✔
246
  const int& surface() const { return surface_; }
2,359,148✔
247

248
  int coord_level() const { return coord_level_; }
249
  int& coord_level() { return coord_level_; }
2,147,483,647✔
250

251
  array<int, 3>& lattice_translation() { return lattice_translation_; }
2,147,483,647✔
252
  const array<int, 3>& lattice_translation() const
2,147,483,647✔
253
  {
254
    return lattice_translation_;
2,147,483,647✔
255
  }
256

257
  // TODO: off-by-one
258
  int surface_index() const { return std::abs(surface()) - 1; }
2,359,148✔
259

260
private:
261
  // Data members
262
  double distance_ {INFINITY}; //!< distance to nearest boundary
263
  int surface_ {
264
    SURFACE_NONE};      //!< surface token, non-zero if boundary is surface
265
  int coord_level_ {0}; //!< coordinate level after crossing boundary
266
  array<int, 3> lattice_translation_ {
267
    0, 0, 0}; //!< which way lattice indices will change
268
};
269

270
/*
271
 * Contains all geometry state information for a particle.
272
 */
273
class GeometryState {
274
public:
275
  GeometryState();
276

277
  /*
278
   * GeometryState does not store any ID info, so give some reasonable behavior
279
   * here. The Particle class redefines this. This is only here for the error
280
   * reporting behavior that occurs in geometry.cpp. The explanation for
281
   * mark_as_lost is the same.
282
   */
283
  virtual void mark_as_lost(const char* message);
284
  void mark_as_lost(const std::string& message);
285
  void mark_as_lost(const std::stringstream& message);
286

287
  // resets all coordinate levels for the particle
288
  void clear()
435,346,132✔
289
  {
290
    for (auto& level : coord_) {
925,206,568✔
291
      level.reset();
489,860,436✔
292
    }
293
    n_coord_ = 1;
435,346,132✔
294

295
    for (auto& cell : cell_last_) {
925,206,568✔
296
      cell = C_NONE;
489,860,436✔
297
    }
298
    n_coord_last_ = 1;
435,346,132✔
299
  }
435,346,132✔
300

301
  //! moves the particle by the specified distance to its next location
302
  //! \param distance the distance the particle is moved
303
  void move_distance(double distance);
304

305
  void advance_to_boundary_from_void();
306

307
  // Initialize all internal state from position and direction
308
  void init_from_r_u(Position r_a, Direction u_a)
3,520,000✔
309
  {
310
    clear();
3,520,000✔
311
    surface() = SURFACE_NONE;
3,520,000✔
312
    material() = C_NONE;
3,520,000✔
313
    r() = r_a;
3,520,000✔
314
    u() = u_a;
3,520,000✔
315
    r_last_current() = r_a;
3,520,000✔
316
    r_last() = r_a;
3,520,000✔
317
    u_last() = u_a;
3,520,000✔
318
  }
3,520,000✔
319

320
  // Unique ID. This is not geometric info, but the
321
  // error reporting in geometry.cpp requires this.
322
  // We could save this to implement it in Particle,
323
  // but that would require virtuals.
324
  int64_t& id() { return id_; }
614,751,782✔
325
  const int64_t& id() const { return id_; }
7,281✔
326

327
  // Number of current coordinate levels
UNCOV
328
  int& n_coord() { return n_coord_; }
×
329
  const int& n_coord() const { return n_coord_; }
518,390,525✔
330

331
  // Offset for distributed properties
332
  int& cell_instance() { return cell_instance_; }
2,147,483,647✔
333
  const int& cell_instance() const { return cell_instance_; }
842,507,110✔
334

335
  // Coordinates for all nesting levels
336
  LocalCoord& coord(int i) { return coord_[i]; }
2,147,483,647✔
337
  const LocalCoord& coord(int i) const { return coord_[i]; }
2,147,483,647✔
338
  const vector<LocalCoord>& coord() const { return coord_; }
×
339

340
  // Innermost universe nesting coordinates
341
  LocalCoord& lowest_coord() { return coord_[n_coord_ - 1]; }
2,147,483,647✔
342
  const LocalCoord& lowest_coord() const { return coord_[n_coord_ - 1]; }
842,507,209✔
343

344
  // Last coordinates on all nesting levels, before crossing a surface
345
  int& n_coord_last() { return n_coord_last_; }
2,147,483,647✔
346
  const int& n_coord_last() const { return n_coord_last_; }
81,210,811✔
347
  int& cell_last(int i) { return cell_last_[i]; }
2,147,483,647✔
348
  const int& cell_last(int i) const { return cell_last_[i]; }
43,755,558✔
349

350
  // Coordinates at birth
351
  Position& r_born() { return r_born_; }
231,595,862✔
352
  const Position& r_born() const { return r_born_; }
60,658,268✔
353

354
  // Coordinates of last collision or reflective/periodic surface
355
  // crossing for current tallies
356
  Position& r_last_current() { return r_last_current_; }
2,147,483,647✔
357
  const Position& r_last_current() const { return r_last_current_; }
112,127,565✔
358

359
  // Previous direction and spatial coordinates before a collision
360
  Position& r_last() { return r_last_; }
2,147,483,647✔
361
  const Position& r_last() const { return r_last_; }
450,163,141✔
362
  Position& u_last() { return u_last_; }
2,147,483,647✔
363
  const Position& u_last() const { return u_last_; }
28,714,213✔
364

365
  // Accessors for position in global coordinates
366
  Position& r() { return coord_[0].r(); }
2,147,483,647✔
367
  const Position& r() const { return coord_[0].r(); }
637,635,069✔
368

369
  // Accessors for position in local coordinates
370
  Position& r_local() { return coord_[n_coord_ - 1].r(); }
2,147,483,647✔
371
  const Position& r_local() const { return coord_[n_coord_ - 1].r(); }
372

373
  // Accessors for direction in global coordinates
374
  Direction& u() { return coord_[0].u(); }
2,147,483,647✔
375
  const Direction& u() const { return coord_[0].u(); }
2,147,483,647✔
376

377
  // Accessors for direction in local coordinates
378
  Direction& u_local() { return coord_[n_coord_ - 1].u(); }
2,147,483,647✔
379
  const Direction& u_local() const { return coord_[n_coord_ - 1].u(); }
380

381
  // Surface token for the surface that the particle is currently on
382
  int& surface() { return surface_; }
2,147,483,647✔
383
  const int& surface() const { return surface_; }
23,764,147✔
384

385
  // Surface index based on the current value of the surface_ attribute
386
  int surface_index() const
1,497,488,733✔
387
  {
388
    // TODO: off-by-one
389
    return std::abs(surface_) - 1;
1,497,488,733✔
390
  }
391

392
  // Boundary information
393
  BoundaryInfo& boundary() { return boundary_; }
2,147,483,647✔
394

395
#ifdef OPENMC_DAGMC_ENABLED
396
  // DagMC state variables
397
  moab::DagMC::RayHistory& history() { return history_; }
414,469,842✔
398
  Direction& last_dir() { return last_dir_; }
637,483✔
399
#endif
400

401
  // material of current and last cell
402
  int& material() { return material_; }
2,147,483,647✔
403
  const int& material() const { return material_; }
2,147,483,647✔
404
  int& material_last() { return material_last_; }
2,147,483,647✔
405
  const int& material_last() const { return material_last_; }
987,349✔
406

407
  // temperature of current and last cell
408
  double& sqrtkT() { return sqrtkT_; }
2,147,483,647✔
409
  const double& sqrtkT() const { return sqrtkT_; }
277,266✔
410
  double& sqrtkT_last() { return sqrtkT_last_; }
2,147,483,647✔
411

412
  // density multiplier of the current and last cell
413
  double& density_mult() { return density_mult_; }
2,147,483,647✔
414
  const double& density_mult() const { return density_mult_; }
12,282,600✔
415
  double& density_mult_last() { return density_mult_last_; }
2,147,483,647✔
416

417
private:
418
  int64_t id_ {-1}; //!< Unique ID
419

420
  int n_coord_ {1};          //!< number of current coordinate levels
421
  int cell_instance_;        //!< offset for distributed properties
422
  vector<LocalCoord> coord_; //!< coordinates for all levels
423

424
  int n_coord_last_ {1};  //!< number of current coordinates
425
  vector<int> cell_last_; //!< coordinates for all levels
426

427
  Position r_born_;         //!< coordinates at birth
428
  Position r_last_current_; //!< coordinates of the last collision or
429
                            //!< reflective/periodic surface crossing for
430
                            //!< current tallies
431
  Position r_last_;         //!< previous coordinates
432
  Direction u_last_;        //!< previous direction coordinates
433

434
  int surface_ {
435
    SURFACE_NONE}; //!< surface token for surface the particle is currently on
436

437
  BoundaryInfo boundary_; //!< Info about the next intersection
438

439
  int material_ {-1};      //!< index for current material
440
  int material_last_ {-1}; //!< index for last material
441

442
  double sqrtkT_ {-1.0};     //!< sqrt(k_Boltzmann * temperature) in eV
443
  double sqrtkT_last_ {0.0}; //!< last temperature
444

445
  double density_mult_ {1.0};      //!< density multiplier
446
  double density_mult_last_ {1.0}; //!< last density multiplier
447

448
#ifdef OPENMC_DAGMC_ENABLED
449
  moab::DagMC::RayHistory history_;
450
  Direction last_dir_;
451
#endif
452
};
453

454
//============================================================================
455
//! Defines how particle data is laid out in memory
456
//============================================================================
457

458
/*
459
 * This class was added in order to separate the layout and access of particle
460
 * data from particle physics operations during a development effort to get
461
 * OpenMC running on GPUs. In the event-based Monte Carlo method, one creates
462
 * an array of particles on which actions like cross section lookup and surface
463
 * crossing are done en masse, which works best on vector computers of yore and
464
 * modern GPUs. It has been shown in the below publication [1] that arranging
465
 * particle data into a structure of arrays rather than an array of structures
466
 * enhances performance on GPUs. For instance, rather than having an
467
 * std::vector<Particle> where consecutive particle energies would be separated
468
 * by about 400 bytes, one would create a structure which has a single
469
 * std::vector<double> of energies.  The motivation here is that more coalesced
470
 * memory accesses occur, in the parlance of GPU programming.
471
 *
472
 * So, this class enables switching between the array-of-structures and
473
 * structure- of-array data layout at compile time. In GPU branches of the
474
 * code, our Particle class inherits from a class that provides an array of
475
 * particle energies, and can access them using the E() method (defined below).
476
 * In the CPU code, we inherit from this class which gives the conventional
477
 * layout of particle data, useful for history-based tracking.
478
 *
479
 * As a result, we always use the E(), r_last(), etc. methods to access
480
 * particle data in order to keep a unified interface between
481
 * structure-of-array and array-of-structure code on either CPU or GPU code
482
 * while sharing the same physics code on each codebase.
483
 *
484
 * [1] Hamilton, Steven P., Stuart R. Slattery, and Thomas M. Evans.
485
 *   “Multigroup Monte Carlo on GPUs: Comparison of History- and Event-Based
486
 *   Algorithms.” Annals of Nuclear Energy 113 (March 2018): 506–18.
487
 *   https://doi.org/10.1016/j.anucene.2017.11.032.
488
 */
489
class ParticleData : public GeometryState {
490
private:
491
  //==========================================================================
492
  // Data members -- see public: below for descriptions
493

494
  vector<NuclideMicroXS> neutron_xs_;
495
  vector<ElementMicroXS> photon_xs_;
496
  MacroXS macro_xs_;
497
  CacheDataMG mg_xs_cache_;
498

499
  ParticleType type_ {ParticleType::neutron};
500

501
  double E_;
502
  double E_last_;
503
  int g_ {0};
504
  int g_last_;
505

506
  double wgt_ {1.0};
507
  double wgt_born_ {1.0};
508
  double wgt_ww_born_ {-1.0};
509
  double mu_;
510
  double time_ {0.0};
511
  double time_last_ {0.0};
512
  double wgt_last_ {1.0};
513

514
  bool fission_ {false};
515
  TallyEvent event_;
516
  int event_nuclide_;
517
  int event_mt_;
518
  int delayed_group_ {0};
519
  int parent_nuclide_ {-1};
520

521
  int n_bank_ {0};
522
  double bank_second_E_ {0.0};
523
  double wgt_bank_ {0.0};
524
  int n_delayed_bank_[MAX_DELAYED_GROUPS];
525

526
  int cell_born_ {-1};
527

528
  // Iterated Fission Probability
529
  double lifetime_ {0.0}; //!< neutron lifetime [s]
530

531
  int n_collision_ {0};
532

533
  bool write_track_ {false};
534

535
  uint64_t seeds_[N_STREAMS];
536
  int stream_;
537

538
  vector<SourceSite> secondary_bank_;
539

540
  int64_t current_work_;
541

542
  vector<double> flux_derivs_;
543

544
  vector<FilterMatch> filter_matches_;
545

546
  vector<TrackStateHistory> tracks_;
547

548
  vector<NuBank> nu_bank_;
549

550
  vector<double> pht_storage_;
551

552
  double keff_tally_absorption_ {0.0};
553
  double keff_tally_collision_ {0.0};
554
  double keff_tally_tracklength_ {0.0};
555
  double keff_tally_leakage_ {0.0};
556

557
  bool trace_ {false};
558

559
  double collision_distance_;
560

561
  int n_event_ {0};
562

563
  int n_split_ {0};
564
  double ww_factor_ {0.0};
565

566
  int64_t n_progeny_ {0};
567

568
public:
569
  //----------------------------------------------------------------------------
570
  // Constructors
571
  ParticleData();
572

573
  //==========================================================================
574
  // Methods and accessors
575

576
  // Cross section caches
577
  NuclideMicroXS& neutron_xs(int i)
2,147,483,647✔
578
  {
579
    return neutron_xs_[i];
2,147,483,647✔
580
  } // Microscopic neutron cross sections
581
  const NuclideMicroXS& neutron_xs(int i) const { return neutron_xs_[i]; }
598,810,441✔
582

583
  // Microscopic photon cross sections
584
  ElementMicroXS& photon_xs(int i) { return photon_xs_[i]; }
185,006,474✔
585

586
  // Macroscopic cross sections
587
  MacroXS& macro_xs() { return macro_xs_; }
×
588
  const MacroXS& macro_xs() const { return macro_xs_; }
1,190,332✔
589

590
  // Multigroup macroscopic cross sections
591
  CacheDataMG& mg_xs_cache() { return mg_xs_cache_; }
2,147,483,647✔
592
  const CacheDataMG& mg_xs_cache() const { return mg_xs_cache_; }
2,063,937,414✔
593

594
  // Particle type (n, p, e, gamma, etc)
595
  ParticleType& type() { return type_; }
2,147,483,647✔
596
  const ParticleType& type() const { return type_; }
2,147,483,647✔
597

598
  // Current particle energy, energy before collision,
599
  // and corresponding multigroup group indices. Energy
600
  // units are eV.
601
  double& E() { return E_; }
2,147,483,647✔
602
  const double& E() const { return E_; }
2,147,483,647✔
603
  double& E_last() { return E_last_; }
2,147,483,647✔
604
  const double& E_last() const { return E_last_; }
886,168,266✔
605
  int& g() { return g_; }
2,147,483,647✔
606
  const int& g() const { return g_; }
2,147,483,647✔
607
  int& g_last() { return g_last_; }
2,147,483,647✔
608
  const int& g_last() const { return g_last_; }
2,768,568✔
609

610
  // Statistic weight of particle. Setting to zero indicates that the particle
611
  // is dead.
612
  double& wgt() { return wgt_; }
2,147,483,647✔
613
  double wgt() const { return wgt_; }
17,488✔
614

615
  // Statistic weight of particle at birth
616
  double& wgt_born() { return wgt_born_; }
219,286,530✔
617
  double wgt_born() const { return wgt_born_; }
618

619
  // Weight window value at birth
620
  double& wgt_ww_born() { return wgt_ww_born_; }
287,250,828✔
621
  const double& wgt_ww_born() const { return wgt_ww_born_; }
622

623
  // Statistic weight of particle at last collision
624
  double& wgt_last() { return wgt_last_; }
2,147,483,647✔
625
  const double& wgt_last() const { return wgt_last_; }
22,684,662✔
626

627
  // Whether particle is alive
628
  bool alive() const { return wgt_ != 0.0; }
2,147,483,647✔
629

630
  // Polar scattering angle after a collision
631
  double& mu() { return mu_; }
2,147,483,647✔
632
  const double& mu() const { return mu_; }
215,091,395✔
633

634
  // Tracks the time of a particle as it traverses the problem.
635
  // Units are seconds.
636
  double& time() { return time_; }
2,147,483,647✔
637
  const double& time() const { return time_; }
13,151,774✔
638
  double& time_last() { return time_last_; }
2,147,483,647✔
639
  const double& time_last() const { return time_last_; }
13,134,286✔
640

641
  // Particle lifetime
642
  double& lifetime() { return lifetime_; }
2,147,483,647✔
643
  const double& lifetime() const { return lifetime_; }
1,352,626✔
644

645
  // What event took place, described in greater detail below
646
  TallyEvent& event() { return event_; }
2,147,483,647✔
647
  const TallyEvent& event() const { return event_; }
623,744✔
648
  bool& fission() { return fission_; }            // true if implicit fission
2,147,483,647✔
649
  int& event_nuclide() { return event_nuclide_; } // index of collision nuclide
2,147,483,647✔
650
  const int& event_nuclide() const { return event_nuclide_; }
18,003,865✔
651
  int& event_mt() { return event_mt_; } // MT number of collision
2,147,483,647✔
652
  const int& event_mt() const { return event_mt_; }
18,106,794✔
653
  int& delayed_group() { return delayed_group_; } // delayed group
453,925,357✔
654
  const int& delayed_group() const { return delayed_group_; }
1,352,626✔
655
  const int& parent_nuclide() const { return parent_nuclide_; }
70,631✔
656
  int& parent_nuclide() { return parent_nuclide_; } // Parent nuclide
231,595,862✔
657

658
  // Post-collision data
659
  double& bank_second_E()
2,147,483,647✔
660
  {
661
    return bank_second_E_;
2,147,483,647✔
662
  } // energy of last reaction secondaries
663
  const double& bank_second_E() const { return bank_second_E_; }
21,328,868✔
664

665
  int& n_bank() { return n_bank_; }        // number of banked fission sites
2,147,483,647✔
666
  double& wgt_bank() { return wgt_bank_; } // weight of banked fission sites
2,147,483,647✔
667
  int* n_delayed_bank()
1,253,890✔
668
  {
669
    return n_delayed_bank_;
1,253,890✔
670
  } // number of delayed fission sites
671
  int& n_delayed_bank(int i)
1,079,956,006✔
672
  {
673
    return n_delayed_bank_[i];
1,079,956,006✔
674
  } // number of delayed fission sites
675

676
  // Index of cell particle is born in
677
  int& cell_born() { return cell_born_; }
694,612,565✔
678
  const int& cell_born() const { return cell_born_; }
3,208,755✔
679

680
  // Total number of collisions suffered by particle
681
  int& n_collision() { return n_collision_; }
2,147,483,647✔
682
  const int& n_collision() const { return n_collision_; }
3,208,755✔
683

684
  // whether this track is to be written
685
  bool& write_track() { return write_track_; }
2,147,483,647✔
686

687
  // RNG state
688
  uint64_t& seeds(int i) { return seeds_[i]; }
961,434,003✔
689
  uint64_t* seeds() { return seeds_; }
167,313,510✔
690
  int& stream() { return stream_; }
2,147,483,647✔
691

692
  // secondary particle bank
693
  SourceSite& secondary_bank(int i) { return secondary_bank_[i]; }
694
  decltype(secondary_bank_)& secondary_bank() { return secondary_bank_; }
418,189,471✔
695

696
  // Current simulation work index
697
  int64_t& current_work() { return current_work_; }
168,345,129✔
698
  const int64_t& current_work() const { return current_work_; }
2,705,609✔
699

700
  // Used in tally derivatives
701
  double& flux_derivs(int i) { return flux_derivs_[i]; }
2,867,810✔
702
  const double& flux_derivs(int i) const { return flux_derivs_[i]; }
2,140,666✔
703

704
  // Matches of tallies
705
  decltype(filter_matches_)& filter_matches() { return filter_matches_; }
2,147,483,647✔
706
  FilterMatch& filter_matches(int i) { return filter_matches_[i]; }
7,347,637✔
707

708
  // Tracks to output to file
709
  decltype(tracks_)& tracks() { return tracks_; }
27,372✔
710

711
  // Bank of recently fissioned particles
712
  decltype(nu_bank_)& nu_bank() { return nu_bank_; }
275,021,775✔
713
  NuBank& nu_bank(int i) { return nu_bank_[i]; }
1,596,199✔
714

715
  // Interim pulse height tally storage
716
  vector<double>& pht_storage() { return pht_storage_; }
330,813,068✔
717

718
  // Global tally accumulators
719
  double& keff_tally_absorption() { return keff_tally_absorption_; }
465,973,263✔
720
  double& keff_tally_collision() { return keff_tally_collision_; }
2,147,483,647✔
721
  double& keff_tally_tracklength() { return keff_tally_tracklength_; }
2,147,483,647✔
722
  double& keff_tally_leakage() { return keff_tally_leakage_; }
365,136,227✔
723

724
  // Shows debug info
725
  bool& trace() { return trace_; }
2,147,483,647✔
726

727
  // Distance to the next collision
728
  double& collision_distance() { return collision_distance_; }
2,147,483,647✔
729

730
  // Number of events particle has undergone
731
  int& n_event() { return n_event_; }
2,147,483,647✔
732

733
  // Number of times variance reduction has caused a particle split
734
  int n_split() const { return n_split_; }
735
  int& n_split() { return n_split_; }
180,163,114✔
736

737
  // Particle-specific factor for on-the-fly weight window adjustment
738
  double ww_factor() const { return ww_factor_; }
739
  double& ww_factor() { return ww_factor_; }
274,530,284✔
740

741
  // Number of progeny produced by this particle
742
  int64_t& n_progeny() { return n_progeny_; }
445,508,906✔
743

744
  //! Gets the pointer to the particle's current PRN seed
745
  uint64_t* current_seed() { return seeds_ + stream_; }
2,147,483,647✔
746
  const uint64_t* current_seed() const { return seeds_ + stream_; }
747

748
  //! Force recalculation of neutron xs by setting last energy to zero
749
  void invalidate_neutron_xs()
53,378,090✔
750
  {
751
    for (auto& micro : neutron_xs_)
254,206,380✔
752
      micro.last_E = 0.0;
200,828,290✔
753
  }
53,378,090✔
754

755
  //! Get track information based on particle's current state
756
  TrackState get_track_state() const;
757

758
  void zero_delayed_bank()
2,147,483,647✔
759
  {
760
    for (int& n : n_delayed_bank_) {
2,147,483,647✔
761
      n = 0;
2,147,483,647✔
762
    }
763
  }
2,147,483,647✔
764

765
  void zero_flux_derivs()
269,785,300✔
766
  {
767
    for (double& d : flux_derivs_) {
269,817,300✔
768
      d = 0;
32,000✔
769
    }
770
  }
269,785,300✔
771
};
772

773
} // namespace openmc
774

775
#endif // OPENMC_PARTICLE_DATA_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