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

openmc-dev / openmc / 23084721708

14 Mar 2026 08:56AM UTC coverage: 81.599% (-0.5%) from 82.058%
23084721708

Pull #2693

github

web-flow
Merge 0ed23ee59 into bc9c31e0f
Pull Request #2693: Add reactivity control to coupled transport-depletion analyses

17575 of 25275 branches covered (69.54%)

Branch coverage included in aggregate %.

74 of 85 new or added lines in 4 files covered. (87.06%)

3755 existing lines in 99 files now uncovered.

58074 of 67433 relevant lines covered (86.12%)

47252067.37 hits per line

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

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

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

UNCOV
37
void get_shape(hid_t obj_id, hsize_t* dims)
×
38
{
UNCOV
39
  auto type = H5Iget_type(obj_id);
×
40
  hid_t dspace;
×
UNCOV
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 {
UNCOV
46
    throw std::runtime_error {
×
47
      "Expected dataset or attribute in call to get_shape."};
×
48
  }
UNCOV
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)
13,700,561✔
54
{
55
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
13,700,561✔
56
  vector<hsize_t> shape = object_shape(attr);
13,700,561✔
57
  H5Aclose(attr);
13,700,561✔
58
  return shape;
13,700,561✔
UNCOV
59
}
×
60

61
vector<hsize_t> object_shape(hid_t obj_id)
25,928,807✔
62
{
63
  // Get number of dimensions
64
  auto type = H5Iget_type(obj_id);
25,928,807✔
65
  hid_t dspace;
25,928,807✔
66
  if (type == H5I_DATASET) {
25,928,807✔
67
    dspace = H5Dget_space(obj_id);
12,228,246✔
68
  } else if (type == H5I_ATTR) {
13,700,561!
69
    dspace = H5Aget_space(obj_id);
13,700,561✔
70
  } else {
UNCOV
71
    throw std::runtime_error {
×
72
      "Expected dataset or attribute in call to object_shape."};
×
73
  }
74
  int n = H5Sget_simple_extent_ndims(dspace);
25,928,807✔
75

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

80
  // Free resources and return
81
  H5Sclose(dspace);
25,928,807✔
82
  return shape;
25,928,807✔
UNCOV
83
}
×
84

UNCOV
85
void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims)
×
86
{
UNCOV
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)
219,425✔
95
{
96
  hid_t out = H5Gcreate(parent_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
219,425✔
97
  if (out < 0) {
219,425!
UNCOV
98
    fatal_error(fmt::format("Failed to create HDF5 group \"{}\"", name));
×
99
  }
100
  return out;
219,425✔
101
}
102

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

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

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

120
void close_object(hid_t obj_id)
3,516,389✔
121
{
122
  if (H5Oclose(obj_id) < 0)
3,516,389!
UNCOV
123
    fatal_error("Failed to close object");
×
124
}
3,516,389✔
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)
170✔
135
{
136
  hid_t dset = open_dataset(obj_id, name);
170✔
137
  hid_t filetype = H5Dget_type(dset);
170✔
138
  size_t n = H5Tget_size(filetype);
170✔
139
  H5Tclose(filetype);
170✔
140
  close_dataset(dset);
170✔
141
  return n;
170✔
142
}
143

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

159
hid_t file_open(const char* filename, char mode, bool parallel)
57,060✔
160
{
161
  bool create;
57,060✔
162
  unsigned int flags;
57,060✔
163
  switch (mode) {
57,060!
164
  case 'r':
40,439✔
165
  case 'a':
40,439✔
166
    create = false;
40,439✔
167
    flags = (mode == 'r' ? H5F_ACC_RDONLY : H5F_ACC_RDWR);
40,439✔
168
    break;
22,815✔
169
  case 'w':
16,621✔
170
  case 'x':
16,621✔
171
    create = true;
16,621✔
172
    flags = (mode == 'x' ? H5F_ACC_EXCL : H5F_ACC_TRUNC);
16,621!
173
    break;
10,448✔
UNCOV
174
  default:
×
175
    fatal_error(fmt::format("Invalid file mode: ", mode));
×
176
  }
177

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

187
  // Open the file collectively
188
  hid_t file_id;
57,060✔
189
  if (create) {
57,060✔
190
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
16,621✔
191
  } else {
192
    file_id = H5Fopen(filename, flags, plist);
40,439✔
193
  }
194
  if (file_id < 0) {
57,060!
UNCOV
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)
23,797✔
202
    H5Pclose(plist);
3,240✔
203
#endif
204

205
  return file_id;
57,060✔
206
}
207

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

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

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

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

