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 | * \brief Reader for the VTK HDF file format for image grids. | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_VTK_HDF_IMAGE_GRID_READER_HPP_ | ||
9 | #define GRIDFORMAT_VTK_HDF_IMAGE_GRID_READER_HPP_ | ||
10 | #if GRIDFORMAT_HAVE_HIGH_FIVE | ||
11 | |||
12 | #include <iterator> | ||
13 | #include <optional> | ||
14 | #include <algorithm> | ||
15 | #include <functional> | ||
16 | #include <concepts> | ||
17 | #include <numeric> | ||
18 | #include <utility> | ||
19 | #include <ranges> | ||
20 | |||
21 | #include <gridformat/common/field.hpp> | ||
22 | #include <gridformat/common/field_transformations.hpp> | ||
23 | #include <gridformat/common/exceptions.hpp> | ||
24 | #include <gridformat/common/lazy_field.hpp> | ||
25 | #include <gridformat/common/ranges.hpp> | ||
26 | |||
27 | #include <gridformat/grid/reader.hpp> | ||
28 | #include <gridformat/parallel/concepts.hpp> | ||
29 | #include <gridformat/vtk/hdf_common.hpp> | ||
30 | |||
31 | namespace GridFormat { | ||
32 | |||
33 | /*! | ||
34 | * \ingroup VTK | ||
35 | * \brief Reader for the VTK-HDF file format for image grids. | ||
36 | */ | ||
37 | class VTKHDFImageGridReader : public GridReader { | ||
38 | using Communicator = NullCommunicator; | ||
39 | using HDF5File = HDF5::File<Communicator>; | ||
40 | static constexpr std::size_t vtk_space_dim = 3; | ||
41 | |||
42 | public: | ||
43 | 67 | explicit VTKHDFImageGridReader() = default; | |
44 | |||
45 | template<Concepts::Communicator C> | ||
46 | explicit VTKHDFImageGridReader(C&&) { | ||
47 | static_assert( | ||
48 | std::is_same_v<std::remove_cvref_t<C>, NullCommunicator>, | ||
49 | "Cannot read vtk-hdf image grid files in parallel" | ||
50 | ); | ||
51 | } | ||
52 | |||
53 | private: | ||
54 | 2 | std::string _name() const override { | |
55 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (_is_transient()) |
56 | ✗ | return "VTKHDFImageGridReader (transient)"; | |
57 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | return "VTKHDFImageGridReader"; |
58 | } | ||
59 | |||
60 | 68 | void _open(const std::string& filename, typename GridReader::FieldNames& field_names) override { | |
61 |
2/4✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
|
68 | _file = HDF5File{filename, _comm, HDF5File::read_only}; |
62 | |||
63 |
2/4✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 68 times.
✗ Branch 5 not taken.
|
68 | const auto type = VTKHDF::get_file_type(_file.value()); |
64 |
3/4✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 30 times.
|
68 | if (type != "ImageData") |
65 |
3/6✓ Branch 2 taken 38 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 38 times.
✗ Branch 10 not taken.
|
38 | throw ValueError("Incompatible VTK-HDF type: '" + type + "', expected 'ImageData'."); |
66 | |||
67 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 | VTKHDF::check_version_compatibility(_file.value(), {2, 0}); |
68 | |||
69 |
4/6✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 15 times.
|
90 | if (_file->exists("/VTKHDF/Steps")) |
70 |
2/4✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
|
75 | _file->visit_attribute("/VTKHDF/Steps/NSteps", [&] (auto&& field) { |
71 | 30 | _num_steps.emplace(); | |
72 | 30 | field.export_to(_num_steps.value()); | |
73 | 30 | _step_index.emplace(0); | |
74 | 30 | }); | |
75 | |||
76 | 90 | const auto copy_names_in = [&] (const std::string& group, auto& storage) { | |
77 |
2/2✓ Branch 2 taken 82 times.
✓ Branch 3 taken 8 times.
|
90 | if (_file->exists(group)) |
78 |
2/4✓ Branch 3 taken 82 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 82 times.
✗ Branch 7 not taken.
|
82 | std::ranges::copy(_file->dataset_names_in(group), std::back_inserter(storage)); |
79 | 90 | }; | |
80 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
60 | copy_names_in("VTKHDF/CellData", field_names.cell_fields); |
81 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
60 | copy_names_in("VTKHDF/PointData", field_names.point_fields); |
82 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
60 | copy_names_in("VTKHDF/FieldData", field_names.meta_data_fields); |
83 | |||
84 |
3/6✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
|
60 | auto spacing = _file.value().template read_attribute_to<std::vector<double>>("/VTKHDF/Spacing"); |
85 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (spacing.size() != vtk_space_dim) |
86 | ✗ | throw SizeError("Unexpected spacing vector read (size = " + as_string(spacing.size()) + ")"); | |
87 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | _cell_spacing = Ranges::to_array<vtk_space_dim>(spacing); |
88 | |||
89 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
60 | auto direction = std::vector<double>{1., 0., 0., 0., 1., 0., 0., 0., 1.}; |
90 |
3/6✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 30 times.
✗ Branch 9 not taken.
|
90 | if (_file->has_attribute_at("/VTKHDF/Direction")) |
91 |
2/4✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
|
90 | direction = _file->template read_attribute_to<std::vector<double>>("/VTKHDF/Direction"); |
92 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (direction.size() != 9) |
93 | ✗ | throw SizeError("Unexpected direction vector read (size = " + as_string(direction.size()) + ")"); | |
94 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | _direction = Ranges::to_array<9>(direction); |
95 | |||
96 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
60 | auto origin = std::vector<double>{0., 0., 0.}; |
97 |
3/6✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 30 times.
✗ Branch 9 not taken.
|
90 | if (_file->has_attribute_at("/VTKHDF/Origin")) |
98 |
2/4✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
|
90 | origin = _file->template read_attribute_to<std::vector<double>>("/VTKHDF/Origin"); |
99 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (origin.size() != vtk_space_dim) |
100 | ✗ | throw SizeError("Unexpected origin read (size = " + as_string(origin.size()) + ")"); | |
101 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | _point_origin = Ranges::to_array<vtk_space_dim>(origin); |
102 | |||
103 |
3/6✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
|
60 | auto extents = _file.value().template read_attribute_to<std::vector<std::size_t>>("/VTKHDF/WholeExtent"); |
104 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (extents.size() != 6) |
105 | ✗ | throw SizeError("Unexpected 'WholeExtents' attribute (size = " + as_string(extents.size()) + ")."); | |
106 | 30 | _piece_location.lower_left = {extents[0], extents[2], extents[4]}; | |
107 | 30 | _piece_location.upper_right = {extents[1], extents[3], extents[5]}; | |
108 | 68 | } | |
109 | |||
110 | ✗ | void _close() override { | |
111 | ✗ | _file = {}; | |
112 | ✗ | _piece_location = {}; | |
113 | ✗ | _cell_spacing = {}; | |
114 | ✗ | _point_origin = {}; | |
115 | ✗ | _direction = {}; | |
116 | ✗ | } | |
117 | |||
118 | 5 | typename GridReader::PieceLocation _location() const override { | |
119 | 5 | return _piece_location; | |
120 | } | ||
121 | |||
122 | 4 | typename GridReader::Vector _spacing() const override { | |
123 | 4 | return _cell_spacing; | |
124 | } | ||
125 | |||
126 | 2 | typename GridReader::Vector _origin() const override { | |
127 | 2 | return _point_origin; | |
128 | } | ||
129 | |||
130 | 1212 | std::size_t _number_of_cells() const override { | |
131 | 1212 | const auto counts = _get_extents(); | |
132 |
2/4✓ Branch 1 taken 1212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1212 times.
✗ Branch 5 not taken.
|
4848 | auto actives = counts | std::views::filter([] (auto e) { return e != 0; }); |
133 |
3/6✓ Branch 1 taken 1212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1212 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1212 times.
✗ Branch 8 not taken.
|
1212 | return std::accumulate( |
134 | std::ranges::begin(actives), | ||
135 | std::ranges::end(actives), | ||
136 | std::size_t{1}, | ||
137 | std::multiplies{} | ||
138 | 2424 | ); | |
139 | } | ||
140 | |||
141 | 1403 | std::size_t _number_of_points() const override { | |
142 |
1/2✓ Branch 2 taken 1403 times.
✗ Branch 3 not taken.
|
1403 | auto counts = Ranges::incremented(_get_extents(), 1); |
143 | 1403 | return std::accumulate( | |
144 | std::ranges::begin(counts), | ||
145 | std::ranges::end(counts), | ||
146 | std::size_t{1}, | ||
147 | std::multiplies{} | ||
148 | 2806 | ); | |
149 | } | ||
150 | |||
151 | 2 | std::size_t _number_of_pieces() const override { | |
152 | 2 | return 1; | |
153 | } | ||
154 | |||
155 | 185 | void _visit_cells(const typename GridReader::CellVisitor& visitor) const override { | |
156 |
1/2✓ Branch 2 taken 185 times.
✗ Branch 3 not taken.
|
185 | VTK::CommonDetail::visit_structured_cells(visitor, _make_vtk_extents_array()); |
157 | 185 | } | |
158 | |||
159 | 65 | FieldPtr _points() const override { | |
160 | 65 | std::array<std::size_t, 6> extents = _make_vtk_extents_array(); | |
161 | 65 | extents[1] += 1; | |
162 | 65 | extents[3] += 1; | |
163 | 65 | extents[5] += 1; | |
164 | 65 | return make_field_ptr(LazyField{ | |
165 | int{}, // dummy source | ||
166 |
1/2✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
|
65 | MDLayout{{VTK::CommonDetail::number_of_entities(extents), std::size_t{vtk_space_dim}}}, |
167 | Precision<double>{}, | ||
168 | ✗ | [ex=extents, o=_point_origin, s=_cell_spacing, d=_direction] (const int&) { | |
169 | 65 | return VTK::CommonDetail::serialize_structured_points(ex, o, s, d); | |
170 | } | ||
171 |
3/6✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 65 times.
✗ Branch 9 not taken.
|
195 | }); |
172 | } | ||
173 | |||
174 | 25 | bool _is_sequence() const override { | |
175 | 25 | return _is_transient(); | |
176 | } | ||
177 | |||
178 | 206 | std::size_t _number_of_steps() const override { | |
179 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 206 times.
|
206 | if (!_num_steps.has_value()) |
180 | ✗ | throw ValueError("Read file is not a sequence"); | |
181 | 206 | return _num_steps.value(); | |
182 | } | ||
183 | |||
184 | 75 | double _time_at_step(std::size_t step_idx) const override { | |
185 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 75 times.
|
75 | if (step_idx >= _number_of_steps()) |
186 | ✗ | throw ValueError("Only " + as_string(_number_of_steps()) + " available"); | |
187 |
4/12✓ Branch 2 taken 75 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 75 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 75 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 75 times.
✗ Branch 14 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
450 | return _file.value().template read_dataset_to<double>("/VTKHDF/Steps/Values", HDF5::Slice{ |
188 | .offset = {step_idx}, | ||
189 | .count = {1} | ||
190 | 150 | }); | |
191 | } | ||
192 | |||
193 | 95 | void _set_step(std::size_t step_idx, typename GridReader::FieldNames&) override { | |
194 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 95 times.
|
95 | if (step_idx >= _number_of_steps()) |
195 | ✗ | throw ValueError("Only " + as_string(_number_of_steps()) + " available"); | |
196 | 95 | _step_index = step_idx; | |
197 | 95 | } | |
198 | |||
199 | 1052 | auto _serialization_callback(std::string path, std::size_t target_size) const { | |
200 | 1052 | return [&, size=target_size, _step=_step_index, _p=std::move(path)] (const HDF5File& file) { | |
201 |
2/4✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 608 times.
✗ Branch 5 not taken.
|
608 | auto count = file.get_dimensions(_p).value(); |
202 |
1/2✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
|
608 | auto offset = count; |
203 |
1/2✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
|
608 | std::ranges::fill(offset, 0); |
204 |
2/2✓ Branch 1 taken 510 times.
✓ Branch 2 taken 98 times.
|
608 | if (_step) { |
205 |
1/2✓ Branch 1 taken 510 times.
✗ Branch 2 not taken.
|
510 | count.at(0) = 1; |
206 |
2/4✓ Branch 1 taken 510 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 510 times.
✗ Branch 5 not taken.
|
510 | offset.at(0) = _step.value(); |
207 | } | ||
208 | 1824 | return file.visit_dataset(_p, [&] <typename F> (F&& field) { | |
209 |
2/2✓ Branch 1 taken 510 times.
✓ Branch 2 taken 98 times.
|
1216 | const std::size_t step_offset = _step.has_value() ? 1 : 0; |
210 |
1/2✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
|
1216 | const auto layout = field.layout(); |
211 |
4/6✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 608 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 396 times.
✓ Branch 7 taken 212 times.
|
1216 | if (layout.dimension() == _grid_dimension() + step_offset) |
212 |
3/6✓ Branch 1 taken 396 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 396 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 396 times.
✗ Branch 9 not taken.
|
1584 | return transform(make_field_ptr(std::move(field)), FieldTransformation::reshape_to( |
213 |
1/2✓ Branch 1 taken 396 times.
✗ Branch 2 not taken.
|
1584 | MDLayout{{size}} |
214 |
1/2✓ Branch 2 taken 396 times.
✗ Branch 3 not taken.
|
792 | ))->serialized(); |
215 |
3/6✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 212 times.
✗ Branch 7 not taken.
|
424 | else if (layout.dimension() == _grid_dimension() + step_offset + 1) |
216 |
3/6✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 212 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 212 times.
✗ Branch 9 not taken.
|
848 | return transform(make_field_ptr(std::move(field)), FieldTransformation::reshape_to( |
217 |
3/6✓ Branch 1 taken 212 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 212 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 212 times.
✗ Branch 8 not taken.
|
424 | MDLayout{{size, layout.extent(_grid_dimension() + step_offset)}} |
218 |
1/2✓ Branch 2 taken 212 times.
✗ Branch 3 not taken.
|
424 | ))->serialized(); |
219 | ✗ | throw InvalidState("Unexpected field layout: " + as_string(layout)); | |
220 |
3/10✓ Branch 1 taken 608 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 608 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 608 times.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
3040 | }, HDF5::Slice{.offset = offset, .count = count}); |
221 | 1660 | }; | |
222 | } | ||
223 | |||
224 | 492 | FieldPtr _cell_field(std::string_view name) const override { | |
225 |
2/4✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 492 times.
✗ Branch 5 not taken.
|
492 | const std::string path = "VTKHDF/CellData/" + std::string{name}; |
226 |
1/2✓ Branch 2 taken 492 times.
✗ Branch 3 not taken.
|
492 | const auto num_components = _get_number_of_components(path); |
227 |
3/4✓ Branch 1 taken 328 times.
✓ Branch 2 taken 164 times.
✓ Branch 4 taken 328 times.
✗ Branch 5 not taken.
|
492 | const auto layout = num_components ? MDLayout{{_number_of_cells(), num_components.value()}} |
228 |
4/8✓ Branch 1 taken 328 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 328 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 164 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 164 times.
✗ Branch 11 not taken.
|
492 | : MDLayout{{_number_of_cells()}}; |
229 | 492 | return make_field_ptr(VTKHDF::DataSetField{ | |
230 | _file.value(), | ||
231 | 492 | std::move(layout), | |
232 |
3/6✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 492 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 492 times.
✗ Branch 8 not taken.
|
492 | _file.value().get_precision(path).value(), |
233 |
1/2✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
|
984 | _serialization_callback(path, _number_of_cells()) |
234 |
5/10✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 492 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 492 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 492 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 492 times.
✗ Branch 15 not taken.
|
2460 | }); |
235 | 492 | } | |
236 | |||
237 | 560 | FieldPtr _point_field(std::string_view name) const override { | |
238 |
2/4✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 560 times.
✗ Branch 5 not taken.
|
560 | const std::string path = "VTKHDF/PointData/" + std::string{name}; |
239 |
1/2✓ Branch 2 taken 560 times.
✗ Branch 3 not taken.
|
560 | const auto num_components = _get_number_of_components(path); |
240 |
3/4✓ Branch 1 taken 372 times.
✓ Branch 2 taken 188 times.
✓ Branch 4 taken 372 times.
✗ Branch 5 not taken.
|
560 | const auto layout = num_components ? MDLayout{{_number_of_points(), num_components.value()}} |
241 |
4/8✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 372 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 188 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 188 times.
✗ Branch 11 not taken.
|
560 | : MDLayout{{_number_of_points()}}; |
242 | 560 | return make_field_ptr(VTKHDF::DataSetField{ | |
243 | _file.value(), | ||
244 | 560 | std::move(layout), | |
245 |
3/6✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 560 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 560 times.
✗ Branch 8 not taken.
|
560 | _file.value().get_precision(path).value(), |
246 |
1/2✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
|
1120 | _serialization_callback(path, _number_of_points()) |
247 |
5/10✓ Branch 1 taken 560 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 560 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 560 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 560 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 560 times.
✗ Branch 15 not taken.
|
2800 | }); |
248 | 560 | } | |
249 | |||
250 | 30 | FieldPtr _meta_data_field(std::string_view name) const override { | |
251 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 | const auto path = "VTKHDF/FieldData/" + std::string{name}; |
252 |
3/6✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
|
30 | const auto dims = _file.value().get_dimensions(path).value(); |
253 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
|
30 | if (dims.size() == 1) |
254 | ✗ | return make_field_ptr(VTKHDF::DataSetField{_file.value(), path}); | |
255 |
3/8✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 30 times.
|
30 | if (dims.size() > 3 || (!_is_transient() && dims.size() != 2)) |
256 | ✗ | throw SizeError("Unexpected field data array size"); | |
257 |
2/4✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
|
30 | if (dims.at(dims.size() - 2) != 1) |
258 | ✗ | throw SizeError("Cannot only read one-dimensional field data"); | |
259 | |||
260 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | auto offset = dims; |
261 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | auto count = offset; |
262 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | std::ranges::fill(offset, 0); |
263 |
1/2✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
|
30 | count.at(0) = 1; |
264 |
3/6✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
|
30 | offset.at(0) = _is_transient() ? _step_index.value() : 0; |
265 | 30 | return make_field_ptr(VTKHDF::DataSetField{ | |
266 | _file.value(), | ||
267 |
2/4✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
|
30 | MDLayout{count | std::views::drop(1)}, |
268 |
3/6✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
|
30 | _file.value().get_precision(path).value(), |
269 |
2/8✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
60 | [p=path, o=offset, c=count] (const HDF5File& f) { |
270 | 18 | return f.visit_dataset(p, [&] <typename F> (F&& field) { | |
271 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
12 | return FlattenedField{make_field_ptr(std::move(field))}.serialized(); |
272 |
3/10✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
12 | }, HDF5::Slice{.offset = o, .count = c}); |
273 | } | ||
274 |
5/10✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 30 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 30 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 30 times.
✗ Branch 14 not taken.
|
90 | }); |
275 | 30 | } | |
276 | |||
277 | 250 | std::array<std::size_t, 6> _make_vtk_extents_array() const { | |
278 | std::array<std::size_t, 6> extents; | ||
279 | 250 | extents[0] = _piece_location.lower_left[0]; | |
280 | 250 | extents[2] = _piece_location.lower_left[1]; | |
281 | 250 | extents[4] = _piece_location.lower_left[2]; | |
282 | 250 | extents[1] = _piece_location.upper_right[0]; | |
283 | 250 | extents[3] = _piece_location.upper_right[1]; | |
284 | 250 | extents[5] = _piece_location.upper_right[2]; | |
285 | 250 | return extents; | |
286 | } | ||
287 | |||
288 | 1052 | std::optional<std::size_t> _get_number_of_components(std::string_view path) const { | |
289 |
4/8✓ Branch 1 taken 1052 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1052 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1052 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1052 times.
✗ Branch 11 not taken.
|
2104 | const auto layout = _file.value().get_dimensions(std::string{path}).value(); |
290 |
2/2✓ Branch 1 taken 870 times.
✓ Branch 2 taken 182 times.
|
1052 | const std::size_t step_offset = _is_transient() ? 1 : 0; |
291 |
3/4✓ Branch 2 taken 1052 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 700 times.
✓ Branch 5 taken 352 times.
|
1052 | if (layout.size() == _grid_dimension() + step_offset + 1) |
292 | 700 | return layout.back(); | |
293 | 352 | return {}; | |
294 | 1052 | } | |
295 | |||
296 | 2084 | std::size_t _grid_dimension() const { | |
297 |
1/2✓ Branch 2 taken 2084 times.
✗ Branch 3 not taken.
|
2084 | return VTK::CommonDetail::structured_grid_dimension(_get_extents()); |
298 | } | ||
299 | |||
300 | 4699 | std::array<std::size_t, 3> _get_extents() const { | |
301 | return { | ||
302 | 4699 | _piece_location.upper_right[0] - _piece_location.lower_left[0], | |
303 | 4699 | _piece_location.upper_right[1] - _piece_location.lower_left[1], | |
304 | 4699 | _piece_location.upper_right[2] - _piece_location.lower_left[2] | |
305 | 14097 | }; | |
306 | } | ||
307 | |||
308 | 1139 | bool _is_transient() const { | |
309 | 1139 | return static_cast<bool>(_num_steps); | |
310 | } | ||
311 | |||
312 | Communicator _comm; | ||
313 | std::optional<HDF5File> _file; | ||
314 | typename GridReader::PieceLocation _piece_location; | ||
315 | std::array<double, 9> _direction; | ||
316 | std::array<double, 3> _cell_spacing; | ||
317 | std::array<double, 3> _point_origin; | ||
318 | std::optional<std::size_t> _num_steps; | ||
319 | std::optional<std::size_t> _step_index; | ||
320 | }; | ||
321 | |||
322 | } // namespace GridFormat | ||
323 | |||
324 | #endif // GRIDFORMAT_HAVE_HIGH_FIVE | ||
325 | #endif // GRIDFORMAT_VTK_HDF_IMAGE_GRID_READER_HPP_ | ||
326 |