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

openmc-dev / openmc / 21686031975

04 Feb 2026 07:50PM UTC coverage: 81.024% (-0.7%) from 81.763%
21686031975

Pull #3755

github

web-flow
Merge 27d6053a4 into b41e22f68
Pull Request #3755: Warn users that tally heating score with photon bin but without electron and positron bins.

16378 of 22828 branches covered (71.75%)

Branch coverage included in aggregate %.

22 of 23 new or added lines in 1 file covered. (95.65%)

862 existing lines in 51 files now uncovered.

54491 of 64639 relevant lines covered (84.3%)

8259986.93 hits per line

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

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

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

7
#include "xtensor/xarray.hpp"
8
#include "xtensor/xtensor.hpp"
9
#include <fmt/core.h>
10

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

18
#include "openmc/array.h"
19

20
namespace openmc {
21

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

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

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

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

62
vector<hsize_t> object_shape(hid_t obj_id)
2,555,317✔
63
{
64
  // Get number of dimensions
65
  auto type = H5Iget_type(obj_id);
2,555,317✔
66
  hid_t dspace;
67
  if (type == H5I_DATASET) {
2,555,317✔
68
    dspace = H5Dget_space(obj_id);
1,207,380✔
69
  } else if (type == H5I_ATTR) {
1,347,937!
70
    dspace = H5Aget_space(obj_id);
1,347,937✔
71
  } else {
72
    throw std::runtime_error {
×
73
      "Expected dataset or attribute in call to object_shape."};
×
74
  }
75
  int n = H5Sget_simple_extent_ndims(dspace);
2,555,317✔
76

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

81
  // Free resources and return
82
  H5Sclose(dspace);
2,555,317✔
83
  return shape;
2,555,317✔
84
}
×
85

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

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

104
hid_t create_group(hid_t parent_id, const std::string& name)
10,113✔
105
{
106
  return create_group(parent_id, name.c_str());
10,113✔
107
}
108

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

115
void close_group(hid_t group_id)
1,618,212✔
116
{
117
  if (H5Gclose(group_id) < 0)
1,618,212!
118
    fatal_error("Failed to close group");
×
119
}
1,618,212✔
120

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

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

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

145
void ensure_exists(hid_t obj_id, const char* name, bool attribute)
2,823,478✔
146
{
147
  if (attribute) {
2,823,478✔
148
    if (!attribute_exists(obj_id, name)) {
316!
149
      fatal_error(fmt::format("Attribute \"{}\" does not exist in object {}",
×
150
        name, object_name(obj_id)));
×
151
    }
152
  } else {
153
    if (!object_exists(obj_id, name)) {
2,823,162!
154
      fatal_error(fmt::format("Object \"{}\" does not exist in object {}", name,
×
155
        object_name(obj_id)));
×
156
    }
157
  }
158
}
2,823,478✔
159

160
hid_t file_open(const char* filename, char mode, bool parallel)
5,436✔
161
{
162
  bool create;
163
  unsigned int flags;
164
  switch (mode) {
5,436!
165
  case 'r':
4,016✔
166
  case 'a':
167
    create = false;
4,016✔
168
    flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR);
4,016✔
169
    break;
4,016✔
170
  case 'w':
1,420✔
171
  case 'x':
172
    create = true;
1,420✔
173
    flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC);
1,420!
174
    break;
1,420✔
175
  default:
×
176
    fatal_error(fmt::format("Invalid file mode: ", mode));
×
177
  }
178

179
  hid_t plist = H5P_DEFAULT;
5,436✔
180
#ifdef PHDF5
181
  if (parallel) {
5,436✔
182
    // Setup file access property list with parallel I/O access
183
    plist = H5Pcreate(H5P_FILE_ACCESS);
755✔
184
    H5Pset_fapl_mpio(plist, openmc::mpi::intracomm, MPI_INFO_NULL);
755✔
185
  }
186
#endif
187

188
  // Open the file collectively
189
  hid_t file_id;
190
  if (create) {
5,436✔
191
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
1,420✔
192
  } else {
193
    file_id = H5Fopen(filename, flags, plist);
4,016✔
194
  }
195
  if (file_id < 0) {
5,436!
196
    fatal_error(fmt::format(
×
197
      "Failed to open HDF5 file with mode '{}': {}", mode, filename));
198
  }
199

200
#ifdef PHDF5
201
  // Close the property list
202
  if (parallel)
