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

openmc-dev / openmc / 35502912243

20 Sep 2026 09:39AM UTC coverage: 81.443% (-0.03%) from 81.477%
35502912243

Pull #3675

github

web-flow
Merge 5a57bab9f into afa7a14ac
Pull Request #3675: Extend level scattering to support incident photons

19979 of 29041 branches covered (68.8%)

Branch coverage included in aggregate %.

87 of 108 new or added lines in 7 files covered. (80.56%)

590 existing lines in 9 files now uncovered.

62436 of 72153 relevant lines covered (86.53%)

49657901.89 hits per line

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

73.26
/src/hdf5_interface.cpp
1
#include "openmc/hdf5_interface.h"
2

3
#include <cstring>
4
#include <stdexcept>
5
#include <string>
6

7
#include "openmc/tensor.h"
8
#include <fmt/core.h>
9

10
#include "hdf5.h"
11
#include "hdf5_hl.h"
12
#ifdef OPENMC_MPI
13
#include "mpi.h"
14
#include "openmc/message_passing.h"
15
#endif
16

17
#include "openmc/array.h"
18

19
namespace openmc {
20

21
bool attribute_exists(hid_t obj_id, const char* name)
58,249,018 ✔
22
{
23
  htri_t out = H5Aexists_by_name(obj_id, ".", name, H5P_DEFAULT);
58,249,018 ✔
24
  return out > 0;
58,249,018 ✔
25
}
26

27
size_t attribute_typesize(hid_t obj_id, const char* name)
19,315,549 ✔
28
{
29
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
19,315,549 ✔
30
  hid_t filetype = H5Aget_type(attr);
19,315,549 ✔
31
  size_t n = H5Tget_size(filetype);
19,315,549 ✔
32
  H5Tclose(filetype);
19,315,549 ✔
33
  H5Aclose(attr);
19,315,549 ✔
34
  return n;
19,315,549 ✔
35
}
36

37
void get_shape(hid_t obj_id, hsize_t* dims)
×
38
{
39
  auto type = H5Iget_type(obj_id);
×
40
  hid_t dspace;
×
41
  if (type == H5I_DATASET) {
×
42
    dspace = H5Dget_space(obj_id);
×
43
  } else if (type == H5I_ATTR) {
×
44
    dspace = H5Aget_space(obj_id);
×
45
  } else {
46
    throw std::runtime_error {
×
47
      "Expected dataset or attribute in call to get_shape."};
×
48
  }
49
  H5Sget_simple_extent_dims(dspace, dims, nullptr);
×
50
  H5Sclose(dspace);
×
51
}
×
52

53
vector<hsize_t> attribute_shape(hid_t obj_id, const char* name)
15,538,209 ✔
54
{
55
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
15,538,209 ✔
56
  vector<hsize_t> shape = object_shape(attr);
15,538,209 ✔
57
  H5Aclose(attr);
15,538,209 ✔
58
  return shape;
15,538,209 ✔
59
}
×
60

61
vector<hsize_t> object_shape(hid_t obj_id)
29,317,492 ✔
62
{
63
  // Get number of dimensions
64
  auto type = H5Iget_type(obj_id);
29,317,492 ✔
65
  hid_t dspace;
29,317,492 ✔
66
  if (type == H5I_DATASET) {
29,317,492 ✔
67
    dspace = H5Dget_space(obj_id);
13,779,283 ✔
68
  } else if (type == H5I_ATTR) {
15,538,209 !
69
    dspace = H5Aget_space(obj_id);
15,538,209 ✔
70
  } else {
71
    throw std::runtime_error {
×
72
      "Expected dataset or attribute in call to object_shape."};
×
73
  }
74
  int n = H5Sget_simple_extent_ndims(dspace);
29,317,492 ✔
75

76
  // Get shape of array
77
  vector<hsize_t> shape(n);
29,317,492 ✔
78
  H5Sget_simple_extent_dims(dspace, shape.data(), nullptr);
29,317,492 ✔
79

80
  // Free resources and return
81
  H5Sclose(dspace);
29,317,492 ✔
82
  return shape;
29,317,492 ✔
83
}
×
84

85
void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims)
×
86
{
87
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
×
88
  hid_t dspace = H5Aget_space(attr);
×
89
  H5Sget_simple_extent_dims(dspace, dims, nullptr);
×
90
  H5Sclose(dspace);
×
91
  H5Aclose(attr);
×
92
}
×
93

