• 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

2.44
/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
//! State of a particle used for particle track files
60
struct TrackState {
61
  Position r;           //!< Position in [cm]
62
  Direction u;          //!< Direction
63
  double E;             //!< Energy in [eV]
64
  double time {0.0};    //!< Time in [s]
65
  double wgt {1.0};     //!< Weight
66
  int cell_id;          //!< Cell ID
67
  int cell_instance;    //!< Cell instance
68
  int material_id {-1}; //!< Material ID (default value indicates void)
69
};
70

71
//! Full history of a single particle's track states
72
struct TrackStateHistory {
73
  ParticleType particle;
74
  std::vector<TrackState> states;
75
};
76

77
//! Saved ("banked") state of a particle, for nu-fission tallying
78
struct NuBank {
79
  double E;          //!< particle energy
80
  double wgt;        //!< particle weight
81
  int delayed_group; //!< particle delayed group
82
};
83

84
class LocalCoord {
85
public:
86
  void rotate(const vector<double>& rotation);
87

88
  //! clear data from a single coordinate level
89
  void reset();
90

91
  // accessors
92
  Position& r() { return r_; }
×
93
  const Position& r() const { return r_; }
×
94

95
  Direction& u() { return u_; }
×
96
  const Direction& u() const { return u_; }
97

98
  int& cell() { return cell_; }
×
UNCOV
99
  const int& cell() const { return cell_; }
×
100

101
  int& universe() { return universe_; }
102
  const int& universe() const { return universe_; }
103

104
  int& lattice() { return lattice_; }
105
  int lattice() const { return lattice_; }
106

107
  array<int, 3>& lattice_index() { return lattice_index_; }
108
  const array<int, 3>& lattice_index() const { return lattice_index_; }
109

110
  bool& rotated() { return rotated_; }
111
  const bool& rotated() const { return rotated_; }
112

113
private:
114
  // Data members
115
  Position r_;  //!< particle position
116
  Direction u_; //!< particle direction
117
  int cell_ {-1};
118
  int universe_ {-1};
119
  int lattice_ {-1};
120
  array<int, 3> lattice_index_ {{-1, -1, -1}};
121
  bool rotated_ {false}; //!< Is the level rotated?
122
};
123

124
//==============================================================================
125
//! Cached microscopic cross sections for a particular nuclide at the current
126
//! energy
127
//==============================================================================
128

129
struct NuclideMicroXS {
130
  // Microscopic cross sections in barns
131
  double total;      //!< total cross section
132
  double absorption; //!< absorption (disappearance)
133
  double fission;    //!< fission
134
  double nu_fission; //!< neutron production from fission
135

136
  double elastic;         //!< If sab_frac is not 1 or 0, then this value is
137
                          //!<   averaged over bound and non-bound nuclei
138
  double thermal;         //!< Bound thermal elastic & inelastic scattering
139
  double thermal_elastic; //!< Bound thermal elastic scattering
140
  double photon_prod;     //!< microscopic photon production xs
141

142
  // Cross sections for depletion reactions (note that these are not stored in
143
  // macroscopic cache)
144
  double reaction[DEPLETION_RX.size()];
145

146
  // Indicies and factors needed to compute cross sections from the data tables
147
  int index_grid;       //!< Index on nuclide energy grid
148
  int index_temp;       //!< Temperature index for nuclide
149
  double interp_factor; //!< Interpolation factor on nuc. energy grid
150
  int index_sab {-1};   //!< Index in sab_tables
151
  int index_temp_sab;   //!< Temperature index for sab_tables
152
  double sab_frac;      //!< Fraction of atoms affected by S(a,b)
153
  bool use_ptable;      //!< In URR range with probability tables?
154

155
  // Energy and temperature last used to evaluate these cross sections.  If
156
  // these values have changed, then the cross sections must be re-evaluated.
157
  double last_E {0.0};      //!< Last evaluated energy
158
  double last_sqrtkT {0.0}; //!< Last temperature in sqrt(Boltzmann constant
159
                            //!< * temperature (eV))
160
};
161

162
//==============================================================================
163
//! Cached microscopic photon cross sections for a particular element at the
164
//! current energy
165
//==============================================================================
166

