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

openmc-dev / openmc / 26672983103

30 May 2026 03:15AM UTC coverage: 81.344% (+0.01%) from 81.333%
26672983103

Pull #3946

github

web-flow
Merge a586ccc51 into 1914e3eef
Pull Request #3946: Fix collision track feature for photon transport

17999 of 26093 branches covered (68.98%)

Branch coverage included in aggregate %.

8 of 8 new or added lines in 2 files covered. (100.0%)

208 existing lines in 10 files now uncovered.

59127 of 68722 relevant lines covered (86.04%)

48521481.78 hits per line

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

86.55
/src/collision_track.cpp
1
#include "openmc/collision_track.h"
2

3
#include <algorithm>
4
#include <string>
5

6
#include <fmt/format.h>
7

8
#include "openmc/bank.h"
9
#include "openmc/bank_io.h"
10
#include "openmc/cell.h"
11
#include "openmc/constants.h"
12
#include "openmc/error.h"
13
#include "openmc/file_utils.h"
14
#include "openmc/hdf5_interface.h"
15
#include "openmc/material.h"
16
#include "openmc/mcpl_interface.h"
17
#include "openmc/message_passing.h"
18
#include "openmc/nuclide.h"
19
#include "openmc/output.h"
20
#include "openmc/particle.h"
21
#include "openmc/settings.h"
22
#include "openmc/simulation.h"
23
#include "openmc/universe.h"
24

25
#ifdef OPENMC_MPI
26
#include <mpi.h>
27
#endif
28

29
namespace openmc {
30

31
namespace {
32

33
hid_t h5_collision_track_banktype()
149✔
34
{
35
  hid_t postype = H5Tcreate(H5T_COMPOUND, sizeof(Position));
149✔
36
  H5Tinsert(postype, "x", HOFFSET(Position, x), H5T_NATIVE_DOUBLE);
149✔
37
  H5Tinsert(postype, "y", HOFFSET(Position, y), H5T_NATIVE_DOUBLE);
149✔
38
  H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE);
149✔
39

40
  hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(CollisionTrackSite));
149✔
41

42
  H5Tinsert(banktype, "r", HOFFSET(CollisionTrackSite, r), postype);
149✔
43
  H5Tinsert(banktype, "u", HOFFSET(CollisionTrackSite, u), postype);
149✔
44
  H5Tinsert(banktype, "E", HOFFSET(CollisionTrackSite, E), H5T_NATIVE_DOUBLE);
149✔
45
  H5Tinsert(banktype, "dE", HOFFSET(CollisionTrackSite, dE), H5T_NATIVE_DOUBLE);
149✔
46
  H5Tinsert(
149✔
47
    banktype, "time", HOFFSET(CollisionTrackSite, time), H5T_NATIVE_DOUBLE);
149✔
48
  H5Tinsert(
149✔
49
    banktype, "wgt", HOFFSET(CollisionTrackSite, wgt), H5T_NATIVE_DOUBLE);
149✔
50
  H5Tinsert(banktype, "event_mt", HOFFSET(CollisionTrackSite, event_mt),
149✔
51
    H5T_NATIVE_INT);
149✔
52
  H5Tinsert(banktype, "delayed_group",
149✔
53
    HOFFSET(CollisionTrackSite, delayed_group), H5T_NATIVE_INT);
149✔
54
  H5Tinsert(
149✔
55
    banktype, "cell_id", HOFFSET(CollisionTrackSite, cell_id), H5T_NATIVE_INT);
149✔
56
  H5Tinsert(banktype, "nuclide_id", HOFFSET(CollisionTrackSite, nuclide_id),
149✔
57
    H5T_NATIVE_INT);
149✔
58
  H5Tinsert(banktype, "material_id", HOFFSET(CollisionTrackSite, material_id),
149✔
59
    H5T_NATIVE_INT);
149✔
60
  H5Tinsert(banktype, "universe_id", HOFFSET(CollisionTrackSite, universe_id),
149✔
61
    H5T_NATIVE_INT);
149✔
62
  H5Tinsert(banktype, "n_collision", HOFFSET(CollisionTrackSite, n_collision),
149✔
63
    H5T_NATIVE_INT);
149✔
64
  H5Tinsert(banktype, "particle", HOFFSET(CollisionTrackSite, particle),
149✔
65
    H5T_NATIVE_INT);
149✔
66
  H5Tinsert(banktype, "parent_id", HOFFSET(CollisionTrackSite, parent_id),
149✔
67
    H5T_NATIVE_INT64);
149✔
68
  H5Tinsert(banktype, "progeny_id", HOFFSET(CollisionTrackSite, progeny_id),
149✔
69
    H5T_NATIVE_INT64);
149✔
70
  H5Tclose(postype);
149✔
71
  return banktype;
149✔
72
}
73

