dune-grid  2.11
basicwriter.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_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  for(auto&& d : data)
140  if (d->ncomps() == 1)
141  return d->name();
142  return "";
143  }
144 
145  static std::string getFirstVector(const WriterList& data) {
146  for(auto&& d : data)
147  if (d->ncomps() == 3)
148  return d->name();
149  return "";
150  }
151 
152  void writeCellData(VTUWriter& vtuWriter, unsigned ncells) const {
153  if(cellData.empty()) return;
154 
155  vtuWriter.beginCellData(getFirstScalar(cellData),
156  getFirstVector(cellData));
157 
158  for (auto&& cD : cellData)
159  writeCellFunction(vtuWriter, *cD, ncells);
160  vtuWriter.endCellData();
161  }
162 
163  void writePointData(VTUWriter& vtuWriter, unsigned npoints) const {
164  if(pointData.empty()) return;
165 
166  vtuWriter.beginPointData(getFirstScalar(pointData),
167  getFirstVector(pointData));
168 
169  for (auto&& pD : pointData)
170  writePointFunction(vtuWriter, *pD, npoints);
171  vtuWriter.endPointData();
172  }
173 
174  void writeGrid(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
175  unsigned ncorners) {
176  vtuWriter.beginPoints();
177  writePointFunction(vtuWriter, coords, npoints);
178  vtuWriter.endPoints();
179 
180  vtuWriter.beginCells();
181  writeCornerFunction(vtuWriter, connectivity, ncorners);
182  writeCellFunction(vtuWriter, offsets, ncells);
183  if(fileType != polyData)
184  writeCellFunction(vtuWriter, types, ncells);
185  vtuWriter.endCells();
186  }
187 
188  void writeAll(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints,
189  unsigned ncorners) {
190  writeCellData(vtuWriter, ncells);
191  writePointData(vtuWriter, npoints);
192  writeGrid(vtuWriter, ncells, npoints, ncorners);
193  }
194 
195  public:
196  void writePiece(const std::string& filename, OutputType outputType) {
197  std::ofstream stream;
198  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
199  std::ios_base::eofbit);
200  stream.open(filename.c_str(), std::ios::binary);
201 
202  VTUWriter vtuWriter(stream, outputType, fileType);
203 
204  unsigned ncells = std::distance(factory.beginCells(),
205  factory.endCells());
206  unsigned npoints = std::distance(factory.beginPoints(),
207  factory.endPoints());
208  unsigned ncorners = std::distance(factory.beginCorners(),
209  factory.endCorners());
210 
211  vtuWriter.beginMain(ncells, npoints);
212  writeAll(vtuWriter, ncells, npoints, ncorners);
213  vtuWriter.endMain();
214 
215  if(vtuWriter.beginAppended())
216  writeAll(vtuWriter, ncells, npoints, ncorners);
217  vtuWriter.endAppended();
218 
219  }
220 
222 
238  void writeCollection(const std::string name,
239  const std::string& piecename,
240  const std::string& piecepath)
241  {
242  std::ofstream stream;
243  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
244  std::ios_base::eofbit);
245  stream.open(name.c_str(), std::ios::binary);
246 
247  PVTUWriter writer(stream, fileType);
248 
249  writer.beginMain();
250 
251  // PPointData
252  writer.beginPointData(getFirstScalar(pointData),
253  getFirstVector(pointData));
254  for(WIterator it=pointData.begin(); it!=pointData.end(); ++it)
255  (*it)->addArray(writer);
256  writer.endPointData();
257 
258  // PCellData
259  writer.beginCellData(getFirstScalar(cellData),
260  getFirstVector(cellData));
261  for(WIterator it=cellData.begin(); it!=cellData.end(); ++it)
262  (*it)->addArray(writer);
263  writer.endCellData();
264 
265  // PPoints
266  writer.beginPoints();
267  coords.addArray(writer);
268  writer.endPoints();
269 
270  // Pieces
271  for( int i = 0; i < factory.comm().size(); ++i )
272  writer.addPiece(getParallelPieceName(piecename, piecepath, i));
273 
274  writer.endMain();
275  }
276 
278  //
279  // Filename generators
280  //
281 
283 
293  std::string getParallelPieceName(const std::string& name,
294  const std::string& path, int rank) const
295  {
296  std::ostringstream s;
297  if(path.size() > 0) {
298  s << path;
299  if(path[path.size()-1] != '/')
300  s << '/';
301  }
302  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
303  << ':';
304  s << 'p' << std::setw(4) << std::setfill('0') << rank << ':';
305  s << name;
306  switch(fileType) {
307  case polyData : s << ".vtp"; break;
308  case unstructuredGrid : s << ".vtu"; break;
309  }
310  return s.str();
311  }
312 
314 
323  std::string getParallelHeaderName(const std::string& name,
324  const std::string& path) const
325  {
326  std::ostringstream s;
327  if(path.size() > 0) {
328  s << path;
329  if(path[path.size()-1] != '/')
330  s << '/';
331  }
332  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
333  << ':';
334  s << name;
335  switch(fileType) {
336  case polyData : s << ".pvtp"; break;
337  case unstructuredGrid : s << ".pvtu"; break;
338  }
339  return s.str();
340  }
341 
343 
355  std::string getSerialPieceName(const std::string& name,
356  const std::string& path) const
357  {
358  switch(fileType) {
359  case polyData : return concatPaths(path, name+".vtp");
360  case unstructuredGrid : return concatPaths(path, name+".vtu");
361  }
362  return concatPaths(path, name); // unknown fileType
363  }
364 
366  //
367  // User interface functions for writing
368  //
369 
371 
393  std::string pwrite(const std::string& name, const std::string& path,
394  const std::string& extendpath, OutputType outputType)
395  {
396  MPIGuard guard(factory.comm());
397 
398  // do some magic because paraview can only cope with relative paths to
399  // piece files
400  std::ofstream file;
401  file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
402  std::ios_base::eofbit);
403  std::string piecepath = concatPaths(path, extendpath);
404  std::string relpiecepath = relativePath(path, piecepath);
405 
406  // write this processes .vtu/.vtp piece file
407  std::string fullname = getParallelPieceName(name, piecepath,
408  factory.comm().rank());
409  writePiece(fullname, outputType);
410 
411  // if we are rank 0, write .pvtu/.pvtp parallel header
412  fullname = getParallelHeaderName(name, path);
413  if(factory.comm().rank() == 0)
414  writeCollection(fullname, name, relpiecepath);
415 
416  guard.finalize();
417 
418  return fullname;
419  }
420 
434  std::string write(const std::string &name, OutputType outputType)
435  {
436  // in the parallel case, just use pwrite, it has all the necessary
437  // stuff, so we don't need to reimplement it here.
438  if(factory.comm().size() > 1)
439  return pwrite(name, "", "", outputType);
440 
441  // generate filename for process data
442  std::string pieceName = getSerialPieceName(name, "");
443 
444  writePiece(pieceName, outputType);
445 
446  return pieceName;
447  }
448 
449  };
450 
451  } // namespace VTK
452 
454 
455 } // namespace Dune
456 
457 #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
FunctionWriterBase< Cell > FunctionWriter
Definition: basicwriter.hh:43
Dump a .vtu/.vtp files contents to a stream.
Definition: pvtuwriter.hh:62
void addCellData(const std::shared_ptr< FunctionWriter > &writer)
Definition: basicwriter.hh:76
for .vtu files (UnstructuredGrid)
Definition: common.hh:256
writer for the offsets array
Definition: functionwriter.hh:298
for .vtp files (PolyData)
Definition: common.hh:254
virtual void addArray(PVTUWriter &writer)
add this field to the given parallel writer
Definition: functionwriter.hh:165
void beginCellData(const std::string &scalars="", const std::string &vectors="")
start CellData section
Definition: vtuwriter.hh:205
void beginCellData(const std::string &scalars="", const std::string &vectors="")
start CellData section
Definition: pvtuwriter.hh:146
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:393
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
std::string getParallelPieceName(const std::string &name, const std::string &path, int rank) const
return name of a parallel piece file
Definition: basicwriter.hh:293
void beginPoints()
start section for the point coordinates
Definition: vtuwriter.hh:238
void addPiece(const std::string &filename)
Add a serial piece to the output file.
Definition: pvtuwriter.hh:215
void endCellData()
finish CellData section
Definition: pvtuwriter.hh:155
void endMain()
finish the main PolyData/UnstructuredGrid section
Definition: pvtuwriter.hh:195
void writePiece(const std::string &filename, OutputType outputType)
Definition: basicwriter.hh:196
std::string getParallelHeaderName(const std::string &name, const std::string &path) const
return name of a parallel header file
Definition: basicwriter.hh:323
static std::string getFirstScalar(const WriterList &data)
Definition: basicwriter.hh:138
virtual void write(const Cell &, const Domain &)
write at the given position
Definition: functionwriter.hh:59
void beginPoints()
start section for the point coordinates
Definition: pvtuwriter.hh:166
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:238
void beginMain(unsigned ncells, unsigned npoints)
start the main PolyData/UnstructuredGrid section
Definition: vtuwriter.hh:310
void writeGrid(VTUWriter &vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners)
Definition: basicwriter.hh:174
static std::string getFirstVector(const WriterList &data)
Definition: basicwriter.hh:145
void beginPointData(const std::string &scalars="", const std::string &vectors="")
start PointData section
Definition: vtuwriter.hh:167
FileType
which type of VTK file to write
Definition: common.hh:252
void beginCells()
start section for the grid cells/PolyData lines
Definition: vtuwriter.hh:274
void endPointData()
finish PointData section
Definition: pvtuwriter.hh:129
virtual void endWrite()=0
signal end of writing
writer for the Coordinates array
Definition: functionwriter.hh:145
Definition: basicwriter.hh:35
void beginPointData(const std::string &scalars="", const std::string &vectors="")
start PointData section
Definition: pvtuwriter.hh:120
void endMain()
finish the main PolyData/UnstructuredGrid section
Definition: vtuwriter.hh:320
void addPointData(const std::shared_ptr< FunctionWriter > &writer)
Definition: basicwriter.hh:80
Include standard header files.
Definition: agrid.hh:59
void writeAll(VTUWriter &vtuWriter, unsigned ncells, unsigned npoints, unsigned ncorners)
Definition: basicwriter.hh:188
bool beginAppended()
start the appended data section
Definition: vtuwriter.hh:345
void clear()
Definition: basicwriter.hh:84
void beginMain(unsigned ghostLevel=0)
start the main PPolyData/PUnstructuredGrid section
Definition: pvtuwriter.hh:189
std::string getSerialPieceName(const std::string &name, const std::string &path) const
return name of a serial piece file
Definition: basicwriter.hh:355
void endAppended()
finish the appended data section
Definition: vtuwriter.hh:359
void endPoints()
finish section for the point coordinates
Definition: pvtuwriter.hh:171
void writePointData(VTUWriter &vtuWriter, unsigned npoints) const
Definition: basicwriter.hh:163
void writeCornerFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned ncorners) const
Definition: basicwriter.hh:121
BasicWriter(const IteratorFactory &factory_)
Definition: basicwriter.hh:67
void writePointFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned npoints) const
Definition: basicwriter.hh:109
Common stuff for the VTKWriter.
Dump a .vtu/.vtp files contents to a stream.
Definition: vtuwriter.hh:98
void writeCellFunction(VTUWriter &vtuWriter, FunctionWriter &functionWriter, unsigned ncells) const
Definition: basicwriter.hh:95
writer for the types array
Definition: functionwriter.hh:338
virtual bool beginWrite(VTUWriter &writer, std::size_t nitems)=0
start writing with the given writer
void endPointData()
finish PointData section
Definition: vtuwriter.hh:182
std::string write(const std::string &name, OutputType outputType)
write output (interface might change later)
Definition: basicwriter.hh:434
OutputType
How the bulk data should be stored in the file.
Definition: common.hh:43
void writeCellData(VTUWriter &vtuWriter, unsigned ncells) const
Definition: basicwriter.hh:152
void endCellData()
finish CellData section
Definition: vtuwriter.hh:220