94
hid_t create_group(hid_t parent_id, const char* name)
248,937 ✔
95
{
96
  hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
248,937 ✔
97
  if (out < 0) {
248,937 !
98
    fatal_error(fmt::format("Failed to create HDF5 group \"{}\"", name));
×
99
  }
100
  return out;
248,937 ✔
101
}
102

103
hid_t create_group(hid_t parent_id, const std::string& name)
148,478 ✔
104
{
105
  return create_group(parent_id, name.c_str());
148,478 ✔
106
}
107

108
void close_dataset(hid_t dataset_id)
9,879,018 ✔
109
{
110
  if (H5Dclose(dataset_id) < 0)
9,879,018 !
111
    fatal_error("Failed to close dataset");
×
112
}
9,879,018 ✔
113

114
void close_group(hid_t group_id)
18,506,829 ✔
115
{
116
  if (H5Gclose(group_id) < 0)
18,506,829 !
117
    fatal_error("Failed to close group");
×
118
}
18,506,829 ✔
119

120
void close_object(hid_t obj_id)
3,938,483 ✔
121
{
122
  if (H5Oclose(obj_id) < 0)
3,938,483 !
123
    fatal_error("Failed to close object");
×
124
}
3,938,483 ✔
125

126
int dataset_ndims(hid_t dset)
75 ✔
127
{
128
  hid_t dspace = H5Dget_space(dset);
75 ✔
129
  int ndims = H5Sget_simple_extent_ndims(dspace);
75 ✔
130
  H5Sclose(dspace);
75 ✔
131
  return ndims;
75 ✔
132
}
133

134
size_t dataset_typesize(hid_t obj_id, const char* name)
233 ✔
135
{
136
  hid_t dset = open_dataset(obj_id, name);
233 ✔
137
  hid_t filetype = H5Dget_type(dset);
233 ✔
138
  size_t n = H5Tget_size(filetype);
233 ✔
139
  H5Tclose(filetype);
233 ✔
140
  close_dataset(dset);
233 ✔
141
  return n;
233 ✔
142
}
143

144
void ensure_exists(hid_t obj_id, const char* name, bool attribute)
88,292,186 ✔
145
{
146
  if (attribute) {
88,292,186 ✔
147
    if (!attribute_exists(obj_id, name)) {
56,018,140 !
148
      fatal_error(fmt::format("Attribute \"{}\" does not exist in object {}",
×
149
        name, object_name(obj_id)));
×
150
    }
151
  } else {
152
    if (!object_exists(obj_id, name)) {
32,274,046 !
153
      fatal_error(fmt::format("Object \"{}\" does not exist in object {}", name,
×
154
        object_name(obj_id)));
×
155
    }
156
  }
157
}
88,292,186 ✔
158

159
hid_t file_open(const char* filename, char mode, bool parallel)
64,835 ✔
160
{
161
  bool create;
64,835 ✔
162
  unsigned int flags;
64,835 ✔
163
  switch (mode) {
64,835 !
164
  case 'r':
46,877 ✔
165
  case 'a':
46,877 ✔
166
    create = false;
46,877 ✔
167
    flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR);
46,877 ✔
168
    break;
26,623 ✔
169
  case 'w':
17,958 ✔
170
  case 'x':
17,958 ✔
171
    create = true;
17,958 ✔
172
    flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC);