167
struct ElementMicroXS {
168
  int index_grid;         //!< index on element energy grid
169
  double last_E {0.0};    //!< last evaluated energy in [eV]
170
  double interp_factor;   //!< interpolation factor on energy grid
171
  double total;           //!< microscopic total photon xs
172
  double coherent;        //!< microscopic coherent xs
173
  double incoherent;      //!< microscopic incoherent xs
174
  double photoelectric;   //!< microscopic photoelectric xs
175
  double pair_production; //!< microscopic pair production xs
176
};
177

178
//==============================================================================
179
// MacroXS contains cached macroscopic cross sections for the material a
180
// particle is traveling through
181
//==============================================================================
182

183
struct MacroXS {
184
  double total;       //!< macroscopic total xs
185
  double absorption;  //!< macroscopic absorption xs
186
  double fission;     //!< macroscopic fission xs
187
  double nu_fission;  //!< macroscopic production xs
188
  double photon_prod; //!< macroscopic photon production xs
189

190
  // Photon cross sections
191
  double coherent;        //!< macroscopic coherent xs
192
  double incoherent;      //!< macroscopic incoherent xs
193
  double photoelectric;   //!< macroscopic photoelectric xs
194
  double pair_production; //!< macroscopic pair production xs
195
};
196

197
//==============================================================================
198
// Cache contains the cached data for an MGXS object
199
//==============================================================================
200

201
struct CacheDataMG {
202
  int material {-1}; //!< material index
203
  double sqrtkT;     //!< last temperature corresponding to t
204
  int t {0};         //!< temperature index
205
  int a {0};         //!< angle index
206
  Direction u;       //!< angle that corresponds to a
207
};
208

209
//==============================================================================
210
// Information about nearest boundary crossing
211
//==============================================================================
212

213
class BoundaryInfo {
214
public:
215
  void reset()
216
  {
217
    distance_ = INFINITY;
218
    surface_ = SURFACE_NONE;
219
    coord_level_ = 0;
220
    lattice_translation_ = {0, 0, 0};
221
  }
222
  double& distance() { return distance_; }
223
  const double& distance() const { return distance_; }
224

225
  int& surface() { return surface_; }
226
  const int& surface() const { return surface_; }
227

228
  int coord_level() const { return coord_level_; }
229
  int& coord_level() { return coord_level_; }
230

231
  array<int, 3>& lattice_translation() { return lattice_translation_; }
232
  const array<int, 3>& lattice_translation() const
233
  {
234
    return lattice_translation_;
235
  }
236

237
  // TODO: off-by-one
238
  int surface_index() const { return std::abs(surface()) - 1; }
239

240
private:
241
  // Data members
242
  double distance_ {INFINITY}; //!< distance to nearest boundary
243
  int surface_ {
244
    SURFACE_NONE};      //!< surface token, non-zero if boundary is surface
245
  int coord_level_ {0}; //!< coordinate level after crossing boundary
246
  array<int, 3> lattice_translation_ {
247
    0, 0, 0}; //!< which way lattice indices will change
248
};
249

250
/*
251
 * Contains all geometry state information for a particle.
252
 */
