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 Writer for the VTK HDF file format for image grids. | ||
7 | */ | ||
8 | #ifndef GRIDFORMAT_VTK_HDF_IMAGE_GRID_WRITER_HPP_ | ||
9 | #define GRIDFORMAT_VTK_HDF_IMAGE_GRID_WRITER_HPP_ | ||
10 | #if GRIDFORMAT_HAVE_HIGH_FIVE | ||
11 | |||
12 | #include <ranges> | ||
13 | #include <iterator> | ||
14 | #include <algorithm> | ||
15 | #include <utility> | ||
16 | #include <tuple> | ||
17 | |||
18 | #include <gridformat/common/exceptions.hpp> | ||
19 | #include <gridformat/common/md_layout.hpp> | ||
20 | #include <gridformat/common/concepts.hpp> | ||
21 | #include <gridformat/common/matrix.hpp> | ||
22 | #include <gridformat/common/ranges.hpp> | ||
23 | #include <gridformat/common/type_traits.hpp> | ||
24 | #include <gridformat/common/lvalue_reference.hpp> | ||
25 | #include <gridformat/common/field_transformations.hpp> | ||
26 | |||
27 | #include <gridformat/parallel/communication.hpp> | ||
28 | #include <gridformat/parallel/concepts.hpp> | ||
29 | |||
30 | #include <gridformat/grid/concepts.hpp> | ||
31 | #include <gridformat/grid/writer.hpp> | ||
32 | |||
33 | #include <gridformat/vtk/common.hpp> | ||
34 | #include <gridformat/vtk/parallel.hpp> | ||
35 | #include <gridformat/vtk/hdf_common.hpp> | ||
36 | |||
37 | namespace GridFormat { | ||
38 | |||
39 | template<bool is_transient, Concepts::ImageGrid Grid, Concepts::Communicator Communicator = NullCommunicator> | ||
40 | class VTKHDFImageGridWriterImpl : public GridDetail::WriterBase<is_transient, Grid>::type { | ||
41 | static constexpr int root_rank = 0; | ||
42 | static constexpr std::size_t dim = dimension<Grid>; | ||
43 | static constexpr std::size_t vtk_space_dim = 3; | ||
44 | static constexpr std::array<std::size_t, 2> version{1, 0}; | ||
45 | |||
46 | using CT = CoordinateType<Grid>; | ||
47 | using IOContext = VTKHDF::IOContext; | ||
48 | using HDF5File = HDF5::File<Communicator>; | ||
49 | |||
50 | struct ImageSpecs { | ||
51 | const std::array<CT, dim> origin; | ||
52 | const std::array<CT, dim> spacing; | ||
53 | const std::array<std::size_t, dim> extents; | ||
54 | |||
55 | template<typename O, typename S, typename E> | ||
56 | 526 | ImageSpecs(O&& origin, S&& spacing, E&& extents) | |
57 | 526 | : origin{Ranges::to_array<dim, CT>(std::forward<O>(origin))} | |
58 | 526 | , spacing{Ranges::to_array<dim, CT>(std::forward<S>(spacing))} | |
59 | 526 | , extents{Ranges::to_array<dim, std::size_t>(std::forward<E>(extents))} | |
60 | 526 | {} | |
61 | }; | ||
62 | |||
63 | static constexpr WriterOptions writer_opts{ | ||
64 | .use_structured_grid_ordering = true, | ||
65 | .append_null_terminator_to_strings = true | ||
66 | }; | ||
67 | |||
68 | public: | ||
69 | 23 | explicit VTKHDFImageGridWriterImpl(LValueReferenceOf<const Grid> grid) | |
70 | requires(std::is_same_v<Communicator, NullCommunicator>) | ||
71 |
3/6✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 13 times.
✗ Branch 11 not taken.
|
115 | : GridWriter<Grid>(grid.get(), ".hdf", writer_opts) |
72 | 23 | {} | |
73 | |||
74 | 149 | explicit VTKHDFImageGridWriterImpl(LValueReferenceOf<const Grid> grid, const Communicator& comm) | |
75 | requires(std::is_copy_constructible_v<Communicator>) | ||
76 | : GridWriter<Grid>(grid.get(), ".hdf", writer_opts) | ||
77 |
3/6✓ Branch 2 taken 77 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 77 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 77 times.
✗ Branch 11 not taken.
|
745 | , _comm{comm} |
78 | 149 | {} | |
79 | |||
80 | 6 | explicit VTKHDFImageGridWriterImpl(LValueReferenceOf<const Grid> grid, | |
81 | std::string filename_without_extension, | ||
82 | VTK::HDFTransientOptions opts = { | ||
83 | .static_grid = true, | ||
84 | .static_meta_data = false | ||
85 | }) | ||
86 | requires(is_transient && std::is_same_v<Communicator, NullCommunicator>) | ||
87 |
2/4✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
|
6 | : VTKHDFImageGridWriterImpl(grid.get(), NullCommunicator{}, filename_without_extension, std::move(opts)) |
88 | 6 | {} | |
89 | |||
90 | 15 | explicit VTKHDFImageGridWriterImpl(LValueReferenceOf<const Grid> grid, | |
91 | const Communicator& comm, | ||
92 | std::string filename_without_extension, | ||
93 | VTK::HDFTransientOptions opts = { | ||
94 | .static_grid = true, | ||
95 | .static_meta_data = false | ||
96 | }) | ||
97 | requires(is_transient && std::is_copy_constructible_v<Communicator>) | ||
98 | : TimeSeriesGridWriter<Grid>(grid.get(), writer_opts) | ||
99 | 8 | , _comm{comm} | |
100 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | , _timeseries_filename{std::move(filename_without_extension) + ".hdf"} |
101 |
1/2✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
30 | , _transient_opts{std::move(opts)} { |
102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!_transient_opts.static_grid) |
103 | ✗ | throw ValueError("Transient VTK-HDF ImageData files do not support evolving grids"); | |
104 | 15 | } | |
105 | |||
106 | const Communicator& communicator() const { | ||
107 | return _comm; | ||
108 | } | ||
109 | |||
110 | private: | ||
111 | ✗ | void _write(std::ostream&) const { | |
112 | ✗ | throw InvalidState("VTKHDFImageGridWriter does not support export into stream"); | |
113 | } | ||
114 | |||
115 | 63 | std::string _write([[maybe_unused]] double t) { | |
116 | if constexpr (!is_transient) | ||
117 | throw InvalidState("This overload only works for transient output"); | ||
118 | |||
119 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 48 times.
|
63 | if (this->_step_count == 0) |
120 |
1/2✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
|
15 | HDF5File::clear(_timeseries_filename, _comm); |
121 | |||
122 |
1/2✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
|
63 | HDF5File file{_timeseries_filename, _comm, HDF5File::Mode::append}; |
123 |
1/2✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
|
63 | _write_to(file); |
124 |
2/4✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 63 times.
✗ Branch 5 not taken.
|
63 | file.write_attribute(this->_step_count+1, "/VTKHDF/Steps/NSteps"); |
125 |
2/4✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 63 times.
✗ Branch 6 not taken.
|
189 | file.write(std::array{t}, "/VTKHDF/Steps/Values"); |
126 |
1/2✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
|
126 | return _timeseries_filename; |
127 | 63 | } | |
128 | |||
129 | 174 | void _write(const std::string& filename_with_ext) const { | |
130 | if constexpr (is_transient) | ||
131 | throw InvalidState("This overload only works for non-transient output"); | ||
132 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
174 | HDF5File file{filename_with_ext, _comm, HDF5File::Mode::overwrite}; |
133 |
1/2✓ Branch 1 taken 92 times.
✗ Branch 2 not taken.
|
174 | _write_to(file); |
134 | 174 | } | |
135 | |||
136 | 274 | void _write_to(HDF5File& file) const { | |
137 |
6/10✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 22 times.
✓ Branch 7 taken 133 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 21 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
|
274 | const ImageSpecs my_specs{origin(this->grid()), spacing(this->grid()), extents(this->grid())}; |
138 |
1/2✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
|
274 | const auto [overall_specs, my_offset] = _get_image_specs(my_specs); |
139 | 274 | const auto cell_slice_base = _make_slice( | |
140 |
1/2✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
|
274 | overall_specs.extents, |
141 | my_specs.extents, | ||
142 | my_offset | ||
143 | ); | ||
144 | |||
145 | // in order to avoid overlapping hyperslabs for point data in parallel I/O, | ||
146 | // we only write the last entries of the slab (per direction) when our portion | ||
147 | // of the image is the last portion of the overall image in that direction. | ||
148 |
1/2✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
|
274 | const auto my_point_extents = Ranges::to_array<dim>( |
149 |
1/2✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
|
274 | std::views::iota(std::size_t{0}, dim) |
150 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
866 | | std::views::transform([&] (std::size_t dir) { |
151 | 390 | const auto overall_end = overall_specs.extents[dir]; | |
152 | 390 | const auto my_end = my_specs.extents[dir] + my_offset[dir]; | |
153 |
8/8✓ Branch 0 taken 23 times.
✓ Branch 1 taken 98 times.
✓ Branch 4 taken 45 times.
✓ Branch 5 taken 174 times.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 24 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 16 times.
|
390 | return my_end < overall_end ? my_specs.extents[dir] : my_specs.extents[dir] + 1; |
154 | })); | ||
155 | 274 | const auto point_slice_base = _make_slice<true>( | |
156 |
1/2✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
|
274 | overall_specs.extents, |
157 | my_point_extents, | ||
158 | my_offset | ||
159 | ); | ||
160 | |||
161 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
548 | file.write_attribute(std::array<std::size_t, 2>{(is_transient ? 2 : 1), 0}, "/VTKHDF/Version"); |
162 |
3/6✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 155 times.
✗ Branch 8 not taken.
|
548 | file.write_attribute(Ranges::to_array<vtk_space_dim>(overall_specs.origin), "/VTKHDF/Origin"); |
163 |
3/6✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 155 times.
✗ Branch 8 not taken.
|
548 | file.write_attribute(Ranges::to_array<vtk_space_dim>(overall_specs.spacing), "/VTKHDF/Spacing"); |
164 |
3/6✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 155 times.
✗ Branch 8 not taken.
|
548 | file.write_attribute(VTK::CommonDetail::get_extents(overall_specs.extents), "/VTKHDF/WholeExtent"); |
165 |
3/6✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 155 times.
✗ Branch 8 not taken.
|
548 | file.write_attribute(_get_direction(), "/VTKHDF/Direction"); |
166 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
274 | file.write_attribute("ImageData", "/VTKHDF/Type"); |
167 | |||
168 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
367 | std::ranges::for_each(this->_meta_data_field_names(), [&] (const std::string& name) { |
169 | if constexpr (is_transient) { | ||
170 |
3/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
|
144 | if (this->_step_count > 0 && _transient_opts.static_meta_data) { |
171 | ✗ | file.write(std::array{0}, "/VTKHDF/Steps/FieldDataOffsets/" + name); | |
172 | ✗ | return; | |
173 | } else { | ||
174 |
2/4✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
|
144 | file.write(std::array{this->_step_count}, "/VTKHDF/Steps/FieldDataOffsets/" + name); |
175 | } | ||
176 |
1/2✓ Branch 1 taken 144 times.
✗ Branch 2 not taken.
|
144 | auto field_ptr = this->_get_meta_data_field_ptr(name); |
177 |
2/4✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
|
144 | auto sub = make_field_ptr(TransformedField{field_ptr, FieldTransformation::as_sub_field}); |
178 |
3/6✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 144 times.
✗ Branch 10 not taken.
|
144 | _write_field(file, sub, "/VTKHDF/FieldData/" + name, _slice_from(sub)); |
179 | 144 | } else { | |
180 |
1/8✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
18 | auto field_ptr = this->_get_meta_data_field_ptr(name); |
181 |
3/24✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 18 times.
✗ Branch 10 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
|
18 | _write_field(file, field_ptr, "/VTKHDF/FieldData/" + name, _slice_from(field_ptr)); |
182 | 18 | } | |
183 | |||
184 | }); | ||
185 | |||
186 | 274 | std::vector<std::size_t> non_zero_extents; | |
187 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
548 | std::ranges::copy( |
188 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
664 | my_specs.extents | std::views::filter([] (auto e) { return e != 0; }), |
189 | std::back_inserter(non_zero_extents) | ||
190 | ); | ||
191 | |||
192 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
1099 | std::ranges::for_each(this->_point_field_names(), [&] (const std::string& name) { |
193 |
4/8✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 468 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
|
825 | auto field_ptr = _reshape( |
194 |
8/16✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 243 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 468 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 468 times.
✗ Branch 15 not taken.
✓ Branch 21 taken 72 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 72 times.
✗ Branch 25 not taken.
✓ Branch 31 taken 42 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 42 times.
✗ Branch 35 not taken.
|
1650 | VTK::make_vtk_field(this->_get_point_field_ptr(name)), |
195 |
4/8✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 468 times.
✗ Branch 9 not taken.
✓ Branch 15 taken 72 times.
✗ Branch 16 not taken.
✓ Branch 22 taken 42 times.
✗ Branch 23 not taken.
|
1650 | Ranges::incremented(non_zero_extents, 1) | std::views::reverse, |
196 |
4/8✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 468 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 72 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 42 times.
✗ Branch 11 not taken.
|
825 | point_slice_base.count |
197 | ); | ||
198 |
8/16✓ Branch 1 taken 243 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 243 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 468 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 468 times.
✗ Branch 17 not taken.
✓ Branch 23 taken 72 times.
✗ Branch 24 not taken.
✓ Branch 27 taken 72 times.
✗ Branch 28 not taken.
✓ Branch 34 taken 42 times.
✗ Branch 35 not taken.
✓ Branch 38 taken 42 times.
✗ Branch 39 not taken.
|
825 | _write_field(file, field_ptr, "/VTKHDF/PointData/" + name, point_slice_base); |
199 | 825 | }); | |
200 | |||
201 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
553 | std::ranges::for_each(this->_cell_field_names(), [&] (const std::string& name) { |
202 |
2/8✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
279 | auto field_ptr = _reshape( |
203 |
4/16✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 129 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 150 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 150 times.
✗ Branch 15 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
|
558 | VTK::make_vtk_field(this->_get_cell_field_ptr(name)), |
204 | ✗ | non_zero_extents | std::views::reverse, | |
205 |
2/8✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
279 | cell_slice_base.count |
206 | ); | ||
207 |
4/16✓ Branch 1 taken 129 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 129 times.
✗ Branch 6 not taken.
✓ Branch 12 taken 150 times.
✗ Branch 13 not taken.
✓ Branch 16 taken 150 times.
✗ Branch 17 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
|
279 | _write_field(file, field_ptr, "/VTKHDF/CellData/" + name, cell_slice_base); |
208 | 279 | }); | |
209 | 274 | } | |
210 | |||
211 | template<std::ranges::range E, std::ranges::range S> | ||
212 | 2208 | FieldPtr _reshape(FieldPtr f, const E& row_major_extents, S&& _slice_end) const { | |
213 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | auto flat = _flatten(f); |
214 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | auto structured = _make_structured(flat, row_major_extents); |
215 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | const auto structured_layout = structured->layout(); |
216 | |||
217 | 2208 | std::vector<std::size_t> slice_end; | |
218 |
2/4✓ Branch 1 taken 1104 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1104 times.
✗ Branch 5 not taken.
|
2208 | std::ranges::copy(_slice_end, std::back_inserter(slice_end)); |
219 |
3/4✓ Branch 2 taken 1812 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 708 times.
✓ Branch 5 taken 1104 times.
|
3624 | for (std::size_t i = slice_end.size(); i < structured_layout.dimension(); ++i) |
220 |
2/4✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 708 times.
✗ Branch 5 not taken.
|
1416 | slice_end.push_back(structured_layout.extent(i)); |
221 | 4416 | return transform(structured, FieldTransformation::take_slice({ | |
222 | 2208 | .from = std::vector<std::size_t>(slice_end.size(), 0), | |
223 | .to = slice_end | ||
224 |
1/2✓ Branch 1 taken 1104 times.
✗ Branch 2 not taken.
|
4416 | })); |
225 |
2/6✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1104 times.
✗ Branch 6 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
|
4416 | } |
226 | |||
227 | 1986 | FieldPtr _flatten(FieldPtr f) const { | |
228 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
1986 | const auto layout = f->layout(); |
229 |
3/4✓ Branch 1 taken 1104 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 756 times.
✓ Branch 4 taken 348 times.
|
1986 | if (layout.dimension() <= 2) |
230 | 1350 | return f; | |
231 | // vtk requires tensors to be made flat | ||
232 |
3/6✓ Branch 1 taken 348 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 348 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 348 times.
✗ Branch 8 not taken.
|
636 | auto nl = MDLayout{{layout.extent(0), layout.number_of_entries(1)}}; |
233 |
3/6✓ Branch 2 taken 348 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 348 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 348 times.
✗ Branch 10 not taken.
|
636 | return transform(f, FieldTransformation::reshape_to(std::move(nl))); |
234 | 1986 | } | |
235 | |||
236 | template<std::ranges::range E> | ||
237 | 2208 | FieldPtr _make_structured(FieldPtr f, const E& row_major_extents) const { | |
238 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | const auto layout = f->layout(); |
239 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | std::vector<std::size_t> target_layout(Ranges::size(row_major_extents)); |
240 |
1/2✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
|
2208 | std::ranges::copy(row_major_extents, target_layout.begin()); |
241 |
3/4✓ Branch 1 taken 1104 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 708 times.
✓ Branch 4 taken 396 times.
|
2208 | if (layout.dimension() > 1) |
242 |
2/4✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 708 times.
✗ Branch 5 not taken.
|
1416 | target_layout.push_back(layout.extent(1)); |
243 |
3/6✓ Branch 2 taken 1104 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1104 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 1104 times.
✗ Branch 10 not taken.
|
4416 | return transform(f, FieldTransformation::reshape_to(MDLayout{std::move(target_layout)})); |
244 | 2208 | } | |
245 | |||
246 | 274 | auto _get_image_specs(const ImageSpecs& piece_specs) const { | |
247 | using OffsetType = std::ranges::range_value_t<decltype(piece_specs.extents)>; | ||
248 |
2/2✓ Branch 1 taken 108 times.
✓ Branch 2 taken 47 times.
|
274 | if (Parallel::size(_comm) > 1) { |
249 | 192 | PVTK::StructuredParallelGridHelper helper{_comm}; | |
250 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | const auto all_origins = Parallel::gather(_comm, piece_specs.origin, root_rank); |
251 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | const auto all_extents = Parallel::gather(_comm, piece_specs.extents, root_rank); |
252 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | const auto is_negative_axis = VTK::CommonDetail::structured_grid_axis_orientation(piece_specs.spacing); |
253 |
2/3✓ Branch 1 taken 96 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
360 | const auto [exts_begin, exts_end, whole_extent, origin] = helper.compute_extents_and_origin( |
254 | all_origins, | ||
255 | all_extents, | ||
256 | is_negative_axis, | ||
257 |
1/2✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
|
360 | basis(this->grid()) |
258 | ); | ||
259 | |||
260 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | const auto my_whole_extent = Parallel::broadcast(_comm, whole_extent, root_rank); |
261 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | const auto my_whole_origin = Parallel::broadcast(_comm, origin, root_rank); |
262 |
2/4✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 108 times.
✗ Branch 5 not taken.
|
192 | const auto my_extent_offset = Parallel::scatter(_comm, Ranges::flat(exts_begin), root_rank); |
263 | ✗ | return std::make_tuple( | |
264 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | ImageSpecs{my_whole_origin, piece_specs.spacing, my_whole_extent}, |
265 | my_extent_offset | ||
266 |
1/2✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
|
192 | ); |
267 | 192 | } else { | |
268 |
1/2✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
|
82 | return std::make_tuple(piece_specs, std::vector<OffsetType>(dim, 0)); |
269 | } | ||
270 | } | ||
271 | |||
272 | template<bool increment = false, typename TotalExtents, typename Extents, typename Offsets> | ||
273 | 620 | HDF5::Slice _make_slice(const TotalExtents& total_extents, | |
274 | const Extents& extents, | ||
275 | const Offsets& offsets) const { | ||
276 | 620 | HDF5::Slice result; | |
277 | 620 | result.total_size.emplace(); | |
278 | |||
279 | // use only those dimensions that are not zero | ||
280 | 620 | std::vector<bool> is_nonzero; | |
281 |
2/4✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 310 times.
✗ Branch 5 not taken.
|
1240 | std::ranges::copy( |
282 |
2/4✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 310 times.
✗ Branch 5 not taken.
|
1400 | total_extents | std::views::transform([] (const auto& v) { return v != 0; }), |
283 | std::back_inserter(is_nonzero) | ||
284 | ); | ||
285 |
1/2✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
|
1400 | std::ranges::for_each(total_extents, [&, i=0] (const auto& value) mutable { |
286 |
16/32✓ Branch 1 taken 121 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 121 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 121 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 219 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 219 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 219 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 219 times.
✗ Branch 26 not taken.
✓ Branch 29 taken 29 times.
✗ Branch 30 not taken.
✓ Branch 32 taken 29 times.
✗ Branch 33 not taken.
✓ Branch 36 taken 29 times.
✗ Branch 37 not taken.
✓ Branch 39 taken 29 times.
✗ Branch 40 not taken.
✓ Branch 43 taken 21 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 21 times.
✗ Branch 47 not taken.
✓ Branch 50 taken 21 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 21 times.
✗ Branch 54 not taken.
|
780 | if (is_nonzero[i++]) |
287 |
8/16✓ Branch 2 taken 121 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 121 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 219 times.
✗ Branch 11 not taken.
✓ Branch 14 taken 219 times.
✗ Branch 15 not taken.
✓ Branch 18 taken 29 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 29 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 21 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 21 times.
✗ Branch 31 not taken.
|
780 | result.total_size.value().push_back(value + (increment ? 1 : 0)); |
288 | }); | ||
289 |
1/2✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
|
1400 | std::ranges::for_each(extents, [&, i=0] (const auto& value) mutable { |
290 |
16/32✓ Branch 1 taken 121 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 121 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 121 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 219 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 219 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 219 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 219 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 29 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 29 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 29 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 29 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 21 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 21 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 21 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 21 times.
✗ Branch 47 not taken.
|
780 | if (is_nonzero[i++]) |
291 | 780 | result.count.push_back(value); | |
292 | }); | ||
293 |
1/2✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
|
1400 | std::ranges::for_each(offsets, [&, i=0] (const auto& value) mutable { |
294 |
16/32✓ Branch 1 taken 121 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 121 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 121 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 121 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 219 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 219 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 219 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 219 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 29 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 29 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 29 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 29 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 21 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 21 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 21 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 21 times.
✗ Branch 47 not taken.
|
780 | if (is_nonzero[i++]) |
295 | 780 | result.offset.push_back(value); | |
296 | }); | ||
297 | |||
298 | // slices in VTK are accessed with the last coordinate first (i.e. values[z][y][x]) | ||
299 |
2/4✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 310 times.
✗ Branch 5 not taken.
|
620 | std::ranges::reverse(result.total_size.value()); |
300 |
1/2✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
|
620 | std::ranges::reverse(result.count); |
301 |
1/2✓ Branch 1 taken 310 times.
✗ Branch 2 not taken.
|
620 | std::ranges::reverse(result.offset); |
302 | |||
303 | 620 | return result; | |
304 | 620 | } | |
305 | |||
306 | 274 | auto _get_direction() const { | |
307 | using T = MDRangeScalar<decltype(basis(this->grid()))>; | ||
308 | std::array<T, vtk_space_dim*vtk_space_dim> coefficients; | ||
309 |
1/2✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
|
274 | std::ranges::fill(coefficients, T{0}); |
310 |
2/4✓ Branch 1 taken 155 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 155 times.
✗ Branch 5 not taken.
|
274 | std::ranges::for_each( |
311 |
3/5✓ Branch 1 taken 141 times.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 141 times.
✗ Branch 5 not taken.
|
274 | Matrix{basis(this->grid())}.transposed(), |
312 | 910 | [it = coefficients.begin()] (const std::ranges::range auto& row) mutable { | |
313 | 390 | std::ranges::copy(row, it); | |
314 | 390 | std::advance(it, vtk_space_dim); | |
315 | } | ||
316 | ); | ||
317 | 274 | return coefficients; | |
318 | } | ||
319 | |||
320 | 2232 | void _write_field(HDF5File& file, | |
321 | FieldPtr field, | ||
322 | const std::string& path, | ||
323 | const HDF5::Slice& slice) const { | ||
324 | 2232 | const std::size_t dimension_offset = is_transient ? 1 : 0; | |
325 |
2/4✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1266 times.
✗ Branch 6 not taken.
|
4464 | std::vector<std::size_t> size(slice.total_size.value().size() + dimension_offset); |
326 |
1/2✓ Branch 2 taken 1266 times.
✗ Branch 3 not taken.
|
4464 | std::vector<std::size_t> count(slice.count.size() + dimension_offset); |
327 |
1/2✓ Branch 2 taken 1266 times.
✗ Branch 3 not taken.
|
2232 | std::vector<std::size_t> offset(slice.offset.size() + dimension_offset); |
328 |
5/10✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1266 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1266 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1266 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1266 times.
✗ Branch 14 not taken.
|
2232 | std::ranges::copy(slice.total_size.value(), std::ranges::begin(size | std::views::drop(dimension_offset))); |
329 |
4/8✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1266 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1266 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1266 times.
✗ Branch 11 not taken.
|
2232 | std::ranges::copy(slice.count, std::ranges::begin(count | std::views::drop(dimension_offset))); |
330 |
4/8✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1266 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1266 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1266 times.
✗ Branch 11 not taken.
|
2232 | std::ranges::copy(slice.offset, std::ranges::begin(offset | std::views::drop(dimension_offset))); |
331 | |||
332 |
1/2✓ Branch 2 taken 1266 times.
✗ Branch 3 not taken.
|
2232 | const auto layout = field->layout(); |
333 |
1/2✓ Branch 1 taken 1266 times.
✗ Branch 2 not taken.
|
2232 | const bool is_vector_field = layout.dimension() > size.size() - dimension_offset; |
334 |
2/2✓ Branch 0 taken 708 times.
✓ Branch 1 taken 558 times.
|
2232 | if (is_vector_field) |
335 |
1/2✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
|
1296 | std::ranges::for_each( |
336 |
2/4✓ Branch 1 taken 708 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 708 times.
✗ Branch 6 not taken.
|
2592 | std::views::iota(size.size() - dimension_offset, layout.dimension()), |
337 | 1416 | [&] (const std::size_t codim) { | |
338 |
8/16✓ Branch 1 taken 220 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 220 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 412 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 412 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 48 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 48 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 28 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 28 times.
✗ Branch 26 not taken.
|
708 | size.push_back(layout.extent(codim)); |
339 |
8/16✓ Branch 1 taken 220 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 220 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 412 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 412 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 48 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 48 times.
✗ Branch 19 not taken.
✓ Branch 22 taken 28 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 28 times.
✗ Branch 26 not taken.
|
708 | count.push_back(layout.extent(codim)); |
340 |
4/8✓ Branch 1 taken 220 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 412 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 48 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 28 times.
✗ Branch 11 not taken.
|
708 | offset.push_back(0); |
341 | } | ||
342 | ); | ||
343 | |||
344 | if constexpr (is_transient) { | ||
345 |
1/2✓ Branch 1 taken 690 times.
✗ Branch 2 not taken.
|
1095 | size.at(0) = 1; |
346 |
1/2✓ Branch 1 taken 690 times.
✗ Branch 2 not taken.
|
1095 | count.at(0) = 1; |
347 |
1/2✓ Branch 1 taken 690 times.
✗ Branch 2 not taken.
|
1095 | offset.at(0) = 0; |
348 |
1/2✓ Branch 2 taken 690 times.
✗ Branch 3 not taken.
|
1095 | FieldPtr sub_field = transform(field, FieldTransformation::as_sub_field); |
349 |
1/2✓ Branch 2 taken 690 times.
✗ Branch 3 not taken.
|
1095 | file.write(*sub_field, path, HDF5::Slice{ |
350 | 1095 | .offset = std::move(offset), | |
351 | 1095 | .count = std::move(count), | |
352 | 1095 | .total_size = std::move(size) | |
353 | }); | ||
354 | 1095 | } else { | |
355 |
1/2✓ Branch 2 taken 576 times.
✗ Branch 3 not taken.
|
1137 | file.write(*field, path, HDF5::Slice{ |
356 | 1137 | .offset = std::move(offset), | |
357 | 1137 | .count = std::move(count), | |
358 | 1137 | .total_size = std::move(size) | |
359 | }); | ||
360 | } | ||
361 |
0/4✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
4464 | } |
362 | |||
363 | 246 | HDF5::Slice _slice_from(FieldPtr field) const { | |
364 |
1/2✓ Branch 2 taken 162 times.
✗ Branch 3 not taken.
|
246 | const auto layout = field->layout(); |
365 |
2/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
|
492 | std::vector<std::size_t> dims(layout.dimension()); |
366 |
2/4✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 162 times.
✗ Branch 5 not taken.
|
246 | std::vector<std::size_t> offset(layout.dimension(), 0); |
367 |
1/2✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
|
246 | layout.export_to(dims); |
368 | return { | ||
369 | 246 | .offset = std::move(offset), | |
370 | .count = dims, | ||
371 | .total_size = dims | ||
372 | 246 | }; | |
373 |
2/8✓ Branch 3 taken 162 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 162 times.
✗ Branch 7 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
|
246 | } |
374 | |||
375 | Communicator _comm; | ||
376 | std::string _timeseries_filename = ""; | ||
377 | VTK::HDFTransientOptions _transient_opts; | ||
378 | }; | ||
379 | |||
380 | /*! | ||
381 | * \ingroup VTK | ||
382 | * \brief Writer for the VTK HDF file format for image grids. | ||
383 | */ | ||
384 | template<Concepts::ImageGrid G, Concepts::Communicator C = NullCommunicator> | ||
385 | class VTKHDFImageGridWriter : public VTKHDFImageGridWriterImpl<false, G, C> { | ||
386 | using ParentType = VTKHDFImageGridWriterImpl<false, G, C>; | ||
387 | public: | ||
388 | using ParentType::ParentType; | ||
389 | }; | ||
390 | |||
391 | /*! | ||
392 | * \ingroup VTK | ||
393 | * \brief Writer for the transient VTK HDF file format for image grids. | ||
394 | */ | ||
395 | template<Concepts::ImageGrid G, Concepts::Communicator C = NullCommunicator> | ||
396 | class VTKHDFImageGridTimeSeriesWriter : public VTKHDFImageGridWriterImpl<true, G, C> { | ||
397 | using ParentType = VTKHDFImageGridWriterImpl<true, G, C>; | ||
398 | public: | ||
399 | using ParentType::ParentType; | ||
400 | }; | ||
401 | |||
402 | template<Concepts::ImageGrid G> | ||
403 | VTKHDFImageGridWriter(const G&) -> VTKHDFImageGridWriter<G, NullCommunicator>; | ||
404 | template<Concepts::ImageGrid G, Concepts::Communicator C> | ||
405 | VTKHDFImageGridWriter(const G&, const C&) -> VTKHDFImageGridWriter<G, C>; | ||
406 | |||
407 | template<Concepts::ImageGrid G> | ||
408 | VTKHDFImageGridTimeSeriesWriter(const G&, std::string, VTK::HDFTransientOptions = {}) -> VTKHDFImageGridTimeSeriesWriter<G, NullCommunicator>; | ||
409 | template<Concepts::ImageGrid G, Concepts::Communicator C> | ||
410 | VTKHDFImageGridTimeSeriesWriter(const G&, const C&, std::string, VTK::HDFTransientOptions = {}) -> VTKHDFImageGridTimeSeriesWriter<G, C>; | ||
411 | |||
412 | |||
413 | namespace Traits { | ||
414 | |||
415 | template<typename... Args> | ||
416 | struct WritesConnectivity<VTKHDFImageGridWriter<Args...>> : public std::false_type {}; | ||
417 | |||
418 | template<typename... Args> | ||
419 | struct WritesConnectivity<VTKHDFImageGridTimeSeriesWriter<Args...>> : public std::false_type {}; | ||
420 | |||
421 | } // namespace Traits | ||
422 | } // namespace GridFormat | ||
423 | |||
424 | #endif // GRIDFORMAT_HAVE_HIGH_FIVE | ||
425 | #endif // GRIDFORMAT_VTK_HDF_IMAGE_GRID_WRITER_HPP_ | ||
426 |