17,958 !
173
    break;
11,287 ✔
174
  default:
×
175
    fatal_error(fmt::format("Invalid file mode: ", mode));
×
176
  }
177

178
  hid_t plist = H5P_DEFAULT;
64,835 ✔
179
#ifdef PHDF5
180
  if (parallel) {
26,925 ✔
181
    // Setup file access property list with parallel I/O access
182
    plist = H5Pcreate(H5P_FILE_ACCESS);
3,212 ✔
183
    H5Pset_fapl_mpio(plist, openmc::mpi::intracomm, MPI_INFO_NULL);
3,212 ✔
184
  }
185
#endif
186

187
  // Open the file collectively
188
  hid_t file_id;
64,835 ✔
189
  if (create) {
64,835 ✔
190
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
17,958 ✔
191
  } else {
192
    file_id = H5Fopen(filename, flags, plist);
46,877 ✔
193
  }
194
  if (file_id < 0) {
64,835 !
195
    fatal_error(fmt::format(
×
196
      "Failed to open HDF5 file with mode '{}': {}", mode, filename));
197
  }
198

199
#ifdef PHDF5
200
  // Close the property list
201
  if (parallel)
26,925 ✔
202
    H5Pclose(plist);
3,212 ✔
203
#endif
204

205
  return file_id;
64,835 ✔
206
}
207

208
hid_t file_open(const std::string& filename, char mode, bool parallel)
63,931 ✔
209
{
210
  return file_open(filename.c_str(), mode, parallel);
63,931 ✔
211
}
212

213
hid_t open_group(hid_t group_id, const std::string& name)
422 ✔
214
{
215
  return open_group(group_id, name.c_str());
422 ✔
216
}
217

218
void file_close(hid_t file_id)
64,815 ✔
219
{
220
  H5Fclose(file_id);
64,815 ✔
221
}
64,815 ✔
222

223
void get_name(hid_t obj_id, std::string& name)
4,079 ✔
224
{
225
  size_t size = 1 + H5Iget_name(obj_id, nullptr, 0);
4,079 ✔
226
  name.resize(size);
4,079 ✔
227
  H5Iget_name(obj_id, name.data(), size);
4,079 ✔
228
}
4,079 ✔
229

