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

openmc-dev / openmc / 18043149402

26 Sep 2025 04:11PM UTC coverage: 85.115% (-0.08%) from 85.197%
18043149402

Pull #3576

github

web-flow
Merge 19d7046af into 767db7e6a
Pull Request #3576: Random Ray Base Source Region Refactor

175 of 182 new or added lines in 6 files covered. (96.15%)

169 existing lines in 13 files now uncovered.

53070 of 62351 relevant lines covered (85.11%)

38634253.34 hits per line

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

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

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

62
vector<hsize_t> object_shape(hid_t obj_id)
23,811,321✔
63
{
64
  // Get number of dimensions
65
  auto type = H5Iget_type(obj_id);
23,811,321✔
66
  hid_t dspace;
67
  if (type == H5I_DATASET) {
23,811,321✔
68
    dspace = H5Dget_space(obj_id);
11,247,792✔
69
  } else if (type == H5I_ATTR) {
12,563,529✔
70
    dspace = H5Aget_space(obj_id);
12,563,529✔
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);
23,811,321✔
76

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

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

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

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

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

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

145
void ensure_exists(hid_t obj_id, const char* name, bool attribute)
26,302,838✔
146
{
147
  if (attribute) {
26,302,838✔
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)) {
26,300,616✔
154
      fatal_error(fmt::format("Object \"{}\" does not exist in object {}", name,
×
155
        object_name(obj_id)));
×
156
    }
157
  }
158
}
26,302,838✔
159

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

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

188
  // Open the file collectively
189
  hid_t file_id;
190
  if (create) {
49,916✔
191
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
14,201✔
192
  } else {
193
    file_id = H5Fopen(filename, flags, plist);
35,715✔
194
  }
195
  if (file_id < 0) {
49,916✔
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)
27,148✔
203
    H5Pclose(plist);
3,430✔
204
#endif
205

206
  return file_id;
49,916✔
207
}
208

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

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

219
void file_close(hid_t file_id)
49,907✔
220
{
221
  H5Fclose(file_id);
49,907✔
222
}
49,907✔
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

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

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

UNCOV
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✔
UNCOV
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

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

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

316
    // Get size of name
UNCOV
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
UNCOV
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,282,225✔
328
{
329
  // Determine number of links in the group
330
  H5G_info_t info;
331
  H5Gget_info(group_id, &info);
1,282,225✔
332

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

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

348
    // Read name
349
    char* buffer = new char[size];
5,697,098✔
350
    H5Lget_name_by_idx(
5,697,098✔
351
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, buffer, size, H5P_DEFAULT);
352
    names.emplace_back(&buffer[0]);
5,697,098✔
353
    delete[] buffer;
5,697,098✔
354
  }
355
  return names;
2,564,450✔
UNCOV
356
}
×
357

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

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

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

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

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

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

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

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

408
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer)
45,674,099✔
409
{
410
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
45,674,099✔
411
  H5Aread(attr, mem_type_id, buffer);
45,674,099✔
412
  H5Aclose(attr);
45,674,099✔
413
}
45,674,099✔
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)
15,790,575✔
426
{
427
  // Create datatype for a string
428
  hid_t datatype = H5Tcopy(H5T_C_S1);
15,790,575✔
429
  H5Tset_size(datatype, slen);
15,790,575✔
430
  // numpy uses null-padding when writing fixed-length strings
431
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
15,790,575✔
432

433
  // Read data into buffer
434
  read_attr(obj_id, name, datatype, buffer);
15,790,575✔
435

436
  // Free resources
437
  H5Tclose(datatype);
15,790,575✔
438
}
15,790,575✔
439

440
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
11,295,022✔
441
  hid_t mem_space_id, bool indep, void* buffer)
442
{
443
  hid_t dset = obj_id;
11,295,022✔
444
  if (name)
11,295,022✔
445
    dset = open_dataset(obj_id, name);
66,935✔
446

447
  if (using_mpio_device(dset)) {
11,295,022✔
448
#ifdef PHDF5
449
    // Set up collective vs independent I/O
450
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
711✔
451

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

456
    // Read data
457
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
711✔
458
    H5Pclose(plist);
711✔
459
#endif
460
  } else {
461
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
11,294,311✔
462
  }
463

464
  if (name)
11,295,022✔
465
    H5Dclose(dset);
66,935✔
466
}
11,295,022✔
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

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

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

