dune-grid  2.9.0
basicwriter.hh
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 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_BASICWRITER_HH
7 #define DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
8 
9 #include <fstream>
10 #include <iomanip>
11 #include <iterator>
12 #include <list>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 
17 #include <dune/common/parallel/mpiguard.hh>
18 #include <dune/common/path.hh>
19 
20 #include <dune/geometry/referenceelements.hh>
21 
26 
27 namespace Dune
28 {
31 
32  namespace VTK {
33 
34  template<typename IteratorFactory>
35  class BasicWriter {
36  typedef typename IteratorFactory::CellIterator CellIterator;
37  typedef typename IteratorFactory::CornerIterator CornerIterator;
38  typedef typename IteratorFactory::PointIterator PointIterator;
39 
40  typedef typename IteratorFactory::Cell Cell;
41 
42  public:
44 
45  private:
46  typedef std::list<std::shared_ptr<FunctionWriter> > WriterList;
47  typedef typename WriterList::const_iterator WIterator;
48 
49  typedef typename Cell::Geometry::ctype ctype;
50  static const unsigned celldim = Cell::mydimension;
51  typedef ReferenceElements<ctype, celldim> Refelems;
52 
53  static const FileType fileType = celldim == 1
55 
56  const IteratorFactory& factory;
57 
58  WriterList cellData;
59  WriterList pointData;
60 
62  typename IteratorFactory::ConnectivityWriter connectivity;
63  OffsetsWriter<Cell> offsets;
64  TypesWriter<Cell> types;
65 
66  public:
67  BasicWriter(const IteratorFactory& factory_)
68  : factory(factory_), connectivity(factory.makeConnectivity())
69  { }
70 
72  //
73  // Methods for adding data
74  //
75 
76  void addCellData(const std::shared_ptr<FunctionWriter>& writer) {
77  cellData.push_back(writer);
78  }
79 
80  void addPointData(const std::shared_ptr<FunctionWriter>& writer) {
81  pointData.push_back(writer);
82  }
83 
84  void clear() {
85  cellData.clear();
86  pointData.clear();
87  }
88 
89  protected:
91  //
92  // Methods for writing single functions
93  //
94 
95  void writeCellFunction(VTUWriter& vtuWriter,
96  FunctionWriter& functionWriter,
97  unsigned ncells) const
98  {
99  if(functionWriter.beginWrite(vtuWriter, ncells)) {
100  const CellIterator& cellend = factory.endCells();
101  for(CellIterator cellit = factory.beginCells(); cellit != cellend;
102  ++cellit)
103  functionWriter.write(*cellit, Refelems::general(cellit->type()).
104  position(0,0));
105  }
106  functionWriter.endWrite();
107  }
108 
109  void writePointFunction(VTUWriter& vtuWriter,
110  FunctionWriter& functionWriter,
111  unsigned npoints) const
112  {
113  if(functionWriter.beginWrite(vtuWriter, npoints)) {
114  const PointIterator& pend = factory.endPoints();
115  for(PointIterator pit = factory.beginPoints(); pit != pend; ++pit)
116  functionWriter.write(pit->cell(), pit->duneIndex());
117  }
118  functionWriter.endWrite();
119  }
120 
122  FunctionWriter& functionWriter,
123  unsigned ncorners) const
124  {
125  if(functionWriter.beginWrite(vtuWriter, ncorners)) {
126  const CornerIterator& cend = factory.endCorners();
127  for(CornerIterator cit = factory.beginCorners(); cit != cend; ++cit)
128  functionWriter.write(cit->cell(), cit->duneIndex());
129  }
130  functionWriter.endWrite();
131  }
132 
134  //
135  // Methods for writing whole sections
136  //
137 
138  static std::string getFirstScalar(const WriterList& data) {
139  const WIterator& wend = data.end();
140  for(WIterator wit = data.begin(); wit != wend; ++wit)
141  if((*wit)->ncomps() == 1)
142  return (*wit)->name();
143  return "";
144  }
145 
146  static std::string getFirstVector(const WriterList& data) {
147  const WIterator& wend = data.end();
148  for(WIterator wit = data.begin(); wit != wend; ++wit)
149  if((*wit)->ncomps() == 3)
150  return (*wit)->name();
151  return "";
152  }
153 
154  void writeCellData(VTUWriter& vtuWriter, unsigned ncells) const {
155  if(cellData.empty()) return;
156 
157  vtuWriter.beginCellData(getFirstScalar(cellData),
158  getFirstVector(cellData));
159  const WIterator& wend = cellData.end();
160  for(WIterator wit = cellData.begin(); wit != wend; ++wit)
161  writeCellFunction(vtuWriter, **wit, ncells);
162  vtuWriter.endCellData();
163  }
164 
165  void writePointData(VTUWriter& vtuWriter, unsigned npoints) const {
166  if(pointData.empty()) return;
167 
168  vtuWriter.beginPointData(getFirstScalar(pointData),
169  getFirstVector(pointData));
170  const WIterator& wend = pointData.end();
171  for(WIterator wit = pointData.begin(); wit != wend; ++wit)
172  writePointFunction(vtuWriter, **wit, npoints);
173  vtuWriter.endPointData();
174  }
175 
176  void writeGrid(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
177  unsigned ncorners) {
178  vtuWriter.beginPoints();
179  writePointFunction(vtuWriter, coords, npoints);
180  vtuWriter.endPoints();
181 
182  vtuWriter.beginCells();
183  writeCornerFunction(vtuWriter, connectivity, ncorners);
184  writeCellFunction(vtuWriter, offsets, ncells);
185  if(fileType != polyData)
186  writeCellFunction(vtuWriter, types, ncells);
187  vtuWriter.endCells();
188  }
189 
190  void writeAll(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
191  unsigned ncorners) {
192  writeCellData(vtuWriter, ncells);
193  writePointData(vtuWriter, npoints);
194  writeGrid(vtuWriter, ncells, npoints, ncorners);
195  }
196 
197  public:
198  void writePiece(const std::string& filename, OutputType outputType) {
199  std::ofstream stream;
200  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
201  std::ios_base::eofbit);
202  stream.open(filename.c_str(), std::ios::binary);
203 
204  VTUWriter vtuWriter(stream, outputType, fileType);
205 
206  unsigned ncells = std::distance(factory.beginCells(),
207  factory.endCells());
208  unsigned npoints = std::distance(factory.beginPoints(),
209  factory.endPoints());
210  unsigned ncorners = std::distance(factory.beginCorners(),
211  factory.endCorners());
212 
213  vtuWriter.beginMain(ncells, npoints);
214  writeAll(vtuWriter, ncells, npoints, ncorners);
215  vtuWriter.endMain();
216 
217  if(vtuWriter.beginAppended())
218  writeAll(vtuWriter, ncells, npoints, ncorners);
219  vtuWriter.endAppended();
220 
221  }
222 
224 
240  void writeCollection(const std::string name,
241  const std::string& piecename,
242  const std::string& piecepath)
243  {
244  std::ofstream stream;
245  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
246  std::ios_base::eofbit);
247  stream.open(name.c_str(), std::ios::binary);
248 
249  PVTUWriter writer(stream, fileType);
250 
251  writer.beginMain();
252 
253  // PPointData
254  writer.beginPointData(getFirstScalar(pointData),
255  getFirstVector(pointData));
256  for(WIterator it=pointData.begin(); it!=pointData.end(); ++it)
257  (*it)->addArray(writer);
258  writer.endPointData();
259 
260  // PCellData
261  writer.beginCellData(getFirstScalar(cellData),
262  getFirstVector(cellData));
263  for(WIterator it=cellData.begin(); it!=cellData.end(); ++it)
264  (*it)->addArray(writer);
265  writer.endCellData();
266 
267  // PPoints
268  writer.beginPoints();
269  coords.addArray(writer);
270  writer.endPoints();
271 
272  // Pieces
273  for( int i = 0; i < factory.comm().size(); ++i )
274  writer.addPiece(getParallelPieceName(piecename, piecepath, i));
275 
276  writer.endMain();
277  }
278 
280  //
281  // Filename generators
282  //
283 
285 
295  std::string getParallelPieceName(const std::string& name,
296  const std::string& path, int rank) const
297  {
298  std::ostringstream s;
299  if(path.size() > 0) {
300  s << path;
301  if(path[path.size()-1] != '/')
302  s << '/';
303  }
304  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
305  << ':';
306  s << 'p' << std::setw(4) << std::setfill('0') << rank << ':';
307  s << name;
308  switch(fileType) {
309  case polyData : s << ".vtp"; break;
310  case unstructuredGrid : s << ".vtu"; break;
311  }
312  return s.str();
313  }
314 
316 
325  std::string getParallelHeaderName(const std::string& name,
326  const std::string& path) const
327  {
328  std::ostringstream s;
329  if(path.size() > 0) {
330  s << path;
331  if(path[path.size()-1] != '/')
332  s << '/';
333  }
334  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
335  << ':';
336  s << name;
337  switch(fileType) {
338  case polyData : s << ".pvtp"; break;
339  case unstructuredGrid : s << ".pvtu"; break;
340  }
341  return s.str();
342  }
343 
345 
357  std::string getSerialPieceName(const std::string& name,
358  const std::string& path) const
359  {
360  switch(fileType) {
361  case polyData : return concatPaths(path, name+".vtp");
362  case unstructuredGrid : return concatPaths(path, name+".vtu");
363  }
364  return concatPaths(path, name); // unknown fileType
365  }
366 
368  //
369  // User interface functions for writing
370  //
371 
373 
395  std::string pwrite(const std::string& name, const std::string& path,
396  const std::string& extendpath, OutputType outputType)
397  {
398  MPIGuard guard(factory.comm());
399 
400  // do some magic because paraview can only cope with relative paths to
401  // piece files
402  std::ofstream file;
403  file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
404  std::ios_base::eofbit);
405  std::string piecepath = concatPaths(path, extendpath);
406  std::string relpiecepath = relativePath(path, piecepath);
407 
408  // write this processes .vtu/.vtp piece file
409  std::string fullname = getParallelPieceName(name, piecepath,
410  factory.comm().rank());
411  writePiece(fullname, outputType);
412 
413  // if we are rank 0, write .pvtu/.pvtp parallel header
414  fullname = getParallelHeaderName(name, path);
415  if(factory.comm().rank() == 0)
416  writeCollection(fullname, name, relpiecepath);
417 
418  guard.finalize();
419 
420  return fullname;
421  }
422 
436  std::string write(const std::string &name, OutputType outputType)
437  {
438  // in the parallel case, just use pwrite, it has all the necessary
439  // stuff, so we don't need to reimplement it here.
440  if(factory.comm().size() > 1)
441  return pwrite(name, "", "", outputType);
442 
443  // generate filename for process data
444  std::string pieceName = getSerialPieceName(name, "");
445 
446  writePiece(pieceName, outputType);
447 
448  return pieceName;
449  }
450 
451  };
452 
453  } // namespace VTK
454 
456 
457 } // namespace Dune
458 
459 #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
Common stuff for the VTKWriter.
Include standard header files.
Definition: agrid.hh:60
OutputType
How the bulk data should be stored in the file.
Definition: common.hh:43
FileType
which type of VTK file to write
Definition: common.hh:252
@ polyData
for .vtp files (PolyData)
Definition: common.hh:254
@ unstructuredGrid
for .vtu files (UnstructuredGrid)
Definition: common.hh:256
Definition: basicwriter.hh:35
void writeCellData(VTUWriter &vtuWriter, unsigned ncells) const
Definition: basicwriter.hh:154
BasicWriter(const IteratorFactory &factory_)
Definition: basicwriter.hh:67
std::string getSerialPieceName(const std::string &name, const std::string &path) const
return name of a serial piece file
Definition: basicwriter.hh:357
void writeCollection(const std::string name, const std::string &piecename, const std::string &piecepath)
write header file in parallel case to stream
Definition: basicwriter.hh:240
void writeGrid(VTUWriter &vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners)
Definition: basicwriter.hh:176
void writeAll(VTUWriter &vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners)
Definition: basicwriter.hh:190
std::string pwrite(const std::string &name, const std::string &path, const std::string &extendpath, OutputType outputType)
write output; interface might change later
Definition: basicwriter.hh:395
void clear()
Definition: basicwriter.hh:84
void writeCellFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned ncells) const
Definition: basicwriter.hh:95
void writeCornerFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned ncorners) const
Definition: basicwriter.hh:121
std::string getParallelHeaderName(const std::string &name, const std::string &path) const
return name of a parallel header file
Definition: basicwriter.hh:325
void writePointData(VTUWriter &vtuWriter, unsigned npoints) const
Definition: basicwriter.hh:165
static std::string getFirstVector(const WriterList &data)
Definition: basicwriter.hh:146
FunctionWriterBase< Cell > FunctionWriter
Definition: basicwriter.hh:43
void writePointFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned npoints) const
Definition: basicwriter.hh:109
void writePiece(const std::string &filename, OutputType outputType)
Definition: basicwriter.hh:198
void addCellData(const std::shared_ptr< FunctionWriter > &writer)
Definition: basicwriter.hh:76
static std::string getFirstScalar(const WriterList &data)
Definition: basicwriter.hh:138
std::string getParallelPieceName(const std::string &name, const std::string &path, int rank) const
return name of a parallel piece file
Definition: basicwriter.hh:295
std::string write(const std::string &name, OutputType outputType)
write output (interface might change later)
Definition: basicwriter.hh:436
void addPointData(const std::shared_ptr< FunctionWriter > &writer)
Definition: basicwriter.hh:80
virtual void write(const Cell &, const Domain &)
write at the given position
Definition: functionwriter.hh:59
virtual void endWrite()=0
signal end of writing
virtual bool beginWrite(VTUWriter &writer, std::size_t nitems)=0
start writing with the given writer
writer for the Coordinates array
Definition: functionwriter.hh:147
virtual void addArray(PVTUWriter &writer)
add this field to the given parallel writer
Definition: functionwriter.hh:165
writer for the offsets array
Definition: functionwriter.hh:300
writer for the types array
Definition: functionwriter.hh:340
Dump a .vtu/.vtp files contents to a stream.
Definition: pvtuwriter.hh:62
void endMain()
finish the main PolyData/UnstructuredGrid section
Definition: pvtuwriter.hh:195
void endCellData()
finish CellData section
Definition: pvtuwriter.hh:155
void beginMain(unsigned ghostLevel=0)
start the main PPolyData/PUnstructuredGrid section
Definition: pvtuwriter.hh:189
void beginCellData(const std::string &scalars="", const std::string &vectors="")
start CellData section
Definition: pvtuwriter.hh:146
void beginPointData(const std::string &scalars="", const std::string &vectors="")
start PointData section
Definition: pvtuwriter.hh:120
void addPiece(const std::string &filename)
Add a serial piece to the output file.
Definition: pvtuwriter.hh:215
void endPointData()
finish PointData section
Definition: pvtuwriter.hh:129
void endPoints()
finish section for the point coordinates
Definition: pvtuwriter.hh:171
void beginPoints()
start section for the point coordinates
Definition: pvtuwriter.hh:166
Dump a .vtu/.vtp files contents to a stream.
Definition: vtuwriter.hh:98
bool beginAppended()
start the appended data section
Definition: vtuwriter.hh:345
void endAppended()
finish the appended data section
Definition: vtuwriter.hh:359
void endCellData()
finish CellData section
Definition: vtuwriter.hh:220
void beginMain(unsigned ncells, unsigned npoints)
start the main PolyData/UnstructuredGrid section
Definition: vtuwriter.hh:310
void beginCells()
start section for the grid cells/PolyData lines
Definition: vtuwriter.hh:274
void endPointData()
finish PointData section
Definition: vtuwriter.hh:182
void beginCellData(const std::string &scalars="", const std::string &vectors="")
start CellData section
Definition: vtuwriter.hh:205
void beginPointData(const std::string &scalars="", const std::string &vectors="")
start PointData section
Definition: vtuwriter.hh:167
void endPoints()
finish section for the point coordinates
Definition: vtuwriter.hh:249
void endCells()
start section for the grid cells/PolyData lines
Definition: vtuwriter.hh:285
void beginPoints()
start section for the point coordinates
Definition: vtuwriter.hh:238
void endMain()
finish the main PolyData/UnstructuredGrid section
Definition: vtuwriter.hh:320