230
int get_num_datasets(hid_t group_id)
3,216✔
231
{
232
  // Determine number of links in the group
233
  H5G_info_t info;
3,216✔
234
  H5Gget_info(group_id, &info);
3,216✔
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) {
7,512✔
240
    // Determine type of object (and skip non-group)
241
    H5Oget_info_by_idx(
4,296✔
242
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
243
    if (oinfo.type == H5O_TYPE_DATASET)
4,296!
244
      ndatasets += 1;
4,296✔
245
  }
246

247
  return ndatasets;
3,216✔
248
}
249

UNCOV
250
int get_num_groups(hid_t group_id)
×
251
{
252
  // Determine number of links in the group
UNCOV
253
  H5G_info_t info;
×
UNCOV
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)
UNCOV
261
    H5Oget_info_by_idx(
×
262
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
UNCOV
263
    if (oinfo.type == H5O_TYPE_GROUP)
×
264
      ngroups += 1;
×
265
  }
266

UNCOV
267
  return ngroups;
×
268
}
269

270
void get_datasets(hid_t group_id, char* name[])
3,216✔
271
{
272
  // Determine number of links in the group
273
  H5G_info_t info;
3,216✔
274
  H5Gget_info(group_id, &info);
3,216✔
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) {
7,512✔
281
    // Determine type of object (and skip non-group)
282
    H5Oget_info_by_idx(
4,296✔
283
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
284
    if (oinfo.type != H5O_TYPE_DATASET)
4,296!
UNCOV
285
      continue;
×
286

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

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

UNCOV
298
void get_groups(hid_t group_id, char* name[])
×
299
{
300
  // Determine number of links in the group
UNCOV
301
  H5G_info_t info;
×
UNCOV
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;
UNCOV
308
  for (hsize_t i = 0; i < info.nlinks; ++i) {
×
309
    // Determine type of object (and skip non-group)
UNCOV
310
    H5Oget_info_by_idx(
×
311
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
UNCOV
312
    if (oinfo.type != H5O_TYPE_GROUP)
×
313
      continue;
×
314

315
    // Get size of name
UNCOV
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
UNCOV
320
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
×
321
      name[count], size, H5P_DEFAULT);
×
322
    count += 1;
×
323
  }
UNCOV
324
}
×
325

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

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

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

347
    // Read name
348
    char* buffer = new char[size];
6,244,172✔
349
    H5Lget_name_by_idx(
6,244,172✔
350
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, buffer, size, H5P_DEFAULT);
351
    names.emplace_back(&buffer[0]);
6,244,172✔
352
    delete[] buffer;
6,244,172✔
353
  }
354
  return names;
1,403,646✔
UNCOV
355
}
×
356

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

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

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

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

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

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

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

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

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

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

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

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

432
  // Read data into buffer
433
  read_attr(obj_id, name, datatype, buffer);
17,220,954✔
434

435
  // Free resources
436
  H5Tclose(datatype);
17,220,954✔
437
}
17,220,954✔
438

439
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
12,322,209✔
440
  hid_t mem_space_id, bool indep, void* buffer)
441
{
442
  hid_t dset = obj_id;
12,322,209✔
443
  if (name)
12,322,209✔
444
    dset = open_dataset(obj_id, name);
76,203✔
445

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

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

455
    // Read data
456
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
552✔
457
    H5Pclose(plist);
552✔
458
#endif
459
  } else {
460
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
12,321,657✔
461
  }
462

463
  if (name)
12,322,209✔
464
    H5Dclose(dset);
76,203✔
465
}
12,322,209✔
466

467
template<>
468
void read_dataset(
1,204✔
469
  hid_t dset, tensor::Tensor<std::complex<double>>& tensor, bool indep)
