Tatooine
triangular_vtu_writer.h
Go to the documentation of this file.
1#ifndef TATOOINE_DETAIL_UNSTRUCTURED_SIMPLICIAL_GRID_TRIANGULAR_VTU_WRITER_H
2#define TATOOINE_DETAIL_UNSTRUCTURED_SIMPLICIAL_GRID_TRIANGULAR_VTU_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 = std::uint64_t,
15 integral ConnectivityInt = std::int64_t,
16 integral OffsetInt = std::int64_t,
17 unsigned_integral CellTypesInt = std::uint8_t>
18requires(Grid::num_dimensions() == 2 ||
19 Grid::num_dimensions() == 3)
21 static auto constexpr num_dimensions() { return Grid::num_dimensions(); }
22 using vertex_property_type = typename Grid::vertex_property_type;
23 template <typename T>
25 typename Grid::template typed_vertex_property_type<T>;
26 //----------------------------------------------------------------------------
27 Grid const& m_grid;
28 //----------------------------------------------------------------------------
29 auto write(filesystem::path const& path) const {
30 auto file = std::ofstream{path};
31 if (!file.is_open()) {
32 throw std::runtime_error{"Could open file " + path.string() +
33 " for writing."};
34 }
35 auto offset = std::size_t{};
36 write_vtk_file(file, offset);
37 }
38 //----------------------------------------------------------------------------
39 private:
40 auto write_vtk_file(std::ofstream& file, auto& offset) const {
41 file << "<VTKFile"
42 << " type=\"UnstructuredGrid\""
43 << " version=\"1.0\""
44 << " byte_order=\"LittleEndian\""
45 << " header_type=\""
47 vtk::xml::to_data_type<HeaderType>())
48 << "\">\n";
49 write_unstructured_grid(file, offset);
50 write_appended_data(file);
51 file << "</VTKFile>";
52 }
53 //----------------------------------------------------------------------------
54 auto write_unstructured_grid(std::ofstream& file, auto& offset) const {
55 file << " <UnstructuredGrid>\n";
56 write_piece(file, offset);
57 file << " </UnstructuredGrid>\n";
58 }
59 //----------------------------------------------------------------------------
60 auto write_piece(std::ofstream& file, auto& offset) const {
61 file << " <Piece"
62 << " NumberOfPoints=\"" << m_grid.vertices().size() << "\""
63 << " NumberOfCells=\"" << m_grid.simplices().size() << "\""
64 << ">\n";
65 write_points(file, offset);
66 write_cells(file, offset);
67 write_point_data(file, offset);
68 write_cell_data(file, offset);
69 file << " </Piece>\n";
70 }
71 //------------------------------------------------------------------------------
72 auto write_point_data(std::ofstream& file, std::size_t& offset) const {
73 file << " <PointData>\n";
74 for (auto const& [name, prop] : m_grid.vertex_properties()) {
75 write_vertex_property_data_array<HeaderType, float, vec2f, vec3f, vec4f,
78 name, *prop, file, offset);
79 }
80 file << " </PointData>\n";
81 }
82 //------------------------------------------------------------------------------
83 auto write_cell_data(std::ofstream& file, std::size_t& /*offset*/) const {
84 file << " <CellData>\n";
85 file << " </CellData>\n";
86 }
87 //----------------------------------------------------------------------------
88 auto write_points(std::ofstream& file, std::size_t& offset) const {
89 file << " <Points>\n"
90 << " <DataArray"
91 << " format=\"appended\""
92 << " offset=\"" << offset << "\""
93 << " type=\""
95 vtk::xml::to_data_type<typename Grid::real_type>())
96 << "\" NumberOfComponents=\"3\"/>\n"
97 << " </Points>\n";
98 auto const num_bytes = HeaderType(sizeof(typename Grid::real_type) * 3 *
99 m_grid.vertices().size());
100 offset += num_bytes + sizeof(HeaderType);
101 }
102 //----------------------------------------------------------------------------
103 auto write_cells(std::ofstream& file, std::size_t& offset) const {
104 write_connectivity(file, offset);
105 write_offsets(file, offset);
106 write_cell_types(file, offset);
107 }
108 //----------------------------------------------------------------------------
109 auto write_connectivity(std::ofstream& file, std::size_t& offset) const {
110 // connectivity
111 file << " <Cells>\n"
112 << " <DataArray format=\"appended\" offset=\"" << offset
113 << "\" type=\""
115 vtk::xml::to_data_type<ConnectivityInt>())
116 << "\" Name=\"connectivity\"/>\n";
117 HeaderType num_bytes = m_grid.simplices().size() *
118 m_grid.num_vertices_per_simplex() *
119 sizeof(ConnectivityInt);
120 offset += num_bytes + sizeof(HeaderType);
121 }
122 //----------------------------------------------------------------------------
123 auto write_offsets(std::ofstream& file, std::size_t& offset) const {
124 // offsets
125 file << " <DataArray format=\"appended\" offset=\"" << offset
126 << "\" type=\""
128 vtk::xml::to_data_type<OffsetInt>())
129 << "\" Name=\"offsets\"/>\n";
130 auto const num_bytes = sizeof(OffsetInt) * (m_grid.simplices().size());
131 offset += num_bytes + sizeof(HeaderType);
132 }
133 //----------------------------------------------------------------------------
134 auto write_cell_types(std::ofstream& file, std::size_t& offset) const {
135 // types
136 file << " <DataArray format=\"appended\" offset=\"" << offset
137 << "\" type=\""
139 vtk::xml::to_data_type<CellTypesInt>())
140 << "\" Name=\"types\"/>\n";
141 file << " </Cells>\n";
142 auto const num_bytes=
143 sizeof(CellTypesInt) * m_grid.simplices().size();
144 offset += num_bytes + sizeof(HeaderType);
145 }
146 //----------------------------------------------------------------------------
147 auto write_appended_data(std::ofstream& file) const {
148 file << " <AppendedData encoding=\"raw\">\n _";
149 write_appended_data_points(file);
150 write_appended_data_cells(file);
151 write_appended_data_point_data(file);
152 write_appended_data_cell_data(file);
153 file << "\n </AppendedData>\n";
154 }
155 //----------------------------------------------------------------------------
156 auto write_appended_data_points(std::ofstream& file) const {
157 using namespace std::ranges;
158 auto const num_bytes = HeaderType(sizeof(typename Grid::real_type) * 3 *
159 m_grid.vertices().size());
160 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
161 if constexpr (Grid::num_dimensions() == 2) {
162 auto point_data = std::vector<vec<typename Grid::real_type, 3>>{};
163 point_data.reserve(m_grid.vertices().size());
164 auto position = [this](auto const v) -> auto& { return at(v); };
165 constexpr auto to_3d = [](auto const& p) {
166 return vec{p.x(), p.y(), typename Grid::real_type(0)};
167 };
168 for (auto const v : m_grid.vertices()) {
169 point_data.push_back(to_3d(m_grid[v]));
170 }
171
172 file.write(reinterpret_cast<char const*>(point_data.data()), num_bytes);
173 } else if constexpr (Grid::num_dimensions() == 3) {
174 file.write(reinterpret_cast<char const*>(m_grid.vertices().data()),
175 num_bytes);
176 }
177 }
178 //------------------------------------------------------------------------------
179 auto write_appended_data_cells(std::ofstream& file) const {
180 write_appended_data_cells_connectivity(file);
181 write_appended_data_cells_offsets(file);
182 write_appended_data_cells_types(file);
183 }
184 //------------------------------------------------------------------------------
185 auto write_appended_data_cells_connectivity(std::ofstream& file) const {
186 using namespace std::ranges;
187 auto connectivity_data = std::vector<ConnectivityInt>(
188 m_grid.simplices().size() * m_grid.num_vertices_per_simplex());
189 auto index = [](auto const x) -> ConnectivityInt { return x.index(); };
190 copy(m_grid.simplices().data_container() | views::transform(index),
191 begin(connectivity_data));
192 HeaderType num_bytes = m_grid.simplices().size() *
193 m_grid.num_vertices_per_simplex() *
194 sizeof(ConnectivityInt);
195 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
196 file.write(reinterpret_cast<char const*>(connectivity_data.data()),
197 num_bytes);
198 }
199 //------------------------------------------------------------------------------
200 auto write_appended_data_cells_offsets(std::ofstream& file) const {
201 auto offsets = std::vector<OffsetInt>(m_grid.simplices().size(),
202 m_grid.num_vertices_per_simplex());
203 for (std::size_t i = 1; i < size(offsets); ++i) {
204 offsets[i] += offsets[i - 1];
205 };
206 auto const num_bytes = sizeof(OffsetInt) * m_grid.simplices().size();
207 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
208 file.write(reinterpret_cast<char const*>(offsets.data()), num_bytes);
209 }
210 //------------------------------------------------------------------------------
211 auto write_appended_data_cells_types(std::ofstream& file) const {
212 auto cell_types = std::vector<CellTypesInt>(m_grid.simplices().size(), 5);
213 auto const num_bytes = sizeof(CellTypesInt) * m_grid.simplices().size();
214 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
215 file.write(reinterpret_cast<char const*>(cell_types.data()), num_bytes);
216 }
217 //----------------------------------------------------------------------------
218 auto write_appended_data_point_data(std::ofstream& file) const {
219 for (auto const& [name, prop] : m_grid.vertex_properties()) {
220 write_vertex_property_appended_data<
221 HeaderType, float, vec2f, vec3f, vec4f, mat2f, mat3f, mat4f, double,
222 vec2d, vec3d, vec4d, mat2d, mat3d, mat4d>(*prop, file);
223 }
224 }
225 //----------------------------------------------------------------------------
226 auto write_appended_data_cell_data(std::ofstream& /*file*/) const {}
227 //----------------------------------------------------------------------------
228 template <typename... Ts>
230 std::ofstream& file) const {
231 (
232 [&] {
233 if (prop.type() == typeid(Ts)) {
234 write_vertex_property_appended_data(
235 prop.template cast_to_typed<Ts>(), file);
236 }
237 }(),
238 ...);
239 }
240 //----------------------------------------------------------------------------
241 template <typename T>
243 typed_vertex_property_type<T> const& prop, std::ofstream& file) const {
244 if constexpr (tensor_rank<T> <= 1) {
245 auto data = std::vector<T>{};
246 for (auto const v : m_grid.vertices()) {
247 data.push_back(prop[v]);
248 };
249 auto const num_bytes =
250 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
251 m_grid.vertices().size());
252 file.write(reinterpret_cast<char const*>(&num_bytes), sizeof(HeaderType));
253 file.write(reinterpret_cast<char const*>(data.data()), num_bytes);
254 } else if constexpr (tensor_rank<T> == 2) {
255 auto const num_bytes =
256 HeaderType(sizeof(tatooine::value_type<T>) * tensor_num_components<T> *
257 m_grid.vertices().size() / tensor_dimension<T, 0>);
258 for (std::size_t i = 0; i < tensor_dimension<T, 1>; ++i) {
259 file.write(reinterpret_cast<char const*>(&num_bytes),
260 sizeof(HeaderType));
261 for (auto const v : m_grid.vertices()) {
262 auto data_begin = &prop[v](0, i);
263 file.write(reinterpret_cast<char const*>(data_begin),
264 sizeof(tatooine::value_type<T>) * tensor_dimension<T, 0>);
265 }
266 }
267 }
268 }
269 //----------------------------------------------------------------------------
270 template <typename... Ts>
271 auto write_vertex_property_data_array(auto const& name,
272 vertex_property_type const& prop,
273 std::ofstream& file,
274 std::size_t& offset) const {
275 (
276 [&] {
277 if (prop.type() == typeid(Ts)) {
278 if constexpr (tensor_rank<Ts> <= 1) {
279 file << " <DataArray"
280 << " Name=\"" << name << "\""
281 << " format=\"appended\""
282 << " offset=\"" << offset << "\""
283 << " type=\""
287 << "\" NumberOfComponents=\""
288 << tensor_num_components<Ts> << "\"/>\n";
289 offset +=
290 m_grid.vertices().size() * sizeof(Ts) + sizeof(HeaderType);
291 } else if constexpr (tensor_rank<Ts> == 2) {
292 for (std::size_t i = 0; i < Ts::dimension(1); ++i) {
293 file << "<DataArray"
294 << " Name=\"" << name << "_col_" << i << "\""
295 << " format=\"appended\""
296 << " offset=\"" << offset << "\""
297 << " type=\""
301 << "\" NumberOfComponents=\"" << Ts::dimension(0)
302 << "\"/>\n";
303 offset += m_grid.vertices().size() *
305 tensor_dimension<Ts, 0> +
306 sizeof(HeaderType);
307 }
308 }
309 }
310 }(),
311 ...);
312 }
313};
314//==============================================================================
315} // namespace tatooine::detail::unstructured_simplicial_grid
316//==============================================================================
317#endif
Definition: edge_vtp_writer.h:12
auto size(simplex_container< Real, NumDimensions, SimplexDim > simplices)
Definition: simplex_container.h:89
auto begin(simplex_container< Real, NumDimensions, SimplexDim > simplices)
Definition: simplex_container.h:79
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
mat33f mat3f
Definition: mat_typedefs.h:298
auto constexpr index(handle< Child, Int > const h)
Definition: handle.h:119
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_piece(std::ofstream &file, auto &offset) const
Definition: triangular_vtu_writer.h:60
auto write_cell_data(std::ofstream &file, std::size_t &) const
Definition: triangular_vtu_writer.h:83
auto write_cell_types(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:134
auto write_offsets(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:123
auto write_appended_data_cells_offsets(std::ofstream &file) const
Definition: triangular_vtu_writer.h:200
auto write_appended_data_point_data(std::ofstream &file) const
Definition: triangular_vtu_writer.h:218
auto write_appended_data_cell_data(std::ofstream &) const
Definition: triangular_vtu_writer.h:226
typename Grid::vertex_property_type vertex_property_type
Definition: triangular_vtu_writer.h:22
auto write_points(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:88
auto write_unstructured_grid(std::ofstream &file, auto &offset) const
Definition: triangular_vtu_writer.h:54
auto write(filesystem::path const &path) const
Definition: triangular_vtu_writer.h:29
auto write_vertex_property_appended_data(typed_vertex_property_type< T > const &prop, std::ofstream &file) const
Definition: triangular_vtu_writer.h:242
auto write_appended_data_cells(std::ofstream &file) const
Definition: triangular_vtu_writer.h:179
auto write_cells(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:103
typename Grid::template typed_vertex_property_type< T > typed_vertex_property_type
Definition: triangular_vtu_writer.h:25
auto write_connectivity(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:109
Grid const & m_grid
Definition: triangular_vtu_writer.h:27
auto write_vertex_property_appended_data(vertex_property_type const &prop, std::ofstream &file) const
Definition: triangular_vtu_writer.h:229
auto write_appended_data_cells_types(std::ofstream &file) const
Definition: triangular_vtu_writer.h:211
auto write_appended_data_points(std::ofstream &file) const
Definition: triangular_vtu_writer.h:156
static auto constexpr num_dimensions()
Definition: triangular_vtu_writer.h:21
auto write_vtk_file(std::ofstream &file, auto &offset) const
Definition: triangular_vtu_writer.h:40
auto write_vertex_property_data_array(auto const &name, vertex_property_type const &prop, std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:271
auto write_point_data(std::ofstream &file, std::size_t &offset) const
Definition: triangular_vtu_writer.h:72
auto write_appended_data(std::ofstream &file) const
Definition: triangular_vtu_writer.h:147
auto write_appended_data_cells_connectivity(std::ofstream &file) const
Definition: triangular_vtu_writer.h:185
Definition: mat.h:14
Definition: vec.h:12