dune-vtk  0.2
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 
13 #include <dune/vtk/utility/enum.hh>
16 
17 namespace Dune {
18 
19 template <class GV, class DC>
20 void 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 
63 template <class GV, class DC>
64 void 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 
111 template <class GV, class DC>
112 void 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 
217 template <class GV, class DC>
218 void 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 
281 template <class GV, class DC>
282 void 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 
337 template <class GV, class DC>
338 void 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 
367 template <class GV, class DC>
368 void 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