253
class GeometryState {
254
public:
255
  GeometryState();
256

257
  /*
258
   * GeometryState does not store any ID info, so give some reasonable behavior
259
   * here. The Particle class redefines this. This is only here for the error
260
   * reporting behavior that occurs in geometry.cpp. The explanation for
261
   * mark_as_lost is the same.
262
   */
263
  virtual void mark_as_lost(const char* message);
264
  void mark_as_lost(const std::string& message);
265
  void mark_as_lost(const std::stringstream& message);
266

267
  // resets all coordinate levels for the particle
268
  void clear()
269
  {
270
    for (auto& level : coord_) {
271
      level.reset();
272
    }
273
    n_coord_ = 1;
274

275
    for (auto& cell : cell_last_) {
276
      cell = C_NONE;
277
    }
278
    n_coord_last_ = 1;
279
  }
280

281
  //! moves the particle by the specified distance to its next location
282
  //! \param distance the distance the particle is moved
283
  void move_distance(double distance);
284

285
  void advance_to_boundary_from_void();
286

287
  // Initialize all internal state from position and direction
288
  void init_from_r_u(Position r_a, Direction u_a)
289
  {
290
    clear();
291
    surface() = SURFACE_NONE;
292
    material() = C_NONE;
293
    r() = r_a;
294
    u() = u_a;
295
    r_last_current() = r_a;
296
    r_last() = r_a;
297
    u_last() = u_a;
298
  }
299

300
  // Unique ID. This is not geometric info, but the
301
  // error reporting in geometry.cpp requires this.
302
  // We could save this to implement it in Particle,
303
  // but that would require virtuals.
304
  int64_t& id() { return id_; }
×
305
  const int64_t& id() const { return id_; }
306

307
  // Number of current coordinate levels
308
  int& n_coord() { return n_coord_; }
309
  const int& n_coord() const { return n_coord_; }
310

311
  // Offset for distributed properties
312
  int& cell_instance() { return cell_instance_; }
×
UNCOV
313
  const int& cell_instance() const { return cell_instance_; }
×
314

315
  // Coordinates for all nesting levels
316
  LocalCoord& coord(int i) { return coord_[i]; }
317
  const LocalCoord& coord(int i) const { return coord_[i]; }
318
  const vector<LocalCoord>& coord() const { return coord_; }
319

320
  // Innermost universe nesting coordinates
321
  LocalCoord& lowest_coord() { return coord_[n_coord_ - 1]; }
×
UNCOV
322
  const LocalCoord& lowest_coord() const { return coord_[n_coord_ - 1]; }
×
323

324
  // Last coordinates on all nesting levels, before crossing a surface
325
  int& n_coord_last() { return n_coord_last_; }
326
  const int& n_coord_last() const { return n_coord_last_; }
327
  int& cell_last(int i) { return cell_last_[i]; }
328
  const int& cell_last(int i) const { return cell_last_[i]; }
329

330
  // Coordinates at birth
331
  Position& r_born() { return r_born_; }
332
  const Position& r_born() const { return r_born_; }
333

334
  // Coordinates of last collision or reflective/periodic surface
335
  // crossing for current tallies
336
  Position& r_last_current() { return r_last_current_; }
337
  const Position& r_last_current() const { return r_last_current_; }
338

339
  // Previous direction and spatial coordinates before a collision
340
  Position& r_last() { return r_last_; }
×
341
  const Position& r_last() const { return r_last_; }
342
  Position& u_last() { return u_last_; }
343
  const Position& u_last() const { return u_last_; }
344

345
  // Accessors for position in global coordinates
346
  Position& r() { return coord_[0].r(); }
×
347
  const Position& r() const { return coord_[0].r(); }
×
348

349
  // Accessors for position in local coordinates
350
  Position& r_local() { return coord_[n_coord_ - 1].r(); }
351
  const Position& r_local() const { return coord_[n_coord_ - 1].r(); }
352

353
  // Accessors for direction in global coordinates
354
  Direction& u() { return coord_[0].u(); }
×
355
  const Direction& u() const { return coord_[0].u(); }
356

357
  // Accessors for direction in local coordinates
358
  Direction& u_local() { return coord_[n_coord_ - 1].u(); }
359
  const Direction& u_local() const { return coord_[n_coord_ - 1].u(); }
360

361
  // Surface token for the surface that the particle is currently on
362
  int& surface() { return surface_; }
363
  const int& surface() const { return surface_; }
364

365
  // Surface index based on the current value of the surface_ attribute
366
  int surface_index() const
367
  {
368
    // TODO: off-by-one
369
    return std::abs(surface_) - 1;
370
  }
371

372
  // Boundary information
373
  BoundaryInfo& boundary() { return boundary_; }
374

375
#ifdef OPENMC_DAGMC_ENABLED
376
  // DagMC state variables
377
  moab::DagMC::RayHistory& history() { return history_; }
378
  Direction& last_dir() { return last_dir_; }
379
#endif
380

381
  // material of current and last cell
382
  int& material() { return material_; }
×
383
  const int& material() const { return material_; }
384
  int& material_last() { return material_last_; }
385
  const int& material_last() const { return material_last_; }
386

387
  // temperature of current and last cell
388
  double& sqrtkT() { return sqrtkT_; }
389
  const double& sqrtkT() const { return sqrtkT_; }
390
  double& sqrtkT_last() { return sqrtkT_last_; }
391

392
  // density multiplier of the current and last cell
393
  double& density_mult() { return density_mult_; }
394
  const double& density_mult() const { return density_mult_; }
395
  double& density_mult_last() { return density_mult_last_; }
396

397
private:
398
  int64_t id_ {-1}; //!< Unique ID
399

400
  int n_coord_ {1};          //!< number of current coordinate levels
401
  int cell_instance_;        //!< offset for distributed properties
402
  vector<LocalCoord> coord_; //!< coordinates for all levels
403

404
  int n_coord_last_ {1};  //!< number of current coordinates
405
  vector<int> cell_last_; //!< coordinates for all levels
406

407
  Position r_born_;         //!< coordinates at birth
408
  Position r_last_current_; //!< coordinates of the last collision or
409
                            //!< reflective/periodic surface crossing for
410
                            //!< current tallies
411
  Position r_last_;         //!< previous coordinates
412
  Direction u_last_;        //!< previous direction coordinates
413

414
  int surface_ {
415
    SURFACE_NONE}; //!< surface token for surface the particle is currently on
416

417
  BoundaryInfo boundary_; //!< Info about the next intersection
418

419
  int material_ {-1};      //!< index for current material
420
  int material_last_ {-1}; //!< index for last material
421

422
  double sqrtkT_ {-1.0};     //!< sqrt(k_Boltzmann * temperature) in eV
423
  double sqrtkT_last_ {0.0}; //!< last temperature
424

425
  double density_mult_ {1.0};      //!< density multiplier
426
  double density_mult_last_ {1.0}; //!< last density multiplier
427

428
#ifdef OPENMC_DAGMC_ENABLED
429
  moab::DagMC::RayHistory history_;
430
  Direction last_dir_;
431
#endif
432
};
433

