/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/data/hdf5_output.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/discretization/data/hdf5_output.hh Source File
DiFfRG
hdf5_output.hh
Go to the documentation of this file.
1#pragma once
2
3// DiFfRG
9
10#include <filesystem>
11#include <list>
12
13namespace DiFfRG
14{
22 {
23 public:
31 HDF5Output(const std::string top_folder, const std::string output_name, const JSONValue &json);
32
34
35 void write_series_record(DiFfRG::hdf5::Group &group, const int series_number)
36 {
37 const std::string value = std::to_string(series_number);
38
39 if (!group.has_dataset("series_numbers")) {
40 // chunked layout so we can append later
43 auto data_set = group.create_chunked_dataset("series_numbers", type, space, {128});
44 data_set.write_at(0, value);
45 } else {
46 auto data_set = group.open_dataset("series_numbers");
47 const std::size_t cur_size = static_cast<std::size_t>(data_set.dataspace().size());
48 data_set.resize({cur_size + 1});
49 data_set.write_at(static_cast<hsize_t>(cur_size), value);
50 }
51 }
52
59 template <typename T> void scalar(const std::string &name, const T value)
60 {
61 if (initial_scalars.size() > 0 &&
62 std::find(initial_scalars.begin(), initial_scalars.end(), name) == initial_scalars.end())
63 throw std::runtime_error("HDF5Output::scalar: The scalar '" + name + "' has not been registered before!");
64
65 open_file();
66
67 if (!scalars.has_dataset(name)) {
70 auto data_set = scalars.create_chunked_dataset(name, type, space, {128});
71 data_set.write_at(0, value);
72 written_scalars.push_back(name);
73 } else {
74 auto data_set = scalars.open_dataset(name);
76 if (data_set.datatype() != type)
77 throw std::runtime_error(
78 "HDF5Output::scalar: The type of the value does not match the type of the dataset '" + name +
79 "' in the file '" + output_name + "'.");
80
81 if (std::find(written_scalars.begin(), written_scalars.end(), name) == written_scalars.end()) {
82 written_scalars.push_back(name);
83 } else {
84 throw std::runtime_error("HDF5Output::scalar: The scalar '" + name +
85 "' has already been written to the file '" + output_name + "'.");
86 }
87
88 const std::size_t cur_size = static_cast<std::size_t>(data_set.dataspace().size());
89 data_set.resize({cur_size + 1});
90 data_set.write_at(static_cast<hsize_t>(cur_size), value);
91 }
92 }
93 void scalar(const std::string &name, const char *value) { scalar<std::string>(name, std::string(value)); }
94
95 template <typename COORD>
97 void map(const std::string &name, const COORD &coordinates)
98 {
99 if (coords.has_dataset(name)) {
100 throw std::runtime_error("HDF5Output::map: The coordinates '" + name +
101 "' have already been written to the file '" + output_name + "'.");
102 }
103
104 open_file();
105
106 const auto grid_data = make_grid(coordinates);
107
109 for (const auto &dim : coordinates.sizes())
110 dims.push_back(dim);
111 auto space = DiFfRG::hdf5::Dataspace::simple(dims);
112 using coord_type = std::decay_t<decltype(grid_data[0])>;
113 auto c_type = DiFfRG::hdf5::type_of<coord_type>();
114 auto dataset = coords.create_dataset(name, c_type, space);
115
116 dataset.write(grid_data);
117
118 coord_identifiers[name] = coordinates.to_string();
119 }
120
121 template <typename COORD, typename T>
122 requires is_coordinates<COORD>
123 void map(const std::string &name, const COORD &coordinates, T *data)
124 {
125 open_file();
126
127 const std::string coord_name = coordinates.to_string();
128 if (coord_identifiers.find(coord_name) == coord_identifiers.end()) map(coord_name, coordinates);
129
130 using value_type = std::decay_t<T>;
131
132 DiFfRG::hdf5::Group n_group;
133 if (!maps.has_group(name)) {
134 n_group = maps.create_group(name);
135 } else {
136 n_group = maps.open_group(name);
137 }
138
139 if (n_group.has_group(std::to_string(map_series_numbers[name])))
140 throw std::runtime_error("HDF5Output::map: The map '" + name + "' has already been written to the file '" +
141 output_name + "' for series number " + std::to_string(map_series_numbers[name]) + ".");
142
143 auto group = n_group.create_group(std::to_string(map_series_numbers[name]));
145
147 for (const auto &dim : coordinates.sizes())
148 dims.push_back(dim);
149 auto space = DiFfRG::hdf5::Dataspace::simple(dims);
150 auto d_type = DiFfRG::hdf5::type_of<value_type>();
151 auto dataset = group.create_dataset("data", d_type, space);
152
153 dataset.write(data, coordinates.size());
154
155 group.create_soft_link("coordinates", "/coordinates/" + coord_name);
156
157 written_maps.push_back(name);
158 map_series_numbers[name]++;
159 }
160
161 template <typename INTERP>
163 void map(const std::string &name, const INTERP &_interpolator)
164 {
165 map(name, _interpolator.get_coordinates().to_string(), _interpolator);
166 }
167
168 template <typename INTERP>
170 void map(const std::string &name, const std::string &coord_name, const INTERP &_interpolator)
171 {
172 open_file();
173
174 using value_type = typename std::decay_t<INTERP>::value_type;
175
176 const auto &interpolator = _interpolator.template get_on<CPU_memory>();
177
178 check_coordinates(coord_name, interpolator.get_coordinates());
179
180 DiFfRG::hdf5::Group n_group;
181 if (!maps.has_group(name)) {
182 n_group = maps.create_group(name);
183 } else {
184 n_group = maps.open_group(name);
185 }
186
187 if (n_group.has_group(std::to_string(map_series_numbers[name])))
188 throw std::runtime_error("HDF5Output::map: The map '" + name + "' has already been written to the file '" +
189 output_name + "' for series number " + std::to_string(map_series_numbers[name]) + ".");
190
191 auto group = n_group.create_group(std::to_string(map_series_numbers[name]));
193
195 const auto coordinates = interpolator.get_coordinates();
196 for (const auto &dim : coordinates.sizes())
197 dims.push_back(dim);
198 auto space = DiFfRG::hdf5::Dataspace::simple(dims);
199 auto d_type = DiFfRG::hdf5::type_of<value_type>();
200 auto dataset = group.create_dataset("data", d_type, space);
201
202 std::vector<value_type> data(interpolator.get_coordinates().size());
203 for (size_t i = 0; i < data.size(); ++i) {
204 const auto lcoord = coordinates.forward(coordinates.from_linear_index(i));
205 data[i] = device::apply([&](const auto &...x) { return interpolator(x...); }, lcoord);
206 }
207 dataset.write(data);
208
209 group.create_soft_link("coordinates", "/coordinates/" + coord_name);
210
211 written_maps.push_back(name);
212 map_series_numbers[name]++;
213 }
214
216
217 void flush(const double time);
218
219 void open_file();
221
222 private:
223 [[maybe_unused]] const JSONValue &json;
224 const std::string top_folder;
225 const std::string output_name;
226
227 bool opened;
228
229 std::list<std::string> written_scalars;
230 std::list<std::string> written_maps;
231 std::map<std::string, size_t> map_series_numbers;
232 std::map<std::string, std::string> coord_identifiers;
233
234 std::list<std::string> initial_scalars;
235
236 template <typename COORD> void check_coordinates(const std::string &coord_name, const COORD &coordinates)
237 {
238 if (!coords.has_dataset(coord_name)) {
239 map(coord_name, coordinates);
240 return;
241 }
242
243 if (coordinates.to_string() != coord_identifiers[coord_name])
244 throw std::runtime_error("HDF5Output::map: The coordinates '" + coord_name +
245 "' do not match the interpolator's coordinates.");
246 }
247
252
253 std::filesystem::path path;
254 };
255} // namespace DiFfRG
A class to output data to a CSV file.
Definition hdf5_output.hh:22
void check_coordinates(const std::string &coord_name, const COORD &coordinates)
Definition hdf5_output.hh:236
void map(const std::string &name, const std::string &coord_name, const INTERP &_interpolator)
Definition hdf5_output.hh:170
DiFfRG::hdf5::File & get_file()
std::map< std::string, size_t > map_series_numbers
Definition hdf5_output.hh:231
const JSONValue & json
Definition hdf5_output.hh:223
void map(const std::string &name, const INTERP &_interpolator)
Definition hdf5_output.hh:163
bool opened
Definition hdf5_output.hh:227
void map(const std::string &name, const COORD &coordinates, T *data)
Definition hdf5_output.hh:123
void flush(const double time)
std::list< std::string > written_scalars
Definition hdf5_output.hh:229
void write_series_record(DiFfRG::hdf5::Group &group, const int series_number)
Definition hdf5_output.hh:35
const std::string top_folder
Definition hdf5_output.hh:224
DiFfRG::hdf5::Group scalars
Definition hdf5_output.hh:249
void scalar(const std::string &name, const T value)
Add a value to the output.
Definition hdf5_output.hh:59
DiFfRG::hdf5::Group maps
Definition hdf5_output.hh:250
void map(const std::string &name, const COORD &coordinates)
Definition hdf5_output.hh:97
HDF5Output(const std::string top_folder, const std::string output_name, const JSONValue &json)
Construct a new Csv Output object.
std::list< std::string > initial_scalars
Definition hdf5_output.hh:234
void scalar(const std::string &name, const char *value)
Definition hdf5_output.hh:93
std::list< std::string > written_maps
Definition hdf5_output.hh:230
DiFfRG::hdf5::Group coords
Definition hdf5_output.hh:251
const std::string output_name
Definition hdf5_output.hh:225
std::map< std::string, std::string > coord_identifiers
Definition hdf5_output.hh:232
DiFfRG::hdf5::File h5_file
Definition hdf5_output.hh:248
std::filesystem::path path
Definition hdf5_output.hh:253
A wrapper around the boost json value class.
Definition json.hh:19
void resize(const Dims &dims)
Definition dataset.hh:38
void write(const T &value)
Definition dataset.hh:49
void write_at(hsize_t offset, const T &value)
Definition dataset.hh:61
static Dataspace simple_unlimited(const Dims &dims)
Definition dataspace.hh:65
static Dataspace simple(const Dims &dims)
Definition dataspace.hh:56
Definition file.hh:13
Definition group.hh:16
Dataset open_dataset(const std::string &name)
Definition group.hh:71
bool has_dataset(const std::string &name) const
Definition group.hh:42
Group create_group(const std::string &name)
Definition group.hh:27
Dataset create_chunked_dataset(const std::string &name, const Datatype &type, const Dataspace &space, const Dims &chunk)
Definition group.hh:55
Dataset create_dataset(const std::string &name, const Datatype &type, const Dataspace &space)
Definition group.hh:46
bool has_group(const std::string &name) const
Definition group.hh:41
Group open_group(const std::string &name)
Definition group.hh:34
Definition coordinates.hh:19
A concept for what is an interpolator class.
Definition interpolation.hh:42
std::vector< hsize_t > Dims
Definition dataspace.hh:9
Datatype type_of()
Convenience factory — type_of<T>() returns the HDF5 datatype for T.
Definition datatype.hh:56
Definition complex_math.hh:10
auto make_grid(const Coordinates &coordinates)
Definition coordinates.hh:388