GridFormat 0.4.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
vtr_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_VTK_VTR_READER_HPP_
9#define GRIDFORMAT_VTK_VTR_READER_HPP_
10
11#include <string>
12#include <optional>
13#include <algorithm>
14#include <utility>
15#include <array>
16
17#include <gridformat/common/exceptions.hpp>
18#include <gridformat/common/ranges.hpp>
20#include <gridformat/common/lazy_field.hpp>
21
25
26namespace GridFormat {
27
32class VTRReader : public GridReader {
33 private:
34 void _open(const std::string& filename, typename GridReader::FieldNames& fields) override {
35 auto helper = VTK::XMLReaderHelper::make_from(filename, "RectilinearGrid");
36 _extents = Ranges::array_from_string<std::size_t, 6>(helper.get("RectilinearGrid/Piece").get_attribute("Extent"));
37 VTK::XMLDetail::copy_field_names_from(helper.get("RectilinearGrid"), fields);
38 _helper.emplace(std::move(helper));
39 }
40
41 void _close() override {
42 _helper.reset();
43 _extents.reset();
44 }
45
46 std::string _name() const override {
47 return "VTRReader";
48 }
49
50 std::size_t _number_of_cells() const override {
51 return VTK::CommonDetail::number_of_entities(_extents.value());
52 }
53
54 std::size_t _number_of_points() const override {
55 return VTK::CommonDetail::number_of_entities(_point_extents());
56 }
57
58 std::size_t _number_of_pieces() const override {
59 return 1;
60 }
61
62 typename GridReader::PieceLocation _location() const override {
63 const auto& ex = _extents.value();
64 typename GridReader::PieceLocation result;
65 result.lower_left = {ex[0], ex[2], ex[4]};
66 result.upper_right = {ex[1], ex[3], ex[5]};
67 return result;
68 }
69
70 bool _is_sequence() const override {
71 return false;
72 }
73
74 std::vector<double> _ordinates(unsigned int i) const override {
75 std::vector<double> result;
76 unsigned int direction = 0;
77 const XMLElement& coords = _helper.value().get("RectilinearGrid/Piece/Coordinates");
78 for (const XMLElement& da : VTK::XML::data_arrays(coords))
79 if (direction++ == i) {
80 FieldPtr ordinates_field = _helper.value().make_data_array_field(da);
81 return ordinates_field->precision().visit([&] <typename T> (const Precision<T>& prec) {
82 auto bytes = ordinates_field->serialized();
83 auto values = bytes.as_span_of(prec);
84 result.resize(values.size());
85 std::ranges::copy(values, result.begin());
86 return result;
87 });
88 }
89 throw IOError("Could not read ordinates in direction " + std::to_string(i));
90 }
91
92
93 FieldPtr _points() const override {
94 const XMLElement& coordinates = _helper.value().get("RectilinearGrid/Piece/Coordinates");
95
96 std::vector<FieldPtr> ordinates;
97 std::ranges::for_each(VTK::XML::data_arrays(coordinates), [&] (const XMLElement& da) {
98 ordinates.push_back(_helper.value().make_data_array_field(da));
99 });
100
101 if (ordinates.size() != 3)
102 throw SizeError("Expected 3 data arrays in the 'Coordinates' section");
103
104 auto precision = ordinates.front()->precision();
105 if (!std::ranges::all_of(ordinates, [&] (const auto f) { return f->precision() == precision; }))
106 throw ValueError("Coordinates must use the same scalar types");
107
108 auto num_points = _number_of_points();
109 return make_field_ptr(LazyField{
110 int{}, // dummy "source"
111 MDLayout{{num_points, std::size_t{3}}},
112 precision,
113 [ordinates=std::move(ordinates), prec=precision, np=num_points] (const int&) {
114 return prec.visit([&] <typename T> (const Precision<T>& p) {
115 auto x_data = ordinates.at(0)->serialized();
116 auto y_data = ordinates.at(1)->serialized();
117 auto z_data = ordinates.at(2)->serialized();
118 if (x_data.size() == 0) { x_data.resize(sizeof(T)); x_data.as_span_of(p)[0] = T{0}; }
119 if (y_data.size() == 0) { y_data.resize(sizeof(T)); y_data.as_span_of(p)[0] = T{0}; }
120 if (z_data.size() == 0) { z_data.resize(sizeof(T)); z_data.as_span_of(p)[0] = T{0}; }
121
122 Serialization result(np*sizeof(T)*3);
123 auto result_span = result.as_span_of(p);
124 std::size_t i = 0;
125 for (auto z : z_data.as_span_of(p))
126 for (auto y : y_data.as_span_of(p))
127 for (auto x : x_data.as_span_of(p)) {
128 assert(i + 3 <= result_span.size());
129 result_span[i + 0] = x;
130 result_span[i + 1] = y;
131 result_span[i + 2] = z;
132 i += 3;
133 }
134 return result;
135 });
136 }
137 });
138 }
139
140 void _visit_cells(const typename GridReader::CellVisitor& visitor) const override {
141 VTK::CommonDetail::visit_structured_cells(visitor, _extents.value());
142 }
143
144 FieldPtr _cell_field(std::string_view name) const override {
145 return _helper.value().make_data_array_field(name, "RectilinearGrid/Piece/CellData", _number_of_cells());
146 }
147
148 FieldPtr _point_field(std::string_view name) const override {
149 return _helper.value().make_data_array_field(name, "RectilinearGrid/Piece/PointData", _number_of_points());
150 }
151
152 FieldPtr _meta_data_field(std::string_view name) const override {
153 return _helper.value().make_data_array_field(name, "RectilinearGrid/FieldData");
154 }
155
156 std::array<std::size_t, 6> _point_extents() const {
157 auto result = _extents.value();
158 result[1] += 1;
159 result[3] += 1;
160 result[5] += 1;
161 return result;
162 }
163
164 std::optional<VTK::XMLReaderHelper> _helper;
165 std::optional<std::array<std::size_t, 6>> _extents;
166};
167
168} // namespace GridFormat
169
170#endif // GRIDFORMAT_VTK_VTR_READER_HPP_
Abstract base class for all readers, defines the common interface.
Definition: reader.hpp:51
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
std::vector< double > ordinates(unsigned int direction) const
Return the ordinates of the grid (only available for rectilinear grid formats)
Definition: reader.hpp:128
Reader for .vtr file format.
Definition: vtr_reader.hpp:32
Base class for grid data readers.
std::shared_ptr< const Field > FieldPtr
Pointer type used by writers/readers for fields.
Definition: field.hpp:186
FieldPtr make_field_ptr(F &&f)
Factory function for field pointers.
Definition: field.hpp:192
std::ranges::range auto data_arrays(const XMLElement &e)
Return a range over all data array elements in the given xml section.
Definition: xml.hpp:662
Definition: reader.hpp:266
Describes the location of a piece within a distributed structured grid.
Definition: reader.hpp:57
Common functionality for VTK writers.
Helper classes and functions for VTK XML-type file format writers & readers.