5,436✔
203
    H5Pclose(plist);
755✔
204
#endif
205

206
  return file_id;
5,436✔
207
}
208

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

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

219
void file_close(hid_t file_id)
5,434✔
220
{
221
  H5Fclose(file_id);
5,434✔
222
}
5,434✔
223

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

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

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

248
  return ndatasets;
399✔
249
}
250

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

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

268
  return ngroups;
×
269
}
270

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

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

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

292
    // Read name
293
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
521✔
294
      name[count], size, H5P_DEFAULT);
521✔
295
    count += 1;
521✔
296
  }
297
}
399✔
298

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

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

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

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

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

333
  // Iterate over links to get names
334
  H5O_info_t oinfo;
335
  size_t size;
336
  vector<std::string> names;
138,284✔
337
  for (hsize_t i = 0; i < info.nlinks; ++i) {
752,190✔
338
    // Determine type of object (and skip non-group)
339
    H5Oget_info_by_idx(
613,906✔
340
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
341
    if (oinfo.type != type)
613,906!
342
      continue;
×
343

344
    // Get size of name
345
    size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
613,906✔
346
                 nullptr, 0, H5P_DEFAULT);
347

348
    // Read name
349
    char* buffer = new char[size];
613,906✔
350
    H5Lget_name_by_idx(
613,906✔
351
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, buffer, size, H5P_DEFAULT);
352
    names.emplace_back(&buffer[0]);
613,906✔
353
    delete[] buffer;
613,906!
354
  }
355
  return names;
276,568✔
356
}
×
357

358
vector<std::string> group_names(hid_t group_id)
135,313✔
359
{
360
  return member_names(group_id, H5O_TYPE_GROUP);
135,313✔
361
}
362

363
vector<std::string> dataset_names(hid_t group_id)
2,971✔
364
{
365
  return member_names(group_id, H5O_TYPE_DATASET);
2,971✔
366
}
367

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

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

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

390
hid_t open_dataset(hid_t group_id, const char* name)
872,435✔
391
{
392
  ensure_exists(group_id, name);
872,435✔
393
  return H5Dopen(group_id, name, H5P_DEFAULT);
872,435✔
394
}
395

396
hid_t open_group(hid_t group_id, const char* name)
1,605,127✔
397
{
398
  ensure_exists(group_id, name);
1,605,127✔
399
  return H5Gopen(group_id, name, H5P_DEFAULT);
1,605,127✔
400
}
401

402
hid_t open_object(hid_t group_id, const std::string& name)
345,600✔
403
{
404
  ensure_exists(group_id, name.c_str());
345,600✔
405
  return H5Oopen(group_id, name.c_str(), H5P_DEFAULT);
345,600✔
406
}
407

408
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer)
4,897,002✔
409
{
410
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
4,897,002✔
411
  H5Aread(attr, mem_type_id, buffer);
4,897,002✔
412
  H5Aclose(attr);
4,897,002✔
413
}
4,897,002✔
414

415
void read_attr_double(hid_t obj_id, const char* name, double* buffer)
16✔
416
{
417
  read_attr(obj_id, name, H5T_NATIVE_DOUBLE, buffer);
16✔
418
}
16✔
419

420
void read_attr_int(hid_t obj_id, const char* name, int* buffer)
806✔
421
{
422
  read_attr(obj_id, name, H5T_NATIVE_INT, buffer);
806✔
423
}
806✔
424

425
void read_attr_string(hid_t obj_id, const char* name, size_t slen, char* buffer)
1,691,885✔
426
{
427
  // Create datatype for a string
428
  hid_t datatype = H5Tcopy(H5T_C_S1);
1,691,885✔
429
  H5Tset_size(datatype, slen);
1,691,885✔
430
  // numpy uses null-padding when writing fixed-length strings
431
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
1,691,885✔
432

433
  // Read data into buffer
434
  read_attr(obj_id, name, datatype, buffer);
1,691,885✔
435

436
  // Free resources
437
  H5Tclose(datatype);
1,691,885✔
438
}
1,691,885✔
439

440
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
1,213,145✔
441
  hid_t mem_space_id, bool indep, void* buffer)
