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

openmc-dev / openmc / 18299973882

07 Oct 2025 02:14AM UTC coverage: 81.92% (-3.3%) from 85.194%
18299973882

push

github

web-flow
Switch to using coveralls github action for reporting (#3594)

16586 of 23090 branches covered (71.83%)

Branch coverage included in aggregate %.

53703 of 62712 relevant lines covered (85.63%)

43428488.21 hits per line

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

72.96
/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)
1,462,392✔
23
{
24
  htri_t out = H5Aexists_by_name(obj_id, ".", name, H5P_DEFAULT);
1,462,392✔
25
  return out > 0;
1,462,392✔
26
}
27

28
size_t attribute_typesize(hid_t obj_id, const char* name)
17,105,056✔
29
{
30
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
17,105,056✔
31
  hid_t filetype = H5Aget_type(attr);
17,105,056✔
32
  size_t n = H5Tget_size(filetype);
17,105,056✔
33
  H5Tclose(filetype);
17,105,056✔
34
  H5Aclose(attr);
17,105,056✔
35
  return n;
17,105,056✔
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)
13,580,215✔
55
{
56
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
13,580,215✔
57
  vector<hsize_t> shape = object_shape(attr);
13,580,215✔
58
  H5Aclose(attr);
13,580,215✔
59
  return shape;
13,580,215✔
60
}
×
61

62
vector<hsize_t> object_shape(hid_t obj_id)
25,750,836✔
63
{
64
  // Get number of dimensions
65
  auto type = H5Iget_type(obj_id);
25,750,836✔
66
  hid_t dspace;
67
  if (type == H5I_DATASET) {
25,750,836✔
68
    dspace = H5Dget_space(obj_id);
12,170,621✔
69
  } else if (type == H5I_ATTR) {
13,580,215!
70
    dspace = H5Aget_space(obj_id);
13,580,215✔
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);
25,750,836✔
76

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

81
  // Free resources and return
82
  H5Sclose(dspace);
25,750,836✔
83
  return shape;
25,750,836✔
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)
208,690✔
96
{
97
  hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
208,690✔
98
  if (out < 0) {
208,690!
99
    fatal_error(fmt::format("Failed to create HDF5 group \"{}\"", name));
×
100
  }
101
  return out;
208,690✔
102
}
103

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

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

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

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

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

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

145
void ensure_exists(hid_t obj_id, const char* name, bool attribute)
28,470,000✔
146
{
147
  if (attribute) {
28,470,000✔
148
    if (!attribute_exists(obj_id, name)) {
2,222!
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)) {
28,467,778!
154
      fatal_error(fmt::format("Object \"{}\" does not exist in object {}", name,
×
155
        object_name(obj_id)));
×
156
    }
157
  }
158
}
28,470,000✔
159

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

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

188
  // Open the file collectively
189
  hid_t file_id;
190
  if (create) {
53,479✔
191
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
15,281✔
192
  } else {
193
    file_id = H5Fopen(filename, flags, plist);
38,198✔
194
  }
195
  if (file_id < 0) {
53,479!
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)
30,573✔
203
    H5Pclose(plist);
3,657✔
204
#endif
205

206
  return file_id;
53,479✔
207
}
208

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

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

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

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

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

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

248
  return ndatasets;
2,771✔
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[])
2,771✔
272
{
273
  // Determine number of links in the group
274
  H5G_info_t info;
275
  H5Gget_info(group_id, &info);
2,771✔
276

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

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

292
    // Read name
293
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
3,747✔
294
      name[count], size, H5P_DEFAULT);
3,747✔
295
    count += 1;
3,747✔
296
  }
297
}
2,771✔
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)
1,386,780✔
328
{
329
  // Determine number of links in the group
330
  H5G_info_t info;
331
  H5Gget_info(group_id, &info);
1,386,780✔
332

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

433
  // Read data into buffer
434
  read_attr(obj_id, name, datatype, buffer);
17,105,056✔
435

436
  // Free resources
437
  H5Tclose(datatype);
17,105,056✔
438
}
17,105,056✔
439