230
int get_num_datasets(hid_t group_id)
4,079 ✔
231
{
232
  // Determine number of links in the group
233
  H5G_info_t info;
4,079 ✔
234
  H5Gget_info(group_id, &info);
4,079 ✔
235

236
  // Iterate over links to get number of groups
237
  H5O_info_t oinfo;
238
  int ndatasets = 0;
239
  for (hsize_t i = 0; i < info.nlinks; ++i) {
9,238 ✔
240
    // Determine type of object (and skip non-group)
241
    H5Oget_info_by_idx(
5,159 ✔
242
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
243
    if (oinfo.type == H5O_TYPE_DATASET)
5,159 !
244
      ndatasets += 1;
5,159 ✔
245
  }
246

247
  return ndatasets;
4,079 ✔
248
}
249

250
int get_num_groups(hid_t group_id)
×
251
{
252
  // Determine number of links in the group
253
  H5G_info_t info;
×
254
  H5Gget_info(group_id, &info);
×
255

256
  // Iterate over links to get number of groups
257
  H5O_info_t oinfo;
258
  int ngroups = 0;
259
  for (hsize_t i = 0; i < info.nlinks; ++i) {
×
260
    // Determine type of object (and skip non-group)
261
    H5Oget_info_by_idx(
×
262
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
263
    if (oinfo.type == H5O_TYPE_GROUP)
×
264
      ngroups += 1;
×
265
  }
266

267
  return ngroups;
×
268
}
269

270
void get_datasets(hid_t group_id, char* name[])
4,079 ✔
271
{
272
  // Determine number of links in the group
273
  H5G_info_t info;
4,079 ✔
274
  H5Gget_info(group_id, &info);
4,079 ✔
275

276
  // Iterate over links to get names
277
  H5O_info_t oinfo;
278
  hsize_t count = 0;
279
  size_t size;
280
  for (hsize_t i = 0; i < info.nlinks; ++i) {
9,238 ✔
281
    // Determine type of object (and skip non-group)
282
    H5Oget_info_by_idx(
5,159 ✔
283
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
284
    if (oinfo.type != H5O_TYPE_DATASET)
5,159 !
285
      continue;
×
286

287
    // Get size of name
288
    size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
5,159 ✔
289
                 nullptr, 0, H5P_DEFAULT);
290

291
    // Read name
292
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
5,159 ✔
293
      name[count], size, H5P_DEFAULT);
5,159 ✔
294
    count += 1;
5,159 ✔
295
  }
296
}
4,079 ✔
297

298
void get_groups(hid_t group_id, char* name[])
×
299
{
300
  // Determine number of links in the group
301
  H5G_info_t info;
×
302
  H5Gget_info(group_id, &info);
×
303

304
  // Iterate over links to get names
305
  H5O_info_t oinfo;
306
  hsize_t count = 0;
307
  size_t size;
308
  for (hsize_t i = 0; i < info.nlinks; ++i) {
×
309
    // Determine type of object (and skip non-group)
310
    H5Oget_info_by_idx(
×
311
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
312
    if (oinfo.type != H5O_TYPE_GROUP)
×
313
      continue;
×
314

315
    // Get size of name
316
    size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
×
317
                 nullptr, 0, H5P_DEFAULT);
318

319
    // Read name
320
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
×
321
      name[count], size, H5P_DEFAULT);
×
322
    count += 1;
×
323
  }
324
}
×
325

326
vector<std::string> member_names(hid_t group_id, H5O_type_t type)
1,555,021 ✔
327
{
328
  // Determine number of links in the group
329
  H5G_info_t info;
1,555,021 ✔
330
  H5Gget_info(group_id, &info);
1,555,021 ✔
331

332
  // Iterate over links to get names
333
  H5O_info_t oinfo;
1,555,021 ✔
334
  size_t size;
1,555,021 ✔
335
  vector<std::string> names;
1,555,021 ✔
336
  for (hsize_t i = 0; i < info.nlinks; ++i) {
8,593,444 ✔
337
    // Determine type of object (and skip non-group)
338
    H5Oget_info_by_idx(
7,038,423 ✔
339
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
340
    if (oinfo.type != type)
7,038,423 !
341
      continue;
×
342

343
    // Get size of name
344
    size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
7,038,423 ✔
345
                 nullptr, 0, H5P_DEFAULT);
346

347
    // Read name
348
    char* buffer = new char[size];
7,038,423 ✔
349
    H5Lget_name_by_idx(
7,038,423 ✔
350
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, buffer, size, H5P_DEFAULT);
351
    names.emplace_back(&buffer[0]);
7,038,423 ✔
352
    delete[] buffer;
7,038,423 ✔
353
  }
354
  return names;
1,555,021 ✔
355
}
×
356

357
vector<std::string> group_names(hid_t group_id)
1,521,910 ✔
358
{
359
  return member_names(group_id, H5O_TYPE_GROUP);
1,521,910 ✔
360
}
361

362
vector<std::string> dataset_names(hid_t group_id)
33,111 ✔
363
{
364
  return member_names(group_id, H5O_TYPE_DATASET);
33,111 ✔
365
}
366

367
bool object_exists(hid_t object_id, const char* name)
40,004,018 ✔
368
{
369
  htri_t out = H5LTpath_valid(object_id, name, true);
40,004,018 ✔
370
  if (out < 0) {
40,004,018 !
371
    fatal_error(fmt::format("Failed to check if object \"{}\" exists.", name));
×
372
  }
373
  return (out > 0);
40,004,018 ✔
374
}
375

