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

openmc-dev / openmc / 13703779155

06 Mar 2025 04:45PM UTC coverage: 85.674% (+0.5%) from 85.129%
13703779155

Pull #3087

github

web-flow
Merge 20c292e2a into e360cb467
Pull Request #3087: wheel building with scikit build core

47261 of 55164 relevant lines covered (85.67%)

29624867.19 hits per line

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

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

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

62
vector<hsize_t> object_shape(hid_t obj_id)
14,017,256✔
63
{
64
  // Get number of dimensions
65
  auto type = H5Iget_type(obj_id);
14,017,256✔
66
  hid_t dspace;
67
  if (type == H5I_DATASET) {
14,017,256✔
68
    dspace = H5Dget_space(obj_id);
6,617,718✔
69
  } else if (type == H5I_ATTR) {
7,399,538✔
70
    dspace = H5Aget_space(obj_id);
7,399,538✔
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);
14,017,256✔
76

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

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

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

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

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

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

145
void ensure_exists(hid_t obj_id, const char* name, bool attribute)
15,421,882✔
146
{
147
  if (attribute) {
15,421,882✔
148
    if (!attribute_exists(obj_id, name)) {
1,868✔
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)) {
15,420,014✔
154
      fatal_error(fmt::format("Object \"{}\" does not exist in object {}", name,
×
155
        object_name(obj_id)));
×
156
    }
157
  }
158
}
15,421,882✔
159

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

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

188
  // Open the file collectively
189
  hid_t file_id;
190
  if (create) {
31,961✔
191
    file_id = H5Fcreate(filename, flags, H5P_DEFAULT, plist);
9,200✔
192
  } else {
193
    file_id = H5Fopen(filename, flags, plist);
22,761✔
194
  }
195
  if (file_id < 0) {
31,961✔
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)
17,404✔
203
    H5Pclose(plist);
2,693✔
204
#endif
205

206
  return file_id;
31,961✔
207
}
208

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

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

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

224
void get_name(hid_t obj_id, std::string& name)
2,258✔
225
{
226
  size_t size = 1 + H5Iget_name(obj_id, nullptr, 0);
2,258✔
227
  name.resize(size);
2,258✔
228
  // TODO: switch to name.data() when using C++17
229
  H5Iget_name(obj_id, &name[0], size);
2,258✔
230
}
2,258✔
231

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

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

249
  return ndatasets;
2,258✔
250
}
251

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

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

269
  return ngroups;
×
270
}
271

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

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

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

293
    // Read name
294
    H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
3,234✔
295
      name[count], size, H5P_DEFAULT);
3,234✔
296
    count += 1;
3,234✔
297
  }
298
}
2,258✔
299

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

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

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

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

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

334
  // Iterate over links to get names
335
  H5O_info_t oinfo;
336
  size_t size;
337
  vector<std::string> names;
761,995✔
338
  for (hsize_t i = 0; i < info.nlinks; ++i) {
4,111,811✔
339
    // Determine type of object (and skip non-group)
340
    H5Oget_info_by_idx(
3,349,816✔
341
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo, H5P_DEFAULT);
342
    if (oinfo.type != type)
3,349,816✔
343
      continue;
×
344

345
    // Get size of name
346
    size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
3,349,816✔
347
                 nullptr, 0, H5P_DEFAULT);
348

349
    // Read name
350
    char* buffer = new char[size];
3,349,816✔
351
    H5Lget_name_by_idx(
3,349,816✔
352
      group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, buffer, size, H5P_DEFAULT);
353
    names.emplace_back(&buffer[0]);
3,349,816✔
354
    delete[] buffer;
3,349,816✔
355
  }
356
  return names;
1,523,990✔
357
}
×
358

359
vector<std::string> group_names(hid_t group_id)
745,652✔
360
{
361
  return member_names(group_id, H5O_TYPE_GROUP);
745,652✔
362
}
363

364
vector<std::string> dataset_names(hid_t group_id)
16,343✔
365
{
366
  return member_names(group_id, H5O_TYPE_DATASET);
16,343✔
367
}
368

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

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

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

391
hid_t open_dataset(hid_t group_id, const char* name)
4,802,674✔
392
{
393
  ensure_exists(group_id, name);
4,802,674✔
394
  return H5Dopen(group_id, name, H5P_DEFAULT);
4,802,674✔
395
}
396

397
hid_t open_group(hid_t group_id, const char* name)
8,740,511✔
398
{
399
  ensure_exists(group_id, name);
8,740,511✔
400
  return H5Gopen(group_id, name, H5P_DEFAULT);
8,740,511✔
401
}
402