503
void read_string(
176✔
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);
176✔
508
  H5Tset_size(datatype, slen);
176✔
509
  // numpy uses null-padding when writing fixed-length strings
510
  H5Tset_strpad(datatype, H5T_STR_NULLPAD);
176✔
511

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

515
  // Free resources
516
  H5Tclose(datatype);
176✔
517
}
176✔
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(
161✔
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;
161✔
544
  hsize_t dims[ndim] {n_filter, n_score, 3};
161✔
545
  hsize_t start[ndim] {0, 0, 1};
161✔
546
  hsize_t count[ndim] {n_filter, n_score, 2};
161✔
547
  hid_t memspace = H5Screate_simple(ndim, dims, nullptr);
161✔
548
  H5Sselect_hyperslab(memspace, H5S_SELECT_SET, start, nullptr, count, nullptr);
161✔
549

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

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

558
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
201,883✔
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) {
201,883✔
565
    dspace = H5Screate_simple(ndim, dims, nullptr);
39,838✔
566
  } else {
567
    dspace = H5Screate(H5S_SCALAR);
162,045✔
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);
201,883✔
573
  H5Awrite(attr, mem_type_id, buffer);
201,883✔
574

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

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

UNCOV
586
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
×
587
  const char* name, const int* buffer)
588
{
UNCOV
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)
33,422✔
593
{
594
  size_t n = strlen(buffer);
33,422✔
595
  if (n > 0) {
33,422✔
596
    // Set up appropriate datatype for a fixed-length string
597
    hid_t datatype = H5Tcopy(H5T_C_S1);
27,012✔
598
    H5Tset_size(datatype, n);
27,012✔
599

600
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
27,012✔
601

602
    // Free resources
603
    H5Tclose(datatype);
27,012✔
604
  }
605
}
33,422✔
606

607
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
766,671✔
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) {
766,671✔
615
    dspace = H5Screate_simple(ndim, dims, nullptr);
243,667✔
616
  } else {
617
    dspace = H5Screate(H5S_SCALAR);
523,004✔
618
  }
619

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

623
  if (using_mpio_device(group_id)) {
766,671✔
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);
766,671✔
638
  }
639

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

UNCOV
645
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
×
646
  const char* name, const double* buffer, bool indep)
647
{
UNCOV
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,379✔
653
  const int* buffer, bool indep)
654
{
655
  write_dataset_lowlevel(
1,379✔
656
    group_id, ndim, dims, name, H5T_NATIVE_INT, H5S_ALL, indep, buffer);
1,379✔
657
}
1,379✔
658

UNCOV
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
{
UNCOV
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,
344,088✔
667
  const char* name, const char* buffer, bool indep)
668
{
669
  if (slen > 0) {
344,088✔
670
    // Set up appropriate datatype for a fixed-length string
671
    hid_t datatype = H5Tcopy(H5T_C_S1);
307,860✔
672
    H5Tset_size(datatype, slen);
307,860✔
673

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

677
    // Free resources
678
    H5Tclose(datatype);
307,860✔
679
  }
680
}
344,088✔
681

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

689
void write_tally_results(
19,701✔
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;
19,701✔
694
  hsize_t count[ndim] {n_filter, n_score, 2};
19,701✔
695

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

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

706
  // Free resources
707
  H5Sclose(memspace);
19,701✔
708
}
19,701✔
709

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

715
  // Get file access property list
716
  hid_t fapl_id = H5Fget_access_plist(file_id);
12,061,693✔
717

718
  // Get low-level driver identifier
719
  hid_t driver = H5Pget_driver(fapl_id);
12,061,693✔
720

721
  // Free resources
722
  H5Pclose(fapl_id);
12,061,693✔
723
  H5Fclose(file_id);
12,061,693✔
724

725
  return driver == H5FD_MPIO;
12,061,693✔
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