74
void write_collision_track_bank(hid_t group_id,
149✔
75
  openmc::span<CollisionTrackSite> collision_track_bank,
76
  const openmc::vector<int64_t>& bank_index)
77
{
78
  hid_t banktype = h5_collision_track_banktype();
149✔
79
#ifdef OPENMC_MPI
80
  write_bank_dataset("collision_track_bank", group_id, collision_track_bank,
72✔
81
    bank_index, banktype, banktype, mpi::collision_track_site);
82
#else
83
  write_bank_dataset("collision_track_bank", group_id, collision_track_bank,
77✔
84
    bank_index, banktype, banktype);
85
#endif
86

87
  H5Tclose(banktype);
149✔
88
}
149✔
89

90
void write_h5_collision_track(const char* filename,
149✔
91
  openmc::span<CollisionTrackSite> collision_track_bank,
92
  const openmc::vector<int64_t>& bank_index)
93
{
94
#ifdef PHDF5
95
  bool parallel = true;
72✔
96
#else
97
  bool parallel = false;
77✔
98
#endif
99

100
  if (!filename)
149!
101
    fatal_error("write_h5_collision_track filename needs a nonempty name.");
×
102

103
  std::string filename_(filename);
149✔
104
  const auto extension = get_file_extension(filename_);
149✔
105
  if (extension.empty()) {
149!
106
    filename_.append(".h5");
×
107
  } else if (extension != "h5") {
149!
108
    warning("write_h5_collision_track was passed a file extension differing "
×
109
            "from .h5, but an hdf5 file will be written.");
110
  }
111

112
  hid_t file_id;
149✔
113
  if (mpi::master || parallel) {
149!
114
    file_id = file_open(filename_.c_str(), 'w', true);
149✔
115

116
    // Write filetype and version info
117
    write_attribute(file_id, "filetype", "collision_track");
149✔
118
    write_attribute(file_id, "version", VERSION_COLLISION_TRACK);
149✔
119
  }
120

121
  write_collision_track_bank(file_id, collision_track_bank, bank_index);
149✔
122

123
  if (mpi::master || parallel)
149!
124
    file_close(file_id);
149✔
125
}
149✔
126

127
} // namespace
128

129
bool should_record_event(int id_cell, int mt_event, const std::string& nuclide,
992,695✔
130
  int id_universe, int id_material, double energy_loss)
131
{
132
  auto matches_filter = [](const auto& filter_set, const auto& value) {
361,999✔
133
    return filter_set.empty() || filter_set.count(value) > 0;
490,765✔
134
  };
135

136
  const auto& cfg = settings::collision_track_config;
992,695✔
137
  return simulation::current_batch > settings::n_inactive &&
1,954,667✔
138
         !simulation::collision_track_bank.full() &&
961,972✔
139
         matches_filter(cfg.cell_ids, id_cell) &&
105,963✔
140
         matches_filter(cfg.mt_numbers, mt_event) &&
77,814✔
141
         matches_filter(cfg.universe_ids, id_universe) &&
63,195!
142
         matches_filter(cfg.material_ids, id_material) &&
115,027✔
143
         matches_filter(cfg.nuclides, nuclide) &&
1,044,527✔
144
         (cfg.deposited_energy_threshold == 0 ||
38,379✔
145
           cfg.deposited_energy_threshold < energy_loss);
992,695✔
146
}
147

148
void collision_track_reserve_bank()
160✔
149
{
150
  simulation::collision_track_bank.reserve(
160✔
151
    settings::collision_track_config.max_collisions);
152
}
160✔
153