376
std::string object_name(hid_t obj_id)
38,943 ✔
377
{
378
  // Determine size and create buffer
379
  size_t size = 1 + H5Iget_name(obj_id, nullptr, 0);
38,943 ✔
380
  char* buffer = new char[size];
38,943 ✔
381

382
  // Read and return name
383
  H5Iget_name(obj_id, buffer, size);
38,943 ✔
384
  std::string str = buffer;
38,943 ✔
385
  delete[] buffer;
38,943 ✔
386
  return str;
38,943 ✔
387
}
388

389
hid_t open_dataset(hid_t group_id, const char* name)
9,963,247 ✔
390
{
391
  ensure_exists(group_id, name);
9,963,247 ✔
392
  return H5Dopen(group_id, name, H5P_DEFAULT);
9,963,247 ✔
393
}
394

395
hid_t open_group(hid_t group_id, const char* name)
18,372,316 ✔
396
{
397
  ensure_exists(group_id, name);
18,372,316 ✔
398
  return H5Gopen(group_id, name, H5P_DEFAULT);
18,372,316 ✔
399
}
400

401
hid_t open_object(hid_t group_id, const std::string& name)
3,938,483 ✔
402
{
403
  ensure_exists(group_id, name.c_str());
3,938,483 ✔
404
  return H5Oopen(group_id, name.c_str(), H5P_DEFAULT);
3,938,483 ✔
405
}
406

407
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer)
56,014,888 ✔
408
{
409
  // Without this, a missing attribute leaves the caller's buffer untouched and
410
  // the run continues on whatever it held. That turns a data-format mismatch
411
  // into silently wrong results rather than an error.
412
  ensure_exists(obj_id, name, true);
56,014,888 ✔
413

414
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
56,014,888 ✔
415
  if (H5Aread(attr, mem_type_id, buffer) < 0) {
56,014,888 !
NEW
416
    H5Aclose(attr);
×
NEW
417
    fatal_error(fmt::format("Failed to read attribute \"{}\" of object {}",
×
NEW
418
      name, object_name(obj_id)));
×
419
  }
420
  H5Aclose(attr);
56,014,888 ✔
421
}
56,014,888 ✔
422

423
void read_attr_double(hid_t obj_id, const char* name, double* buffer)
120 ✔
424
{
425
  read_attr(obj_id, name, H5T_NATIVE_DOUBLE, buffer);
120 ✔
426
}
120 ✔
427

428
void read_attr_int(hid_t obj_id, const char* name, int* buffer)
8,218 ✔
429
{
430
  read_attr(obj_id, name, H5T_NATIVE_INT, buffer);
8,218 ✔
431
}
8,218 ✔
432

433
void read_attr_string(hid_t obj_id, const char* name, size_t slen, char* buffer)
19,315,549 ✔
434
{
435
  // Create datatype for a string
436
  hid_t datatype = H5Tcopy(H5T_C_S1);
19,315,549 ✔
437
  H5Tset_size(datatype, slen);
19,315,549 ✔
438
  // numpy uses null-padding when writing fixed-length strings
439
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
19,315,549 ✔
440

441
  // Read data into buffer
442
  read_attr(obj_id, name, datatype, buffer);
19,315,549 ✔
443

444
  // Free resources
445
  H5Tclose(datatype);
19,315,549 ✔
446
}
19,315,549 ✔
447

448
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
13,882,297 ✔
449
  hid_t mem_space_id, bool indep, void* buffer)
