dune-grid  2.11
dataarraywriter.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
4 // vi: set et ts=4 sw=2 sts=2:
5 
6 #ifndef DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
7 #define DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
8 
9 #include <cstdint>
10 #include <iostream>
11 #include <string>
12 #include <iomanip>
13 #include <cstdint>
14 #include <cmath>
15 
16 #include <dune/common/exceptions.hh>
17 #include <dune/common/indent.hh>
18 
21 
30 namespace Dune
31 {
34 
35  namespace VTK {
36 
38 
56  {
57  public:
59 
64  : prec(_prec)
65  {}
66 
68  template<class T>
69  void write(T data)
70  {
71  switch(prec)
72  {
73  case Precision::float32:
74  writeFloat32(data); break;
75  case Precision::float64:
76  writeFloat64(data); break;
77  case Precision::uint32:
78  writeUInt32(data); break;
79  case Precision::uint8:
80  writeUInt8(data); break;
81  case Precision::int32:
82  writeInt32(data); break;
83  default:
84  DUNE_THROW(Dune::NotImplemented, "Unknown precision type");
85  }
86  }
87 
89  virtual bool writeIsNoop() const { return false; }
91  virtual ~DataArrayWriter () {}
92 
93  private:
95  virtual void writeFloat32 (float data) = 0;
97  virtual void writeFloat64 (double data) = 0;
99  virtual void writeInt32 (std::int32_t data) = 0;
101  virtual void writeUInt8 (std::uint8_t data) = 0;
103  virtual void writeUInt32 (std::uint32_t data) = 0;
104 
105  Precision prec;
106  };
107 
110  {
111  public:
113 
122  AsciiDataArrayWriter(std::ostream& theStream, std::string name,
123  int ncomps, const Indent& indent_, Precision prec_)
124  : DataArrayWriter(prec_), s(theStream), counter(0), numPerLine(12), indent(indent_)
125  {
126  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
127  << "Name=\"" << name << "\" ";
128  s << "NumberOfComponents=\"" << ncomps << "\" ";
129  s << "format=\"ascii\">\n";
130  ++indent;
131  }
132 
135  {
136  if (counter%numPerLine!=0) s << "\n";
137  --indent;
138  s << indent << "</DataArray>\n";
139  }
140 
141  private:
143  void writeFloat64 (double data) final
144  { write_float(data); }
146  void writeFloat32 (float data) final
147  { write_float(data); }
149  void writeInt32 (std::int32_t data) final
150  { write_(data); }
152  void writeUInt32 (std::uint32_t data) final
153  { write_(data); }
155  void writeUInt8 (std::uint8_t data) final
156  { write_(data); }
157 
158  template<class T>
159  void write_(T data)
160  {
161  typedef typename PrintType<T>::Type PT;
162  if(counter%numPerLine==0) s << indent;
163  else s << " ";
164  const auto original_precision = std::cout.precision();
165  s << std::setprecision(std::numeric_limits<PT>::digits10) << (PT) data;
166  std::cout.precision(original_precision);
167  counter++;
168  if (counter%numPerLine==0) s << "\n";
169  }
170 
171  template<class T>
172  void write_float(T data)
173  {
174  typedef typename PrintType<T>::Type PT;
175  if(counter%numPerLine==0) s << indent;
176  else s << " ";
177  PT out_data = (PT) data;
178  if (std::fpclassify(out_data) == FP_SUBNORMAL)
179  {
180  // truncate denormalized data to 0 to avoid Paraview segfaults on macOS
181  out_data = 0;
182  }
183  const auto original_precision = std::cout.precision();
184  s << std::setprecision(std::numeric_limits<PT>::digits10) << out_data;
185  std::cout.precision(original_precision);
186  counter++;
187  if (counter%numPerLine==0) s << "\n";
188  }
189 
190  std::ostream& s;
191  int counter;
192  int numPerLine;
193  Indent indent;
194  };
195 
198  {
199  public:
201 
212  BinaryDataArrayWriter(std::ostream& theStream, std::string name,
213  int ncomps, int nitems, const Indent& indent_, Precision prec_)
214  : DataArrayWriter(prec_), s(theStream), b64(theStream), indent(indent_)
215  {
216  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
217  << "Name=\"" << name << "\" ";
218  s << "NumberOfComponents=\"" << ncomps << "\" ";
219  s << "format=\"binary\">\n";
220 
221  // write indentation for the data chunk
222  s << indent+1;
223  // store size, needs to be exactly 32 bit
224  std::uint32_t size = ncomps*nitems*typeSize(prec_);
225  b64.write(size);
226  b64.flush();
227  }
228 
231  {
232  b64.flush();
233  // append newline to written data
234  s << "\n";
235  s << indent << "</DataArray>\n";
236  s.flush();
237  }
238 
239  private:
241  void writeFloat64 (double data) final
242  { write_(data); }
244  void writeFloat32 (float data) final
245  { write_(data); }
247  void writeInt32 (std::int32_t data) final
248  { write_(data); }
250  void writeUInt32 (std::uint32_t data) final
251  { write_(data); }
253  void writeUInt8 (std::uint8_t data) final
254  { write_(data); }
255 
257  template<class T>
258  void write_(T data)
259  {
260  b64.write(data);
261  }
262 
263  std::ostream& s;
264  Base64Stream b64;
265  const Indent& indent;
266  };
267 
270  {
271  public:
273 
286  AppendedRawDataArrayWriter(std::ostream& s, std::string name,
287  int ncomps, unsigned nitems, unsigned& offset,
288  const Indent& indent, Precision prec_)
289  : DataArrayWriter(prec_)
290  {
291  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
292  << "Name=\"" << name << "\" ";
293  s << "NumberOfComponents=\"" << ncomps << "\" ";
294  s << "format=\"appended\" offset=\""<< offset << "\" />\n";
295  offset += 4; // header
296  offset += ncomps*nitems*typeSize(prec_);
297  }
298 
300  bool writeIsNoop() const { return true; }
301 
302  private:
304  void writeFloat64 (double) final {}
305  void writeFloat32 (float) final {}
306  void writeInt32 (std::int32_t) final {}
307  void writeUInt32 (std::uint32_t) final {}
308  void writeUInt8 (std::uint8_t) final {}
309  };
310 
313  {
314  public:
316 
329  AppendedBase64DataArrayWriter(std::ostream& s, std::string name,
330  int ncomps, unsigned nitems,
331  unsigned& offset, const Indent& indent, Precision prec_)
332  : DataArrayWriter(prec_)
333  {
334  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
335  << "Name=\"" << name << "\" ";
336  s << "NumberOfComponents=\"" << ncomps << "\" ";
337  s << "format=\"appended\" offset=\""<< offset << "\" />\n";
338  offset += 8; // header
339  std::size_t bytes = ncomps*nitems*typeSize(prec_);
340  offset += bytes/3*4;
341  if(bytes%3 != 0)
342  offset += 4;
343  }
344 
346  bool writeIsNoop() const { return true; }
347 
348  private:
350  void writeFloat64 (double) final {}
351  void writeFloat32 (float) final {}
352  void writeInt32 (std::int32_t) final {}
353  void writeUInt32 (std::uint32_t) final {}
354  void writeUInt8 (std::uint8_t) final {}
355  };
356 
358  //
359  // Naked ArrayWriters for the appended section
360  //
361 
364  {
365  public:
367 
374  NakedBase64DataArrayWriter(std::ostream& theStream, int ncomps,
375  int nitems, Precision prec_)
376  : DataArrayWriter(prec_), b64(theStream)
377  {
378  // store size
379  std::uint32_t size = ncomps*nitems*typeSize(prec_);
380  b64.write(size);
381  b64.flush();
382  }
383 
384  private:
386  void writeFloat64 (double data) final
387  { write_(data); }
389  void writeFloat32 (float data) final
390  { write_(data); }
392  void writeInt32 (std::int32_t data) final
393  { write_(data); }
395  void writeUInt32 (std::uint32_t data) final
396  { write_(data); }
398  void writeUInt8 (std::uint8_t data) final
399  { write_(data); }
400 
402  template<class T>
403  void write_(T data)
404  {
405  b64.write(data);
406  }
407 
408  Base64Stream b64;
409  };
410 
413  {
414  RawStream s;
415 
416  public:
418 
425  NakedRawDataArrayWriter(std::ostream& theStream, int ncomps,
426  int nitems, Precision prec_)
427  : DataArrayWriter(prec_), s(theStream)
428  {
429  s.write((unsigned int)(ncomps*nitems*typeSize(prec_)));
430  }
431 
432  private:
434  void writeFloat64 (double data) final
435  { write_(data); }
437  void writeFloat32 (float data) final
438  { write_(data); }
440  void writeInt32 (std::int32_t data) final
441  { write_(data); }
443  void writeUInt32 (std::uint32_t data) final
444  { write_(data); }
446  void writeUInt8 (std::uint8_t data) final
447  { write_(data); }
448 
450  template<class T>
451  void write_(T data)
452  {
453  s.write(data);
454  }
455  };
456 
458  //
459  // Factory
460  //
461 
463 
469  enum Phase { main, appended };
470 
471  OutputType type;
472  std::ostream& stream;
473  unsigned offset;
475  Phase phase;
476 
477  public:
479 
488  inline DataArrayWriterFactory(OutputType type_, std::ostream& stream_)
489  : type(type_), stream(stream_), offset(0), phase(main)
490  { }
491 
493 
503  inline bool beginAppended() {
504  phase = appended;
505  switch(type) {
506  case ascii : return false;
507  case base64 : return false;
508  case appendedraw : return true;
509  case appendedbase64 : return true;
510  }
511  DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
512  "OutputType " << type);
513  }
514 
516  const std::string& appendedEncoding() const {
517  static const std::string rawString = "raw";
518  static const std::string base64String = "base64";
519 
520  switch(type) {
521  case ascii :
522  case base64 :
523  DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): No "
524  "appended encoding for OutputType " << type);
525  case appendedraw : return rawString;
526  case appendedbase64 : return base64String;
527  }
528  DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): "
529  "unsupported OutputType " << type);
530  }
531 
533 
547  DataArrayWriter* make(const std::string& name, unsigned ncomps,
548  unsigned nitems, const Indent& indent,
549  Precision prec)
550  {
551  switch(phase) {
552  case main :
553  switch(type) {
554  case ascii :
555  return new AsciiDataArrayWriter(stream, name, ncomps, indent, prec);
556  case base64 :
557  return new BinaryDataArrayWriter(stream, name, ncomps, nitems,
558  indent, prec);
559  case appendedraw :
560  return new AppendedRawDataArrayWriter(stream, name, ncomps,
561  nitems, offset, indent, prec);
562  case appendedbase64 :
563  return new AppendedBase64DataArrayWriter(stream, name, ncomps,
564  nitems, offset,
565  indent, prec);
566  }
567  break;
568  case appended :
569  switch(type) {
570  case ascii :
571  case base64 :
572  break; // invalid in appended mode
573  case appendedraw :
574  return new NakedRawDataArrayWriter(stream, ncomps, nitems, prec);
575  case appendedbase64 :
576  return new NakedBase64DataArrayWriter(stream, ncomps, nitems, prec);
577  }
578  break;
579  }
580  DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
581  "OutputType " << type << " in phase " << phase);
582  }
583  };
584 
585  } // namespace VTK
586 
588 
589 } // namespace Dune
590 
591 #endif // DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
NakedBase64DataArrayWriter(std::ostream &theStream, int ncomps, int nitems, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:374
void write(T data)
write one element of data
Definition: dataarraywriter.hh:69
virtual ~DataArrayWriter()
virtual destructor
Definition: dataarraywriter.hh:91
DataArrayWriter * make(const std::string &name, unsigned ncomps, unsigned nitems, const Indent &indent, Precision prec)
create a DataArrayWriter
Definition: dataarraywriter.hh:547
~AsciiDataArrayWriter()
finish output; writes end tag
Definition: dataarraywriter.hh:134
const std::string & appendedEncoding() const
query encoding string for appended data
Definition: dataarraywriter.hh:516
std::string toString(Precision p)
map precision to VTK type name
Definition: common.hh:280
void write(T data)
write data to stream
Definition: streams.hh:93
DataArrayWriterFactory(OutputType type_, std::ostream &stream_)
create a DataArrayWriterFactory
Definition: dataarraywriter.hh:488
bool beginAppended()
signal start of the appended section
Definition: dataarraywriter.hh:503
Output is to the file is appended raw binary.
Definition: common.hh:49
virtual bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:89
std::size_t typeSize(Precision p)
map precision to byte size
Definition: common.hh:300
a streaming writer for data array tags, uses appended raw format
Definition: dataarraywriter.hh:269
Output to the file is inline base64 binary.
Definition: common.hh:47
bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:300
base class for data array writers
Definition: dataarraywriter.hh:55
bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:346
Output to the file is in ascii.
Definition: common.hh:45
AppendedRawDataArrayWriter(std::ostream &s, std::string name, int ncomps, unsigned nitems, unsigned &offset, const Indent &indent, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:286
a streaming writer for appended data array tags, uses base64 format
Definition: dataarraywriter.hh:363
a streaming writer for data array tags, uses binary inline format
Definition: dataarraywriter.hh:197
Include standard header files.
Definition: agrid.hh:59
write out data in binary
Definition: streams.hh:83
a factory for DataArrayWriters
Definition: dataarraywriter.hh:468
Output is to the file is appended base64 binary.
Definition: common.hh:51
a streaming writer for data array tags, uses appended base64 format
Definition: dataarraywriter.hh:312
void write(X &data)
encode a data item
Definition: streams.hh:42
a streaming writer for data array tags, uses ASCII inline format
Definition: dataarraywriter.hh:109
AppendedBase64DataArrayWriter(std::ostream &s, std::string name, int ncomps, unsigned nitems, unsigned &offset, const Indent &indent, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:329
~BinaryDataArrayWriter()
finish output; writes end tag
Definition: dataarraywriter.hh:230
AsciiDataArrayWriter(std::ostream &theStream, std::string name, int ncomps, const Indent &indent_, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:122
NakedRawDataArrayWriter(std::ostream &theStream, int ncomps, int nitems, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:425
a streaming writer for appended data arrays, uses raw format
Definition: dataarraywriter.hh:412
BinaryDataArrayWriter(std::ostream &theStream, std::string name, int ncomps, int nitems, const Indent &indent_, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:212
Common stuff for the VTKWriter.
T Type
type to convert T to before putting it into a stream with <<
Definition: common.hh:97
Precision
which precision to use when writing out data to vtk files
Definition: common.hh:271
DataArrayWriter(Precision _prec)
construct a data array writer
Definition: dataarraywriter.hh:63
OutputType
How the bulk data should be stored in the file.
Definition: common.hh:43
void flush()
flush the current unwritten data to the stream.
Definition: streams.hh:64