434
//============================================================================
435
//! Defines how particle data is laid out in memory
436
//============================================================================
437

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

474
  vector<NuclideMicroXS> neutron_xs_;
475
  vector<ElementMicroXS> photon_xs_;
476
  MacroXS macro_xs_;
477
  CacheDataMG mg_xs_cache_;
478

479
  ParticleType type_ {ParticleType::neutron};
480

481
  double E_;
482
  double E_last_;
483
  int g_ {0};
484
  int g_last_;
485

486
  double wgt_ {1.0};
487
  double wgt_born_ {1.0};
488
  double wgt_ww_born_ {-1.0};
489
  double mu_;
490
  double time_ {0.0};
491
  double time_last_ {0.0};
492
  double wgt_last_ {1.0};
493

494
  bool fission_ {false};
495
  TallyEvent event_;
496
  int event_nuclide_;
497
  int event_mt_;
498
  int delayed_group_ {0};
499
  int parent_nuclide_ {-1};
500

501
  int n_bank_ {0};
502
  double bank_second_E_ {0.0};
503
  double wgt_bank_ {0.0};
504
  int n_delayed_bank_[MAX_DELAYED_GROUPS];
505

506
  int cell_born_ {-1};
507

508
  // Iterated Fission Probability
509
  double lifetime_ {0.0}; //!< neutron lifetime [s]
510

511
  int n_collision_ {0};
512

513
  bool write_track_ {false};
514

515
  uint64_t seeds_[N_STREAMS];
516
  int stream_;
517

518
  vector<SourceSite> secondary_bank_;
519

520
  int64_t current_work_;
521

522
  vector<double> flux_derivs_;
523

524
  vector<FilterMatch> filter_matches_;
525

526
  vector<TrackStateHistory> tracks_;
527

528
  vector<NuBank> nu_bank_;
529

530
  vector<double> pht_storage_;
531

532
  double keff_tally_absorption_ {0.0};
533
  double keff_tally_collision_ {0.0};
534
  double keff_tally_tracklength_ {0.0};
535
  double keff_tally_leakage_ {0.0};
536

537
  bool trace_ {false};
538

539
  double collision_distance_;
540

541
  int n_event_ {0};
542

543
  int n_split_ {0};
