GridFormat 0.4.0
I/O-Library for grid-like data structures
Loading...
Searching...
No Matches
hdf_common.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2// SPDX-License-Identifier: MIT
3
9#ifndef GRIDFORMAT_VTK_HDF_COMMON_HPP_
10#define GRIDFORMAT_VTK_HDF_COMMON_HPP_
11
12#include <vector>
13#include <cstddef>
14#include <numeric>
15#include <string>
16
17#include <gridformat/common/hdf5.hpp>
18#include <gridformat/common/lazy_field.hpp>
19#include <gridformat/common/string_conversion.hpp>
20
21namespace GridFormat {
22
23namespace VTK {
24
27 bool static_grid = false;
28 bool static_meta_data = true;
29};
30
31} // namespace VTK
32
33
34namespace VTKHDF {
35
37struct IOContext {
38 const int my_rank;
39 const int num_ranks;
40 const bool is_parallel;
41 const std::vector<std::size_t> rank_cells;
42 const std::vector<std::size_t> rank_points;
43 const std::size_t num_cells_total;
44 const std::size_t num_points_total;
45 const std::size_t my_cell_offset;
46 const std::size_t my_point_offset;
47
48 IOContext(int _my_rank,
49 int _num_ranks,
50 std::vector<std::size_t> _rank_cells,
51 std::vector<std::size_t> _rank_points)
52 : my_rank{_my_rank}
53 , num_ranks{_num_ranks}
54 , is_parallel{_num_ranks > 1}
55 , rank_cells{std::move(_rank_cells)}
56 , rank_points{std::move(_rank_points)}
57 , num_cells_total{_accumulate(rank_cells)}
58 , num_points_total{_accumulate(rank_points)}
59 , my_cell_offset{_accumulate_rank_offset(rank_cells)}
60 , my_point_offset{_accumulate_rank_offset(rank_points)} {
61 if (my_rank >= num_ranks)
62 throw ValueError(as_error("Given rank is not within communicator size"));
63 if (num_ranks != static_cast<int>(rank_cells.size()))
64 throw ValueError(as_error("Cells vector does not match communicator size"));
65 if (num_ranks != static_cast<int>(rank_points.size()))
66 throw ValueError(as_error("Points vector does not match communicator size"));
67 }
68
69 template<Concepts::Grid Grid, Concepts::Communicator Communicator>
70 static IOContext from(const Grid& grid, const Communicator& comm, int root_rank = 0) {
71 const int size = Parallel::size(comm);
72 const int rank = Parallel::rank(comm);
73 const std::size_t num_points = number_of_points(grid);
74 const std::size_t num_cells = number_of_cells(grid);
75 if (size == 1)
76 return IOContext{rank, size, std::vector{num_cells}, std::vector{num_points}};
77
78 const auto all_num_points = Parallel::gather(comm, num_points, root_rank);
79 const auto all_num_cells = Parallel::gather(comm, num_cells, root_rank);
80 const auto my_all_num_points = Parallel::broadcast(comm, all_num_points, root_rank);
81 const auto my_all_num_cells = Parallel::broadcast(comm, all_num_cells, root_rank);
82 return IOContext{rank, size, my_all_num_cells, my_all_num_points};
83 }
84
85 private:
86 std::size_t _accumulate(const std::vector<std::size_t>& in) const {
87 return std::accumulate(in.begin(), in.end(), std::size_t{0});
88 }
89
90 std::size_t _accumulate_rank_offset(const std::vector<std::size_t>& in) const {
91 if (in.size() <= static_cast<std::size_t>(my_rank))
92 throw ValueError("Rank-vector length must be equal to number of ranks");
93 return std::accumulate(in.begin(), std::next(in.begin(), my_rank), std::size_t{0});
94 }
95};
96
97#if GRIDFORMAT_HAVE_HIGH_FIVE
98
103template<typename C>
104class DataSetField : public LazyField<const HDF5::File<C>&> {
105 using ParentType = LazyField<const HDF5::File<C>&>;
106
107 public:
108 using ParentType::ParentType;
109
110 explicit DataSetField(const HDF5::File<C>& file, std::string path)
111 : ParentType{
112 file,
113 MDLayout{file.get_dimensions(path).value()},
114 DynamicPrecision{file.get_precision(path).value()},
115 [_p=std::move(path)] (const HDF5::File<C>& file) {
116 return file.visit_dataset(_p, [&] <typename F> (F&& field) {
117 return field.serialized();
118 });
119 }
120 } {}
121};
122
123template<typename C>
124DataSetField(const HDF5::File<C>&, std::string) -> DataSetField<C>;
125
126template<typename C, typename CB>
127DataSetField(const HDF5::File<C>&, MDLayout, DynamicPrecision, CB&&) -> DataSetField<C>;
128
130template<typename C>
131std::string get_file_type(const HDF5::File<C>& file) {
132 if (!file.exists("/VTKHDF"))
133 throw IOError("Given file is not a VTK-HDF file");
134 if (!file.has_attribute_at("/VTKHDF/Type"))
135 throw IOError("VTKHDF-Type attribute missing");
136 return file.template read_attribute_to<std::string>("/VTKHDF/Type");
137}
138
140template<typename C>
141void check_version_compatibility(const HDF5::File<C>& file, const std::array<std::size_t, 2>& supported) {
142 if (file.has_attribute_at("/VTKHDF/Version"))
143 file.visit_attribute("/VTKHDF/Version", [&] (auto&& field) {
144 const auto version = field.template export_to<std::vector<std::size_t>>();
145 if ((version.size() > 0 && version.at(0) > supported[0]) ||
146 (version.size() > 1 && version.at(0) == supported[0] && version.at(1) > supported[1]))
147 throw ValueError(
148 "File version is higher than supported by the reader (" + as_string(supported, ".") + ")"
149 );
150 });
151}
152
153#endif // GRIDFORMAT_HAVE_HIGH_FIVE
154
155} // namespace VTKHDF
156} // namespace GridFormat
157
158#endif // GRIDFORMAT_VTK_HDF_COMMON_HPP_
Field implementation that draws values from an open HDF5 file upon request.
Definition: hdf_common.hpp:104
void check_version_compatibility(const HDF5::File< C > &file, const std::array< std::size_t, 2 > &supported)
Check that the version stated in the file is supported.
Definition: hdf_common.hpp:141
std::string get_file_type(const HDF5::File< C > &file)
Read the vtk-hdf file type from an hdf5 file.
Definition: hdf_common.hpp:131
Helper class to store processor offsets in parallel writes.
Definition: hdf_common.hpp:37
Options for transient vtk-hdf file formats.
Definition: hdf_common.hpp:26
bool static_grid
Set to true the grid is the same for all time steps (will only be written once)
Definition: hdf_common.hpp:27
bool static_meta_data
Set to true if the metadata is same for all time steps (will only be written once)
Definition: hdf_common.hpp:28