GridFormat 0.6.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
reader.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_READER_HPP_
9#define GRIDFORMAT_READER_HPP_
10
11#include <array>
12#include <vector>
13#include <memory>
14#include <utility>
15#include <concepts>
16#include <functional>
17#include <optional>
18#include <algorithm>
19#include <iterator>
20#include <string>
21
22#include <gridformat/common/type_traits.hpp>
23#include <gridformat/parallel/concepts.hpp>
24#include <gridformat/parallel/communication.hpp>
26
27namespace GridFormat {
28
29namespace FileFormat { struct Any; }
30
31template<typename FileFormat>
32struct ReaderFactory;
33
34// Forward declaration, implementation in main API header.
35template<Concepts::Communicator C = NullCommunicator>
36class AnyReaderFactory {
37 public:
38 AnyReaderFactory() requires(std::same_as<C, NullCommunicator>) = default;
39 explicit AnyReaderFactory(const C& comm) : _comm{comm} {}
40 std::unique_ptr<GridReader> make_for(const std::string& filename) const;
41 private:
42 C _comm;
43};
44
45#ifndef DOXYGEN
46namespace ReaderDetail {
47
48 template<typename FileFormat>
49 concept SequentiallyConstructible
50 = is_complete<ReaderFactory<FileFormat>>
51 and requires(const FileFormat& f) {
52 { ReaderFactory<FileFormat>::make(f) } -> std::derived_from<GridReader>;
53 };
54
55 template<typename FileFormat, typename Communicator>
56 concept ParallelConstructible
57 = is_complete<ReaderFactory<FileFormat>>
58 and Concepts::Communicator<Communicator>
59 and requires(const FileFormat& f, const Communicator& comm) {
60 { ReaderFactory<FileFormat>::make(f, comm) } -> std::derived_from<GridReader>;
61 };
62
63 template<typename FieldNameStorage>
64 void copy_field_names(const GridReader& reader, FieldNameStorage& names) {
65 std::ranges::copy(cell_field_names(reader), std::back_inserter(names.cell_fields));
66 std::ranges::copy(point_field_names(reader), std::back_inserter(names.point_fields));
67 std::ranges::copy(meta_data_field_names(reader), std::back_inserter(names.meta_data_fields));
68 }
69
70 using ReaderFactoryFunctor = std::function<std::unique_ptr<GridReader>(const std::string&)>;
71
72 template<Concepts::Communicator C = NullCommunicator>
73 ReaderFactoryFunctor default_reader_factory(const C& c = {}) {
74 if constexpr (!std::same_as<C, NullCommunicator>)
75 return [fac = AnyReaderFactory<C>{c}] (const std::string& f) { return fac.make_for(f); };
76 else
77 return [fac = AnyReaderFactory<>{}] (const std::string& f) { return fac.make_for(f); };
78 }
79
80} // namespace ReaderDetail
81#endif // DOXYGEN
82
95class Reader : public GridReader {
96 public:
97 using ReaderFactoryFunctor = ReaderDetail::ReaderFactoryFunctor;
98
99 Reader()
100 : Reader(ReaderDetail::default_reader_factory())
101 {}
102
103 explicit Reader(ReaderFactoryFunctor f)
104 : _reader_factory{std::move(f)}
105 {}
106
107 explicit Reader(const FileFormat::Any&, ReaderFactoryFunctor f = ReaderDetail::default_reader_factory())
108 : Reader(f)
109 {}
110
111 template<Concepts::Communicator C>
112 explicit Reader(const FileFormat::Any&, const C& c)
113 : Reader(ReaderDetail::default_reader_factory(c))
114 {}
115
116 template<ReaderDetail::SequentiallyConstructible FileFormat>
117 explicit Reader(const FileFormat& f)
118 : _reader{_make_unique(ReaderFactory<FileFormat>::make(f))}
119 {}
120
121 template<typename FileFormat,
122 Concepts::Communicator Communicator>
123 requires(ReaderDetail::ParallelConstructible<FileFormat, Communicator>)
124 explicit Reader(const FileFormat& f, const Communicator& c)
125 : _reader{_make_unique(ReaderFactory<FileFormat>::make(f, c))}
126 {}
127
129 template<typename... ConstructorArgs>
130 static Reader from(const std::string& filename, ConstructorArgs&&... args) {
131 return Reader{std::forward<ConstructorArgs>(args)...}.with_opened(filename);
132 }
133
135 Reader& with_opened(const std::string& filename) & {
136 this->open(filename);
137 return *this;
138 }
139
141 Reader&& with_opened(const std::string& filename) && {
142 this->open(filename);
143 return std::move(*this);
144 }
145
146 private:
147 template<typename ReaderImpl>
148 auto _make_unique(ReaderImpl&& reader) const {
149 return std::make_unique<std::remove_cvref_t<ReaderImpl>>(std::move(reader));
150 }
151
152 std::string _name() const override {
153 if (_reader_is_set())
154 return _access_reader().name();
155 return "undefined";
156 }
157
158 void _open(const std::string& filename, typename GridReader::FieldNames& names) override {
159 if (_reader_factory)
160 _reader = (*_reader_factory)(filename);
161 _access_reader().close();
162 _access_reader().open(filename);
163 ReaderDetail::copy_field_names(_access_reader(), names);
164 };
165
166 void _close() override {
167 _access_reader().close();
168 }
169
170 std::size_t _number_of_cells() const override {
171 return _access_reader().number_of_cells();
172 }
173
174 std::size_t _number_of_points() const override {
175 return _access_reader().number_of_points();
176 }
177
178 std::size_t _number_of_pieces() const override {
179 return _access_reader().number_of_pieces();
180 }
181
182 FieldPtr _cell_field(std::string_view name) const override {
183 return _access_reader().cell_field(name);
184 }
185
186 FieldPtr _point_field(std::string_view name) const override {
187 return _access_reader().point_field(name);
188 }
189
190 FieldPtr _meta_data_field(std::string_view name) const override {
191 return _access_reader().meta_data_field(name);
192 }
193
194 void _visit_cells(const CellVisitor& v) const override {
195 _access_reader().visit_cells(v);
196 }
197
198 FieldPtr _points() const override {
199 return _access_reader().points();
200 }
201
202 typename GridReader::PieceLocation _location() const override {
203 return _access_reader().location();
204 }
205
206 std::vector<double> _ordinates(unsigned int dir) const override {
207 return _access_reader().ordinates(dir);
208 }
209
210 std::array<double, 3> _spacing() const override {
211 return _access_reader().spacing();
212 }
213
214 std::array<double, 3> _origin() const override {
215 return _access_reader().origin();
216 }
217
218 std::array<double, 3> _basis_vector(unsigned int dir) const override {
219 return _access_reader().basis_vector(dir);
220 }
221
222 bool _is_sequence() const override {
223 return _access_reader().is_sequence();
224 }
225
226 std::size_t _number_of_steps() const override {
227 return _access_reader().number_of_steps();
228 }
229
230 double _time_at_step(std::size_t step) const override {
231 return _access_reader().time_at_step(step);
232 }
233
234 void _set_step(std::size_t step, typename GridReader::FieldNames& field_names) override {
235 _access_reader().set_step(step);
236 field_names.clear();
237 ReaderDetail::copy_field_names(_access_reader(), field_names);
238 }
239
240 const GridReader& _access_reader() const {
241 _check_reader_access();
242 return *_reader;
243 }
244
245 GridReader& _access_reader() {
246 _check_reader_access();
247 return *_reader;
248 }
249
250 void _check_reader_access() const {
251 if (!_reader_is_set())
252 throw InvalidState("No file has been read");
253 }
254
255 bool _reader_is_set() const {
256 return static_cast<bool>(_reader);
257 }
258
259 std::unique_ptr<GridReader> _reader;
260 std::optional<ReaderFactoryFunctor> _reader_factory;
261};
262
263} // namespace GridFormat
264
265#endif // GRIDFORMAT_WRITER_HPP_
const std::string & filename() const
Return the name of the opened grid file (empty string until open() is called).
Definition reader.hpp:92
std::string name() const
Return the name of this reader.
Definition reader.hpp:73
void open(const std::string &filename)
Open the given grid file.
Definition reader.hpp:78
Reader && with_opened(const std::string &filename) &&
Read the data from the given file and return this reader (lvalue references overload).
Definition reader.hpp:141
static Reader from(const std::string &filename, ConstructorArgs &&... args)
Construct a reader instance from the given arguments, while directly opening the given file.
Definition reader.hpp:130
Reader & with_opened(const std::string &filename) &
Read the data from the given file and return this reader.
Definition reader.hpp:135
Base class for grid data readers.
std::shared_ptr< const Field > FieldPtr
Pointer type used by writers/readers for fields.
Definition field.hpp:205
Selector for an unspecified file format. When using this format, GridFormat will automatically select...
Definition gridformat.hpp:221
Factory class to create a reader for the given file format.
Definition gridformat.hpp:166