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

openmc-dev / openmc / 23916574395

02 Apr 2026 06:50PM UTC coverage: 81.336% (+0.01%) from 81.324%
23916574395

Pull #3734

github

web-flow
Merge 3420117d8 into d9b30bbbd
Pull Request #3734: Specify temperature from a field (structured mesh only)

17720 of 25601 branches covered (69.22%)

Branch coverage included in aggregate %.

183 of 204 new or added lines in 15 files covered. (89.71%)

69 existing lines in 3 files now uncovered.

58284 of 67843 relevant lines covered (85.91%)

44753955.49 hits per line

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

78.02
/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/particle_type.h"
7
#include "openmc/position.h"
8
#include "openmc/random_lcg.h"
9
#include "openmc/tallies/filter_match.h"
10
#include "openmc/vector.h"
11

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

16
namespace openmc {
17

18
//==============================================================================
19
// Constants
20
//==============================================================================
21

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

29
constexpr double CACHE_INVALID {-1.0};
30

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

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

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

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

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

88
//! Full history of a single particle's track states
89
struct TrackStateHistory {
19,961✔
90
  ParticleType particle;
91
  std::vector<TrackState> states;
92
};
93

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

101
class LocalCoord {
243,669,976✔
102
public:
103
  void rotate(const vector<double>& rotation);
104

105
  //! clear data from a single coordinate level
106
  void reset();
107

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

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

115
  int& cell() { return cell_; }
1,815,253!
116
  const int& cell() const { return cell_; }
121,923,839✔
117

118
  int& universe() { return universe_; }
119
  const int& universe() const { return universe_; }
9,540,949✔
120

121
  int& lattice() { return lattice_; }
122
  int lattice() const { return lattice_; }
2,147,483,647!
123

124
  array<int, 3>& lattice_index() { return lattice_index_; }
897,482,115✔
125
  const array<int, 3>& lattice_index() const { return lattice_index_; }
2,147,483,647!
126

127
  bool& rotated() { return rotated_; }
128
  const bool& rotated() const { return rotated_; }
129

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

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

146
struct NuclideMicroXS {
220,085,722✔
147
  // Microscopic cross sections in barns
148
  double total;      //!< total cross section
149
  double absorption; //!< absorption (disappearance)
150
  double fission;    //!< fission
151
  double nu_fission; //!< neutron production from fission
152

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

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

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

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

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

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

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

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

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

215
//==============================================================================
216
// Cache contains the cached data for an MGXS object
217
//==============================================================================
218

219
struct CacheDataMG {
161,577,399✔
220
  int material {-1}; //!< material index
221
  double sqrtkT;     //!< last temperature corresponding to t
222
  int t {0};         //!< temperature index
223
  int a {0};         //!< angle index
224
  Direction u;       //!< angle that corresponds to a
225
};
226

227
//==============================================================================
228
// Information about nearest boundary crossing
229
//==============================================================================
230

231
class BoundaryInfo {
207,309,309✔
232
public:
233
  void reset()
15,618,438✔
234
  {
235
    distance_ = INFINITY;
15,618,438✔
236
    surface_ = SURFACE_NONE;
15,618,438✔
237
    coord_level_ = 0;
15,618,438✔
238
    lattice_translation_ = {0, 0, 0};
15,618,438✔
239
  }
240
  double& distance() { return distance_; }
3,790,787✔
241
  const double& distance() const { return distance_; }
242

243
  int& surface() { return surface_; }
244
  const int& surface() const { return surface_; }
245

246
  int coord_level() const { return coord_level_; }
247
  int& coord_level() { return coord_level_; }
248

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

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

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

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

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

285
  // resets all coordinate levels for the particle
286
  void clear()
452,509,619✔
287
  {
288
    for (auto& level : coord_) {
962,802,340✔
289
      level.reset();
510,292,721✔
290
    }
291
    n_coord_ = 1;
452,509,619✔
292

293
    for (auto& cell : cell_last_) {
962,802,340✔
294
      cell = C_NONE;
510,292,721✔
295
    }
296
    n_coord_last_ = 1;
452,509,619✔
297
  }
452,509,619✔
298

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

303
  void advance_to_boundary_from_void();
304

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

318
  // Unique ID. This is not geometric info, but the
319
  // error reporting in geometry.cpp requires this.
320
  // We could save this to implement it in Particle,
321
  // but that would require virtuals.
322
  int64_t& id() { return id_; }
1,087✔
323
  const int64_t& id() const { return id_; }
352✔
324

325
  // Number of current coordinate levels
326
  int& n_coord() { return n_coord_; }
327
  const int& n_coord() const { return n_coord_; }
×
328

329
  // Offset for distributed properties
330
  int& cell_instance() { return cell_instance_; }
331
  const int& cell_instance() const { return cell_instance_; }
332

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

338
  // Innermost universe nesting coordinates
339
  LocalCoord& lowest_coord() { return coord_[n_coord_ - 1]; }
2,147,483,647!
340
  const LocalCoord& lowest_coord() const { return coord_[n_coord_ - 1]; }
989,852,054✔
341

342
  // Last coordinates on all nesting levels, before crossing a surface
343
  int& n_coord_last() { return n_coord_last_; }
344
  const int& n_coord_last() const { return n_coord_last_; }
345
  int& cell_last(int i) { return cell_last_[i]; }
2,147,483,647✔
346
  const int& cell_last(int i) const { return cell_last_[i]; }
43,756,658✔
347

348
  // Coordinates at birth
349
  Position& r_born() { return r_born_; }
350
  const Position& r_born() const { return r_born_; }
351

352
  // Coordinates of last collision or reflective/periodic surface
353
  // crossing for current tallies
354
  Position& r_last_current() { return r_last_current_; }
355
  const Position& r_last_current() const { return r_last_current_; }
356

357
  // Previous direction and spatial coordinates before a collision
358
  Position& r_last() { return r_last_; }
359
  const Position& r_last() const { return r_last_; }
360
  Position& u_last() { return u_last_; }
361
  const Position& u_last() const { return u_last_; }
5,663,933✔
362

363
  // Accessors for position in global coordinates
364
  Position& r() { return coord_[0].r(); }
2,147,483,647!
365
  const Position& r() const { return coord_[0].r(); }
649,269,000✔
366

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

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

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

379
  // Surface token for the surface that the particle is currently on
380
  int& surface() { return surface_; }
381
  const int& surface() const { return surface_; }
382

383
  // Surface index based on the current value of the surface_ attribute
384
  int surface_index() const
1,710,835,886✔
385
  {
386
    // TODO: off-by-one
387
    return std::abs(surface_) - 1;
1,710,835,886!
388
  }
389

390
  // Boundary information
391
  BoundaryInfo& boundary() { return boundary_; }
2,147,483,647!
392

393
#ifdef OPENMC_DAGMC_ENABLED
394
  // DagMC state variables
395
  moab::DagMC::RayHistory& history() { return history_; }
453,034,403✔
396
  Direction& last_dir() { return last_dir_; }
397
#endif
398

399
  // material of current and last cell
400
  int& material() { return material_; }
545,919✔
401
  const int& material() const { return material_; }
2,075,309,688✔
402
  int& material_last() { return material_last_; }
403
  const int& material_last() const { return material_last_; }
987,349✔
404

405
  // temperature of current and last cell
406
  double& sqrtkT() { return sqrtkT_; }
407
  const double& sqrtkT() const { return sqrtkT_; }
408
  double& sqrtkT_last() { return sqrtkT_last_; }
409

410
  // density multiplier of the current and last cell
411
  double& density_mult() { return density_mult_; }
412
  const double& density_mult() const { return density_mult_; }
413
  double& density_mult_last() { return density_mult_last_; }
414

415
private:
416
  int64_t id_ {-1}; //!< Unique ID
417

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

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

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

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

435
  BoundaryInfo boundary_; //!< Info about the next intersection
436

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

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

443
  double density_mult_ {1.0};      //!< density multiplier
444
  double density_mult_last_ {1.0}; //!< last density multiplier
445

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

452
//============================================================================
453
//! Defines how particle data is laid out in memory
454
//============================================================================
455

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

492
  vector<NuclideMicroXS> neutron_xs_;
493
  vector<ElementMicroXS> photon_xs_;
494
  MacroXS macro_xs_;
495
  CacheDataMG mg_xs_cache_;
496

497
  ParticleType type_;
498

499
  double E_;
500
  double E_last_;
501
  int g_ {0};
502
  int g_last_;
503

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

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

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

524
  int cell_born_ {-1};
525

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

529
  int n_collision_ {0};
530

531
  bool write_track_ {false};
532

533
  uint64_t seeds_[N_STREAMS];
534
  int stream_;
535

536
  vector<SourceSite> secondary_bank_;
537

538
  // Keep track of how many secondary particles were created in the collision
539
  // and what the starting index is in the secondary bank for this particle
540
  int n_secondaries_ {0};
541
  int secondary_bank_index_ {0};
542

543
  int64_t current_work_;
544

545
  vector<double> flux_derivs_;
546

547
  vector<FilterMatch> filter_matches_;
548

549
  vector<TrackStateHistory> tracks_;
550

551
  vector<NuBank> nu_bank_;
552

553
  vector<double> pht_storage_;
554

555
  double keff_tally_absorption_ {0.0};
556
  double keff_tally_collision_ {0.0};
557
  double keff_tally_tracklength_ {0.0};
558
  double keff_tally_leakage_ {0.0};
559

560
  bool trace_ {false};
561

562
  double collision_distance_;
563

564
  int n_event_ {0};
565

566
  int n_split_ {0};
567
  double ww_factor_ {0.0};
568

569
  int64_t n_progeny_ {0};
570

571
  int next_event_ {0};
572

573
public:
574
  //----------------------------------------------------------------------------
575
  // Constructors
576
  ParticleData();
577

578
  //==========================================================================
579
  // Methods and accessors
580

581
  // Cross section caches
582
  NuclideMicroXS& neutron_xs(int i)
2,147,483,647✔
583
  {
584
    return neutron_xs_[i];
2,147,483,647!
585
  } // Microscopic neutron cross sections
586
  const NuclideMicroXS& neutron_xs(int i) const { return neutron_xs_[i]; }
599,021,014!
587

588
  // Microscopic photon cross sections
589
  ElementMicroXS& photon_xs(int i) { return photon_xs_[i]; }
183,565,527!
590

591
  // Macroscopic cross sections
592
  MacroXS& macro_xs() { return macro_xs_; }
593
  const MacroXS& macro_xs() const { return macro_xs_; }
594

595
  // Multigroup macroscopic cross sections
596
  CacheDataMG& mg_xs_cache() { return mg_xs_cache_; }
597
  const CacheDataMG& mg_xs_cache() const { return mg_xs_cache_; }
598

599
  // Particle type (n, p, e, gamma, etc)
600
  ParticleType& type() { return type_; }
2,147,483,647!
601
  const ParticleType& type() const { return type_; }
2,147,483,647✔
602

603
  // Current particle energy, energy before collision,
604
  // and corresponding multigroup group indices. Energy
605
  // units are eV.
606
  double& E() { return E_; }
2,147,483,647!
607
  const double& E() const { return E_; }
561,873,460✔
608
  double& E_last() { return E_last_; }
609
  const double& E_last() const { return E_last_; }
610
  int& g() { return g_; }
9,226,712✔
611
  const int& g() const { return g_; }
612
  int& g_last() { return g_last_; }
613
  const int& g_last() const { return g_last_; }
614

615
  // Statistic weight of particle. Setting to zero indicates that the particle
616
  // is dead.
617
  double& wgt() { return wgt_; }
1,669,415,770✔
618
  double wgt() const { return wgt_; }
16,553!
619

620
  // Statistic weight of particle at birth
621
  double& wgt_born() { return wgt_born_; }
622
  double wgt_born() const { return wgt_born_; }
623

624
  // Weight window value at birth
625
  double& wgt_ww_born() { return wgt_ww_born_; }
626
  const double& wgt_ww_born() const { return wgt_ww_born_; }
627

628
  // Statistic weight of particle at last collision
629
  double& wgt_last() { return wgt_last_; }
630
  const double& wgt_last() const { return wgt_last_; }
631

632
  // Whether particle is alive
633
  bool alive() const { return wgt_ != 0.0; }
2,147,483,647!
634

635
  // Polar scattering angle after a collision
636
  double& mu() { return mu_; }
1,817,638,059✔
637
  const double& mu() const { return mu_; }
848,815✔
638

639
  // Tracks the time of a particle as it traverses the problem.
640
  // Units are seconds.
641
  double& time() { return time_; }
33✔
642
  const double& time() const { return time_; }
643
  double& time_last() { return time_last_; }
644
  const double& time_last() const { return time_last_; }
645

646
  // Particle lifetime
647
  double& lifetime() { return lifetime_; }
648
  const double& lifetime() const { return lifetime_; }
1,352,626✔
649

650
  // What event took place, described in greater detail below
651
  TallyEvent& event() { return event_; }
652
  const TallyEvent& event() const { return event_; }
653
  bool& fission() { return fission_; }            // true if implicit fission
654
  int& event_nuclide() { return event_nuclide_; } // index of collision nuclide
655
  const int& event_nuclide() const { return event_nuclide_; }
656
  int& event_mt() { return event_mt_; } // MT number of collision
657
  const int& event_mt() const { return event_mt_; }
658
  int& delayed_group() { return delayed_group_; } // delayed group
33✔
659
  const int& delayed_group() const { return delayed_group_; }
1,352,626✔
660
  const int& parent_nuclide() const { return parent_nuclide_; }
661
  int& parent_nuclide() { return parent_nuclide_; } // Parent nuclide
662

663
  // Post-collision data
664
  double& bank_second_E()
665
  {
666
    return bank_second_E_;
667
  } // energy of last reaction secondaries
668
  const double& bank_second_E() const { return bank_second_E_; }
669

670
  int& n_bank() { return n_bank_; }        // number of banked fission sites
671
  double& wgt_bank() { return wgt_bank_; } // weight of banked fission sites
672
  int* n_delayed_bank()
626,945✔
673
  {
674
    return n_delayed_bank_;
626,945✔
675
  } // number of delayed fission sites
676
  int& n_delayed_bank(int i)
1,087,847,502✔
677
  {
678
    return n_delayed_bank_[i];
1,087,847,502!
679
  } // number of delayed fission sites
680

681
  // Index of cell particle is born in
682
  int& cell_born() { return cell_born_; }
605!
683
  const int& cell_born() const { return cell_born_; }
3,208,755✔
684

685
  // Total number of collisions suffered by particle
686
  int& n_collision() { return n_collision_; }
687
  const int& n_collision() const { return n_collision_; }
688

689
  // whether this track is to be written
690
  bool& write_track() { return write_track_; }
691

692
  // RNG state
693
  uint64_t& seeds(int i) { return seeds_[i]; }
976,901,149✔
694
  uint64_t* seeds() { return seeds_; }
171,109,630✔
695
  int& stream() { return stream_; }
696

697
  // secondary particle bank
698
  SourceSite& secondary_bank(int i) { return secondary_bank_[i]; }
699
  const SourceSite& secondary_bank(int i) const { return secondary_bank_[i]; }
207,834!
700
  decltype(secondary_bank_)& secondary_bank() { return secondary_bank_; }
2,147,483,647!
701
  decltype(secondary_bank_) const& secondary_bank() const
702
  {
703
    return secondary_bank_;
704
  }
705

706
  // Number of secondaries created in a collision
707
  int& n_secondaries() { return n_secondaries_; }
708
  const int& n_secondaries() const { return n_secondaries_; }
709

710
  // Starting index in secondary bank for this collision
711
  int& secondary_bank_index() { return secondary_bank_index_; }
712
  const int& secondary_bank_index() const { return secondary_bank_index_; }
713

714
  // Current simulation work index
715
  int64_t& current_work() { return current_work_; }
716
  const int64_t& current_work() const { return current_work_; }
717

718
  // Used in tally derivatives
719
  double& flux_derivs(int i) { return flux_derivs_[i]; }
2,867,810✔
720
  const double& flux_derivs(int i) const { return flux_derivs_[i]; }
2,140,666✔
721

722
  // Matches of tallies
723
  decltype(filter_matches_)& filter_matches() { return filter_matches_; }
2,147,483,647✔
724
  FilterMatch& filter_matches(int i) { return filter_matches_[i]; }
6,567,979!
725

726
  // Tracks to output to file
727
  decltype(tracks_)& tracks() { return tracks_; }
25,827✔
728

729
  // Bank of recently fissioned particles
730
  decltype(nu_bank_)& nu_bank() { return nu_bank_; }
135,933,129✔
731
  NuBank& nu_bank(int i) { return nu_bank_[i]; }
1,925,583✔
732

733
  // Interim pulse height tally storage
734
  vector<double>& pht_storage() { return pht_storage_; }
168,965,406✔
735

736
  // Global tally accumulators
737
  double& keff_tally_absorption() { return keff_tally_absorption_; }
738
  double& keff_tally_collision() { return keff_tally_collision_; }
739
  double& keff_tally_tracklength() { return keff_tally_tracklength_; }
740
  double& keff_tally_leakage() { return keff_tally_leakage_; }
741

742
  // Shows debug info
743
  bool& trace() { return trace_; }
744

745
  // Distance to the next collision
746
  double& collision_distance() { return collision_distance_; }
747

748
  // Number of events particle has undergone
749
  int& n_event() { return n_event_; }
750

751
  // Number of times variance reduction has caused a particle split
752
  int n_split() const { return n_split_; }
753
  int& n_split() { return n_split_; }
754

755
  // Particle-specific factor for on-the-fly weight window adjustment
756
  double ww_factor() const { return ww_factor_; }
757
  double& ww_factor() { return ww_factor_; }
758

759
  // Number of progeny produced by this particle
760
  int64_t& n_progeny() { return n_progeny_; }
761

762
  //! Gets the pointer to the particle's current PRN seed
763
  uint64_t* current_seed() { return seeds_ + stream_; }
2,147,483,647✔
764
  const uint64_t* current_seed() const { return seeds_ + stream_; }
765

766
  //! Force recalculation of neutron xs by setting last energy to zero
767
  void invalidate_neutron_xs()
56,932,980✔
768
  {
769
    for (auto& micro : neutron_xs_)
280,206,560✔
770
      micro.last_E = 0.0;
223,273,580✔
771
  }
772

773
  //! Get track information based on particle's current state
774
  TrackState get_track_state() const;
775

776
  void zero_delayed_bank()
2,147,483,647✔
777
  {
778
    for (int& n : n_delayed_bank_) {
2,147,483,647✔
779
      n = 0;
2,147,483,647✔
780
    }
781
  }
782

783
  void zero_flux_derivs()
281,652,592✔
784
  {
785
    for (double& d : flux_derivs_) {
281,684,592✔
786
      d = 0;
32,000✔
787
    }
788
  }
789

790
  // Next event identifier for history-based transport
791
  int next_event() const { return next_event_; }
NEW
792
  int& next_event() { return next_event_; }
×
793
};
794

795
} // namespace openmc
796

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