450
{
451
  hid_t dset = obj_id;
13,882,297 ✔
452
  if (name)
13,882,297 ✔
453
    dset = open_dataset(obj_id, name);
84,229 ✔
454

455
  if (using_mpio_device(dset)) {
13,882,297 ✔
456
#ifdef PHDF5
457
    // Set up collective vs independent I/O
458
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
552 !
459

460
    // Create dataset transfer property list
461
    hid_t plist = H5Pcreate(H5P_DATASET_XFER);
552 ✔
462
    H5Pset_dxpl_mpio(plist, data_xfer_mode);
552 ✔
463

464
    // Read data
465
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
552 ✔
466
    H5Pclose(plist);
552 ✔
467
#endif
468
  } else {
469
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
13,881,745 ✔
470
  }
471

472
  if (name)
13,882,297 ✔
473
    H5Dclose(dset);
84,229 ✔
474
}
13,882,297 ✔
475

476
template<>
477
void read_dataset(
1,204 ✔
478
  hid_t dset, tensor::Tensor<std::complex<double>>& tensor, bool indep)
479
{
480
  // Get shape of dataset
481
  vector<hsize_t> shape = object_shape(dset);
1,204 ✔
482

483
  // Resize tensor and read data directly
484
  vector<size_t> tshape(shape.begin(), shape.end());
1,204 ✔
485
  tensor.resize(tshape);
1,204 ✔
486

487
  // Read data from dataset
488
  read_complex(dset, nullptr,
1,204 ✔
489
    reinterpret_cast<std::complex<double>*>(tensor.data()), indep);
490
}
1,204 ✔
491

492
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep)
9,388 ✔
493
{
494
  read_dataset_lowlevel(
9,388 ✔
495
    obj_id, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
9,388 ✔
496
}
9,388 ✔
497

498
void read_int(hid_t obj_id, const char* name, int* buffer, bool indep)
×
499
{
500
  read_dataset_lowlevel(obj_id, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
×
501
}
×
502

503
void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep)
×
504
{
505
  read_dataset_lowlevel(obj_id, name, H5T_NATIVE_LLONG, H5S_ALL, indep, buffer);
×
506
}
×
507

508
void read_string(
233 ✔
509
  hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep)
510
{
511
  // Create datatype for a string
512
  hid_t datatype = H5Tcopy(H5T_C_S1);
233 ✔
513
  H5Tset_size(datatype, slen);
233 ✔
514
  // numpy uses null-padding when writing fixed-length strings
515
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
233 ✔
516

517
  // Read data into buffer
518
  read_dataset_lowlevel(obj_id, name, datatype, H5S_ALL, indep, buffer);
233 ✔
519

520
  // Free resources
521
  H5Tclose(datatype);
233 ✔
522
}
233 ✔
523

524
void read_complex(
1,204 ✔
525
  hid_t obj_id, const char* name, std::complex<double>* buffer, bool indep)
526
{
527
  // Create compound datatype for complex numbers
528
  struct complex_t {
1,204 ✔
529
    double re;
530
    double im;
531
  };
532
  complex_t tmp;
1,204 ✔
533
  hid_t complex_id = H5Tcreate(H5T_COMPOUND, sizeof tmp);
1,204 ✔
534
  H5Tinsert(complex_id, "r", HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE);
1,204 ✔
535
  H5Tinsert(complex_id, "i", HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE);
1,204 ✔
536

537
  // Read data
538
  read_dataset_lowlevel(obj_id, name, complex_id, H5S_ALL, indep, buffer);
1,204 ✔
539

540
  // Free resources
541
  H5Tclose(complex_id);
1,204 ✔
542
}
1,204 ✔
543

544
void read_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score,
155 ✔
545
  hsize_t n_results, double* results)
546
{
547
  // Create dataspace for hyperslab in memory
548
  constexpr int ndim = 3;
155 ✔
549
  hsize_t dims[ndim] {n_filter, n_score, n_results};
155 ✔
550
  hsize_t start[ndim] {0, 0, 1};
155 ✔
551
  hsize_t count[ndim] {n_filter, n_score, n_results - 1};
155 ✔
552
  hid_t memspace = H5Screate_simple(ndim, dims, nullptr);
155 ✔
553
  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
155 ✔
554

555
  // Read the dataset
556
  read_dataset_lowlevel(
155 ✔
557
    group_id, "results", H5T_NATIVE_DOUBLE, memspace, false, results);
155 ✔
558

559
  // Free resources
560
  H5Sclose(memspace);
155 ✔
561
}
155 ✔
562

