dune-grid  2.3beta2
basicwriter.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
5 #define DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
6 
7 #include <fstream>
8 #include <iomanip>
9 #include <iterator>
10 #include <list>
11 #include <sstream>
12 #include <string>
13 
14 #include <dune/common/parallel/mpiguard.hh>
15 #include <dune/common/path.hh>
16 #include <dune/common/shared_ptr.hh>
17 
18 #include <dune/geometry/referenceelements.hh>
19 
24 
25 namespace Dune
26 {
29 
30  namespace VTK {
31 
32  template<typename IteratorFactory>
33  class BasicWriter {
34  typedef typename IteratorFactory::CellIterator CellIterator;
35  typedef typename IteratorFactory::CornerIterator CornerIterator;
36  typedef typename IteratorFactory::PointIterator PointIterator;
37 
38  typedef typename IteratorFactory::Cell Cell;
39 
40  public:
42 
43  private:
44  typedef std::list<shared_ptr<FunctionWriter> > WriterList;
45  typedef typename WriterList::const_iterator WIterator;
46 
47  typedef typename Cell::ctype ctype;
48  static const unsigned celldim = Cell::mydimension;
49  typedef ReferenceElements<ctype, celldim> Refelems;
50 
51  static const FileType fileType = celldim == 1
53 
54  const IteratorFactory& factory;
55 
56  WriterList cellData;
57  WriterList pointData;
58 
60  typename IteratorFactory::ConnectivityWriter connectivity;
61  OffsetsWriter<Cell> offsets;
62  TypesWriter<Cell> types;
63 
64  public:
65  BasicWriter(const IteratorFactory& factory_)
66  : factory(factory_), connectivity(factory.makeConnectivity())
67  { }
68 
70  //
71  // Methods for adding data
72  //
73 
74  void addCellData(const shared_ptr<FunctionWriter>& writer) {
75  cellData.push_back(writer);
76  }
77 
78  void addPointData(const shared_ptr<FunctionWriter>& writer) {
79  pointData.push_back(writer);
80  }
81 
82  void clear() {
83  cellData.clear();
84  pointData.clear();
85  }
86 
87  protected:
89  //
90  // Methods for writing single functions
91  //
92 
93  void writeCellFunction(VTUWriter& vtuWriter,
94  FunctionWriter& functionWriter,
95  unsigned ncells) const
96  {
97  if(functionWriter.beginWrite(vtuWriter, ncells)) {
98  const CellIterator& cellend = factory.endCells();
99  for(CellIterator cellit = factory.beginCells(); cellit != cellend;
100  ++cellit)
101  functionWriter.write(*cellit, Refelems::general(cellit->type()).
102  position(0,0));
103  }
104  functionWriter.endWrite();
105  }
106 
107  void writePointFunction(VTUWriter& vtuWriter,
108  FunctionWriter& functionWriter,
109  unsigned npoints) const
110  {
111  if(functionWriter.beginWrite(vtuWriter, npoints)) {
112  const PointIterator& pend = factory.endPoints();
113  for(PointIterator pit = factory.beginPoints(); pit != pend; ++pit)
114  functionWriter.write(pit->cell(), pit->duneIndex());
115  }
116  functionWriter.endWrite();
117  }
118 
120  FunctionWriter& functionWriter,
121  unsigned ncorners) const
122  {
123  if(functionWriter.beginWrite(vtuWriter, ncorners)) {
124  const CornerIterator& cend = factory.endCorners();
125  for(CornerIterator cit = factory.beginCorners(); cit != cend; ++cit)
126  functionWriter.write(cit->cell(), cit->duneIndex());
127  }
128  functionWriter.endWrite();
129  }
130 
132  //
133  // Methods for writing whole sections
134  //
135 
136  static std::string getFirstScalar(const WriterList& data) {
137  const WIterator& wend = data.end();
138  for(WIterator wit = data.begin(); wit != wend; ++wit)
139  if((*wit)->ncomps() == 1)
140  return (*wit)->name();
141  return "";
142  }
143 
144  static std::string getFirstVector(const WriterList& data) {
145  const WIterator& wend = data.end();
146  for(WIterator wit = data.begin(); wit != wend; ++wit)
147  if((*wit)->ncomps() == 3)
148  return (*wit)->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  const WIterator& wend = cellData.end();
158  for(WIterator wit = cellData.begin(); wit != wend; ++wit)
159  writeCellFunction(vtuWriter, **wit, 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  const WIterator& wend = pointData.end();
169  for(WIterator wit = pointData.begin(); wit != wend; ++wit)
170  writePointFunction(vtuWriter, **wit, 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  }
363 
365  //
366  // User interface functions for writing
367  //
368 
370 
392  std::string pwrite(const std::string& name, const std::string& path,
393  const std::string& extendpath, OutputType outputType)
394  {
395  MPIGuard guard(factory.comm());
396 
397  // do some magic because paraview can only cope with relative pathes to
398  // piece files
399  std::ofstream file;
400  file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
401  std::ios_base::eofbit);
402  std::string piecepath = concatPaths(path, extendpath);
403  std::string relpiecepath = relativePath(path, piecepath);
404 
405  // write this processes .vtu/.vtp piece file
406  std::string fullname = getParallelPieceName(name, piecepath,
407  factory.comm().rank());
408  writePiece(fullname, outputType);
409 
410  // if we are rank 0, write .pvtu/.pvtp parallel header
411  fullname = getParallelHeaderName(name, path);
412  if(factory.comm().rank() == 0)
413  writeCollection(fullname, name, relpiecepath);
414 
415  guard.finalize();
416 
417  return fullname;
418  }
419 
433  std::string write(const std::string &name, OutputType outputType)
434  {
435  // in the parallel case, just use pwrite, it has all the necessary
436  // stuff, so we don't need to reimplement it here.
437  if(factory.comm().size() > 1)
438  return pwrite(name, "", "", outputType);
439 
440  // generate filename for process data
441  std::string pieceName = getSerialPieceName(name, "");
442 
443  writePiece(pieceName, outputType);
444 
445  return pieceName;
446  }
447 
448  };
449 
450  } // namespace VTK
451 
453 
454 } // namespace Dune
455 
456 #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH