Dune Core Modules (unstable)

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 
17 #include <dune/common/indent.hh>
18 
19 #include <dune/grid/io/file/vtk/streams.hh>
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 
121  AsciiDataArrayWriter(std::ostream& theStream, std::string name,
122  int ncomps, const Indent& indent_, Precision prec_)
123  : DataArrayWriter(prec_), s(theStream), counter(0), numPerLine(12), indent(indent_)
124  {
125  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
126  << "Name=\"" << name << "\" ";
127  s << "NumberOfComponents=\"" << ncomps << "\" ";
128  s << "format=\"ascii\">\n";
129  ++indent;
130  }
131 
134  {
135  if (counter%numPerLine!=0) s << "\n";
136  --indent;
137  s << indent << "</DataArray>\n";
138  }
139 
140  private:
142  void writeFloat64 (double data) final
143  { write_float(data); }
145  void writeFloat32 (float data) final
146  { write_float(data); }
148  void writeInt32 (std::int32_t data) final
149  { write_(data); }
151  void writeUInt32 (std::uint32_t data) final
152  { write_(data); }
154  void writeUInt8 (std::uint8_t data) final
155  { write_(data); }
156 
157  template<class T>
158  void write_(T data)
159  {
160  typedef typename PrintType<T>::Type PT;
161  if(counter%numPerLine==0) s << indent;
162  else s << " ";
163  const auto original_precision = std::cout.precision();
164  s << std::setprecision(std::numeric_limits<PT>::digits10) << (PT) data;
165  std::cout.precision(original_precision);
166  counter++;
167  if (counter%numPerLine==0) s << "\n";
168  }
169 
170  template<class T>
171  void write_float(T data)
172  {
173  typedef typename PrintType<T>::Type PT;
174  if(counter%numPerLine==0) s << indent;
175  else s << " ";
176  PT out_data = (PT) data;
177  if (std::fpclassify(out_data) == FP_SUBNORMAL)
178  {
179  // truncate denormalized data to 0 to avoid Paraview segfaults on macOS
180  out_data = 0;
181  }
182  const auto original_precision = std::cout.precision();
183  s << std::setprecision(std::numeric_limits<PT>::digits10) << out_data;
184  std::cout.precision(original_precision);
185  counter++;
186  if (counter%numPerLine==0) s << "\n";
187  }
188 
189  std::ostream& s;
190  int counter;
191  int numPerLine;
192  Indent indent;
193  };
194 
197  {
198  public:
200 
210  BinaryDataArrayWriter(std::ostream& theStream, std::string name,
211  int ncomps, int nitems, const Indent& indent_, Precision prec_)
212  : DataArrayWriter(prec_), s(theStream), b64(theStream), indent(indent_)
213  {
214  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
215  << "Name=\"" << name << "\" ";
216  s << "NumberOfComponents=\"" << ncomps << "\" ";
217  s << "format=\"binary\">\n";
218 
219  // write indentation for the data chunk
220  s << indent+1;
221  // store size, needs to be exactly 32 bit
222  std::uint32_t size = ncomps*nitems*typeSize(prec_);
223  b64.write(size);
224  b64.flush();
225  }
226 
229  {
230  b64.flush();
231  // append newline to written data
232  s << "\n";
233  s << indent << "</DataArray>\n";
234  s.flush();
235  }
236 
237  private:
239  void writeFloat64 (double data) final
240  { write_(data); }
242  void writeFloat32 (float data) final
243  { write_(data); }
245  void writeInt32 (std::int32_t data) final
246  { write_(data); }
248  void writeUInt32 (std::uint32_t data) final
249  { write_(data); }
251  void writeUInt8 (std::uint8_t data) final
252  { write_(data); }
253 
255  template<class T>
256  void write_(T data)
257  {
258  b64.write(data);
259  }
260 
261  std::ostream& s;
262  Base64Stream b64;
263  const Indent& indent;
264  };
265 
268  {
269  public:
271 
283  AppendedRawDataArrayWriter(std::ostream& s, std::string name,
284  int ncomps, unsigned nitems, unsigned& offset,
285  const Indent& indent, Precision prec_)
286  : DataArrayWriter(prec_)
287  {
288  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
289  << "Name=\"" << name << "\" ";
290  s << "NumberOfComponents=\"" << ncomps << "\" ";
291  s << "format=\"appended\" offset=\""<< offset << "\" />\n";
292  offset += 4; // header
293  offset += ncomps*nitems*typeSize(prec_);
294  }
295 
297  bool writeIsNoop() const { return true; }
298 
299  private:
301  void writeFloat64 (double) final {}
302  void writeFloat32 (float) final {}
303  void writeInt32 (std::int32_t) final {}
304  void writeUInt32 (std::uint32_t) final {}
305  void writeUInt8 (std::uint8_t) final {}
306  };
307 
310  {
311  public:
313 
325  AppendedBase64DataArrayWriter(std::ostream& s, std::string name,
326  int ncomps, unsigned nitems,
327  unsigned& offset, const Indent& indent, Precision prec_)
328  : DataArrayWriter(prec_)
329  {
330  s << indent << "<DataArray type=\"" << toString(prec_) << "\" "
331  << "Name=\"" << name << "\" ";
332  s << "NumberOfComponents=\"" << ncomps << "\" ";
333  s << "format=\"appended\" offset=\""<< offset << "\" />\n";
334  offset += 8; // header
335  std::size_t bytes = ncomps*nitems*typeSize(prec_);
336  offset += bytes/3*4;
337  if(bytes%3 != 0)
338  offset += 4;
339  }
340 
342  bool writeIsNoop() const { return true; }
343 
344  private:
346  void writeFloat64 (double) final {}
347  void writeFloat32 (float) final {}
348  void writeInt32 (std::int32_t) final {}
349  void writeUInt32 (std::uint32_t) final {}
350  void writeUInt8 (std::uint8_t) final {}
351  };
352 
354  //
355  // Naked ArrayWriters for the appended section
356  //
357 
360  {
361  public:
363 
369  NakedBase64DataArrayWriter(std::ostream& theStream, int ncomps,
370  int nitems, Precision prec_)
371  : DataArrayWriter(prec_), b64(theStream)
372  {
373  // store size
374  std::uint32_t size = ncomps*nitems*typeSize(prec_);
375  b64.write(size);
376  b64.flush();
377  }
378 
379  private:
381  void writeFloat64 (double data) final
382  { write_(data); }
384  void writeFloat32 (float data) final
385  { write_(data); }
387  void writeInt32 (std::int32_t data) final
388  { write_(data); }
390  void writeUInt32 (std::uint32_t data) final
391  { write_(data); }
393  void writeUInt8 (std::uint8_t data) final
394  { write_(data); }
395 
397  template<class T>
398  void write_(T data)
399  {
400  b64.write(data);
401  }
402 
403  Base64Stream b64;
404  };
405 
408  {
409  RawStream s;
410 
411  public:
413 
419  NakedRawDataArrayWriter(std::ostream& theStream, int ncomps,
420  int nitems, Precision prec_)
421  : DataArrayWriter(prec_), s(theStream)
422  {
423  s.write((unsigned int)(ncomps*nitems*typeSize(prec_)));
424  }
425 
426  private:
428  void writeFloat64 (double data) final
429  { write_(data); }
431  void writeFloat32 (float data) final
432  { write_(data); }
434  void writeInt32 (std::int32_t data) final
435  { write_(data); }
437  void writeUInt32 (std::uint32_t data) final
438  { write_(data); }
440  void writeUInt8 (std::uint8_t data) final
441  { write_(data); }
442 
444  template<class T>
445  void write_(T data)
446  {
447  s.write(data);
448  }
449  };
450 
452  //
453  // Factory
454  //
455 
457 
463  enum Phase { main, appended };
464 
465  OutputType type;
466  std::ostream& stream;
467  unsigned offset;
469  Phase phase;
470 
471  public:
473 
482  inline DataArrayWriterFactory(OutputType type_, std::ostream& stream_)
483  : type(type_), stream(stream_), offset(0), phase(main)
484  { }
485 
487 
497  inline bool beginAppended() {
498  phase = appended;
499  switch(type) {
500  case ascii : return false;
501  case base64 : return false;
502  case appendedraw : return true;
503  case appendedbase64 : return true;
504  }
505  DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
506  "OutputType " << type);
507  }
508 
510  const std::string& appendedEncoding() const {
511  static const std::string rawString = "raw";
512  static const std::string base64String = "base64";
513 
514  switch(type) {
515  case ascii :
516  case base64 :
517  DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): No "
518  "appended encoding for OutputType " << type);
519  case appendedraw : return rawString;
520  case appendedbase64 : return base64String;
521  }
522  DUNE_THROW(IOError, "DataArrayWriterFactory::appendedEncoding(): "
523  "unsupported OutputType " << type);
524  }
525 
527 
541  DataArrayWriter* make(const std::string& name, unsigned ncomps,
542  unsigned nitems, const Indent& indent,
543  Precision prec)
544  {
545  switch(phase) {
546  case main :
547  switch(type) {
548  case ascii :
549  return new AsciiDataArrayWriter(stream, name, ncomps, indent, prec);
550  case base64 :
551  return new BinaryDataArrayWriter(stream, name, ncomps, nitems,
552  indent, prec);
553  case appendedraw :
554  return new AppendedRawDataArrayWriter(stream, name, ncomps,
555  nitems, offset, indent, prec);
556  case appendedbase64 :
557  return new AppendedBase64DataArrayWriter(stream, name, ncomps,
558  nitems, offset,
559  indent, prec);
560  }
561  break;
562  case appended :
563  switch(type) {
564  case ascii :
565  case base64 :
566  break; // invalid in appended mode
567  case appendedraw :
568  return new NakedRawDataArrayWriter(stream, ncomps, nitems, prec);
569  case appendedbase64 :
570  return new NakedBase64DataArrayWriter(stream, ncomps, nitems, prec);
571  }
572  break;
573  }
574  DUNE_THROW(IOError, "Dune::VTK::DataArrayWriter: unsupported "
575  "OutputType " << type << " in phase " << phase);
576  }
577  };
578 
579  } // namespace VTK
580 
582 
583 } // namespace Dune
584 
585 #endif // DUNE_GRID_IO_FILE_VTK_DATAARRAYWRITER_HH
void write(X &data)
encode a data item
Definition: streams.hh:42
void flush()
flush the current unwritten data to the stream.
Definition: streams.hh:64
Default exception class for I/O errors.
Definition: exceptions.hh:231
Utility class for handling nested indentation in output.
Definition: indent.hh:53
Default exception for dummy implementations.
Definition: exceptions.hh:263
write out data in binary
Definition: streams.hh:84
void write(T data)
write data to stream
Definition: streams.hh:93
a streaming writer for data array tags, uses appended base64 format
Definition: dataarraywriter.hh:310
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:325
bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:342
a streaming writer for data array tags, uses appended raw format
Definition: dataarraywriter.hh:268
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:283
bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:297
a streaming writer for data array tags, uses ASCII inline format
Definition: dataarraywriter.hh:110
~AsciiDataArrayWriter()
finish output; writes end tag
Definition: dataarraywriter.hh:133
AsciiDataArrayWriter(std::ostream &theStream, std::string name, int ncomps, const Indent &indent_, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:121
a streaming writer for data array tags, uses binary inline format
Definition: dataarraywriter.hh:197
~BinaryDataArrayWriter()
finish output; writes end tag
Definition: dataarraywriter.hh:228
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:210
a factory for DataArrayWriters
Definition: dataarraywriter.hh:462
bool beginAppended()
signal start of the appended section
Definition: dataarraywriter.hh:497
DataArrayWriter * make(const std::string &name, unsigned ncomps, unsigned nitems, const Indent &indent, Precision prec)
create a DataArrayWriter
Definition: dataarraywriter.hh:541
DataArrayWriterFactory(OutputType type_, std::ostream &stream_)
create a DataArrayWriterFactory
Definition: dataarraywriter.hh:482
const std::string & appendedEncoding() const
query encoding string for appended data
Definition: dataarraywriter.hh:510
base class for data array writers
Definition: dataarraywriter.hh:56
void write(T data)
write one element of data
Definition: dataarraywriter.hh:69
DataArrayWriter(Precision _prec)
construct a data array writer
Definition: dataarraywriter.hh:63
virtual bool writeIsNoop() const
whether calls to write may be skipped
Definition: dataarraywriter.hh:89
virtual ~DataArrayWriter()
virtual destructor
Definition: dataarraywriter.hh:91
a streaming writer for appended data array tags, uses base64 format
Definition: dataarraywriter.hh:360
NakedBase64DataArrayWriter(std::ostream &theStream, int ncomps, int nitems, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:369
a streaming writer for appended data arrays, uses raw format
Definition: dataarraywriter.hh:408
NakedRawDataArrayWriter(std::ostream &theStream, int ncomps, int nitems, Precision prec_)
make a new data array writer
Definition: dataarraywriter.hh:419
A few common exception classes.
Common stuff for the VTKWriter.
Precision
which precision to use when writing out data to vtk files
Definition: common.hh:271
OutputType
How the bulk data should be stored in the file.
Definition: common.hh:43
@ ascii
Output to the file is in ascii.
Definition: common.hh:45
@ appendedraw
Output is to the file is appended raw binary.
Definition: common.hh:49
@ appendedbase64
Output is to the file is appended base64 binary.
Definition: common.hh:51
@ base64
Output to the file is inline base64 binary.
Definition: common.hh:47
std::string toString(Precision p)
map precision to VTK type name
Definition: common.hh:280
std::size_t typeSize(Precision p)
map precision to byte size
Definition: common.hh:300
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Utility class for handling nested indentation in output.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
T Type
type to convert T to before putting it into a stream with <<
Definition: common.hh:97
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)