544
  double ww_factor_ {0.0};
545

546
  int64_t n_progeny_ {0};
547

548
public:
549
  //----------------------------------------------------------------------------
550
  // Constructors
551
  ParticleData();
552

553
  //==========================================================================
554
  // Methods and accessors
555

556
  // Cross section caches
557
  NuclideMicroXS& neutron_xs(int i)
558
  {
559
    return neutron_xs_[i];
560
  } // Microscopic neutron cross sections
561
  const NuclideMicroXS& neutron_xs(int i) const { return neutron_xs_[i]; }
562

563
  // Microscopic photon cross sections
564
  ElementMicroXS& photon_xs(int i) { return photon_xs_[i]; }
565

566
  // Macroscopic cross sections
567
  MacroXS& macro_xs() { return macro_xs_; }
×
568
  const MacroXS& macro_xs() const { return macro_xs_; }
569

570
  // Multigroup macroscopic cross sections
571
  CacheDataMG& mg_xs_cache() { return mg_xs_cache_; }
×
572
  const CacheDataMG& mg_xs_cache() const { return mg_xs_cache_; }
573

574
  // Particle type (n, p, e, gamma, etc)
575
  ParticleType& type() { return type_; }
576
  const ParticleType& type() const { return type_; }
577

578
  // Current particle energy, energy before collision,
579
  // and corresponding multigroup group indices. Energy
580
  // units are eV.
581
  double& E() { return E_; }
×
582
  const double& E() const { return E_; }
583
  double& E_last() { return E_last_; }
×
584
  const double& E_last() const { return E_last_; }
585
  int& g() { return g_; }
×
586
  const int& g() const { return g_; }
587
  int& g_last() { return g_last_; }
×
588
  const int& g_last() const { return g_last_; }
589

590
  // Statistic weight of particle. Setting to zero indicates that the particle
591
  // is dead.
592
  double& wgt() { return wgt_; }
×
593
  double wgt() const { return wgt_; }
594

595
  // Statistic weight of particle at birth
596
  double& wgt_born() { return wgt_born_; }
×
597
  double wgt_born() const { return wgt_born_; }
598

599
  // Weight window value at birth
600
  double& wgt_ww_born() { return wgt_ww_born_; }
601
  const double& wgt_ww_born() const { return wgt_ww_born_; }
602

603
  // Statistic weight of particle at last collision
604
  double& wgt_last() { return wgt_last_; }
605
  const double& wgt_last() const { return wgt_last_; }
606

607
  // Whether particle is alive
608
  bool alive() const { return wgt_ != 0.0; }
×
609

610
  // Polar scattering angle after a collision
611
  double& mu() { return mu_; }
×
612
  const double& mu() const { return mu_; }
613

614
  // Tracks the time of a particle as it traverses the problem.
615
  // Units are seconds.
616
  double& time() { return time_; }
×
617
  const double& time() const { return time_; }
618
  double& time_last() { return time_last_; }
619
  const double& time_last() const { return time_last_; }
620

621
  // Particle lifetime
622
  double& lifetime() { return lifetime_; }
623
  const double& lifetime() const { return lifetime_; }
624

625
  // What event took place, described in greater detail below
626
  TallyEvent& event() { return event_; }
×
627
  const TallyEvent& event() const { return event_; }
628
  bool& fission() { return fission_; }            // true if implicit fission
×
629
  int& event_nuclide() { return event_nuclide_; } // index of collision nuclide
630
  const int& event_nuclide() const { return event_nuclide_; }
631
  int& event_mt() { return event_mt_; } // MT number of collision
632
  const int& event_mt() const { return event_mt_; }
633
  int& delayed_group() { return delayed_group_; } // delayed group
×
634
  const int& delayed_group() const { return delayed_group_; }
635
  const int& parent_nuclide() const { return parent_nuclide_; }
636
  int& parent_nuclide() { return parent_nuclide_; } // Parent nuclide
637

638
  // Post-collision data
639
  double& bank_second_E()
640
  {
641
    return bank_second_E_;
642
  } // energy of last reaction secondaries
643
  const double& bank_second_E() const { return bank_second_E_; }
644