154
void collision_track_flush_bank()
580✔
155
{
156
  const auto& cfg = settings::collision_track_config;
580✔
157
  if (simulation::ct_current_file > cfg.max_files)
580!
158
    return;
420✔
159

160
  bool last_batch = (simulation::current_batch == settings::n_batches);
580✔
161
  if (!simulation::collision_track_bank.full() && !last_batch)
580✔
162
    return;
163

164
  auto size = simulation::collision_track_bank.size();
160✔
165
  if (size == 0 && !last_batch)
160!
166
    return;
167

168
  auto collision_track_work_index = mpi::calculate_parallel_index_vector(size);
160✔
169
  openmc::span<CollisionTrackSite> collisiontrackbankspan(
160✔
170
    simulation::collision_track_bank.begin(), size);
160✔
171

172
  std::string ext = cfg.mcpl_write ? "mcpl" : "h5";
309✔
173
  auto filename = fmt::format("{}collision_track.{}.{}", settings::path_output,
160✔
174
    simulation::ct_current_file, ext);
160✔
175

176
  if (cfg.max_files == 1 || (simulation::ct_current_file == 1 && last_batch)) {
160!
177
    filename = settings::path_output + "collision_track." + ext;
160✔
178
  }
179
  write_message("Creating {}...", filename, 4);
160✔
180

181
  if (cfg.mcpl_write) {
160✔
182
    write_mcpl_collision_track(
11✔
183
      filename.c_str(), collisiontrackbankspan, collision_track_work_index);
184
  } else {
185
    write_h5_collision_track(
149✔
186
      filename.c_str(), collisiontrackbankspan, collision_track_work_index);
187
  }
188

189
  simulation::collision_track_bank.clear();
160✔
190
  if (!last_batch && cfg.max_files >= 1) {
160!
UNCOV
191
    collision_track_reserve_bank();
×
192
  }
193
  ++simulation::ct_current_file;
160✔
194
}
160✔
195

196
void collision_track_record(Particle& particle)
992,695✔
197
{
198
  int cell_index = particle.lowest_coord().cell();
992,695!
199
  if (cell_index == C_NONE)
992,695!
200
    return;
971,663✔
201

202
  int cell_id = model::cells[cell_index]->id_;
992,695✔
203
  std::string nuclide {};
992,695✔
204
  int nuclide_id {-1};
992,695✔
205
  if (particle.event_nuclide() != NUCLIDE_NONE) {
992,695✔
206
    const auto* nuclide_ptr = data::nuclides[particle.event_nuclide()].get();
580,426✔
207
    nuclide = nuclide_ptr->name_;
580,426✔
208
    nuclide_id = nuclide_ptr->particle_type().pdg_number();
580,426✔
209
  }
210
  int universe_id = model::universes[particle.lowest_coord().universe()]->id_;
992,695!
211
  double delta_E = particle.E_last() - particle.E();
992,695✔
212
  int material_index = particle.material();
992,695✔
213
  if (material_index == C_NONE)
992,695!
214
    return;
215

216
  int material_id = model::materials[material_index]->id_;
992,695✔
217

218
  if (!should_record_event(cell_id, particle.event_mt(), nuclide, universe_id,
992,695✔
219
        material_id, delta_E))
220
    return;
221

222
  CollisionTrackSite site;
21,032✔
223
  site.r = particle.r();
21,032✔
224
  site.u = particle.u();
21,032✔
225
  site.E = particle.E_last();
21,032✔
226
  site.dE = delta_E;
21,032✔
227
  site.time = particle.time();
21,032✔
228
  site.wgt = particle.wgt();
21,032✔
229
  site.event_mt = particle.event_mt();
21,032✔
230
  site.delayed_group = particle.delayed_group();
21,032✔
231
  site.cell_id = cell_id;
21,032✔
232
  site.nuclide_id = nuclide_id;
21,032✔
233
  site.material_id = material_id;
21,032✔
234
  site.universe_id = universe_id;
21,032✔
235
  site.n_collision = particle.n_collision();
21,032✔
236
  site.particle = particle.type();
21,032✔
237
  site.parent_id = particle.id();
21,032✔
238
  site.progeny_id = particle.n_progeny();
21,032✔
239
  simulation::collision_track_bank.thread_safe_append(site);
21,032✔
240
}
992,695✔
241

242
} // namespace openmc
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