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

openmc-dev / openmc / 13546000884

26 Feb 2025 02:19PM UTC coverage: 85.015% (-0.2%) from 85.186%
13546000884

Pull #3328

github

web-flow
Merge 67a173195 into e060534ff
Pull Request #3328: NCrystal becomes runtime rather than buildtime dependency

81 of 108 new or added lines in 6 files covered. (75.0%)

467 existing lines in 21 files now uncovered.

51062 of 60062 relevant lines covered (85.02%)

32488887.43 hits per line

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

0.0
/include/openmc/hdf5_interface.h
1
#ifndef OPENMC_HDF5_INTERFACE_H
2
#define OPENMC_HDF5_INTERFACE_H
3

4
#include <algorithm> // for min
5
#include <complex>
6
#include <cstddef>
7
#include <cstring> // for strlen
8
#include <sstream>
9
#include <string>
10
#include <type_traits>
11

12
#include "hdf5.h"
13
#include "hdf5_hl.h"
14
#include "xtensor/xadapt.hpp"
15
#include "xtensor/xarray.hpp"
16

17
#include "openmc/array.h"
18
#include "openmc/error.h"
19
#include "openmc/position.h"
20
#include "openmc/vector.h"
21

22
namespace openmc {
23

24
//==============================================================================
25
// Low-level internal functions
26
//==============================================================================
27

28
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id, void* buffer);
29

30
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
31
  hid_t mem_type_id, const void* buffer);
32

33
void read_dataset_lowlevel(hid_t obj_id, const char* name, hid_t mem_type_id,
34
  hid_t mem_space_id, bool indep, void* buffer);
35

36
void write_dataset_lowlevel(hid_t group_id, int ndim, const hsize_t* dims,
37
  const char* name, hid_t mem_type_id, hid_t mem_space_id, bool indep,
38
  const void* buffer);
39

40
bool using_mpio_device(hid_t obj_id);
41

42
//==============================================================================
43
// Normal functions that are used to read/write files
44
//==============================================================================
45

46
hid_t create_group(hid_t parent_id, const std::string& name);
47

48
inline hid_t create_group(hid_t parent_id, const std::stringstream& name)
49
{
50
  return create_group(parent_id, name.str());
51
}
52

53
hid_t file_open(const std::string& filename, char mode, bool parallel = false);
54
hid_t open_group(hid_t group_id, const std::string& name);
55
void write_string(
56
  hid_t group_id, const char* name, const std::string& buffer, bool indep);
57

58
vector<hsize_t> attribute_shape(hid_t obj_id, const char* name);
59
vector<std::string> dataset_names(hid_t group_id);
60
void ensure_exists(hid_t obj_id, const char* name, bool attribute = false);
61
vector<std::string> group_names(hid_t group_id);
62
vector<hsize_t> object_shape(hid_t obj_id);
63
std::string object_name(hid_t obj_id);
64
hid_t open_object(hid_t group_id, const std::string& name);
65
void close_object(hid_t obj_id);
66

67
//==============================================================================
68
// Fortran compatibility functions
69
//==============================================================================
70

71
extern "C" {
72
bool attribute_exists(hid_t obj_id, const char* name);
73
size_t attribute_typesize(hid_t obj_id, const char* name);
74
hid_t create_group(hid_t parent_id, const char* name);
75
void close_dataset(hid_t dataset_id);
76
void close_group(hid_t group_id);
77
int dataset_ndims(hid_t dset);
78
size_t dataset_typesize(hid_t obj_id, const char* name);
79
hid_t file_open(const char* filename, char mode, bool parallel);
80
void file_close(hid_t file_id);
81
void get_name(hid_t obj_id, std::string& name);
82
int get_num_datasets(hid_t group_id);
83
int get_num_groups(hid_t group_id);
84
void get_datasets(hid_t group_id, char* name[]);
85
void get_groups(hid_t group_id, char* name[]);
86
void get_shape(hid_t obj_id, hsize_t* dims);
87
void get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims);
88
bool object_exists(hid_t object_id, const char* name);
89
hid_t open_dataset(hid_t group_id, const char* name);
90
hid_t open_group(hid_t group_id, const char* name);
91
void read_attr_double(hid_t obj_id, const char* name, double* buffer);
92
void read_attr_int(hid_t obj_id, const char* name, int* buffer);
93
void read_attr_string(
94
  hid_t obj_id, const char* name, size_t slen, char* buffer);
