TRIQS/h5 1.3.0
C++ interface to HDF5
Loading...
Searching...
No Matches
array.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2024 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Thomas Hahn, Nils Wentzell
16
22#ifndef LIBH5_STL_ARRAY_HPP
23#define LIBH5_STL_ARRAY_HPP
24
26#include "../complex.hpp"
27#include "../macros.hpp"
28
29#include <algorithm>
30#include <array>
31#include <iostream>
32#include <string>
33#include <type_traits>
34
35namespace h5 {
36
51 template <typename T, size_t N>
52 void h5_write(group g, std::string const &name, std::array<T, N> const &a) {
53 if constexpr (std::is_same_v<T, std::string>) {
54 // array of strings
55 auto char_arr = std::array<const char *, N>{};
56 std::transform(cbegin(a), cend(a), begin(char_arr), [](std::string const &s) { return s.c_str(); });
57 h5_write(g, name, char_arr);
58 } else if constexpr (std::is_arithmetic_v<T> or is_complex_v<T> or std::is_same_v<T, dcplx_t> or std::is_same_v<T, char *>
59 or std::is_same_v<T, const char *>) {
60 // array of arithmetic/complex types or char* or const char*
62 v.slab.count[0] = N;
63 v.slab.stride[0] = 1;
64 v.parent_shape[0] = N;
65 h5::array_interface::write(g, name, v, true);
66 } else {
67 // array of generic type
68 auto g2 = g.create_group(name);
69 h5_write(g2, "shape", std::array<long, 1>{N});
70 for (int i = 0; i < N; ++i) h5_write(g2, std::to_string(i), a[i]);
71 }
72 }
73
83 template <typename T, size_t N>
84 void h5_read(group g, std::string name, std::array<T, N> &a) {
85 if constexpr (std::is_same_v<T, std::string>) {
86 // array of strings
87 auto char_arr = std::array<char *, N>{};
88 h5_read(g, name, char_arr);
89 std::copy(cbegin(char_arr), cend(char_arr), begin(a));
90 std::for_each(begin(char_arr), end(char_arr), [](char *cb) { free(cb); }); // NOLINT (we have to free the memory allocated by h5_read)
91 } else if constexpr (std::is_arithmetic_v<T> or is_complex_v<T> or std::is_same_v<T, dcplx_t> or std::is_same_v<T, char *>
92 or std::is_same_v<T, const char *>) {
93 // array of arithmetic/complex types or char* or const char*
94 auto ds_info = array_interface::get_dataset_info(g, name);
95 H5_EXPECTS(ds_info.rank() == 1 + ds_info.has_complex_attribute);
96 H5_EXPECTS(N == ds_info.lengths[0]);
97
98 if constexpr (is_complex_v<T>) {
99 // read complex values stored as a compound HDF5 datatype
100 if (hdf5_type_equal(ds_info.ty, hdf5_type<dcplx_t>())) {
101 h5_read(g, name, reinterpret_cast<std::array<dcplx_t, N> &>(a)); // NOLINT (reinterpret_cast is safe here)
102 return;
103 }
104
105 // read non-complex data into std::array<std::complex>
106 if (!ds_info.has_complex_attribute) {
107 std::cerr << "WARNING: HDF5 type mismatch while reading into a std::array: std::complex<" + get_name_of_h5_type(hdf5_type<T>())
108 + "> != " + get_name_of_h5_type(ds_info.ty) + "\n";
109 std::array<double, N> tmp{};
110 h5_read(g, name, tmp);
111 std::copy(begin(tmp), end(tmp), begin(a));
112 return;
113 }
114 }
115
116 // use array_interface to read
117 array_interface::array_view v{hdf5_type<T>(), (void *)(a.data()), 1, is_complex_v<T>};
118 v.slab.count[0] = N;
119 v.slab.stride[0] = 1;
120 v.parent_shape[0] = N;
121 array_interface::read(g, name, v);
122 } else {
123 // array of generic type
124 auto g2 = g.open_group(name);
125
126 // check that shapes are compatible
127 auto h5_shape = std::array<long, 1>{};
128 h5_read(g2, "shape", h5_shape);
129 H5_EXPECTS(N == h5_shape[0]);
130
131 // read using specialized h5_read implementation
132 for (int i = 0; i < N; ++i) h5_read(g2, std::to_string(i), a[i]);
133 }
134 }
135
138} // namespace h5
139
140#endif // LIBH5_STL_ARRAY_HPP
Provides a generic interface to read/write n-dimensional arrays from/to HDF5.
A handle to an HDF5 group.
Definition group.hpp:44
group create_group(std::string const &key, bool delete_if_exists=true) const
Create a subgroup with the given key in the group.
Definition group.cpp:109
group open_group(std::string const &key) const
Open a subgroup with the given key in the group.
Definition group.cpp:96
Provides a compound type and type traits for complex numbers.
bool hdf5_type_equal(datatype dt1, datatype dt2)
Check if two HDF5 datatypes are equal.
Definition object.cpp:198
constexpr bool is_complex_v
Boolean type trait set to true for std::complex types.
Definition complex.hpp:64
datatype hdf5_type()
Map a given C++ type to an HDF5 datatype.
Definition object.hpp:156
std::string get_name_of_h5_type(datatype dt)
Get the name of an h5::datatype (for error messages).
Definition object.cpp:183
void read(group g, std::string const &name, array_view v, hyperslab sl)
Read a given hyperslab from an HDF5 dataset into an array view.
dataset_info get_dataset_info(dataset ds)
Retrieve the shape and the h5::datatype from a dataset.
void write(group g, std::string const &name, array_view const &v, bool compress)
Write an array view to an HDF5 dataset.
T h5_read(group g, std::string const &key)
Generic implementation for reading from an HDF5 dataset/subgroup.
Definition generic.hpp:51
void h5_write(group g, std::string const &name, T const &x) H5_REQUIRES(std
Write a scalar to an HDF5 dataset.
Definition scalar.hpp:70
Macros used in the h5 library.
Struct representing a view on an n-dimensional array/dataspace.
hyperslab slab
h5::array_interface::hyperslab specifying the selection of the view.
v_t count
Number of elements or blocks to select along each dimension.