563
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
278,788 ✔
564
  hid_t mem_type_id, const void* buffer)
565
{
566
  // If array is given, create a simple dataspace. Otherwise, create a scalar
567
  // datascape.
568
  hid_t dspace;
278,788 ✔
569
  if (ndim > 0) {
278,788 ✔
570
    dspace = H5Screate_simple(ndim, dims, nullptr);
51,832 ✔
571
  } else {
572
    dspace = H5Screate(H5S_SCALAR);
226,956 ✔
573
  }
574

575
  // Create attribute and Write data
576
  hid_t attr =
278,788 ✔
577
    H5Acreate(obj_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT);
278,788 ✔
578
  H5Awrite(attr, mem_type_id, buffer);
278,788 ✔
579

580
  // Free resources
581
  H5Aclose(attr);
278,788 ✔
582
  H5Sclose(dspace);
278,788 ✔
583
}
278,788 ✔
584

585
void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims,
×
586
  const char* name, const double* buffer)
587
{
588
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer);
×
589
}
×
590

591
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
×
592
  const char* name, const int* buffer)
593
{
594
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_INT, buffer);
×
595
}
×
596

597
void write_attr_string(hid_t obj_id, const char* name, const char* buffer)
42,970 ✔
598
{
599
  size_t n = strlen(buffer);
42,970 ✔
600
  if (n > 0) {
42,970 ✔
601
    // Set up appropriate datatype for a fixed-length string
602
    hid_t datatype = H5Tcopy(H5T_C_S1);
34,752 ✔
603
    H5Tset_size(datatype, n);
34,752 ✔
604

605
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
34,752 ✔
606

607
    // Free resources
608
    H5Tclose(datatype);
34,752 ✔
609
  }
610
}
42,970 ✔
611

612
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
954,445 ✔
613
  const char* name, hid_t mem_type_id, hid_t mem_space_id, bool indep,
614
  const void* buffer)
615
{
616
  // If array is given, create a simple dataspace. Otherwise, create a scalar
617
  // datascape.
618
  hid_t dspace;
954,445 ✔
619
  if (ndim > 0) {
954,445 ✔
620
    dspace = H5Screate_simple(ndim, dims, nullptr);
297,966 ✔
621
  } else {
622
    dspace = H5Screate(H5S_SCALAR);
656,479 ✔
623
  }
624

625
  hid_t dset = H5Dcreate(
954,445 ✔
626
    group_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
627

628
  if (using_mpio_device(group_id)) {
954,445 ✔
629
#ifdef PHDF5
630
    // Set up collective vs independent I/O
631
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
×
632

633
    // Create dataset transfer property list
634
    hid_t plist = H5Pcreate(H5P_DATASET_XFER);
635
    H5Pset_dxpl_mpio(plist, data_xfer_mode);
636

637
    // Write data
638
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
639
    H5Pclose(plist);
640
#endif
641
  } else {
642
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
954,445 ✔
643
  }
644

645
  // Free resources
646
  H5Dclose(dset);
954,445 ✔
647
  H5Sclose(dspace);
954,445 ✔
648
}
954,445 ✔
649

650
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
×
651
  const char* name, const double* buffer, bool indep)
652
{
653
  write_dataset_lowlevel(
×
654
    group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
×
655
}
×
656

657
void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name,
1,649 ✔
658
  const int* buffer, bool indep)