440
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
12,220,840✔
441
  hid_t mem_space_id, bool indep, void* buffer)
442
{
443
  hid_t dset = obj_id;
12,220,840✔
444
  if (name)
12,220,840✔
445
    dset = open_dataset(obj_id, name);
71,597✔
446

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

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

456
    // Read data
457
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
826✔
458
    H5Pclose(plist);
826✔
459
#endif
460
  } else {
461
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
12,220,014✔
462
  }
463

464
  if (name)
12,220,840✔
465
    H5Dclose(dset);
71,597✔
466
}
12,220,840✔
467

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

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

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

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

487
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep)
6,662✔
488
{
489
  read_dataset_lowlevel(
6,662✔
490
    obj_id, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
6,662✔
491
}
6,662✔
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(
188✔
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);
188✔
508
  H5Tset_size(datatype, slen);
188✔
509
  // numpy uses null-padding when writing fixed-length strings
510
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
188✔
511

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

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

519
void read_complex(
416✔
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);
416✔
529
  H5Tinsert(complex_id, "r", HOFFSET(complex_t, re), H5T_NATIVE_DOUBLE);
416✔
530
  H5Tinsert(complex_id, "i", HOFFSET(complex_t, im), H5T_NATIVE_DOUBLE);
416✔
531

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

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

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

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

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

558
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
216,836✔
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) {
216,836✔
565
    dspace = H5Screate_simple(ndim, dims, nullptr);
43,066✔
566
  } else {
567
    dspace = H5Screate(H5S_SCALAR);
173,770✔
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);
216,836✔
573
  H5Awrite(attr, mem_type_id, buffer);
216,836✔
574

575
  // Free resources
576
  H5Aclose(attr);
216,836✔
577
  H5Sclose(dspace);
216,836✔
578
}
216,836✔
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)
36,098✔
593
{
594
  size_t n = strlen(buffer);
36,098✔
595
  if (n > 0) {
36,098✔
596
    // Set up appropriate datatype for a fixed-length string
597
    hid_t datatype = H5Tcopy(H5T_C_S1);
29,105✔
598
    H5Tset_size(datatype, n);
29,105✔
599

600
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
29,105✔
601

602
    // Free resources
603
    H5Tclose(datatype);
29,105✔
604
  }
605
}
36,098✔
606

607
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
812,763✔
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) {
812,763✔
615
    dspace = H5Screate_simple(ndim, dims, nullptr);
256,999✔
616
  } else {
617
    dspace = H5Screate(H5S_SCALAR);
555,764✔
618
  }
619

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

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

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

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

640
  // Free resources
641
  H5Dclose(dset);
812,763✔
642
  H5Sclose(dspace);
812,763✔
643
}
812,763✔
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,
1,431✔
653
  const int* buffer, bool indep)
654
{
655
  write_dataset_lowlevel(
1,431✔
656
    group_id, ndim, dims, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
1,431✔
657
}
1,431✔
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,
363,764✔
667
  const char* name, const char* buffer, bool indep)
668
{
669
  if (slen > 0) {
363,764✔
670
    // Set up appropriate datatype for a fixed-length string
671
    hid_t datatype = H5Tcopy(H5T_C_S1);
325,826✔
672
    H5Tset_size(datatype, slen);
325,826✔
673

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

677
    // Free resources
678
    H5Tclose(datatype);
325,826✔
679
  }
680
}
363,764✔
681

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

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

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

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

706
  // Free resources
707
  H5Sclose(memspace);
20,520✔
708
}
20,520✔
709

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

715
  // Get file access property list
716
  hid_t fapl_id = H5Fget_access_plist(file_id);
13,033,603✔
717

718
  // Get low-level driver identifier
719
  hid_t driver = H5Pget_driver(fapl_id);
13,033,603✔
720

721
  // Free resources
722
  H5Pclose(fapl_id);
13,033,603✔
723
  H5Fclose(file_id);
13,033,603✔
724

725
  return driver == H5FD_MPIO;
13,033,603✔
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

© 2025 Coveralls, Inc