95
void read_complex(
96
  hid_t obj_id, const char* name, std::complex<double>* buffer, bool indep);
97
void read_double(hid_t obj_id, const char* name, double* buffer, bool indep);
98
void read_int(hid_t obj_id, const char* name, int* buffer, bool indep);
99
void read_llong(hid_t obj_id, const char* name, long long* buffer, bool indep);
100
void read_string(
101
  hid_t obj_id, const char* name, size_t slen, char* buffer, bool indep);
102

103
void read_tally_results(
104
  hid_t group_id, hsize_t n_filter, hsize_t n_score, double* results);
105
void write_attr_double(hid_t obj_id, int ndim, const hsize_t* dims,
106
  const char* name, const double* buffer);
107
void write_attr_int(hid_t obj_id, int ndim, const hsize_t* dims,
108
  const char* name, const int* buffer);
109
void write_attr_string(hid_t obj_id, const char* name, const char* buffer);
110
void write_double(hid_t group_id, int ndim, const hsize_t* dims,
111
  const char* name, const double* buffer, bool indep);
112
void write_int(hid_t group_id, int ndim, const hsize_t* dims, const char* name,
113
  const int* buffer, bool indep);
114
void write_llong(hid_t group_id, int ndim, const hsize_t* dims,
115
  const char* name, const long long* buffer, bool indep);
116
void write_string(hid_t group_id, int ndim, const hsize_t* dims, size_t slen,
117
  const char* name, char const* buffer, bool indep);
118
void write_tally_results(
119
  hid_t group_id, hsize_t n_filter, hsize_t n_score, const double* results);
120
} // extern "C"
121

122
//==============================================================================
123
// Template struct used to map types to HDF5 datatype IDs, which are stored
124
// using the type hid_t. By having a single static data member, the template can
125
// be specialized for each type we know of. The specializations appear in the
126
// .cpp file since they are definitions.
127
//==============================================================================
128

129
template<typename T>
130
struct H5TypeMap {
131
  static const hid_t type_id;
132
};
133

134
//==============================================================================
135
// Templates/overloads for read_attribute
136
//==============================================================================
137

138
// Scalar version
139
template<typename T>
UNCOV
140
void read_attribute(hid_t obj_id, const char* name, T& buffer)
×
141
{
UNCOV
142
  read_attr(obj_id, name, H5TypeMap<T>::type_id, &buffer);
×
143
}
144

145
// array version
146
template<typename T, std::size_t N>
147
inline void read_attribute(hid_t obj_id, const char* name, array<T, N>& buffer)
148
{
149
  read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer.data());
150
}
151

152
// vector version
153
template<typename T>
154
void read_attribute(hid_t obj_id, const char* name, vector<T>& vec)
155
{
156
  // Get shape of attribute array
157
  auto shape = attribute_shape(obj_id, name);
158

159
  // Allocate new array to read data into
160
  std::size_t size = 1;
161
  for (const auto x : shape)
162
    size *= x;
163
  vec.resize(size);
164

165
  // Read data from attribute
166
  read_attr(obj_id, name, H5TypeMap<T>::type_id, vec.data());
167
}
168

169
// Generic array version
170
template<typename T>
171
void read_attribute(hid_t obj_id, const char* name, xt::xarray<T>& arr)
172
{
173
  // Get shape of attribute array
174
  auto shape = attribute_shape(obj_id, name);
175

176
  // Allocate new array to read data into
177
  std::size_t size = 1;
178
  for (const auto x : shape)
179
    size *= x;
180
  vector<T> buffer(size);
181

182
  // Read data from attribute
183
  read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer.data());
184

185
  // Adapt array into xarray
186
  arr = xt::adapt(buffer, shape);
187
}
188

