dune-grid  2.2.1
basicwriter.hh
Go to the documentation of this file.
1 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=8 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/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 GenericReferenceElements<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(filename.c_str(), std::ios::binary);
198  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
199  std::ios_base::eofbit);
200 
201  VTUWriter vtuWriter(stream, outputType, fileType);
202 
203  unsigned ncells = std::distance(factory.beginCells(),
204  factory.endCells());
205  unsigned npoints = std::distance(factory.beginPoints(),
206  factory.endPoints());
207  unsigned ncorners = std::distance(factory.beginCorners(),
208  factory.endCorners());
209 
210  vtuWriter.beginMain(ncells, npoints);
211  writeAll(vtuWriter, ncells, npoints, ncorners);
212  vtuWriter.endMain();
213 
214  if(vtuWriter.beginAppended())
215  writeAll(vtuWriter, ncells, npoints, ncorners);
216  vtuWriter.endAppended();
217 
218  }
219 
221 
237  void writeCollection(const std::string name,
238  const std::string& piecename,
239  const std::string& piecepath)
240  {
241  std::ofstream stream(name.c_str(), std::ios::binary);
242  stream.exceptions(std::ios_base::badbit | std::ios_base::failbit |
243  std::ios_base::eofbit);
244  PVTUWriter writer(stream, fileType);
245 
246  writer.beginMain();
247 
248  // PPointData
249  writer.beginPointData(getFirstScalar(pointData),
250  getFirstVector(pointData));
251  for(WIterator it=pointData.begin(); it!=pointData.end(); ++it)
252  (*it)->addArray(writer);
253  writer.endPointData();
254 
255  // PCellData
256  writer.beginCellData(getFirstScalar(cellData),
257  getFirstVector(cellData));
258  for(WIterator it=cellData.begin(); it!=cellData.end(); ++it)
259  (*it)->addArray(writer);
260  writer.endCellData();
261 
262  // PPoints
263  writer.beginPoints();
264  coords.addArray(writer);
265  writer.endPoints();
266 
267  // Pieces
268  for( int i = 0; i < factory.comm().size(); ++i )
269  writer.addPiece(getParallelPieceName(piecename, piecepath, i));
270 
271  writer.endMain();
272  }
273 
275  //
276  // Filename generators
277  //
278 
280 
290  std::string getParallelPieceName(const std::string& name,
291  const std::string& path, int rank) const
292  {
293  std::ostringstream s;
294  if(path.size() > 0) {
295  s << path;
296  if(path[path.size()-1] != '/')
297  s << '/';
298  }
299  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
300  << ':';
301  s << 'p' << std::setw(4) << std::setfill('0') << rank << ':';
302  s << name;
303  switch(fileType) {
304  case polyData: s << ".vtp"; break;
305  case unstructuredGrid: s << ".vtu"; break;
306  }
307  return s.str();
308  }
309 
311 
320  std::string getParallelHeaderName(const std::string& name,
321  const std::string& path) const
322  {
323  std::ostringstream s;
324  if(path.size() > 0) {
325  s << path;
326  if(path[path.size()-1] != '/')
327  s << '/';
328  }
329  s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size()
330  << ':';
331  s << name;
332  switch(fileType) {
333  case polyData: s << ".pvtp"; break;
334  case unstructuredGrid: s << ".pvtu"; break;
335  }
336  return s.str();
337  }
338 
340 
352  std::string getSerialPieceName(const std::string& name,
353  const std::string& path) const
354  {
355  switch(fileType) {
356  case polyData: return concatPaths(path, name+".vtp");
357  case unstructuredGrid: return concatPaths(path, name+".vtu");
358  }
359  }
360 
362  //
363  // User interface functions for writing
364  //
365 
367 
389  std::string pwrite(const std::string& name, const std::string& path,
390  const std::string& extendpath, OutputType outputType)
391  {
392  MPIGuard guard(factory.comm());
393 
394  // do some magic because paraview can only cope with relative pathes to
395  // piece files
396  std::ofstream file;
397  std::string piecepath = concatPaths(path, extendpath);
398  std::string relpiecepath = relativePath(path, piecepath);
399 
400  // write this processes .vtu/.vtp piece file
401  std::string fullname = getParallelPieceName(name, piecepath,
402  factory.comm().rank());
403  writePiece(fullname, outputType);
404 
405  // if we are rank 0, write .pvtu/.pvtp parallel header
406  fullname = getParallelHeaderName(name, path);
407  if(factory.comm().rank() == 0)
408  writeCollection(fullname, name, relpiecepath);
409 
410  guard.finalize();
411 
412  return fullname;
413  }
414 
428  std::string write(const std::string &name, OutputType outputType)
429  {
430  // in the parallel case, just use pwrite, it has all the necessary
431  // stuff, so we don't need to reimplement it here.
432  if(factory.comm().size() > 1)
433  return pwrite(name, "", "", outputType);
434 
435  // generate filename for process data
436  std::string pieceName = getSerialPieceName(name, "");
437 
438  writePiece(pieceName, outputType);
439 
440  return pieceName;
441  }
442 
443  };
444 
445  } // namespace VTK
446 
448 
449 } // namespace Dune
450 
451 #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH