Tatooine
vtr_writer.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_RECTILINEAR_GRID_VTR_WRITER_H
2#define TATOOINE_DETAIL_RECTILINEAR_GRID_VTR_WRITER_H
3//==============================================================================
4#include <tatooine/concepts.h>
6#include <tatooine/linspace.h>
7#include <tatooine/vtk/xml.h>
8
9#include <array>
10#include <vector>
11//==============================================================================
13//==============================================================================
14template <typename Grid, unsigned_integral HeaderType>
15requires(Grid::num_dimensions() == 2 || Grid::num_dimensions() == 3)
16struct vtr_writer {
17 static auto constexpr num_dimensions() { return Grid::num_dimensions(); }
18 using vertex_property_type = typename Grid::vertex_property_type;
19 template <typename T, bool H>
21 typename Grid::template typed_vertex_property_interface_type<T, H>;
22 //----------------------------------------------------------------------------
23 Grid const& m_grid;
24 //----------------------------------------------------------------------------
25 auto write(filesystem::path const& path) const {
26 auto file = std::ofstream{path};
27 if (!file.is_open()) {
28 throw std::runtime_error{"Could open file " + path.string() +
29 " for writing."};
30 }
31 auto offset = std::size_t{};
32 write_vtk_file(file, offset);
33 }
34 //----------------------------------------------------------------------------
35 private:
36 auto write_vtk_file(std::ofstream& file, auto& offset) const {
37 file << "<VTKFile"
38 << " type=\"RectilinearGrid\""
39 << " version=\"1.0\""
40 << " byte_order=\"LittleEndian\""
41 << " header_type=\""
43 tatooine::vtk::xml::to_data_type<HeaderType>())
44 << "\">\n";
45 write_rectilinear_grid(file, offset);
46 write_appended_data(file);
47 file << "</VTKFile>";
48 }
49 //----------------------------------------------------------------------------
50 auto write_rectilinear_grid(std::ofstream& file, auto& offset) const {
51 file << " <RectilinearGrid WholeExtent=\"" << 0 << " "
52 << m_grid.template size<0>() - 1 << " " << 0 << " "
53 << m_grid.template size<1>() - 1;
54 if constexpr (num_dimensions() >= 3) {
55 file << " " << 0 << " " << m_grid.template size<2>() - 1;
56 } else {
57 file << " " << 0 << " " << 0;
58 }
59 file << "\">\n";
60 write_piece(file, offset);
61 file << " </RectilinearGrid>\n";
62 }
63 //----------------------------------------------------------------------------
64 auto write_piece(std::ofstream& file, auto& offset) const {
65 file << " <Piece Extent=\"" << 0 << " " << m_grid.template size<0>() - 1
66 << " " << 0 << " " << m_grid.template size<1>() - 1 << " ";
67 if constexpr (num_dimensions() >= 3) {
68 file << 0 << " " << m_grid.template size<2>() - 1;
69 } else {
70 file << 0 << " " << 0;
71 }
72 file << "\">\n";
73 {
74 write_point_data(file, offset);
75 write_cell_data(file, offset);
76 write_coordinates(file, offset);
77 }
78 file << " </Piece>\n";
79 }
80 //------------------------------------------------------------------------------
81 auto write_point_data(std::ofstream& file, std::size_t& offset) const {
82 file << " <PointData>\n";
83 for (auto const& [name, prop] : m_grid.vertex_properties()) {
84 write_vertex_property_data_array<HeaderType, float, double, vec2f, vec2d,
87 name, *prop, file, offset);
88 }
89 file << " </PointData>\n";
90 }
91 //------------------------------------------------------------------------------
92 auto write_cell_data(std::ofstream& file, std::size_t& /*offset*/) const {
93 file << " <CellData>\n";
94 file << " </CellData>\n";
95 }
96 //----------------------------------------------------------------------------
97 auto write_coordinates(std::ofstream& file, std::size_t& offset) const {
98 file << " <Coordinates>\n";
99 write_dimension_data_array(m_grid.template dimension<0>(), "x_coordinates",
100 file, offset);
101 write_dimension_data_array(m_grid.template dimension<1>(), "y_coordinates",
102 file, offset);
103 if constexpr (num_dimensions() >= 3) {
104 write_dimension_data_array(m_grid.template dimension<2>(),
105 "z_coordinates", file, offset);
106 } else {
107 write_dimension_data_array(std::vector<typename Grid::real_type>{0},
108 "z_coordinates", file, offset);
109 }
110 file << " </Coordinates>\n";
111 }
112 //----------------------------------------------------------------------------
113 template <typename T>
114 auto write_dimension_data_array(std::vector<T> const& dim,
115 std::string const& name, std::ofstream& file,
116 std::size_t& offset) const {
117 file << " <DataArray"
118 << " type=\""
119 << tatooine::vtk::xml::to_string(tatooine::vtk::xml::to_data_type<T>())
120 << "\""
121 << " Name=\"" << name << "\""
122 << " format=\"appended\""
123 << " offset=\"" << offset << "\""
124 << "/>\n";
125 offset += dim.size() * sizeof(T) + sizeof(HeaderType);
126 }
127 //----------------------------------------------------------------------------
128 template <typename T, std::size_t N>
129 auto write_dimension_data_array(std::array<T, N> const& /*dim*/,
130 std::string const& name, std::ofstream& file,
131 std::size_t& offset) const {
132 file << " <DataArray"
133 << " type=\""
134 << tatooine::vtk::xml::to_string(tatooine::vtk::xml::to_data_type<T>())
135 << "\""
136 << " Name=\"" << name << "\""
137 << " format=\"appended\""
138 << " offset=\"" << offset << "\""
139 << "/>\n";
140 offset += N * sizeof(T) + sizeof(HeaderType);
141 }
142 //----------------------------------------------------------------------------
143 template <typename T>
145 std::string const& name, std::ofstream& file,
146 std::size_t& offset) const {
147 file << " <DataArray"
148 << " type=\""
149 << tatooine::vtk::xml::to_string(tatooine::vtk::xml::to_data_type<T>())
150 << "\""
151 << " Name=\"" << name << "\""
152 << " format=\"appended\""
153 << " offset=\"" << offset << "\""
154 << "/>\n";
155 file.flush();
156 offset += dim.size() * sizeof(T) + sizeof(HeaderType);
157 }
158 //----------------------------------------------------------------------------
159 auto write_appended_data(std::ofstream& file) const {
160 file << " <AppendedData encoding=\"raw\">\n _";
161 write_appended_data_point_data(file);
162 write_appended_data_cell_data(file);
163 write_appended_data_coordinates(file);
164 file << "\n </AppendedData>\n";
165 }
166 //----------------------------------------------------------------------------
167 auto write_appended_data_point_data(std::ofstream& file) const {
168 for (auto const& [name, prop] : m_grid.vertex_properties()) {
169 write_vertex_property_appended_data<
170 HeaderType, float, vec2f, vec3f, vec4f, mat2f, mat3f, mat4f, double,
171 vec2d, vec3d, vec4d, mat2d, mat3d, mat4d>(*prop, file);
172 }
173 }
174 //----------------------------------------------------------------------------
175 auto write_appended_data_cell_data(std::ofstream& /*file*/) const {}
176 //----------------------------------------------------------------------------
177 auto write_appended_data_coordinates(std::ofstream& file) const {
178 write_dimension_appended_data(m_grid.template dimension<0>(), file);
179 write_dimension_appended_data(m_grid.template dimension<1>(), file);
180 if constexpr (num_dimensions() >= 3) {
181 write_dimension_appended_data(m_grid.template dimension<2>(), file);
182 } else {
183 write_dimension_appended_data(std::vector{typename Grid::real_type(0)},
184 file);
185 }
186 }
187 //----------------------------------------------------------------------------
188 template <typename T>
189 auto write_dimension_appended_data(std::vector<T> const& dim,
190 std::ofstream& file) const {
191 auto const num_bytes = HeaderType(sizeof(T) * dim.size());
192 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
193 file.write(reinterpret_cast<char const*>(dim.data()), num_bytes);
194 }
195 //----------------------------------------------------------------------------
196 template <typename T, std::size_t N>
197 auto write_dimension_appended_data(std::array<T, N> const& dim,
198 std::ofstream& file) const {
199 auto const num_bytes = HeaderType(sizeof(T) * N);
200 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
201 file.write(reinterpret_cast<char const*>(dim.data()), num_bytes);
202 }
203 //----------------------------------------------------------------------------
204 template <typename T>
206 std::ofstream& file) const {
207 auto data = std::vector<T>(dim.size());
208 std::ranges::copy(dim, begin(data));
209 auto const num_bytes = HeaderType(sizeof(T) * data.size());
210 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
211 file.flush();
212 file.write(reinterpret_cast<char const*>(data.data()), num_bytes);
213 file.flush();
214 }
215 //----------------------------------------------------------------------------
216 template <typename... Ts>
218 std::ofstream& file) const {
219 invoke([&] {
220 if (prop.type() == typeid(Ts)) {
221 write_vertex_property_appended_data(prop.template cast_to_typed<Ts>(),
222 file);
223 }
224 }...);
225 }
226 //----------------------------------------------------------------------------
227 template <typename T, bool H>
230 std::ofstream& file) const {
231 if constexpr (tensor_rank<T> <= 1) {
232 auto data = std::vector<T>{};
233 m_grid.vertices().iterate_indices(
234 [&](auto const... is) { data.push_back(prop(is...)); });
235 auto const num_bytes =
236 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
237 m_grid.vertices().size());
238 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
239 file.write(reinterpret_cast<char const*>(data.data()), num_bytes);
240 } else if constexpr (tensor_rank<T> == 2) {
241 auto const num_bytes =
242 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
243 m_grid.vertices().size() / tensor_dimension<T, 0>);
244 for (std::size_t i = 0; i < tensor_dimension<T, 1>; ++i) {
245 file.write(reinterpret_cast<char const*>(&num_bytes),
246 sizeof(HeaderType));
247 m_grid.vertices().iterate_indices([&](auto const... is) {
248 auto data_begin = &prop(is...)(0, i);
249 file.write(reinterpret_cast<char const*>(data_begin),
250 sizeof(tatooine::value_type<T>) * tensor_dimension<T, 0>);
251 });
252 }
253 }
254 }
255 //----------------------------------------------------------------------------
256 template <typename... Ts>
257 auto write_vertex_property_data_array(auto const& name,
258 vertex_property_type const& prop,
259 std::ofstream& file,
260 std::size_t& offset) const {
261 invoke([&] {
262 if (prop.type() == typeid(Ts)) {
263 if constexpr (tensor_rank<Ts> <= 1) {
264 file << "<DataArray"
265 << " Name=\"" << name << "\""
266 << " format=\"appended\""
267 << " offset=\"" << offset << "\""
268 << " type=\""
269 << tatooine::vtk::xml::to_string(
270 tatooine::vtk::xml::to_data_type<tatooine::value_type<Ts>>())
271 << "\" NumberOfComponents=\""
272 << tensor_num_components<Ts> << "\"/>\n";
273 offset += m_grid.vertices().size() * sizeof(Ts) + sizeof(HeaderType);
274 } else if constexpr (tensor_rank<Ts> == 2) {
275 for (std::size_t i = 0; i < Ts::dimension(1); ++i) {
276 file << "<DataArray"
277 << " Name=\"" << name << "_col_" << i << "\""
278 << " format=\"appended\""
279 << " offset=\"" << offset << "\""
280 << " type=\""
283 << "\" NumberOfComponents=\"" << Ts::dimension(0) << "\"/>\n";
284 offset += m_grid.vertices().size() * sizeof(tatooine::value_type<Ts>) *
285 tensor_dimension<Ts, 0> +
286 sizeof(HeaderType);
287 }
288 }
289 }
290 }...);
291 }
292};
293//==============================================================================
294} // namespace tatooine::detail::rectilinear_grid
295//==============================================================================
296#endif
Definition: cell_container.h:15
auto begin(vertex_container< Dimensions... > const &c)
Definition: vertex_container.h:137
auto to_string(data_type const t) -> std::string_view
static auto constexpr to_data_type()
Definition: data_type.h:88
VecF< 3 > vec3f
Definition: vec_typedefs.h:40
typename value_type_impl< T >::type value_type
Definition: type_traits.h:280
mat44f mat4f
Definition: mat_typedefs.h:299
VecD< 3 > vec3d
Definition: vec_typedefs.h:51
mat22d mat2d
Definition: mat_typedefs.h:370
mat33d mat3d
Definition: mat_typedefs.h:371
constexpr auto invoke(invocable auto &&...funcs)
Definition: functional.h:8
mat33f mat3f
Definition: mat_typedefs.h:298
VecD< 2 > vec2d
Definition: vec_typedefs.h:50
VecF< 4 > vec4f
Definition: vec_typedefs.h:41
VecD< 4 > vec4d
Definition: vec_typedefs.h:52
mat22f mat2f
Definition: mat_typedefs.h:297
VecF< 2 > vec2f
Definition: vec_typedefs.h:39
auto write_vertex_property_appended_data(vertex_property_type const &prop, std::ofstream &file) const
Definition: vtr_writer.h:217
auto write_appended_data(std::ofstream &file) const
Definition: vtr_writer.h:159
auto write_dimension_appended_data(tatooine::linspace< T > const &dim, std::ofstream &file) const
Definition: vtr_writer.h:205
auto write_dimension_data_array(std::array< T, N > const &, std::string const &name, std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:129
auto write_dimension_data_array(std::vector< T > const &dim, std::string const &name, std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:114
auto write_dimension_appended_data(std::array< T, N > const &dim, std::ofstream &file) const
Definition: vtr_writer.h:197
auto write_coordinates(std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:97
auto write_appended_data_cell_data(std::ofstream &) const
Definition: vtr_writer.h:175
auto write_vtk_file(std::ofstream &file, auto &offset) const
Definition: vtr_writer.h:36
auto write_dimension_data_array(tatooine::linspace< T > const &dim, std::string const &name, std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:144
Grid const & m_grid
Definition: vtr_writer.h:23
typename Grid::vertex_property_type vertex_property_type
Definition: vtr_writer.h:18
auto write_dimension_appended_data(std::vector< T > const &dim, std::ofstream &file) const
Definition: vtr_writer.h:189
static auto constexpr num_dimensions()
Definition: vtr_writer.h:17
auto write_rectilinear_grid(std::ofstream &file, auto &offset) const
Definition: vtr_writer.h:50
auto write_appended_data_coordinates(std::ofstream &file) const
Definition: vtr_writer.h:177
typename Grid::template typed_vertex_property_interface_type< T, H > typed_vertex_property_interface_type
Definition: vtr_writer.h:21
auto write_piece(std::ofstream &file, auto &offset) const
Definition: vtr_writer.h:64
auto write_vertex_property_data_array(auto const &name, vertex_property_type const &prop, std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:257
auto write(filesystem::path const &path) const
Definition: vtr_writer.h:25
auto write_vertex_property_appended_data(typed_vertex_property_interface_type< T, H > const &prop, std::ofstream &file) const
Definition: vtr_writer.h:228
auto write_appended_data_point_data(std::ofstream &file) const
Definition: vtr_writer.h:167
auto write_point_data(std::ofstream &file, std::size_t &offset) const
Definition: vtr_writer.h:81
auto write_cell_data(std::ofstream &file, std::size_t &) const
Definition: vtr_writer.h:92
Definition: linspace.h:26
constexpr auto size() const
Definition: linspace.h:91
Definition: mat.h:14