403
hid_t open_object(hid_t group_id, const std::string& name)
1,876,829✔
404
{
405
  ensure_exists(group_id, name.c_str());
1,876,829✔
406
  return H5Oopen(group_id, name.c_str(), H5P_DEFAULT);
1,876,829✔
407
}
408

409
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer)
26,675,195✔
410
{
411
  hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
26,675,195✔
412
  H5Aread(attr, mem_type_id, buffer);
26,675,195✔
413
  H5Aclose(attr);
26,675,195✔
414
}
26,675,195✔
415

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

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

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

434
  // Read data into buffer
435
  read_attr(obj_id, name, datatype, buffer);
9,184,829✔
436

437
  // Free resources
438
  H5Tclose(datatype);
9,184,829✔
439
}
9,184,829✔
440

441
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
6,645,599✔
442
  hid_t mem_space_id, bool indep, void* buffer)
443
{
444
  hid_t dset = obj_id;
6,645,599✔
445
  if (name)
6,645,599✔
446
    dset = open_dataset(obj_id, name);
42,280✔
447

448
  if (using_mpio_device(dset)) {
6,645,599✔
449
#ifdef PHDF5
450
    // Set up collective vs independent I/O
451
    auto data_xfer_mode = indep ? H5FD_MPIO_INDEPENDENT : H5FD_MPIO_COLLECTIVE;
455✔
452

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

457
    // Read data
458
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, plist, buffer);
455✔
459
    H5Pclose(plist);
455✔
460
#endif
461
  } else {
462
    H5Dread(dset, mem_type_id, mem_space_id, H5S_ALL, H5P_DEFAULT, buffer);
6,645,144✔
463
  }
464

465
  if (name)
6,645,599✔
466
    H5Dclose(dset);
42,280✔
467
}
6,645,599✔
468

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

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

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

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

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

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

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

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

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

516
  // Free resources
517
  H5Tclose(datatype);
119✔
518
}
119✔
519

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

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

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

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

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

555
  // Free resources
556
  H5Sclose(memspace);
70✔
557
}
70✔
558

559
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
133,315✔
560
  hid_t mem_type_id, const void* buffer)
561
{
562
  // If array is given, create a simple dataspace. Otherwise, create a scalar
563
  // datascape.
564
  hid_t dspace;
565
  if (ndim > 0) {
133,315✔
566
    dspace = H5Screate_simple(ndim, dims, nullptr);
25,702✔
567
  } else {
568
    dspace = H5Screate(H5S_SCALAR);
107,613✔
569
  }
570

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

576
  // Free resources
577
  H5Aclose(attr);
133,315✔
578
  H5Sclose(dspace);
133,315✔
579
}
133,315✔
580

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

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

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

601
    write_attr(obj_id, 0, nullptr, name, datatype, buffer);
17,677✔
602

603
    // Free resources
604
    H5Tclose(datatype);
17,677✔
605
  }
606
}
21,678✔
607

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

621
  hid_t dset = H5Dcreate(
487,925✔
622
    group_id, name, mem_type_id, dspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
623

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

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

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

641
  // Free resources
642
  H5Dclose(dset);
487,925✔
643
  H5Sclose(dspace);
487,925✔
644
}
487,925✔
645

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

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

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

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

675
    write_dataset_lowlevel(
203,295✔
676
      group_id, ndim, dims, name, datatype, H5S_ALL, indep, buffer);
677

678
    // Free resources
679
    H5Tclose(datatype);
203,295✔
680
  }
681
}
224,429✔
682

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

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

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

703
  // Create and write dataset
704
  write_dataset_lowlevel(group_id, ndim, count, "results", H5T_NATIVE_DOUBLE,
16,433✔
705
    memspace, false, results);
706

707
  // Free resources
708
  H5Sclose(memspace);
16,433✔
709
}
16,433✔
710

711
bool using_mpio_device(hid_t obj_id)
7,133,524✔
712
{
713
  // Determine file that this object is part of
714
  hid_t file_id = H5Iget_file_id(obj_id);
7,133,524✔
715

716
  // Get file access property list
717
  hid_t fapl_id = H5Fget_access_plist(file_id);
7,133,524✔
718

719
  // Get low-level driver identifier
720
  hid_t driver = H5Pget_driver(fapl_id);
7,133,524✔
721

722
  // Free resources
723
  H5Pclose(fapl_id);
7,133,524✔
724
  H5Fclose(file_id);
7,133,524✔
725

726
  return driver == H5FD_MPIO;
7,133,524✔
727
}
728

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

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