GridFormat 0.4.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
writer.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2// SPDX-License-Identifier: MIT
8#ifndef GRIDFORMAT_WRITER_HPP_
9#define GRIDFORMAT_WRITER_HPP_
10
11#include <string>
12#include <memory>
13#include <utility>
14#include <functional>
15#include <type_traits>
16
17#include <gridformat/common/exceptions.hpp>
20#include <gridformat/grid/type_traits.hpp>
21#include <gridformat/parallel/concepts.hpp>
22
23namespace GridFormat {
24
25template<typename FileFormat>
26struct WriterFactory;
27
28
29#ifndef DOXYGEN
30namespace WriterDetail {
31
32 template<typename FileFormat, typename Grid>
33 static constexpr bool has_sequential_factory
34 = is_complete<WriterFactory<FileFormat>>
35 and Concepts::Grid<Grid>
36 and requires(const FileFormat& f, const Grid& grid) {
37 { WriterFactory<FileFormat>::make(f, grid) } -> std::derived_from<GridWriter<Grid>>;
38 };
39
40 template<typename FileFormat, typename Grid>
41 static constexpr bool has_sequential_time_series_factory
42 = is_complete<WriterFactory<FileFormat>>
43 and Concepts::Grid<Grid>
44 and requires(const FileFormat& f, const Grid& grid) {
45 { WriterFactory<FileFormat>::make(f, grid, std::string{}) } -> std::derived_from<TimeSeriesGridWriter<Grid>>;
46 };
47
48 template<typename FileFormat, typename Grid, typename Comm>
49 static constexpr bool has_parallel_factory
50 = is_complete<WriterFactory<FileFormat>>
51 and Concepts::Grid<Grid>
52 and Concepts::Communicator<Comm>
53 and requires(const FileFormat& f, const Grid& grid, const Comm& comm) {
54 { WriterFactory<FileFormat>::make(f, grid, comm) } -> std::derived_from<GridWriter<Grid>>;
55 };
56
57 template<typename FileFormat, typename Grid, typename Comm>
58 static constexpr bool has_parallel_time_series_factory
59 = is_complete<WriterFactory<FileFormat>>
60 and Concepts::Grid<Grid>
61 and Concepts::Communicator<Comm>
62 and requires(const FileFormat& f, const Grid& grid, const Comm& comm) {
63 { WriterFactory<FileFormat>::make(f, grid, comm, std::string{}) } -> std::derived_from<TimeSeriesGridWriter<Grid>>;
64 };
65
66 template<typename _Grid, typename Grid>
67 concept Compatible = std::same_as<std::remove_cvref_t<_Grid>, Grid> and std::is_lvalue_reference_v<_Grid>;
68
69} // namespace WriterDetail
70#endif // DOXYGEN
71
72
89template<Concepts::Grid G>
90class Writer {
91 public:
92 using Grid = G;
93
99 template<typename FileFormat, WriterDetail::Compatible<Grid> _Grid>
100 requires(WriterDetail::has_sequential_factory<FileFormat, Grid>)
101 Writer(const FileFormat& f, _Grid&& grid)
103 {}
104
111 template<typename FileFormat, WriterDetail::Compatible<Grid> _Grid>
112 requires(WriterDetail::has_sequential_time_series_factory<FileFormat, Grid>)
113 Writer(const FileFormat& f, _Grid&& grid, const std::string& base_filename)
114 : Writer(WriterFactory<FileFormat>::make(f, grid, base_filename))
115 {}
116
123 template<typename FileFormat, WriterDetail::Compatible<Grid> _Grid, Concepts::Communicator Comm>
124 requires(WriterDetail::has_parallel_factory<FileFormat, Grid, Comm>)
125 Writer(const FileFormat& f, _Grid&& grid, const Comm& comm)
127 {}
128
136 template<typename FileFormat, WriterDetail::Compatible<Grid> _Grid, Concepts::Communicator Comm>
137 requires(WriterDetail::has_parallel_time_series_factory<FileFormat, Grid, Comm>)
138 Writer(const FileFormat& f, _Grid&& grid, const Comm& comm, const std::string& base_filename)
139 : Writer(WriterFactory<FileFormat>::make(f, grid, comm, base_filename))
140 {}
141
143 template<std::derived_from<GridWriter<Grid>> W>
144 requires(!std::is_lvalue_reference_v<W>)
145 explicit Writer(W&& writer)
146 : _writer(std::make_unique<W>(std::move(writer)))
147 {}
148
150 template<std::derived_from<TimeSeriesGridWriter<Grid>> W>
151 requires(!std::is_lvalue_reference_v<W>)
152 explicit Writer(W&& writer)
153 : _time_series_writer(std::make_unique<W>(std::move(writer)))
154 {}
155
163 std::string write(const std::string& filename) const {
164 if (!_writer)
165 throw InvalidState(
166 "Writer was constructed as a time series writer. Only write(Scalar) can be used."
167 );
168 return _writer->write(filename);
169 }
170
178 template<Concepts::Scalar T>
179 std::string write(const T& time_value) const {
180 if (!_time_series_writer)
181 throw InvalidState(
182 "Writer was not constructed as a time series writer. Only write(std::string) can be used."
183 );
184 return _time_series_writer->write(time_value);
185 }
186
193 template<typename Field>
194 void set_meta_data(const std::string& name, Field&& field) {
195 _visit_writer([&] (auto& writer) {
196 writer.set_meta_data(name, std::forward<Field>(field));
197 });
198 }
199
209 template<typename Field>
210 void set_point_field(const std::string& name, Field&& field) {
211 _visit_writer([&] (auto& writer) {
212 writer.set_point_field(name, std::forward<Field>(field));
213 });
214 }
215
222 template<typename Field, typename T>
223 void set_point_field(const std::string& name, Field&& field, const Precision<T>& prec) {
224 _visit_writer([&] (auto& writer) {
225 writer.set_point_field(name, std::forward<Field>(field), prec);
226 });
227 }
228
238 template<typename Field>
239 void set_cell_field(const std::string& name, Field&& field) {
240 _visit_writer([&] (auto& writer) {
241 writer.set_cell_field(name, std::forward<Field>(field));
242 });
243 }
244
251 template<typename Field, typename T>
252 void set_cell_field(const std::string& name, Field&& field, const Precision<T>& prec) {
253 _visit_writer([&] (auto& writer) {
254 writer.set_cell_field(name, std::forward<Field>(field), prec);
255 });
256 }
257
262 FieldPtr remove_meta_data(const std::string& name) {
263 return _visit_writer([&] (auto& writer) {
264 return writer.remove_meta_data(name);
265 });
266 }
267
272 FieldPtr remove_point_field(const std::string& name) {
273 return _visit_writer([&] (auto& writer) {
274 return writer.remove_point_field(name);
275 });
276 }
277
282 FieldPtr remove_cell_field(const std::string& name) {
283 return _visit_writer([&] (auto& writer) {
284 return writer.remove_cell_field(name);
285 });
286 }
287
289 void clear() {
290 _visit_writer([&] (auto& writer) {
291 writer.clear();
292 });
293 }
294
296 void set_ignore_warnings(bool value) {
297 _visit_writer([&] (auto& writer) {
298 writer.set_ignore_warnings(value);
299 });
300 }
301
306 template<typename Writer>
307 void copy_fields(Writer& out) const {
308 _visit_writer([&] (const auto& writer) {
309 writer.copy_fields(out);
310 });
311 }
312
317 const std::optional<WriterOptions>& writer_options() const {
318 return _visit_writer([&] (const auto& writer) -> const std::optional<WriterOptions>& {
319 return writer.writer_options();
320 });
321 }
322
326 const Grid& grid() const {
327 return _visit_writer([&] (const auto& writer) -> const Grid& {
328 return writer.grid();
329 });
330 }
331
341 friend decltype(auto) point_fields(const Writer& w) {
342 return w._visit_writer([&] (const auto& writer) {
343 return point_fields(writer);
344 });
345 }
346
356 friend decltype(auto) cell_fields(const Writer& w) {
357 return w._visit_writer([&] (const auto& writer) {
358 return cell_fields(writer);
359 });
360 }
361
371 friend decltype(auto) meta_data_fields(const Writer& w) {
372 return w._visit_writer([&] (const auto& writer) {
373 return meta_data_fields(writer);
374 });
375 }
376
377 private:
378 template<typename Visitor>
379 decltype(auto) _visit_writer(const Visitor& visitor) {
380 if (_writer)
381 return std::invoke(visitor, *_writer);
382 else {
383 if (!_time_series_writer)
384 throw InvalidState("No writer set");
385 return std::invoke(visitor, *_time_series_writer);
386 }
387 }
388
389 template<typename Visitor>
390 decltype(auto) _visit_writer(const Visitor& visitor) const {
391 if (_writer)
392 return std::invoke(visitor, *_writer);
393 else {
394 if (!_time_series_writer)
395 throw InvalidState("No writer set");
396 return std::invoke(visitor, *_time_series_writer);
397 }
398 }
399
400 std::unique_ptr<GridWriter<Grid>> _writer{nullptr};
401 std::unique_ptr<TimeSeriesGridWriter<Grid>> _time_series_writer{nullptr};
402};
403
404template<typename F, typename G>
405 requires(Concepts::Grid<std::remove_cvref_t<G>>)
406Writer(const F&, G&&) -> Writer<std::remove_cvref_t<G>>;
407
408template<typename F, typename G, Concepts::Communicator C>
409 requires(Concepts::Grid<std::remove_cvref_t<G>>)
410Writer(const F&, G&&, const C&) -> Writer<std::remove_cvref_t<G>>;
411
412template<typename F, typename G>
413 requires(Concepts::Grid<std::remove_cvref_t<G>>)
414Writer(const F&, G&&, const std::string&) -> Writer<std::remove_cvref_t<G>>;
415
416template<typename F, typename G, Concepts::Communicator C>
417 requires(Concepts::Grid<std::remove_cvref_t<G>>)
418Writer(const F&, G&&, const C&, const std::string&) -> Writer<std::remove_cvref_t<G>>;
419
420} // namespace GridFormat
421
422#endif // GRIDFORMAT_WRITER_HPP_
Abstract interface for fields of values that is used by writers/readers to store fields.
Definition: field.hpp:37
Interface to the writers for all supported file formats. Depending on the chosen format,...
Definition: writer.hpp:90
void set_point_field(const std::string &name, Field &&field)
Set a point data field to be added to the output.
Definition: writer.hpp:210
friend decltype(auto) meta_data_fields(const Writer &w)
Return a range over all meta data fields that were added to the given writer.
Definition: writer.hpp:371
Writer(const FileFormat &f, _Grid &&grid)
Construct a sequential grid file writer.
Definition: writer.hpp:101
std::string write(const T &time_value) const
Write a time step in a time series.
Definition: writer.hpp:179
const std::optional< WriterOptions > & writer_options() const
Return the basic options used by this writer.
Definition: writer.hpp:317
void set_ignore_warnings(bool value)
Ignore/consider warnings (default: true)
Definition: writer.hpp:296
FieldPtr remove_meta_data(const std::string &name)
Remove a meta data field from the output.
Definition: writer.hpp:262
Writer(const FileFormat &f, _Grid &&grid, const std::string &base_filename)
Construct a sequential time series writer.
Definition: writer.hpp:113
void set_point_field(const std::string &name, Field &&field, const Precision< T > &prec)
Overload with custom precision with which to write the field.
Definition: writer.hpp:223
Writer(const FileFormat &f, _Grid &&grid, const Comm &comm)
Construct a parallel grid file writer.
Definition: writer.hpp:125
void copy_fields(Writer &out) const
Copy all inserted fields into another writer.
Definition: writer.hpp:307
Writer(const FileFormat &f, _Grid &&grid, const Comm &comm, const std::string &base_filename)
Construct a parallel time series file writer.
Definition: writer.hpp:138
FieldPtr remove_cell_field(const std::string &name)
Remove a cell field from the output.
Definition: writer.hpp:282
const Grid & grid() const
Return a reference to the underlying grid.
Definition: writer.hpp:326
void set_cell_field(const std::string &name, Field &&field)
Set a cell data field to be added to the output.
Definition: writer.hpp:239
void clear()
Remove all data inserted to the writer.
Definition: writer.hpp:289
friend decltype(auto) point_fields(const Writer &w)
Return a range over all point fields that were added to the given writer.
Definition: writer.hpp:341
std::string write(const std::string &filename) const
Write the grid and data to a file.
Definition: writer.hpp:163
Writer(W &&writer)
Construct a grid file writer from a writer implementation.
Definition: writer.hpp:145
void set_meta_data(const std::string &name, Field &&field)
Set a meta data field to be added to the output.
Definition: writer.hpp:194
void set_cell_field(const std::string &name, Field &&field, const Precision< T > &prec)
Overload with custom precision with which to write the field.
Definition: writer.hpp:252
friend decltype(auto) cell_fields(const Writer &w)
Return a range over all cell fields that were added to the given writer.
Definition: writer.hpp:356
FieldPtr remove_point_field(const std::string &name)
Remove a point field from the output.
Definition: writer.hpp:272
Grid concepts.
Base classes for grid data writers.
std::shared_ptr< const Field > FieldPtr
Pointer type used by writers/readers for fields.
Definition: field.hpp:186
Factory class to create a writer for the given file format.
Definition: gridformat.hpp:146