645
  int& n_bank() { return n_bank_; }        // number of banked fission sites
×
646
  double& wgt_bank() { return wgt_bank_; } // weight of banked fission sites
×
647
  int* n_delayed_bank()
648
  {
649
    return n_delayed_bank_;
650
  } // number of delayed fission sites
651
  int& n_delayed_bank(int i)
×
652
  {
653
    return n_delayed_bank_[i];
×
654
  } // number of delayed fission sites
655

656
  // Index of cell particle is born in
657
  int& cell_born() { return cell_born_; }
658
  const int& cell_born() const { return cell_born_; }
659

660
  // Total number of collisions suffered by particle
661
  int& n_collision() { return n_collision_; }
×
662
  const int& n_collision() const { return n_collision_; }
663

664
  // whether this track is to be written
665
  bool& write_track() { return write_track_; }
666

667
  // RNG state
668
  uint64_t& seeds(int i) { return seeds_[i]; }
669
  uint64_t* seeds() { return seeds_; }
670
  int& stream() { return stream_; }
671

672
  // secondary particle bank
673
  SourceSite& secondary_bank(int i) { return secondary_bank_[i]; }
674
  decltype(secondary_bank_)& secondary_bank() { return secondary_bank_; }
×
675

676
  // Current simulation work index
677
  int64_t& current_work() { return current_work_; }
678
  const int64_t& current_work() const { return current_work_; }
679

680
  // Used in tally derivatives
681
  double& flux_derivs(int i) { return flux_derivs_[i]; }
682
  const double& flux_derivs(int i) const { return flux_derivs_[i]; }
683

684
  // Matches of tallies
685
  decltype(filter_matches_)& filter_matches() { return filter_matches_; }
2,147,483,647✔
686
  FilterMatch& filter_matches(int i) { return filter_matches_[i]; }
687

688
  // Tracks to output to file
689
  decltype(tracks_)& tracks() { return tracks_; }
690

691
  // Bank of recently fissioned particles
692
  decltype(nu_bank_)& nu_bank() { return nu_bank_; }
×
693
  NuBank& nu_bank(int i) { return nu_bank_[i]; }
694

695
  // Interim pulse height tally storage
696
  vector<double>& pht_storage() { return pht_storage_; }
697

698
  // Global tally accumulators
699
  double& keff_tally_absorption() { return keff_tally_absorption_; }
×
700
  double& keff_tally_collision() { return keff_tally_collision_; }
701
  double& keff_tally_tracklength() { return keff_tally_tracklength_; }
702
  double& keff_tally_leakage() { return keff_tally_leakage_; }
703

704
  // Shows debug info
705
  bool& trace() { return trace_; }
×
706

707
  // Distance to the next collision
708
  double& collision_distance() { return collision_distance_; }
709

710
  // Number of events particle has undergone
711
  int& n_event() { return n_event_; }
712

713
  // Number of times variance reduction has caused a particle split
714
  int n_split() const { return n_split_; }
715
  int& n_split() { return n_split_; }
716

717
  // Particle-specific factor for on-the-fly weight window adjustment
718
  double ww_factor() const { return ww_factor_; }
719
  double& ww_factor() { return ww_factor_; }
720

721
  // Number of progeny produced by this particle
722
  int64_t& n_progeny() { return n_progeny_; }
×
723

724
  //! Gets the pointer to the particle's current PRN seed
725
  uint64_t* current_seed() { return seeds_ + stream_; }
×
726
  const uint64_t* current_seed() const { return seeds_ + stream_; }
727

728
  //! Force recalculation of neutron xs by setting last energy to zero
729
  void invalidate_neutron_xs()
730
  {
731
    for (auto& micro : neutron_xs_)
732
      micro.last_E = 0.0;
733
  }
734

735
  //! Get track information based on particle's current state
736
  TrackState get_track_state() const;
737

738
  void zero_delayed_bank()
739
  {
740
    for (int& n : n_delayed_bank_) {
741
      n = 0;
742
    }
743
  }
744

745
  void zero_flux_derivs()
746
  {
747
    for (double& d : flux_derivs_) {
748
      d = 0;
749
    }
750
  }
751
};
752

753
} // namespace openmc
754

755
#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