189
// overload for std::string
190
inline void read_attribute(hid_t obj_id, const char* name, std::string& str)
191
{
192
  // Create buffer to read data into
UNCOV
193
  auto n = attribute_typesize(obj_id, name);
×
UNCOV
194
  char* buffer = new char[n];
×
195

196
  // Read attribute and set string
UNCOV
197
  read_attr_string(obj_id, name, n, buffer);
×
UNCOV
198
  str = std::string {buffer, n};
×
UNCOV
199
  delete[] buffer;
×
200
}
201

202
// overload for vector<std::string>
203
inline void read_attribute(
204
  hid_t obj_id, const char* name, vector<std::string>& vec)
205
{
UNCOV
206
  auto dims = attribute_shape(obj_id, name);
×
UNCOV
207
  auto m = dims[0];
×
208

209
  // Allocate a C char array to get strings
UNCOV
210
  auto n = attribute_typesize(obj_id, name);
×
UNCOV
211
  char* buffer = new char[m * n];
×
212

213
  // Read char data in attribute
UNCOV
214
  read_attr_string(obj_id, name, n, buffer);
×
215

UNCOV
216
  for (decltype(m) i = 0; i < m; ++i) {
×
217
    // Determine proper length of string -- strlen doesn't work because
218
    // buffer[i] might not have any null characters
UNCOV
219
    std::size_t k = 0;
×
UNCOV
220
    for (; k < n; ++k)
×
UNCOV
221
      if (buffer[i * n + k] == '\0')
×
UNCOV
222
        break;
×
223

224
    // Create string based on (char*, size_t) constructor
UNCOV
225
    vec.emplace_back(&buffer[i * n], k);
×
226
  }
UNCOV
227
  delete[] buffer;
×
228
}
229

230
//==============================================================================
231
// Templates/overloads for read_dataset and related methods
232
//==============================================================================
233

234
// Template for scalars. We need to be careful that the compiler does not use
235
// this version of read_dataset for vectors, arrays, or other non-scalar types.
236
// enable_if_t allows us to conditionally remove the function from overload
237
// resolution when the type T doesn't meet a certain criterion.
238
template<typename T>
239
inline std::enable_if_t<std::is_scalar<std::decay_t<T>>::value> read_dataset(
240
  hid_t obj_id, const char* name, T& buffer, bool indep = false)
241
{
UNCOV
242
  read_dataset_lowlevel(
×
243
    obj_id, name, H5TypeMap<T>::type_id, H5S_ALL, indep, &buffer);
244
}
245

246
// overload for std::string
247
inline void read_dataset(
248
  hid_t obj_id, const char* name, std::string& str, bool indep = false)
249
{
250
  // Create buffer to read data into
251
  auto n = dataset_typesize(obj_id, name);
252
  std::vector<std::string::value_type> buffer(n, '\0');
253

254
  // Read attribute and set string
255
  read_string(obj_id, name, n, buffer.data(), indep);
256
  str = std::string {buffer.begin(), buffer.end()};
257
}
258

259
// array version
260
template<typename T, std::size_t N>
261
inline void read_dataset(
262
  hid_t dset, const char* name, array<T, N>& buffer, bool indep = false)
263
{
264
  read_dataset_lowlevel(
265
    dset, name, H5TypeMap<T>::type_id, H5S_ALL, indep, buffer.data());
266
}
267

268
// vector version
269
template<typename T>
270
void read_dataset(hid_t dset, vector<T>& vec, bool indep = false)
271
{
272
  // Get shape of dataset
273
  vector<hsize_t> shape = object_shape(dset);
274

275
  // Resize vector to appropriate size
276
  vec.resize(shape[0]);
277

278
  // Read data into vector
279
  read_dataset_lowlevel(
280
    dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, vec.data());
281
}
282

283
template<typename T>
284
void read_dataset(
285
  hid_t obj_id, const char* name, vector<T>& vec, bool indep = false)
286
{
287
  hid_t dset = open_dataset(obj_id, name);
288
  read_dataset(dset, vec, indep);
289
  close_dataset(dset);
290
}
291

