GCC Code Coverage Report


Directory: gridformat/
File: gridformat/vtk/pvd_reader.hpp
Date: 2024-11-20 14:41:59
Exec Total Coverage
Lines: 124 129 96.1%
Functions: 59 66 89.4%
Branches: 84 158 53.2%

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::PVDReader
7 */
8 #ifndef GRIDFORMAT_VTK_PVD_READER_HPP_
9 #define GRIDFORMAT_VTK_PVD_READER_HPP_
10
11 #include <memory>
12 #include <optional>
13 #include <filesystem>
14 #include <functional>
15 #include <type_traits>
16 #include <iterator>
17
18 #include <gridformat/common/string_conversion.hpp>
19 #include <gridformat/parallel/communication.hpp>
20 #include <gridformat/grid/reader.hpp>
21 #include <gridformat/vtk/xml.hpp>
22
23 #include <gridformat/vtk/vtu_reader.hpp>
24 #include <gridformat/vtk/vtp_reader.hpp>
25 #include <gridformat/vtk/vts_reader.hpp>
26 #include <gridformat/vtk/vtr_reader.hpp>
27 #include <gridformat/vtk/vti_reader.hpp>
28
29 #include <gridformat/vtk/pvtu_reader.hpp>
30 #include <gridformat/vtk/pvtp_reader.hpp>
31 #include <gridformat/vtk/pvts_reader.hpp>
32 #include <gridformat/vtk/pvtr_reader.hpp>
33 #include <gridformat/vtk/pvti_reader.hpp>
34
35 namespace GridFormat {
36
37 /*!
38 * \ingroup VTK
39 * \brief Reader for .pvd time series file format
40 */
41 template<Concepts::Communicator C = NullCommunicator>
42 class PVDReader : public GridReader {
43 struct Step {
44 std::string filename;
45 double time;
46 };
47
48 static constexpr bool is_parallel = !std::is_same_v<NullCommunicator, C>;
49
50 public:
51 using StepReaderFactory = std::conditional_t<
52 is_parallel,
53 std::function<std::unique_ptr<GridReader>(const C&, const std::string&)>,
54 std::function<std::unique_ptr<GridReader>(const std::string&)>
55 >;
56
57
58 40 PVDReader() requires(std::same_as<C, NullCommunicator>)
59 40 : _step_reader_factory{_make_default_step_reader_factory()}
60 40 {}
61
62 1 explicit PVDReader(StepReaderFactory&& f) requires(std::same_as<C, NullCommunicator>)
63 1 : _step_reader_factory{std::move(f)}
64 1 {}
65
66 58 explicit PVDReader(const C& comm)
67 58 : _communicator{comm}
68 58 , _step_reader_factory{_make_default_step_reader_factory()}
69 58 {}
70
71 2 explicit PVDReader(const C& comm, StepReaderFactory&& f)
72 2 : _communicator{comm}
73 2 , _step_reader_factory{std::move(f)}
74 2 {}
75
76 private:
77 161 StepReaderFactory _make_default_step_reader_factory() const {
78 if constexpr (is_parallel)
79 550 return [&] (const C& comm, const std::string& filename) {
80 448 return _make_reader_from_file(comm, filename);
81 114 };
82 else
83 79 return [&] (const std::string& filename) {
84
1/2
✓ Branch 1 taken 255 times.
✗ Branch 2 not taken.
255 return _make_reader_from_file(NullCommunicator{}, filename);
85 47 };
86 }
87
88 1171 static std::unique_ptr<GridReader> _make_reader_from_file(const C& comm, const std::string& filename) {
89
1/2
✓ Branch 1 taken 703 times.
✗ Branch 2 not taken.
1171 std::filesystem::path path{filename};
90
4/6
✓ Branch 1 taken 703 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 703 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 663 times.
1171 if (path.extension() == ".vtu")
91
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 return std::make_unique<VTUReader>();
92
4/6
✓ Branch 1 taken 663 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 663 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 623 times.
1131 else if (path.extension() == ".vtp")
93
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 return std::make_unique<VTPReader>();
94
4/6
✓ Branch 1 taken 623 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 623 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 40 times.
✓ Branch 10 taken 583 times.
1091 else if (path.extension() == ".vts")
95
1/2
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
40 return std::make_unique<VTSReader>();
96
4/6
✓ Branch 1 taken 583 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 583 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 43 times.
✓ Branch 10 taken 540 times.
1051 else if (path.extension() == ".vtr")
97
1/2
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
43 return std::make_unique<VTRReader>();
98
4/6
✓ Branch 1 taken 540 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 540 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 60 times.
✓ Branch 10 taken 480 times.
1008 else if (path.extension() == ".vti")
99
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 return std::make_unique<VTIReader>();
100
4/6
✓ Branch 1 taken 480 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 480 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 86 times.
✓ Branch 10 taken 394 times.
948 else if (path.extension() == ".pvtu")
101
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
172 return std::make_unique<PVTUReader>(comm);
102
4/6
✓ Branch 1 taken 394 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 394 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 86 times.
✓ Branch 10 taken 308 times.
776 else if (path.extension() == ".pvtp")
103
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
172 return std::make_unique<PVTPReader>(comm);
104
4/6
✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 308 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 86 times.
✓ Branch 10 taken 222 times.
604 else if (path.extension() == ".pvts")
105
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
172 return std::make_unique<PVTSReader>(comm);
106
4/6
✓ Branch 1 taken 222 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 88 times.
✓ Branch 10 taken 134 times.
432 else if (path.extension() == ".pvtr")
107
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
176 return std::make_unique<PVTRReader>(comm);
108
3/6
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 134 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 134 times.
✗ Branch 10 not taken.
256 else if (path.extension() == ".pvti")
109
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
256 return std::make_unique<PVTIReader>(comm);
110 throw IOError("Could not find reader for format with extension " + std::string{path.extension()});
111 1171 }
112
113 1 std::string _name() const override {
114
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return "PVDReader";
115 }
116
117 176 void _open(const std::string& filename, typename GridReader::FieldNames& names) override {
118 176 _reset();
119 176 _read_steps(filename);
120 171 _make_step_reader();
121 166 _read_current_field_names(names);
122 166 }
123
124 129 void _close() override {
125 129 _reset();
126 129 }
127
128 1990 std::size_t _number_of_cells() const override {
129 1990 return _access_reader().number_of_cells();
130 }
131
132 2630 std::size_t _number_of_points() const override {
133 2630 return _access_reader().number_of_points();
134 }
135
136 45 std::size_t _number_of_pieces() const override {
137 45 return _access_reader().number_of_pieces();
138 }
139
140 4185 virtual FieldPtr _cell_field(std::string_view name) const override {
141 4185 return _access_reader().cell_field(name);
142 }
143
144 4185 virtual FieldPtr _point_field(std::string_view name) const override {
145 4185 return _access_reader().point_field(name);
146 }
147
148 375 virtual FieldPtr _meta_data_field(std::string_view name) const override {
149 375 return _access_reader().meta_data_field(name);
150 }
151
152 1495 virtual void _visit_cells(const typename GridReader::CellVisitor& visitor) const override {
153 1495 _access_reader().visit_cells(visitor);
154 1495 }
155
156 595 virtual FieldPtr _points() const override {
157 595 return _access_reader().points();
158 }
159
160 18 virtual typename GridReader::PieceLocation _location() const override {
161 18 return _access_reader().location();
162 }
163
164 6 virtual std::vector<double> _ordinates(unsigned int i) const override {
165 6 return _access_reader().ordinates(i);
166 }
167
168 6 virtual typename GridReader::Vector _spacing() const override {
169 6 return _access_reader().spacing();
170 }
171
172 6 virtual typename GridReader::Vector _origin() const override {
173 6 return _access_reader().origin();
174 }
175
176 virtual typename GridReader::Vector _basis_vector(unsigned int i) const override {
177 return _access_reader().basis_vector(i);
178 }
179
180 127 virtual bool _is_sequence() const override {
181 127 return true;
182 }
183
184 487 std::size_t _number_of_steps() const override {
185 487 return _steps.size();
186 }
187
188 760 double _time_at_step(std::size_t step_idx) const override {
189 760 return _steps.at(step_idx).time;
190 }
191
192 1010 void _set_step(std::size_t step_idx, typename GridReader::FieldNames& names) override {
193 1010 names.clear();
194 1010 _step_index = step_idx;
195 1010 _make_step_reader();
196 1010 _read_current_field_names(names);
197 1010 }
198
199 176 void _read_steps(const std::string& filename) {
200
2/2
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 3 times.
176 auto helper = VTK::XMLReaderHelper::make_from(filename, "Collection");
201
7/12
✓ Branch 1 taken 104 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 104 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 104 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 104 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 104 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 520 times.
✓ Branch 20 taken 104 times.
1361 for (const auto& data_set : children(helper.get("Collection")) | std::views::filter([] (const XMLElement& e) {
202 520 return e.name() == "DataSet";
203 }))
204 855 _steps.emplace_back(Step{
205
4/8
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 520 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 520 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 520 times.
✗ Branch 14 not taken.
1710 .filename = _get_piece_path(data_set.get_attribute("file"), filename),
206
2/4
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 520 times.
✗ Branch 5 not taken.
1710 .time = from_string<double>(data_set.get_attribute("timestep"))
207 });
208
2/6
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 520 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1881 }
209
210 855 std::string _get_piece_path(std::filesystem::path vtk_file,
211 std::filesystem::path pvtk_file) const {
212
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 520 times.
855 if (vtk_file.is_absolute())
213 return vtk_file;
214
3/6
✓ Branch 1 taken 520 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 520 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 520 times.
✗ Branch 8 not taken.
855 return pvtk_file.parent_path() / vtk_file;
215 }
216
217 1181 void _make_step_reader() {
218 1181 const std::string& filename = _steps.at(_step_index).filename;
219
1/2
✓ Branch 1 taken 709 times.
✗ Branch 2 not taken.
1181 _step_reader = _invoke_reader_factory(filename);
220 1181 _step_reader->open(filename);
221 1176 }
222
223 1181 std::unique_ptr<GridReader> _invoke_reader_factory(const std::string& filename) const {
224 if constexpr (is_parallel)
225 892 return _step_reader_factory(_communicator, filename);
226 else
227 289 return _step_reader_factory(filename);
228 }
229
230 1176 void _read_current_field_names(typename GridReader::FieldNames& names) const {
231
3/6
✓ Branch 2 taken 706 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 706 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 706 times.
✗ Branch 9 not taken.
1176 std::ranges::copy(cell_field_names(_access_reader()), std::back_inserter(names.cell_fields));
232
3/6
✓ Branch 2 taken 706 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 706 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 706 times.
✗ Branch 9 not taken.
1176 std::ranges::copy(point_field_names(_access_reader()), std::back_inserter(names.point_fields));
233
3/6
✓ Branch 2 taken 706 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 706 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 706 times.
✗ Branch 9 not taken.
1176 std::ranges::copy(meta_data_field_names(_access_reader()), std::back_inserter(names.meta_data_fields));
234 1176 }
235
236 305 void _reset() {
237 305 _step_reader.reset();
238 305 _steps.clear();
239 305 _step_index = 0;
240 305 }
241
242 11513 const GridReader& _access_reader() const {
243
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3962 times.
11513 if (!_step_reader)
244 throw ValueError("No data available");
245 11513 return *_step_reader;
246 }
247
248 C _communicator;
249 StepReaderFactory _step_reader_factory;
250 std::unique_ptr<GridReader> _step_reader;
251 std::vector<Step> _steps;
252 std::size_t _step_index = 0;
253 };
254
255 } // namespace GridFormat
256
257 #endif // GRIDFORMAT_VTK_PVD_READER_HPP_
258