| 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 | 1226 | std::size_t _number_of_cells() const override { | |
| 131 | 1226 | const auto counts = _get_extents(); | |
| 132 |
2/4✓ Branch 1 taken 1226 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1226 times.
✗ Branch 5 not taken.
|
4904 | auto actives = counts | std::views::filter([] (auto e) { return e != 0; }); |
| 133 |
3/6✓ Branch 1 taken 1226 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1226 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1226 times.
✗ Branch 8 not taken.
|
1226 | return std::accumulate( |
| 134 | std::ranges::begin(actives), | ||
| 135 | std::ranges::end(actives), | ||
| 136 | std::size_t{1}, | ||
| 137 | std::multiplies{} | ||
| 138 | 2452 | ); | |
| 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 | 4713 | std::array<std::size_t, 3> _get_extents() const { | |
| 301 | return { | ||
| 302 | 4713 | _piece_location.upper_right[0] - _piece_location.lower_left[0], | |
| 303 | 4713 | _piece_location.upper_right[1] - _piece_location.lower_left[1], | |
| 304 | 4713 | _piece_location.upper_right[2] - _piece_location.lower_left[2] | |
| 305 | 14139 | }; | |
| 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 |