292
template<typename T>
293
void read_dataset(hid_t dset, xt::xarray<T>& arr, bool indep = false)
294
{
295
  // Get shape of dataset
296
  vector<hsize_t> shape = object_shape(dset);
297

298
  // Allocate space in the array to read data into
299
  std::size_t size = 1;
300
  for (const auto x : shape)
301
    size *= x;
302
  arr.resize(shape);
303

304
  // Read data from attribute
305
  read_dataset_lowlevel(
306
    dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, arr.data());
307
}
308

309
template<>
310
void read_dataset(
311
  hid_t dset, xt::xarray<std::complex<double>>& arr, bool indep);
312

313
template<typename T>
314
void read_dataset(
315
  hid_t obj_id, const char* name, xt::xarray<T>& arr, bool indep = false)
316
{
317
  // Open dataset and read array
318
  hid_t dset = open_dataset(obj_id, name);
319
  read_dataset(dset, arr, indep);
320
  close_dataset(dset);
321
}
322

323
template<typename T, std::size_t N>
324
void read_dataset(
325
  hid_t obj_id, const char* name, xt::xtensor<T, N>& arr, bool indep = false)
326
{
327
  // Open dataset and read array
328
  hid_t dset = open_dataset(obj_id, name);
329

330
  // Get shape of dataset
331
  vector<hsize_t> hsize_t_shape = object_shape(dset);
332
  close_dataset(dset);
333

334
  // cast from hsize_t to size_t
335
  vector<size_t> shape(hsize_t_shape.size());
336
  for (int i = 0; i < shape.size(); i++) {
337
    shape[i] = static_cast<size_t>(hsize_t_shape[i]);
338
  }
339

340
  // Allocate new xarray to read data into
341
  xt::xarray<T> xarr(shape);
342

343
  // Read data from the dataset
344
  read_dataset(obj_id, name, xarr);
345

346
  // Copy into xtensor
347
  arr = xarr;
348
}
349

350
// overload for Position
351
inline void read_dataset(
352
  hid_t obj_id, const char* name, Position& r, bool indep = false)
353
{
354
  array<double, 3> x;
355
  read_dataset(obj_id, name, x, indep);
356
  r.x = x[0];
357
  r.y = x[1];
358
  r.z = x[2];
359
}
360

361
template<typename T, std::size_t N>
362
inline void read_dataset_as_shape(
363
  hid_t obj_id, const char* name, xt::xtensor<T, N>& arr, bool indep = false)
364
{
365
  hid_t dset = open_dataset(obj_id, name);
366

367
  // Allocate new array to read data into
368
  std::size_t size = 1;
369
  for (const auto x : arr.shape())
370
    size *= x;
371
  vector<T> buffer(size);
372

373
  // Read data from attribute
374
  read_dataset_lowlevel(
375
    dset, nullptr, H5TypeMap<T>::type_id, H5S_ALL, indep, buffer.data());
376

377
  // Adapt into xarray
378
  arr = xt::adapt(buffer, arr.shape());
379

380
  close_dataset(dset);
381
}
382

383
template<typename T, std::size_t N>
384
inline void read_nd_vector(hid_t obj_id, const char* name,
385
  xt::xtensor<T, N>& result, bool must_have = false)
386
{
387
  if (object_exists(obj_id, name)) {
388
    read_dataset_as_shape(obj_id, name, result, true);
389
  } else if (must_have) {
390
    fatal_error(std::string("Must provide " + std::string(name) + "!"));
391
  }
392
}
393

394
//==============================================================================
395
// Templates/overloads for write_attribute
396
//==============================================================================
397

398
template<typename T>
399
inline void write_attribute(hid_t obj_id, const char* name, T buffer)
400
{
401
  write_attr(obj_id, 0, nullptr, name, H5TypeMap<T>::type_id, &buffer);
402
}
403

404
inline void write_attribute(hid_t obj_id, const char* name, const char* buffer)
405
{
406
  write_attr_string(obj_id, name, buffer);
407
}
408

409
inline void write_attribute(
410
  hid_t obj_id, const char* name, const std::string& buffer)