442
{
443
  hid_t dset = obj_id;
1,213,145✔
444
  if (name)
1,213,145✔
445
    dset = open_dataset(obj_id, name);
7,428✔
446

447
  if (using_mpio_device(dset)) {
1,213,145✔
448
#ifdef PHDF5
449
    // Set up collective vs independent I/O
450
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
138!
451

452
    // Create dataset transfer property list
453
    hid_t plist = H5Pcreate(H5P_DATASET_XFER);
138✔
454
    H5Pset_dxpl_mpio(plist, data_xfer_mode);
138✔
455

456
    // Read data
457
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
138✔
458
    H5Pclose(plist);
138✔
459
#endif
460
  } else {
461
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
1,213,007✔
462
  }
463

464
  if (name)
1,213,145✔
465
    H5Dclose(dset);
7,428✔
466
}
1,213,145✔
467

468
template<>
469
void read_dataset(hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep)
52✔
470
{
471
  // Get shape of dataset
472
  vector<hsize_t> shape = object_shape(dset);
52✔
473

474
  // Allocate new array to read data into
475
  std::size_t size = 1;
52✔
476
  for (const auto x : shape)
156✔
477
    size *= x;
104✔
478
  vector<std::complex<double>> buffer(size);
52✔
479

480
  // Read data from attribute
481
  read_complex(dset, nullptr, buffer.data(), indep);
52✔
482

483
  // Adapt into xarray
484
  arr = xt::adapt(buffer, shape);
52✔
485
}
52✔
486

487
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep)
938✔
488
{
489
  read_dataset_lowlevel(
938✔
490
    obj_id, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
938✔
491
}
938✔
492

493
void read_int(hid_t obj_id, const char* name, int* buffer, bool indep)
×
494
{
495
  read_dataset_lowlevel(obj_id, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
×
496
}
×
497

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

503
void read_string(
18✔
504
  hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep)
505
{
506
  // Create datatype for a string
507
  hid_t datatype = H5Tcopy(H5T_C_S1);
18✔
508
  H5Tset_size(datatype, slen);
18✔
509
  // numpy uses null-padding when writing fixed-length strings
510
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
18✔
511

512
  // Read data into buffer
513
  read_dataset_lowlevel(obj_id, name, datatype, H5S_ALL, indep, buffer);
18✔
514

515
  // Free resources
516
  H5Tclose(datatype);
18✔
517
}
18✔
518

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

532
  // Read data
533
  read_dataset_lowlevel(obj_id, name, complex_id, H5S_ALL, indep, buffer);
52✔
534

535
  // Free resources
536
  H5Tclose(complex_id);
52✔
537
}
52✔
538

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

550
  // Read the dataset
551
  read_dataset_lowlevel(
16✔
552
    group_id, "results", H5T_NATIVE_DOUBLE, memspace, false, results);
16✔
553

554
  // Free resources
555
  H5Sclose(memspace);
16✔
556
}
16✔
557

558
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
21,261✔
559
  hid_t mem_type_id, const void* buffer)
560
{
561
  // If array is given, create a simple dataspace. Otherwise, create a scalar
562
  // datascape.
563
  hid_t dspace;
564
  if (ndim > 0) {
21,261✔
565
    dspace = H5Screate_simple(ndim, dims, nullptr);
3,996✔
566
  } else {
567
    dspace = H5Screate(H5S_SCALAR);
17,265✔
568
  }
569

570
  // Create attribute and Write data
571
  hid_t attr =
572
    H5Acreate(obj_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT);
21,261✔
573
  H5Awrite(attr, mem_type_id, buffer);
21,261✔
574

575
  // Free resources
576
  H5Aclose(attr);
21,261✔
577
  H5Sclose(dspace);
21,261✔
578
}
21,261✔
579

580
void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims,
×
581
  const char* name, const double* buffer)
582
{
583
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer);
×
584
}
×
585

586
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
×
587
  const char* name, const int* buffer)
588
{
589
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_INT, buffer);
×
590
}
×
591

592
void write_attr_string(hid_t obj_id, const char* name, const char* buffer)
3,273✔
593
{
594
  size_t n = strlen(buffer);
3,273✔
595
  if (n > 0) {
3,273✔
596
    // Set up appropriate datatype for a fixed-length string
597
    hid_t datatype = H5Tcopy(H5T_C_S1);
2,667✔
598
    H5Tset_size(datatype, n);
2,667✔
599

600
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
2,667✔
601

602
    // Free resources
603
    H5Tclose(datatype);
2,667✔
604
  }
605
}
3,273✔
606

607
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
68,273✔
608
  const char* name, hid_t mem_type_id, hid_t mem_space_id, bool indep,
609
  const void* buffer)