470
{
471
  // Get shape of dataset
472
  vector<hsize_t> shape = object_shape(dset);
1,204✔
473

474
  // Resize tensor and read data directly
475
  vector<size_t> tshape(shape.begin(), shape.end());
1,204✔
476
  tensor.resize(tshape);
1,204✔
477

478
  // Read data from dataset
479
  read_complex(dset, nullptr,
1,204✔
480
    reinterpret_cast<std::complex<double>*>(tensor.data()), indep);
481
}
1,204✔
482

483
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep)
7,662✔
484
{
485
  read_dataset_lowlevel(
7,662✔
486
    obj_id, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
7,662✔
487
}
7,662✔
488

UNCOV
489
void read_int(hid_t obj_id, const char* name, int* buffer, bool indep)
×
490
{
UNCOV
491
  read_dataset_lowlevel(obj_id, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
×
UNCOV
492
}
×
493

UNCOV
494
void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep)
×
495
{
496
  read_dataset_lowlevel(obj_id, name, H5T_NATIVE_LLONG, H5S_ALL, indep, buffer);
×
UNCOV
497
}
×
498

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

508
  // Read data into buffer
509
  read_dataset_lowlevel(obj_id, name, datatype, H5S_ALL, indep, buffer);
170✔
510

511
  // Free resources
512
  H5Tclose(datatype);
170✔
513
}
170✔
514

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

528
  // Read data
529
  read_dataset_lowlevel(obj_id, name, complex_id, H5S_ALL, indep, buffer);
1,204✔
530

531
  // Free resources
532
  H5Tclose(complex_id);
1,204✔
533
}
1,204✔
534

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

546
  // Read the dataset
547
  read_dataset_lowlevel(
155✔
548
    group_id, "results", H5T_NATIVE_DOUBLE, memspace, false, results);
155✔
549

550
  // Free resources
551
  H5Sclose(memspace);
155✔
552
}
155✔
553

554
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
249,625✔
555
  hid_t mem_type_id, const void* buffer)
556
{
557
  // If array is given, create a simple dataspace. Otherwise, create a scalar
558
  // datascape.
559
  hid_t dspace;
249,625✔
560
  if (ndim > 0) {
249,625✔
561
    dspace = H5Screate_simple(ndim, dims, nullptr);
46,413✔
562
  } else {
563
    dspace = H5Screate(H5S_SCALAR);
203,212✔
564
  }
565

566
  // Create attribute and Write data
567
  hid_t attr =
249,625✔
568
    H5Acreate(obj_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT);
249,625✔
569
  H5Awrite(attr, mem_type_id, buffer);
249,625✔
570

571
  // Free resources
572
  H5Aclose(attr);
249,625✔
573
  H5Sclose(dspace);
249,625✔
574
}
249,625✔
575

UNCOV
576
void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims,
×
577
  const char* name, const double* buffer)
578
{
UNCOV
579
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_DOUBLE, buffer);
×
580
}
×
581

UNCOV
582
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
×
583
  const char* name, const int* buffer)
584
{
UNCOV
585
  write_attr(obj_id, ndim, dims, name, H5T_NATIVE_INT, buffer);
×
586
}
×
587

588
void write_attr_string(hid_t obj_id, const char* name, const char* buffer)
38,715✔
589
{
590
  size_t n = strlen(buffer);
38,715✔
591
  if (n > 0) {
38,715✔
592
    // Set up appropriate datatype for a fixed-length string
593
    hid_t datatype = H5Tcopy(H5T_C_S1);
31,391✔
594
    H5Tset_size(datatype, n);
31,391✔
595

596
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
31,391✔
597

598
    // Free resources
599
    H5Tclose(datatype);
31,391✔
600
  }
601
}
38,715✔
602

603
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
854,262✔
604
  const char* name, hid_t mem_type_id, hid_t mem_space_id, bool indep,
605
  const void* buffer)
