GCC Code Coverage Report


Directory: gridformat/
File: gridformat/vtk/vtr_reader.hpp
Date: 2024-11-10 16:24:00
Exec Total Coverage
Lines: 90 94 95.7%
Functions: 20 40 50.0%
Branches: 73 154 47.4%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \file
5 * \ingroup VTK
6 * \copydoc GridFormat::VTRReader
7 */
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>
19 #include <gridformat/common/field.hpp>
20 #include <gridformat/common/lazy_field.hpp>
21
22 #include <gridformat/grid/reader.hpp>
23 #include <gridformat/vtk/common.hpp>
24 #include <gridformat/vtk/xml.hpp>
25
26 namespace GridFormat {
27
28 /*!
29 * \ingroup VTK
30 * \brief Reader for .vtr file format
31 */
32 class VTRReader : public GridReader {
33 private:
34 238 void _open(const std::string& filename, typename GridReader::FieldNames& fields) override {
35
1/2
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
238 auto helper = VTK::XMLReaderHelper::make_from(filename, "RectilinearGrid");
36
3/6
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 238 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 238 times.
✗ Branch 10 not taken.
238 _extents = Ranges::array_from_string<std::size_t, 6>(helper.get("RectilinearGrid/Piece").get_attribute("Extent"));
37
2/4
✓ Branch 2 taken 238 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 238 times.
✗ Branch 6 not taken.
238 VTK::XMLDetail::copy_field_names_from(helper.get("RectilinearGrid"), fields);
38 238 _helper.emplace(std::move(helper));
39 238 }
40
41 43 void _close() override {
42 43 _helper.reset();
43 43 _extents.reset();
44 43 }
45
46 1 std::string _name() const override {
47
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return "VTRReader";
48 }
49
50 887 std::size_t _number_of_cells() const override {
51 887 return VTK::CommonDetail::number_of_entities(_extents.value());
52 }
53
54 1157 std::size_t _number_of_points() const override {
55
2/4
✓ Branch 1 taken 1157 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1157 times.
✗ Branch 5 not taken.
1157 return VTK::CommonDetail::number_of_entities(_point_extents());
56 }
57
58 7 std::size_t _number_of_pieces() const override {
59 7 return 1;
60 }
61
62 302 typename GridReader::PieceLocation _location() const override {
63 302 const auto& ex = _extents.value();
64 typename GridReader::PieceLocation result;
65 302 result.lower_left = {ex[0], ex[2], ex[4]};
66 302 result.upper_right = {ex[1], ex[3], ex[5]};
67 302 return result;
68 }
69
70 85 bool _is_sequence() const override {
71 85 return false;
72 }
73
74 16 std::vector<double> _ordinates(unsigned int i) const override {
75 16 std::vector<double> result;
76 16 unsigned int direction = 0;
77
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 const XMLElement& coords = _helper.value().get("RectilinearGrid/Piece/Coordinates");
78
5/10
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 16 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 15 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 31 times.
✗ Branch 15 not taken.
46 for (const XMLElement& da : VTK::XML::data_arrays(coords))
79
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 15 times.
31 if (direction++ == i) {
80
2/4
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 FieldPtr ordinates_field = _helper.value().make_data_array_field(da);
81
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
48 return ordinates_field->precision().visit([&] <typename T> (const Precision<T>& prec) {
82
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
32 auto bytes = ordinates_field->serialized();
83
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
32 auto values = bytes.as_span_of(prec);
84
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
32 result.resize(values.size());
85
1/2
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
32 std::ranges::copy(values, result.begin());
86
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
64 return result;
87
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
64 });
88 16 }
89 throw IOError("Could not read ordinates in direction " + std::to_string(i));
90 16 }
91
92
93 161 FieldPtr _points() const override {
94
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
161 const XMLElement& coordinates = _helper.value().get("RectilinearGrid/Piece/Coordinates");
95
96 161 std::vector<FieldPtr> ordinates;
97
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 161 times.
✗ Branch 5 not taken.
161 std::ranges::for_each(VTK::XML::data_arrays(coordinates), [&] (const XMLElement& da) {
98
3/6
✓ Branch 1 taken 483 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 483 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 483 times.
✗ Branch 9 not taken.
483 ordinates.push_back(_helper.value().make_data_array_field(da));
99 483 });
100
101
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
161 if (ordinates.size() != 3)
102 throw SizeError("Expected 3 data arrays in the 'Coordinates' section");
103
104
1/2
✓ Branch 3 taken 161 times.
✗ Branch 4 not taken.
161 auto precision = ordinates.front()->precision();
105
3/6
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 161 times.
✓ Branch 7 taken 483 times.
✗ Branch 8 not taken.
644 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
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
161 auto num_points = _number_of_points();
109 161 return make_field_ptr(LazyField{
110 int{}, // dummy "source"
111 MDLayout{{num_points, std::size_t{3}}},
112 precision,
113
0/2
✗ Branch 4 not taken.
✗ Branch 5 not taken.
322 [ordinates=std::move(ordinates), prec=precision, np=num_points] (const int&) {
114 483 return prec.visit([&] <typename T> (const Precision<T>& p) {
115
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
322 auto x_data = ordinates.at(0)->serialized();
116
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
322 auto y_data = ordinates.at(1)->serialized();
117
2/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
322 auto z_data = ordinates.at(2)->serialized();
118
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
322 if (x_data.size() == 0) { x_data.resize(sizeof(T)); x_data.as_span_of(p)[0] = T{0}; }
119
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
322 if (y_data.size() == 0) { y_data.resize(sizeof(T)); y_data.as_span_of(p)[0] = T{0}; }
120
4/6
✓ Branch 1 taken 70 times.
✓ Branch 2 taken 91 times.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 70 times.
✗ Branch 8 not taken.
322 if (z_data.size() == 0) { z_data.resize(sizeof(T)); z_data.as_span_of(p)[0] = T{0}; }
121
122
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
322 Serialization result(np*sizeof(T)*3);
123
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
322 auto result_span = result.as_span_of(p);
124 322 std::size_t i = 0;
125
3/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 161 times.
✓ Branch 9 taken 161 times.
644 for (auto z : z_data.as_span_of(p))
126
3/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 996 times.
✓ Branch 9 taken 161 times.
2314 for (auto y : y_data.as_span_of(p))
127
3/4
✓ Branch 1 taken 996 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 5814 times.
✓ Branch 8 taken 996 times.
13620 for (auto x : x_data.as_span_of(p)) {
128
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5814 times.
11628 assert(i + 3 <= result_span.size());
129 11628 result_span[i + 0] = x;
130 11628 result_span[i + 1] = y;
131 11628 result_span[i + 2] = z;
132 11628 i += 3;
133 }
134 322 return result;
135
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
644 });
136 }
137
3/6
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 161 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 161 times.
✗ Branch 9 not taken.
483 });
138 161 }
139
140 265 void _visit_cells(const typename GridReader::CellVisitor& visitor) const override {
141 265 VTK::CommonDetail::visit_structured_cells(visitor, _extents.value());
142 265 }
143
144 631 FieldPtr _cell_field(std::string_view name) const override {
145
2/4
✓ Branch 2 taken 631 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 631 times.
✗ Branch 8 not taken.
631 return _helper.value().make_data_array_field(name, "RectilinearGrid/Piece/CellData", _number_of_cells());
146 }
147
148 634 FieldPtr _point_field(std::string_view name) const override {
149
2/4
✓ Branch 2 taken 634 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 634 times.
✗ Branch 8 not taken.
634 return _helper.value().make_data_array_field(name, "RectilinearGrid/Piece/PointData", _number_of_points());
150 }
151
152 54 FieldPtr _meta_data_field(std::string_view name) const override {
153
1/2
✓ Branch 4 taken 54 times.
✗ Branch 5 not taken.
54 return _helper.value().make_data_array_field(name, "RectilinearGrid/FieldData");
154 }
155
156 1157 std::array<std::size_t, 6> _point_extents() const {
157 1157 auto result = _extents.value();
158 1157 result[1] += 1;
159 1157 result[3] += 1;
160 1157 result[5] += 1;
161 1157 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_
171