610
{
611
  // If array is given, create a simple dataspace. Otherwise, create a scalar
612
  // datascape.
613
  hid_t dspace;
614
  if (ndim > 0) {
68,273✔
615
    dspace = H5Screate_simple(ndim, dims, nullptr);
21,316✔
616
  } else {
617
    dspace = H5Screate(H5S_SCALAR);
46,957✔
618
  }
619

620
  hid_t dset = H5Dcreate(
68,273✔
621
    group_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
622

623
  if (using_mpio_device(group_id)) {
68,273!
624
#ifdef PHDF5
625
    // Set up collective vs independent I/O
UNCOV
626
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
×
627

628
    // Create dataset transfer property list
UNCOV
629
    hid_t plist = H5Pcreate(H5P_DATASET_XFER);
×
UNCOV
630
    H5Pset_dxpl_mpio(plist, data_xfer_mode);
×
631

632
    // Write data
UNCOV
633
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
×
UNCOV
634
    H5Pclose(plist);
×
635
#endif
636
  } else {
637
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
68,273✔
638
  }
639

640
  // Free resources
641
  H5Dclose(dset);
68,273✔
642
  H5Sclose(dspace);
68,273✔
643
}
68,273✔
644

645
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
×
646
  const char* name, const double* buffer, bool indep)
647
{
648
  write_dataset_lowlevel(
×
649
    group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
×
650
}
×
651

652
void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name,
124✔
653
  const int* buffer, bool indep)
654
{
655
  write_dataset_lowlevel(
124✔
656
    group_id, ndim, dims, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
124✔
657
}
124✔
658

659
void write_llong(hid_t group_id, int ndim, const hsize_t* dims,
×
660
  const char* name, const long long* buffer, bool indep)
661
{
662
  write_dataset_lowlevel(
×
663
    group_id, ndim, dims, name, H5T_NATIVE_LLONG, H5S_ALL, indep, buffer);
×
664
}
×
665

666
void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen,
30,275✔
667
  const char* name, const char* buffer, bool indep)
668
{
669
  if (slen > 0) {
30,275✔
670
    // Set up appropriate datatype for a fixed-length string
671
    hid_t datatype = H5Tcopy(H5T_C_S1);
27,517✔
672
    H5Tset_size(datatype, slen);
27,517✔
673

674
    write_dataset_lowlevel(
27,517✔
675
      group_id, ndim, dims, name, datatype, H5S_ALL, indep, buffer);
676

677
    // Free resources
678
    H5Tclose(datatype);
27,517✔
679
  }
680
}
30,275✔
681

682
void write_string(
24,843✔
683
  hid_t group_id, const char* name, const std::string& buffer, bool indep)
684
{
685
  write_string(
24,843✔
686
    group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep);
687
}
24,843✔
688

689
void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score,
1,850✔
690
  hsize_t n_results, const double* results)
691
{
692
  // Set dimensions of sum/sum_sq hyperslab to store
693
  constexpr int ndim = 3;
1,850✔
694
  hsize_t count[ndim] {n_filter, n_score, n_results - 1};
1,850✔
695

696
  // Set dimensions of results array
697
  hsize_t dims[ndim] {n_filter, n_score, n_results};
1,850✔
698
  hsize_t start[ndim] {0, 0, 1};
1,850✔
699
  hid_t memspace = H5Screate_simple(ndim, dims, nullptr);
1,850✔
700
  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
1,850✔
701

702
  // Create and write dataset
703
  write_dataset_lowlevel(group_id, ndim, count, "results", H5T_NATIVE_DOUBLE,
1,850✔
704
    memspace, false, results);
705

706
  // Free resources
707
  H5Sclose(memspace);
1,850✔
708
}
1,850✔
709

710
bool using_mpio_device(hid_t obj_id)
1,281,418✔
711
{
712
  // Determine file that this object is part of
713
  hid_t file_id = H5Iget_file_id(obj_id);
1,281,418✔
714

715
  // Get file access property list
716
  hid_t fapl_id = H5Fget_access_plist(file_id);
1,281,418✔
717

718
  // Get low-level driver identifier
719
  hid_t driver = H5Pget_driver(fapl_id);
1,281,418✔
720

721
  // Free resources
722
  H5Pclose(fapl_id);
1,281,418✔
723
  H5Fclose(file_id);
1,281,418✔
724

725
  return driver == H5FD_MPIO;
1,281,418✔
726
}
727

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

746
} // 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