606
{
607
  // If array is given, create a simple dataspace. Otherwise, create a scalar
608
  // datascape.
609
  hid_t dspace;
854,262✔
610
  if (ndim > 0) {
854,262✔
611
    dspace = H5Screate_simple(ndim, dims, nullptr);
267,441✔
612
  } else {
613
    dspace = H5Screate(H5S_SCALAR);
586,821✔
614
  }
615

616
  hid_t dset = H5Dcreate(
854,262✔
617
    group_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
618

619
  if (using_mpio_device(group_id)) {
854,262✔
620
#ifdef PHDF5
621
    // Set up collective vs independent I/O
622
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
×
623

624
    // Create dataset transfer property list
625
    hid_t plist = H5Pcreate(H5P_DATASET_XFER);
626
    H5Pset_dxpl_mpio(plist, data_xfer_mode);
627

628
    // Write data
629
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
630
    H5Pclose(plist);
631
#endif
632
  } else {
633
    H5Dwrite(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
854,262✔
634
  }
635

636
  // Free resources
637
  H5Dclose(dset);
854,262✔
638
  H5Sclose(dspace);
854,262✔
639
}
854,262✔
640

UNCOV
641
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
×
642
  const char* name, const double* buffer, bool indep)
643
{
UNCOV
644
  write_dataset_lowlevel(
×
645
    group_id, ndim, dims, name, H5T_NATIVE_DOUBLE, H5S_ALL, indep, buffer);
×
UNCOV
646
}
×
647

648
void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name,
1,454✔
649
  const int* buffer, bool indep)
650
{
651
  write_dataset_lowlevel(
1,454✔
652
    group_id, ndim, dims, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
1,454✔
653
}
1,454✔
654

UNCOV
655
void write_llong(hid_t group_id, int ndim, const hsize_t* dims,
×
656
  const char* name, const long long* buffer, bool indep)
657
{
UNCOV
658
  write_dataset_lowlevel(
×
659
    group_id, ndim, dims, name, H5T_NATIVE_LLONG, H5S_ALL, indep, buffer);
×
UNCOV
660
}
×
661

662
void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen,
381,457✔
663
  const char* name, const char* buffer, bool indep)
664
{
665
  if (slen > 0) {
381,457✔
666
    // Set up appropriate datatype for a fixed-length string
667
    hid_t datatype = H5Tcopy(H5T_C_S1);
343,386✔
668
    H5Tset_size(datatype, slen);
343,386✔
669

670
    write_dataset_lowlevel(
343,386✔
671
      group_id, ndim, dims, name, datatype, H5S_ALL, indep, buffer);
672

673
    // Free resources
674
    H5Tclose(datatype);
343,386✔
675
  }
676
}
381,457✔
677

678
void write_string(
318,507✔
679
  hid_t group_id, const char* name, const std::string& buffer, bool indep)
680
{
681
  write_string(
318,507✔
682
    group_id, 0, nullptr, buffer.length(), name, buffer.c_str(), indep);
683
}
318,507✔
684

685
void write_tally_results(hid_t group_id, hsize_t n_filter, hsize_t n_score,
21,110✔
686
  hsize_t n_results, const double* results)
687
{
688
  // Set dimensions of sum/sum_sq hyperslab to store
689
  constexpr int ndim = 3;
21,110✔
690
  hsize_t count[ndim] {n_filter, n_score, n_results - 1};
21,110✔
691

692
  // Set dimensions of results array
693
  hsize_t dims[ndim] {n_filter, n_score, n_results};
21,110✔
694
  hsize_t start[ndim] {0, 0, 1};
21,110✔
695
  hid_t memspace = H5Screate_simple(ndim, dims, nullptr);
21,110✔
696
  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
21,110✔
697

698
  // Create and write dataset
699
  write_dataset_lowlevel(group_id, ndim, count, "results", H5T_NATIVE_DOUBLE,
21,110✔
700
    memspace, false, results);
701

702
  // Free resources
703
  H5Sclose(memspace);
21,110✔
704
}
21,110✔
705

706
bool using_mpio_device(hid_t obj_id)
13,176,471✔
707
{
708
  // Determine file that this object is part of
709
  hid_t file_id = H5Iget_file_id(obj_id);
13,176,471✔
710

711
  // Get file access property list
712
  hid_t fapl_id = H5Fget_access_plist(file_id);
13,176,471✔
713

714
  // Get low-level driver identifier
715
  hid_t driver = H5Pget_driver(fapl_id);
13,176,471✔
716

717
  // Free resources
718
  H5Pclose(fapl_id);
13,176,471✔
719
  H5Fclose(file_id);
13,176,471✔
720

721
  return driver == H5FD_MPIO;
13,176,471✔
722
}
723

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

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