411
{
412
  write_attr_string(obj_id, name, buffer.c_str());
413
}
414

415
template<typename T, std::size_t N>
416
inline void write_attribute(
417
  hid_t obj_id, const char* name, const array<T, N>& buffer)
418
{
419
  hsize_t dims[] {N};
420
  write_attr(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data());
421
}
422

423
template<typename T>
424
inline void write_attribute(
425
  hid_t obj_id, const char* name, const vector<T>& buffer)
426
{
427
  hsize_t dims[] {buffer.size()};
428
  write_attr(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data());
429
}
430

431
inline void write_attribute(hid_t obj_id, const char* name, Position r)
432
{
433
  array<double, 3> buffer {r.x, r.y, r.z};
434
  write_attribute(obj_id, name, buffer);
435
}
436

437
//==============================================================================
438
// Templates/overloads for write_dataset
439
//==============================================================================
440

441
// Template for scalars (ensured by SFINAE)
442
template<typename T>
443
inline std::enable_if_t<std::is_scalar<std::decay_t<T>>::value> write_dataset(
444
  hid_t obj_id, const char* name, T buffer)
445
{
446
  write_dataset_lowlevel(
×
447
    obj_id, 0, nullptr, name, H5TypeMap<T>::type_id, H5S_ALL, false, &buffer);
448
}
449

450
inline void write_dataset(hid_t obj_id, const char* name, const char* buffer)
451
{
452
  write_string(obj_id, name, buffer, false);
453
}
454

455
template<typename T, std::size_t N>
456
inline void write_dataset(
457
  hid_t obj_id, const char* name, const array<T, N>& buffer)
458
{
459
  hsize_t dims[] {N};
460
  write_dataset_lowlevel(obj_id, 1, dims, name, H5TypeMap<T>::type_id, H5S_ALL,
461
    false, buffer.data());
462
}
463

464
inline void write_dataset(
465
  hid_t obj_id, const char* name, const vector<std::string>& buffer)
466
{
467
  auto n {buffer.size()};
468
  hsize_t dims[] {n};
469

470
  // Determine length of longest string, including \0
471
  size_t m = 1;
472
  for (const auto& s : buffer) {
473
    m = std::max(m, s.size() + 1);
474
  }
475

476
  // Copy data into contiguous buffer
477
  char* temp = new char[n * m];
478
  std::fill(temp, temp + n * m, '\0');
479
  for (decltype(n) i = 0; i < n; ++i) {
480
    std::copy(buffer[i].begin(), buffer[i].end(), temp + i * m);
481
  }
482

483
  // Write 2D data
484
  write_string(obj_id, 1, dims, m, name, temp, false);
485

486
  // Free temp array
487
  delete[] temp;
488
}
489

490
template<typename T>
491
inline void write_dataset(
492
  hid_t obj_id, const char* name, const vector<T>& buffer)
493
{
494
  hsize_t dims[] {buffer.size()};
×
495
  write_dataset_lowlevel(obj_id, 1, dims, name, H5TypeMap<T>::type_id, H5S_ALL,
×
496
    false, buffer.data());
×
497
}
498

499
// Template for xarray, xtensor, etc.
500
template<typename D>
501
inline void write_dataset(
502
  hid_t obj_id, const char* name, const xt::xcontainer<D>& arr)
503
{
504
  using T = typename D::value_type;
505
  auto s = arr.shape();
506
  vector<hsize_t> dims {s.cbegin(), s.cend()};
507
  write_dataset_lowlevel(obj_id, dims.size(), dims.data(), name,
508
    H5TypeMap<T>::type_id, H5S_ALL, false, arr.data());
509
}
510

511
inline void write_dataset(hid_t obj_id, const char* name, Position r)
512
{
513
  array<double, 3> buffer {r.x, r.y, r.z};
514
  write_dataset(obj_id, name, buffer);
515
}
516

517
inline void write_dataset(hid_t obj_id, const char* name, std::string buffer)
518
{
519
  write_string(obj_id, name, buffer.c_str(), false);
×
520
}
521

522
} // namespace openmc
523
#endif // OPENMC_HDF5_INTERFACE_H
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