dune-vtk 2.8
Loading...
Searching...
No Matches
vtkunstructuredgridwriter.impl.hh
Go to the documentation of this file.
1#pragma once
2
3#include <iomanip>
4#include <iostream>
5#include <iterator>
6#include <fstream>
7#include <sstream>
8#include <string>
9
10#include <dune/geometry/referenceelements.hh>
11#include <dune/geometry/type.hh>
12
16
17namespace Dune {
18
19template <class GV, class DC>
20void VtkUnstructuredGridWriter<GV,DC>
21 ::writeSerialFile (std::ofstream& out) const
22{
23 std::vector<pos_type> offsets; // pos => offset
24 this->writeHeader(out, "UnstructuredGrid");
25 out << "<UnstructuredGrid>\n";
26
27 out << "<Piece"
28 << " NumberOfPoints=\"" << dataCollector_->numPoints() << "\""
29 << " NumberOfCells=\"" << dataCollector_->numCells() << "\""
30 << ">\n";
31
32 // Write point coordinates
33 out << "<Points>\n";
34 this->writePoints(out, offsets);
35 out << "</Points>\n";
36
37 // Write element connectivity, types and offsets
38 out << "<Cells>\n";
39 writeCells(out, offsets);
40 writePointIds(out, offsets);
41 out << "</Cells>\n";
42
43 // Write data associated with grid points
44 out << "<PointData" << this->getNames(pointData_) << ">\n";
45 for (auto const& v : pointData_)
46 this->writeData(out, offsets, v, Super::POINT_DATA);
47 out << "</PointData>\n";
48
49 // Write data associated with grid cells
50 out << "<CellData" << this->getNames(cellData_) << ">\n";
51 for (auto const& v : cellData_)
52 this->writeData(out, offsets, v, Super::CELL_DATA);
53 out << "</CellData>\n";
54
55 out << "</Piece>\n";
56 out << "</UnstructuredGrid>\n";
57
58 this->writeAppended(out, offsets);
59 out << "</VTKFile>";
60}
61
62
63template <class GV, class DC>
64void VtkUnstructuredGridWriter<GV,DC>
65 ::writeParallelFile (std::ofstream& out, std::string const& pfilename, int size) const
66{
67 this->writeHeader(out, "PUnstructuredGrid");
68 out << "<PUnstructuredGrid GhostLevel=\"0\">\n";
69
70 // Write points
71 out << "<PPoints>\n";
72 out << "<PDataArray"
73 << " type=\"" << to_string(datatype_) << "\""
74 << " NumberOfComponents=\"3\""
75 << " />\n";
76 out << "</PPoints>\n";
77
78 // Write data associated with grid points
79 out << "<PPointData" << this->getNames(pointData_) << ">\n";
80 for (auto const& v : pointData_) {
81 out << "<PDataArray"
82 << " Name=\"" << v.name() << "\""
83 << " type=\"" << to_string(v.dataType()) << "\""
84 << " NumberOfComponents=\"" << v.numComponents() << "\""
85 << " />\n";
86 }
87 out << "</PPointData>\n";
88
89 // Write data associated with grid cells
90 out << "<PCellData" << this->getNames(cellData_) << ">\n";
91 for (auto const& v : cellData_) {
92 out << "<PDataArray"
93 << " Name=\"" << v.name() << "\""
94 << " type=\"" << to_string(v.dataType()) << "\""
95 << " NumberOfComponents=\"" << v.numComponents() << "\""
96 << " />\n";
97 }
98 out << "</PCellData>\n";
99
100 // Write piece file references
101 for (int p = 0; p < size; ++p) {
102 std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + this->fileExtension();
103 out << "<Piece Source=\"" << piece_source << "\" />\n";
104 }
105
106 out << "</PUnstructuredGrid>\n";
107 out << "</VTKFile>";
108}
109
110
111template <class GV, class DC>
112void VtkUnstructuredGridWriter<GV,DC>
113 ::writeTimeseriesSerialFile (std::ofstream& out,
114 std::string const& filenameMesh,
115 std::vector<std::pair<double, std::string>> const& timesteps,
116 std::vector<std::uint64_t> const& blocks) const
117{
118 assert(is_a(format_, Vtk::FormatTypes::APPENDED));
119
120 std::vector<std::vector<pos_type>> offsets(timesteps.size()); // pos => offset
121 this->writeHeader(out, "UnstructuredGrid");
122 out << "<UnstructuredGrid"
123 << " TimeValues=\"";
124 {
125 std::size_t i = 0;
126 for (auto const& timestep : timesteps)
127 out << timestep.first << (++i % 6 != 0 ? ' ' : '\n');
128 }
129 out << "\">\n";
130
131 out << "<Piece"
132 << " NumberOfPoints=\"" << dataCollector_->numPoints() << "\""
133 << " NumberOfCells=\"" << dataCollector_->numCells() << "\""
134 << ">\n";
135
136 // Write point coordinates
137 out << "<Points>\n";
138 for (std::size_t i = 0; i < timesteps.size(); ++i) {
139 this->writePoints(out, offsets[i], i);
140 }
141 out << "</Points>\n";
142
143 // Write element connectivity, types and offsets
144 out << "<Cells>\n";
145 for (std::size_t i = 0; i < timesteps.size(); ++i) {
146 writeCells(out, offsets[i], i);
147 writePointIds(out, offsets[i], i);
148 }
149 out << "</Cells>\n";
150
151 const std::size_t shift = offsets[0].size(); // number of blocks to write the grid
152
153 // Write data associated with grid points
154 out << "<PointData" << this->getNames(pointData_) << ">\n";
155 for (std::size_t i = 0; i < timesteps.size(); ++i) {
156 for (auto const& v : pointData_)
157 this->writeData(out, offsets[i], v, Super::POINT_DATA, i);
158 }
159 out << "</PointData>\n";
160
161 // Write data associated with grid cells
162 out << "<CellData" << this->getNames(cellData_) << ">\n";
163 for (std::size_t i = 0; i < timesteps.size(); ++i) {
164 for (auto const& v : cellData_)
165 this->writeData(out, offsets[i], v, Super::CELL_DATA, i);
166 }
167 out << "</CellData>\n";
168
169 out << "</Piece>\n";
170 out << "</UnstructuredGrid>\n";
171
172 out << "<AppendedData encoding=\"raw\">\n_";
173 pos_type appended_pos = out.tellp();
174
175 { // write grid (points, cells)
176 std::ifstream file_mesh(filenameMesh, std::ios_base::in | std::ios_base::binary);
177 out << file_mesh.rdbuf();
178 assert( std::uint64_t(out.tellp()) == std::accumulate(blocks.begin(), std::next(blocks.begin(),shift), std::uint64_t(appended_pos)) );
179 }
180
181 // write point-data and cell-data
182 for (auto const& timestep : timesteps) {
183 std::ifstream file(timestep.second, std::ios_base::in | std::ios_base::binary);
184 out << file.rdbuf();
185 }
186 out << "</AppendedData>\n";
187
188 out << "</VTKFile>";
189
190 // write correct offsets in file.
191 pos_type offset = 0;
192 for (std::size_t i = 0; i < timesteps.size(); ++i) {
193 offset = 0;
194 auto const& off = offsets[i];
195
196 // write mesh data offsets
197 for (std::size_t j = 0; j < shift; ++j) {
198 out.seekp(off[j]);
199 out << '"' << offset << '"';
200 offset += pos_type(blocks[j]);
201 }
202 }
203
204 std::size_t j = shift;
205 for (std::size_t i = 0; i < timesteps.size(); ++i) {
206 auto const& off = offsets[i];
207
208 for (std::size_t k = shift; k < off.size(); ++k) {
209 out.seekp(off[k]);
210 out << '"' << offset << '"';
211 offset += pos_type(blocks[j++]);
212 }
213 }
214}
215
216
217template <class GV, class DC>
218void VtkUnstructuredGridWriter<GV,DC>
219 ::writeTimeseriesParallelFile (std::ofstream& out,
220 std::string const& pfilename,
221 int size,
222 std::vector<std::pair<double, std::string>> const& timesteps) const
223{
224 this->writeHeader(out, "PUnstructuredGrid");
225 out << "<PUnstructuredGrid GhostLevel=\"0\""
226 << " TimeValues=\"";
227 {
228 std::size_t i = 0;
229 for (auto const& timestep : timesteps)
230 out << timestep.first << (++i % 6 != 0 ? ' ' : '\n');
231 }
232 out << "\">\n";
233
234 // Write points
235 out << "<PPoints>\n";
236 out << "<PDataArray"
237 << " type=\"" << to_string(datatype_) << "\""
238 << " NumberOfComponents=\"3\""
239 << " />\n";
240 out << "</PPoints>\n";
241
242 // Write data associated with grid points
243 out << "<PPointData" << this->getNames(pointData_) << ">\n";
244 for (std::size_t i = 0; i < timesteps.size(); ++i) {
245 for (auto const& v : pointData_) {
246 out << "<PDataArray"
247 << " Name=\"" << v.name() << "\""
248 << " type=\"" << to_string(v.dataType()) << "\""
249 << " NumberOfComponents=\"" << v.numComponents() << "\""
250 << " TimeStep=\"" << i << "\""
251 << " />\n";
252 }
253 }
254 out << "</PPointData>\n";
255
256 // Write data associated with grid cells
257 out << "<PCellData" << this->getNames(cellData_) << ">\n";
258 for (std::size_t i = 0; i < timesteps.size(); ++i) {
259 for (auto const& v : cellData_) {
260 out << "<PDataArray"
261 << " Name=\"" << v.name() << "\""
262 << " type=\"" << to_string(v.dataType()) << "\""
263 << " NumberOfComponents=\"" << v.numComponents() << "\""
264 << " TimeStep=\"" << i << "\""
265 << " />\n";
266 }
267 }
268 out << "</PCellData>\n";
269
270 // Write piece file references
271 for (int p = 0; p < size; ++p) {
272 std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + this->fileExtension();
273 out << "<Piece Source=\"" << piece_source << "\" />\n";
274 }
275
276 out << "</PUnstructuredGrid>\n";
277 out << "</VTKFile>";
278}
279
280
281template <class GV, class DC>
282void VtkUnstructuredGridWriter<GV,DC>
283 ::writeCells (std::ofstream& out, std::vector<pos_type>& offsets,
284 std::optional<std::size_t> timestep) const
285{
286 if (format_ == Vtk::FormatTypes::ASCII) {
287 auto cells = dataCollector_->cells();
288 out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"ascii\"";
289 if (timestep)
290 out << " TimeStep=\"" << *timestep << "\"";
291 out << ">\n";
292 this->writeValuesAscii(out, cells.connectivity);
293 out << "</DataArray>\n";
294
295 out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\"";
296 if (timestep)
297 out << " TimeStep=\"" << *timestep << "\"";
298 out << ">\n";
299 this->writeValuesAscii(out, cells.offsets);
300 out << "</DataArray>\n";
301
302 out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\"";
303 if (timestep)
304 out << " TimeStep=\"" << *timestep << "\"";
305 out << ">\n";
306 this->writeValuesAscii(out, cells.types);
307 out << "</DataArray>\n";
308 }
309 else { // Vtk::FormatTypes::APPENDED format
310 out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"appended\"";
311 if (timestep)
312 out << " TimeStep=\"" << *timestep << "\"";
313 out << " offset=";
314 offsets.push_back(out.tellp());
315 out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' ');
316 out << "/>\n";
317
318 out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"appended\"";
319 if (timestep)
320 out << " TimeStep=\"" << *timestep << "\"";
321 out << " offset=";
322 offsets.push_back(out.tellp());
323 out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' ');
324 out << "/>\n";
325
326 out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"appended\"";
327 if (timestep)
328 out << " TimeStep=\"" << *timestep << "\"";
329 out << " offset=";
330 offsets.push_back(out.tellp());
331 out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' ');
332 out << "/>\n";
333 }
334}
335
336
337template <class GV, class DC>
338void VtkUnstructuredGridWriter<GV,DC>
339 ::writePointIds (std::ofstream& out,
340 std::vector<pos_type>& offsets,
341 std::optional<std::size_t> timestep) const
342{
343 auto ids = dataCollector_->pointIds();
344 if (ids.empty())
345 return;
346
347 if (format_ == Vtk::FormatTypes::ASCII) {
348 out << "<DataArray type=\"UInt64\" Name=\"global_point_ids\" format=\"ascii\"";
349 if (timestep)
350 out << " TimeStep=\"" << *timestep << "\"";
351 out << ">\n";
352 this->writeValuesAscii(out, ids);
353 out << "</DataArray>\n";
354 }
355 else { // Vtk::FormatTypes::APPENDED format
356 out << "<DataArray type=\"UInt64\" Name=\"global_point_ids\" format=\"appended\"";
357 if (timestep)
358 out << " TimeStep=\"" << *timestep << "\"";
359 out << " offset=";
360 offsets.push_back(out.tellp());
361 out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' ');
362 out << "/>\n";
363 }
364}
365
366
367template <class GV, class DC>
368void VtkUnstructuredGridWriter<GV,DC>
369 ::writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const
370{
371 assert(is_a(format_, Vtk::FormatTypes::APPENDED) && "Function should by called only in appended mode!\n");
372
373 Vtk::mapDataTypes<std::is_floating_point, std::is_integral>(datatype_, headertype_,
374 [&](auto f, auto h) {
375 using F = typename decltype(f)::type;
376 using H = typename decltype(h)::type;
377
378 // write points
379 blocks.push_back(this->template writeValuesAppended<H>(out, dataCollector_->template points<F>()));
380
381 // write connectivity, offsets, and types
382 auto cells = dataCollector_->cells();
383 blocks.push_back(this->template writeValuesAppended<H>(out, cells.connectivity));
384 blocks.push_back(this->template writeValuesAppended<H>(out, cells.offsets));
385 blocks.push_back(this->template writeValuesAppended<H>(out, cells.types));
386
387 // optionally, write global point IDs
388 auto ids = dataCollector_->pointIds();
389 if (!ids.empty())
390 blocks.push_back(this->template writeValuesAppended<H>(out, ids));
391 });
392}
393
394} // end namespace Dune
Definition: writer.hh:13
std::string to_string(Vtk::FormatTypes type)
Definition: types.cc:12
constexpr bool is_a(E a, Integer b)
Definition: enum.hh:12