659
{
660
  write_dataset_lowlevel(
1,649 ✔
661
    group_id, ndim, dims, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
1,649 ✔
662
}
1,649 ✔
663

664
void write_llong(hid_t group_id, int ndim, const hsize_t* dims,
×
665
  const char* name, const long long* buffer, bool indep)
666
{
667
  write_dataset_lowlevel(
×
668
    group_id, ndim, dims, name, H5T_NATIVE_LLONG, H5S_ALL, indep, buffer);
×
669
}
×
670

671
void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen,
429,033 ✔
672
  const char* name, const char* buffer, bool indep)
673
{
674
  if (slen > 0) {
429,033 ✔
675
    // Set up appropriate datatype for a fixed-length string
676
    hid_t datatype = H5Tcopy(H5T_C_S1);
388,231 ✔
677
    H5Tset_size(datatype, slen);
388,231 ✔
678

679
    write_dataset_lowlevel(
388,231 ✔
680
      group_id, ndim, dims, name, datatype, H5S_ALL, indep, buffer);
681

682
    // Free resources
683
    H5Tclose(datatype);
388,231 ✔
684
  }
685
}
429,033 ✔
686

687
void write_string(
359,345 ✔
688
  hid_t group_id, const char* name, const std::string& buffer, bool indep)
689
{
690
  write_string(
359,345 ✔
691
    group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep);
692
}
359,345 ✔
693

694
void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score,
23,004 ✔
695
  hsize_t n_results, const double* results)
696
{
697
  // Set dimensions of sum/sum_sq hyperslab to store
698
  constexpr int ndim = 3;
23,004 ✔
699
  hsize_t count[ndim] {n_filter, n_score, n_results - 1};
23,004 ✔
700

701
  // Set dimensions of results array
702
  hsize_t dims[ndim] {n_filter, n_score, n_results};
23,004 ✔
703
  hsize_t start[ndim] {0, 0, 1};
23,004 ✔
704
  hid_t memspace = H5Screate_simple(ndim, dims, nullptr);
23,004 ✔
705
  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
23,004 ✔
706

707
  // Create and write dataset
708
  write_dataset_lowlevel(group_id, ndim, count, "results", H5T_NATIVE_DOUBLE,
23,004 ✔
709
    memspace, false, results);
710

711
  // Free resources
712
  H5Sclose(memspace);
23,004 ✔
713
}
23,004 ✔
714

715
bool using_mpio_device(hid_t obj_id)
14,836,742 ✔
716
{
717
  // Determine file that this object is part of
718
  hid_t file_id = H5Iget_file_id(obj_id);
14,836,742 ✔
719

720
  // Get file access property list
721
  hid_t fapl_id = H5Fget_access_plist(file_id);
14,836,742 ✔
722

723
  // Get low-level driver identifier
724
  hid_t driver = H5Pget_driver(fapl_id);
14,836,742 ✔
725

726
  // Free resources
727
  H5Pclose(fapl_id);
14,836,742 ✔
728
  H5Fclose(file_id);
14,836,742 ✔
729

730
  return driver == H5FD_MPIO;
14,836,742 ✔
731
}
732

733
// Specializations of the H5TypeMap template struct
734
template<>
735
const hid_t H5TypeMap<bool>::type_id = H5T_NATIVE_INT8;
736
template<>
737
const hid_t H5TypeMap<int>::type_id = H5T_NATIVE_INT;
738
template<>
739
const hid_t H5TypeMap<unsigned long>::type_id = H5T_NATIVE_ULONG;
740
template<>
741
const hid_t H5TypeMap<unsigned long long>::type_id = H5T_NATIVE_ULLONG;
742
template<>
743
const hid_t H5TypeMap<unsigned int>::type_id = H5T_NATIVE_UINT;
744
template<>
745
const hid_t H5TypeMap<int64_t>::type_id = H5T_NATIVE_INT64;
746
template<>
747
const hid_t H5TypeMap<double>::type_id = H5T_NATIVE_DOUBLE;
748
template<>
749
const hid_t H5TypeMap<char>::type_id = H5T_NATIVE_CHAR;
750

751
} // namespace openmc
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc