GridFormat 0.2.1
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_GRID_READER_HPP_
9#define GRIDFORMAT_GRID_READER_HPP_
10
11#include <array>
12#include <vector>
13#include <utility>
14#include <functional>
15#include <type_traits>
16#include <string_view>
17#include <sstream>
18#include <string>
19#include <span>
20
22#include <gridformat/common/ranges.hpp>
23#include <gridformat/common/exceptions.hpp>
24#include <gridformat/common/concepts.hpp>
25#include <gridformat/common/logging.hpp>
26#include <gridformat/grid/cell_type.hpp>
27
28namespace GridFormat::Concepts {
29
32
34template<typename T, std::size_t space_dim = 3>
35concept GridFactory = requires(T& t) {
36 typename T::ctype;
37 { t.insert_point(std::declval<const std::array<typename T::ctype, space_dim>&>()) };
38 { t.insert_cell(GridFormat::CellType{}, std::declval<const std::vector<std::size_t>&>()) };
39};
40
42
43} // namespace Concepts
44
45namespace GridFormat {
46
49
52 public:
53 using Vector = std::array<double, 3>;
54 using CellVisitor = std::function<void(CellType, const std::vector<std::size_t>&)>;
55
58 std::array<std::size_t, 3> lower_left;
59 std::array<std::size_t, 3> upper_right;
60 };
61
62 GridReader() = default;
63
64 GridReader(GridReader&&) = default;
65 GridReader(const GridReader&) = delete;
66 GridReader& operator=(GridReader&&) = default;
67 GridReader& operator=(const GridReader&) = delete;
68
69 explicit GridReader(const std::string& filename) { open(filename); }
70 virtual ~GridReader() = default;
71
73 std::string name() const {
74 return _name();
75 }
76
78 void open(const std::string& filename) {
79 _filename = filename;
80 _field_names.clear();
81 _open(filename, _field_names);
82 }
83
85 void close() {
86 _close();
87 _field_names.clear();
88 _filename.clear();
89 }
90
92 const std::string& filename() const {
93 return _filename;
94 }
95
97 std::size_t number_of_cells() const {
98 return _number_of_cells();
99 }
100
102 std::size_t number_of_points() const {
103 return _number_of_points();
104 }
105
108 std::size_t number_of_pieces() const {
109 return _number_of_pieces();
110 }
111
113 std::array<std::size_t, 3> extents() const {
114 const auto loc = location();
115 return {
116 loc.upper_right.at(0) - loc.lower_left.at(0),
117 loc.upper_right.at(1) - loc.lower_left.at(1),
118 loc.upper_right.at(2) - loc.lower_left.at(2)
119 };
120 }
121
124 return _location();
125 }
126
128 std::vector<double> ordinates(unsigned int direction) const {
129 if (direction >= 3)
130 throw ValueError("direction must be < 3");
131 return _ordinates(direction);
132 }
133
135 Vector spacing() const {
136 return _spacing();
137 }
138
140 Vector origin() const {
141 return _origin();
142 }
143
145 Vector basis_vector(unsigned int direction) const {
146 if (direction >= 3)
147 throw ValueError("direction must be < 3");
148 return _basis_vector(direction);
149 }
150
152 bool is_sequence() const {
153 return _is_sequence();
154 }
155
157 std::size_t number_of_steps() const {
158 return _number_of_steps();
159 }
160
162 double time_at_step(std::size_t step_idx) const {
163 return _time_at_step(step_idx);
164 }
165
167 void set_step(std::size_t step_idx) {
168 _set_step(step_idx, _field_names);
169 }
170
172 template<std::size_t space_dim = 3, Concepts::GridFactory<space_dim> Factory>
173 void export_grid(Factory& factory) const {
174 if (number_of_points() > 0) {
175 const auto point_field = points();
176 const auto point_layout = point_field->layout();
177 const auto read_space_dim = point_layout.extent(1);
178 const auto copied_space_dim = std::min(space_dim, read_space_dim);
179 if (point_layout.extent(0) != number_of_points()) {
180 std::ostringstream s; s << point_layout;
181 throw SizeError(
182 "Point layout " + s.str() + " does not match number of points: " + std::to_string(number_of_points())
183 );
184 }
185
186 point_field->visit_field_values([&] <typename T> (std::span<const T> coords) {
187 auto p = Ranges::filled_array<space_dim>(typename Factory::ctype{0.0});
188 for (std::size_t i = 0; i < point_layout.extent(0); ++i) {
189 for (std::size_t dir = 0; dir < copied_space_dim; ++dir)
190 p[dir] = static_cast<typename Factory::ctype>(coords[i*read_space_dim + dir]);
191 factory.insert_point(std::as_const(p));
192 }
193 });
194 }
195 visit_cells([&] (GridFormat::CellType ct, const std::vector<std::size_t>& corners) {
196 factory.insert_cell(std::move(ct), corners);
197 });
198 }
199
201 void visit_cells(const CellVisitor& visitor) const {
202 _visit_cells(visitor);
203 }
204
206 FieldPtr points() const {
207 return _points();
208 }
209
211 FieldPtr cell_field(std::string_view name) const {
212 return _cell_field(name);
213 }
214
216 FieldPtr point_field(std::string_view name) const {
217 return _point_field(name);
218 }
219
221 FieldPtr meta_data_field(std::string_view name) const {
222 return _meta_data_field(name);
223 }
224
226 friend std::ranges::range auto cell_field_names(const GridReader& reader) {
227 return reader._field_names.cell_fields;
228 }
229
231 friend std::ranges::range auto point_field_names(const GridReader& reader) {
232 return reader._field_names.point_fields;
233 }
234
236 friend std::ranges::range auto meta_data_field_names(const GridReader& reader) {
237 return reader._field_names.meta_data_fields;
238 }
239
241 friend std::ranges::range auto cell_fields(const GridReader& reader) {
242 return reader._field_names.cell_fields | std::views::transform([&] (const std::string& n) {
243 return std::make_pair(std::move(n), reader.cell_field(n));
244 });
245 }
246
248 friend std::ranges::range auto point_fields(const GridReader& reader) {
249 return reader._field_names.point_fields | std::views::transform([&] (const std::string& n) {
250 return std::make_pair(std::move(n), reader.point_field(n));
251 });
252 }
253
255 friend std::ranges::range auto meta_data_fields(const GridReader& reader) {
256 return reader._field_names.meta_data_fields | std::views::transform([&] (std::string n) {
257 return std::make_pair(std::move(n), reader.meta_data_field(n));
258 });
259 }
260
261 void set_ignore_warnings(bool value) {
262 _ignore_warnings = value;
263 }
264
265 protected:
266 struct FieldNames {
267 std::vector<std::string> cell_fields;
268 std::vector<std::string> point_fields;
269 std::vector<std::string> meta_data_fields;
270
271 void clear() {
272 cell_fields.clear();
273 point_fields.clear();
274 meta_data_fields.clear();
275 }
276 };
277
278 void _log_warning(std::string_view warning) const {
279 if (!_ignore_warnings)
280 log_warning(
281 std::string{warning}
282 + (warning.ends_with("\n") ? "" : "\n")
283 + "To deactivate this warning, call set_ignore_warnings(true);"
284 );
285 }
286
287 private:
288 std::string _filename = "";
289 FieldNames _field_names;
290 bool _ignore_warnings = false;
291
292 virtual std::string _name() const = 0;
293 virtual void _open(const std::string&, FieldNames&) = 0;
294 virtual void _close() = 0;
295
296 virtual std::size_t _number_of_cells() const = 0;
297 virtual std::size_t _number_of_points() const = 0;
298 virtual std::size_t _number_of_pieces() const = 0;
299
300 virtual FieldPtr _cell_field(std::string_view) const = 0;
301 virtual FieldPtr _point_field(std::string_view) const = 0;
302 virtual FieldPtr _meta_data_field(std::string_view) const = 0;
303
304 virtual void _visit_cells(const CellVisitor&) const {
305 throw NotImplemented("'" + _name() + "' does not implement cell visiting");
306 }
307
308 virtual FieldPtr _points() const {
309 throw NotImplemented("'" + _name() + "' does not implement points()");
310 }
311
312 virtual PieceLocation _location() const {
313 throw NotImplemented("Extents/Location are only available with structured grid formats");
314 }
315
316 virtual std::vector<double> _ordinates(unsigned int) const {
317 throw NotImplemented("Ordinates are only available with rectilinear grid formats.");
318 }
319
320 virtual Vector _spacing() const {
321 throw NotImplemented("Spacing is only available with image grid formats.");
322 }
323
324 virtual Vector _origin() const {
325 throw NotImplemented("Origin is only available with image grid formats.");
326 }
327
328 virtual Vector _basis_vector(unsigned int i) const {
329 std::array<double, 3> result{0., 0., 0.};
330 result[i] = 1.0;
331 return result;
332 }
333
334 virtual bool _is_sequence() const = 0;
335
336 virtual std::size_t _number_of_steps() const {
337 throw NotImplemented("The format read by '" + _name() + "' is not a sequence");
338 }
339
340 virtual double _time_at_step(std::size_t) const {
341 throw NotImplemented("The format read by '" + _name() + "' is not a sequence");
342 }
343
344 virtual void _set_step(std::size_t, FieldNames&) {
345 throw NotImplemented("The format read by '" + _name() + "' is not a sequence");
346 }
347};
348
350
351} // namespace GridFormat
352
353#endif // GRIDFORMAT_GRID_READER_HPP_
Abstract base class for all readers, defines the common interface.
Definition: reader.hpp:51
void visit_cells(const CellVisitor &visitor) const
Visit all cells in the grid read from the file.
Definition: reader.hpp:201
bool is_sequence() const
Return true if the read file is a sequence.
Definition: reader.hpp:152
std::array< std::size_t, 3 > extents() const
Return the extents of the grid (only available for structured grid formats)
Definition: reader.hpp:113
std::size_t number_of_pieces() const
Definition: reader.hpp:108
FieldPtr meta_data_field(std::string_view name) const
Return the meta data field with the given name.
Definition: reader.hpp:221
const std::string & filename() const
Return the name of the opened grid file (empty string until open() is called)
Definition: reader.hpp:92
friend std::ranges::range auto point_field_names(const GridReader &reader)
Return a range over the names of all read point fields.
Definition: reader.hpp:231
std::string name() const
Return the name of this reader.
Definition: reader.hpp:73
Vector origin() const
Return the origin of the grid (only available for image grid formats)
Definition: reader.hpp:140
friend std::ranges::range auto meta_data_field_names(const GridReader &reader)
Return a range over the names of all read metadata fields.
Definition: reader.hpp:236
void open(const std::string &filename)
Open the given grid file.
Definition: reader.hpp:78
void export_grid(Factory &factory) const
Export the grid read from the file into the given grid factory.
Definition: reader.hpp:173
friend std::ranges::range auto point_fields(const GridReader &reader)
Return a range over name-field pairs for all read point fields.
Definition: reader.hpp:248
void set_step(std::size_t step_idx)
Set the step from which to read data (only available for sequence formats)
Definition: reader.hpp:167
FieldPtr point_field(std::string_view name) const
Return the point field with the given name.
Definition: reader.hpp:216
double time_at_step(std::size_t step_idx) const
Return the time at the current step (only available for sequence formats)
Definition: reader.hpp:162
PieceLocation location() const
Return the location of this piece in a structured grid (only available for structured grid formats)
Definition: reader.hpp:123
FieldPtr cell_field(std::string_view name) const
Return the cell field with the given name.
Definition: reader.hpp:211
friend std::ranges::range auto cell_field_names(const GridReader &reader)
Return a range over the names of all read cell fields.
Definition: reader.hpp:226
void close()
Close the grid file.
Definition: reader.hpp:85
FieldPtr points() const
Return the points of the grid as field.
Definition: reader.hpp:206
std::vector< double > ordinates(unsigned int direction) const
Return the ordinates of the grid (only available for rectilinear grid formats)
Definition: reader.hpp:128
std::size_t number_of_cells() const
Return the number of cells in the grid read from the file.
Definition: reader.hpp:97
std::size_t number_of_points() const
Return the number of points in the grid read from the file.
Definition: reader.hpp:102
Vector spacing() const
Return the spacing of the grid (only available for image grid formats)
Definition: reader.hpp:135
friend std::ranges::range auto meta_data_fields(const GridReader &reader)
Return a range over name-field pairs for all read metadata fields.
Definition: reader.hpp:255
Vector basis_vector(unsigned int direction) const
Return the basis vector of the grid in the given direction (only available for image grid formats)
Definition: reader.hpp:145
friend std::ranges::range auto cell_fields(const GridReader &reader)
Return a range over name-field pairs for all read cell fields.
Definition: reader.hpp:241
std::size_t number_of_steps() const
Return the number of available steps (only available for sequence formats)
Definition: reader.hpp:157
Concept for grid factories, to allow for convenient creation of grids from grid files.
Definition: reader.hpp:35
std::shared_ptr< const Field > FieldPtr
Pointer type used by writers/readers for fields.
Definition: field.hpp:186
Definition: reader.hpp:266
Describes the location of a piece within a distributed structured grid.
Definition: reader.hpp:57