Dune Core Modules (2.5.2)

vtkwriter.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_VTKWRITER_HH
5 #define DUNE_VTKWRITER_HH
6 
7 #include <cstring>
8 #include <iostream>
9 #include <string>
10 #include <fstream>
11 #include <sstream>
12 #include <iomanip>
13 #include <memory>
14 
15 #include <vector>
16 #include <list>
17 #include <map>
18 
21 #include <dune/common/std/memory.hh>
22 #include <dune/common/indent.hh>
24 #include <dune/common/path.hh>
25 #include <dune/geometry/referenceelements.hh>
27 #include <dune/grid/common/gridenums.hh>
31 #include <dune/grid/io/file/vtk/pvtuwriter.hh>
32 #include <dune/grid/io/file/vtk/streams.hh>
33 #include <dune/grid/io/file/vtk/vtuwriter.hh>
34 
48 namespace Dune
49 {
50 
51  namespace detail {
52 
53  template<typename F, typename = int>
54  struct _has_local_context
55  : public std::false_type
56  {};
57 
58  template<typename T>
59  struct _has_local_context<T,typename std::enable_if<(sizeof(std::declval<T>().localContext()) > 0),int>::type>
60  : public std::true_type
61  {};
62 
63  }
64 
65  namespace VTKWriteTypeTraits {
66  template<typename T>
67  struct IsLocalFunction
68  {
69  };
70  }
71 
72  // Forward-declaration here, so the class can be friend of VTKWriter
73  template <class GridView>
74  class VTKSequenceWriterBase;
75  template <class GridView>
76  class VTKSequenceWriter;
77 
86  template< class GridView >
87  class VTKWriter {
88 
89  // VTKSequenceWriterBase needs getSerialPieceName
90  // and getParallelHeaderName
91  friend class VTKSequenceWriterBase<GridView>;
92  // VTKSequenceWriter needs the grid view, to get the MPI size and rank
93  friend class VTKSequenceWriter<GridView>;
94 
95  // extract types
96  typedef typename GridView::Grid Grid;
97  typedef typename GridView::ctype DT;
98  enum { n = GridView::dimension };
99  enum { w = GridView::dimensionworld };
100 
101  typedef typename GridView::template Codim< 0 >::Entity Cell;
102  typedef typename GridView::template Codim< n >::Entity Vertex;
103  typedef Cell Entity;
104 
105  typedef typename GridView::IndexSet IndexSet;
106 
107  static const PartitionIteratorType VTK_Partition = InteriorBorder_Partition;
108  //static const PartitionIteratorType VTK_Partition = All_Partition;
109 
110  typedef typename GridView::template Codim< 0 >
111  ::template Partition< VTK_Partition >::Iterator
112  GridCellIterator;
113  typedef typename GridView::template Codim< n >
114  ::template Partition< VTK_Partition >::Iterator
115  GridVertexIterator;
116 
117  typedef typename GridCellIterator::Reference EntityReference;
118 
119  typedef typename GridView::template Codim< 0 >
120  ::Entity::Geometry::LocalCoordinate Coordinate;
121 
123 
124  // return true if entity should be skipped in Vertex and Corner iterator
125  static bool skipEntity( const PartitionType entityType )
126  {
127  switch( VTK_Partition )
128  {
129  // for All_Partition no entity has to be skipped
130  case All_Partition: return false;
131  case InteriorBorder_Partition: return ( entityType != InteriorEntity );
132  default: DUNE_THROW(NotImplemented,"Add check for this partition type");
133  }
134  return false ;
135  }
136 
137  public:
138 
140 
141  protected:
142 
144 
148  {
149 
150  public:
151 
153 
156  {
157 
159  virtual void bind(const Entity& e) = 0;
160 
162  virtual void unbind() = 0;
163 
165 
168  virtual void write(const Coordinate& pos, Writer& w, std::size_t count) const = 0;
169 
170  virtual ~FunctionWrapperBase()
171  {}
172 
173  };
174 
176  template<typename F>
178  : public FunctionWrapperBase
179  {
180  using Function = typename std::decay<F>::type;
181 
182  template<typename F_>
183  FunctionWrapper(F_&& f)
184  : _f(std::forward<F_>(f))
185  {}
186 
187  virtual void bind(const Entity& e)
188  {
189  _f.bind(e);
190  }
191 
192  virtual void unbind()
193  {
194  _f.unbind();
195  }
196 
197  virtual void write(const Coordinate& pos, Writer& w, std::size_t count) const
198  {
199  auto r = _f(pos);
200  // we need to do different things here depending on whether r supports indexing into it or not.
201  do_write(w,r,count,is_indexable<decltype(r)>());
202  }
203 
204  private:
205 
206  template<typename R>
207  void do_write(Writer& w, const R& r, std::size_t count, std::true_type) const
208  {
209  for (std::size_t i = 0; i < count; ++i)
210  w.write(r[i]);
211  }
212 
213  template<typename R>
214  void do_write(Writer& w, const R& r, std::size_t count, std::false_type) const
215  {
216  assert(count == 1);
217  w.write(r);
218  }
219 
220  Function _f;
221  };
222 
225  : public FunctionWrapperBase
226  {
227  VTKFunctionWrapper(const std::shared_ptr< const VTKFunction >& f)
228  : _f(f)
229  , _entity(nullptr)
230  {}
231 
232  virtual void bind(const Entity& e)
233  {
234  _entity = &e;
235  }
236 
237  virtual void unbind()
238  {
239  _entity = nullptr;
240  }
241 
242  virtual void write(const Coordinate& pos, Writer& w, std::size_t count) const
243  {
244  for (std::size_t i = 0; i < count; ++i)
245  w.write(_f->evaluate(i,*_entity,pos));
246  }
247 
248  private:
249 
250  std::shared_ptr< const VTKFunction > _f;
251  const Entity* _entity;
252 
253  };
254 
256  template<typename F>
258  typename std::enable_if<detail::_has_local_context<F>::value,int>::type dummy = 0)
259  : _f(Dune::Std::make_unique<FunctionWrapper<F> >(std::forward<F>(f)))
260  , _fieldInfo(fieldInfo)
261  {}
262 
264  template<typename F>
266  typename std::enable_if<not detail::_has_local_context<F>::value,int>::type dummy = 0)
267  : _f(Dune::Std::make_unique< FunctionWrapper<
268  typename std::decay<decltype(localFunction(std::forward<F>(f)))>::type
269  > >(localFunction(std::forward<F>(f))))
270  , _fieldInfo(fieldInfo)
271  {}
272 
274  explicit VTKLocalFunction (const std::shared_ptr< const VTKFunction >& vtkFunctionPtr)
275  : _f(Dune::Std::make_unique<VTKFunctionWrapper>(vtkFunctionPtr))
276  , _fieldInfo(
277  vtkFunctionPtr->name(),
278  vtkFunctionPtr->ncomps() > 1 ? VTK::FieldInfo::Type::vector : VTK::FieldInfo::Type::scalar,
279  vtkFunctionPtr->ncomps()
280  )
281  {}
282 
284  std::string name() const
285  {
286  return fieldInfo().name();
287  }
288 
290  const VTK::FieldInfo& fieldInfo() const
291  {
292  return _fieldInfo;
293  }
294 
296  void bind(const Entity& e) const
297  {
298  _f->bind(e);
299  }
300 
302  void unbind() const
303  {
304  _f->unbind();
305  }
306 
308  void write(const Coordinate& pos, Writer& w) const
309  {
310  _f->write(pos,w,fieldInfo().size());
311  }
312 
313  std::shared_ptr<FunctionWrapperBase> _f;
314  VTK::FieldInfo _fieldInfo;
315 
316  };
317 
318  typedef typename std::list<VTKLocalFunction>::const_iterator FunctionIterator;
319 
321 
326  class CellIterator : public GridCellIterator
327  {
328  public:
330  CellIterator(const GridCellIterator & x) : GridCellIterator(x) {}
334  {
335  return ReferenceElements<DT,n>::general((*this)->type()).position(0,0);
336  }
337  };
338 
339  CellIterator cellBegin() const
340  {
341  return gridView_.template begin< 0, VTK_Partition >();
342  }
343 
344  CellIterator cellEnd() const
345  {
346  return gridView_.template end< 0, VTK_Partition >();
347  }
348 
350 
365  public ForwardIteratorFacade<VertexIterator, const Entity, EntityReference, int>
366  {
367  GridCellIterator git;
368  GridCellIterator gend;
369  VTK::DataMode datamode;
370  // Index of the currently visited corner within the current element.
371  // NOTE: this is in Dune-numbering, in contrast to CornerIterator.
372  int cornerIndexDune;
373  const VertexMapper & vertexmapper;
374  std::vector<bool> visited;
375  // in conforming mode, for each vertex id (as obtained by vertexmapper)
376  // hold its number in the iteration order (VertexIterator)
377  int offset;
378 
379  // hide operator ->
380  void operator->();
381  protected:
382  void basicIncrement ()
383  {
384  if( git == gend )
385  return;
386  ++cornerIndexDune;
387  const int numCorners = git->subEntities(n);
388  if( cornerIndexDune == numCorners )
389  {
390  offset += numCorners;
391  cornerIndexDune = 0;
392 
393  ++git;
394  while( (git != gend) && skipEntity( git->partitionType() ) )
395  ++git;
396  }
397  }
398  public:
399  VertexIterator(const GridCellIterator & x,
400  const GridCellIterator & end,
401  const VTK::DataMode & dm,
402  const VertexMapper & vm) :
403  git(x), gend(end), datamode(dm), cornerIndexDune(0),
404  vertexmapper(vm), visited(vm.size(), false),
405  offset(0)
406  {
407  if (datamode == VTK::conforming && git != gend)
408  visited[vertexmapper.subIndex(*git,cornerIndexDune,n)] = true;
409  }
410  void increment ()
411  {
412  switch (datamode)
413  {
414  case VTK::conforming :
415  while(visited[vertexmapper.subIndex(*git,cornerIndexDune,n)])
416  {
417  basicIncrement();
418  if (git == gend) return;
419  }
420  visited[vertexmapper.subIndex(*git,cornerIndexDune,n)] = true;
421  break;
422  case VTK::nonconforming :
423  basicIncrement();
424  break;
425  }
426  }
427  bool equals (const VertexIterator & cit) const
428  {
429  return git == cit.git
430  && cornerIndexDune == cit.cornerIndexDune
431  && datamode == cit.datamode;
432  }
433  EntityReference dereference() const
434  {
435  return *git;
436  }
438  int localindex () const
439  {
440  return cornerIndexDune;
441  }
443  const FieldVector<DT,n> & position () const
444  {
445  return ReferenceElements<DT,n>::general(git->type())
446  .position(cornerIndexDune,n);
447  }
448  };
449 
450  VertexIterator vertexBegin () const
451  {
452  return VertexIterator( gridView_.template begin< 0, VTK_Partition >(),
453  gridView_.template end< 0, VTK_Partition >(),
454  datamode, *vertexmapper );
455  }
456 
457  VertexIterator vertexEnd () const
458  {
459  return VertexIterator( gridView_.template end< 0, VTK_Partition >(),
460  gridView_.template end< 0, VTK_Partition >(),
461  datamode, *vertexmapper );
462  }
463 
465 
480  public ForwardIteratorFacade<CornerIterator, const Entity, EntityReference, int>
481  {
482  GridCellIterator git;
483  GridCellIterator gend;
484  VTK::DataMode datamode;
485  // Index of the currently visited corner within the current element.
486  // NOTE: this is in VTK-numbering, in contrast to VertexIterator.
487  int cornerIndexVTK;
488  const VertexMapper & vertexmapper;
489  // in conforming mode, for each vertex id (as obtained by vertexmapper)
490  // hold its number in the iteration order of VertexIterator (*not*
491  // CornerIterator)
492  const std::vector<int> & number;
493  // holds the number of corners of all the elements we have seen so far,
494  // excluding the current element
495  int offset;
496 
497  // hide operator ->
498  void operator->();
499  public:
500  CornerIterator(const GridCellIterator & x,
501  const GridCellIterator & end,
502  const VTK::DataMode & dm,
503  const VertexMapper & vm,
504  const std::vector<int> & num) :
505  git(x), gend(end), datamode(dm), cornerIndexVTK(0),
506  vertexmapper(vm),
507  number(num), offset(0) {}
508  void increment ()
509  {
510  if( git == gend )
511  return;
512  ++cornerIndexVTK;
513  const int numCorners = git->subEntities(n);
514  if( cornerIndexVTK == numCorners )
515  {
516  offset += numCorners;
517  cornerIndexVTK = 0;
518 
519  ++git;
520  while( (git != gend) && skipEntity( git->partitionType() ) )
521  ++git;
522  }
523  }
524  bool equals (const CornerIterator & cit) const
525  {
526  return git == cit.git
527  && cornerIndexVTK == cit.cornerIndexVTK
528  && datamode == cit.datamode;
529  }
530  EntityReference dereference() const
531  {
532  return *git;
533  }
535 
539  int id () const
540  {
541  switch (datamode)
542  {
543  case VTK::conforming :
544  return
545  number[vertexmapper.subIndex(*git,VTK::renumber(*git,cornerIndexVTK),
546  n)];
547  case VTK::nonconforming :
548  return offset + VTK::renumber(*git,cornerIndexVTK);
549  default :
550  DUNE_THROW(IOError,"VTKWriter: unsupported DataMode" << datamode);
551  }
552  }
553  };
554 
555  CornerIterator cornerBegin () const
556  {
557  return CornerIterator( gridView_.template begin< 0, VTK_Partition >(),
558  gridView_.template end< 0, VTK_Partition >(),
559  datamode, *vertexmapper, number );
560  }
561 
562  CornerIterator cornerEnd () const
563  {
564  return CornerIterator( gridView_.template end< 0, VTK_Partition >(),
565  gridView_.template end< 0, VTK_Partition >(),
566  datamode, *vertexmapper, number );
567  }
568 
569  public:
577  explicit VTKWriter ( const GridView &gridView,
578  VTK::DataMode dm = VTK::conforming )
579  : gridView_( gridView ),
580  datamode( dm ),
581  polyhedralCellsPresent_( checkForPolyhedralCells() )
582  { }
583 
588  void addCellData (const std::shared_ptr< const VTKFunction > & p)
589  {
590  celldata.push_back(VTKLocalFunction(p));
591  }
592 
593  template<typename F>
594  void addCellData(F&& f, VTK::FieldInfo vtkFieldInfo)
595  {
596  celldata.push_back(VTKLocalFunction(std::forward<F>(f),vtkFieldInfo));
597  }
598 
614  template<class Container>
615  void addCellData (const Container& v, const std::string &name, int ncomps = 1)
616  {
618  for (int c=0; c<ncomps; ++c) {
619  std::stringstream compName;
620  compName << name;
621  if (ncomps>1)
622  compName << "[" << c << "]";
623  VTKFunction* p = new Function(gridView_, v, compName.str(), ncomps, c);
624  addCellData(std::shared_ptr< const VTKFunction >(p));
625  }
626  }
627 
632  void addVertexData (const std::shared_ptr< const VTKFunction > & p)
633  {
634  vertexdata.push_back(VTKLocalFunction(p));
635  }
636 
637  template<typename F>
638  void addVertexData(F&& f, VTK::FieldInfo vtkFieldInfo)
639  {
640  vertexdata.push_back(VTKLocalFunction(std::forward<F>(f),vtkFieldInfo));
641  }
642 
643 
659  template<class Container>
660  void addVertexData (const Container& v, const std::string &name, int ncomps=1)
661  {
663  for (int c=0; c<ncomps; ++c) {
664  std::stringstream compName;
665  compName << name;
666  if (ncomps>1)
667  compName << "[" << c << "]";
668  VTKFunction* p = new Function(gridView_, v, compName.str(), ncomps, c);
669  addVertexData(std::shared_ptr< const VTKFunction >(p));
670  }
671  }
672 
674  void clear ()
675  {
676  celldata.clear();
677  vertexdata.clear();
678  }
679 
681  virtual ~VTKWriter ()
682  {
683  this->clear();
684  }
685 
697  std::string write ( const std::string &name,
698  VTK::OutputType type = VTK::ascii )
699  {
700  return write( name, type, gridView_.comm().rank(), gridView_.comm().size() );
701  }
702 
729  std::string pwrite ( const std::string & name, const std::string & path, const std::string & extendpath,
730  VTK::OutputType type = VTK::ascii )
731  {
732  return pwrite( name, path, extendpath, type, gridView_.comm().rank(), gridView_.comm().size() );
733  }
734 
735  protected:
737 
748  std::string getParallelPieceName(const std::string& name,
749  const std::string& path,
750  int commRank, int commSize) const
751  {
752  std::ostringstream s;
753  if(path.size() > 0) {
754  s << path;
755  if(path[path.size()-1] != '/')
756  s << '/';
757  }
758  s << 's' << std::setw(4) << std::setfill('0') << commSize << '-';
759  s << 'p' << std::setw(4) << std::setfill('0') << commRank << '-';
760  s << name;
761  if(GridView::dimension > 1)
762  s << ".vtu";
763  else
764  s << ".vtp";
765  return s.str();
766  }
767 
769 
779  std::string getParallelHeaderName(const std::string& name,
780  const std::string& path,
781  int commSize) const
782  {
783  std::ostringstream s;
784  if(path.size() > 0) {
785  s << path;
786  if(path[path.size()-1] != '/')
787  s << '/';
788  }
789  s << 's' << std::setw(4) << std::setfill('0') << commSize << '-';
790  s << name;
791  if(GridView::dimension > 1)
792  s << ".pvtu";
793  else
794  s << ".pvtp";
795  return s.str();
796  }
797 
799 
811  std::string getSerialPieceName(const std::string& name,
812  const std::string& path) const
813  {
814  static const std::string extension =
815  GridView::dimension == 1 ? ".vtp" : ".vtu";
816 
817  return concatPaths(path, name+extension);
818  }
819 
835  std::string write ( const std::string &name,
836  VTK::OutputType type,
837  const int commRank,
838  const int commSize )
839  {
840  // in the parallel case, just use pwrite, it has all the necessary
841  // stuff, so we don't need to reimplement it here.
842  if(commSize > 1)
843  return pwrite(name, "", "", type, commRank, commSize);
844 
845  // make data mode visible to private functions
846  outputtype = type;
847 
848  // generate filename for process data
849  std::string pieceName = getSerialPieceName(name, "");
850 
851  // write process data
852  std::ofstream file;
853  file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
854  std::ios_base::eofbit);
855  // check if file can be opened
856  try {
857  file.open( pieceName.c_str(), std::ios::binary );
858  }
859  catch(...) {
860  std::cerr << "Filename: " << pieceName << " could not be opened" << std::endl;
861  throw;
862  }
863  if (! file.is_open())
864  DUNE_THROW(IOError, "Could not write to piece file " << pieceName);
865  writeDataFile( file );
866  file.close();
867 
868  return pieceName;
869  }
870 
872 
895  std::string pwrite(const std::string& name, const std::string& path,
896  const std::string& extendpath,
897  VTK::OutputType ot, const int commRank,
898  const int commSize )
899  {
900  // make data mode visible to private functions
901  outputtype=ot;
902 
903  // do some magic because paraview can only cope with relative paths to piece files
904  std::ofstream file;
905  file.exceptions(std::ios_base::badbit | std::ios_base::failbit |
906  std::ios_base::eofbit);
907  std::string piecepath = concatPaths(path, extendpath);
908  std::string relpiecepath = relativePath(path, piecepath);
909 
910  // write this processes .vtu/.vtp piece file
911  std::string fullname = getParallelPieceName(name, piecepath, commRank,
912  commSize);
913  // check if file can be opened
914  try {
915  file.open(fullname.c_str(),std::ios::binary);
916  }
917  catch(...) {
918  std::cerr << "Filename: " << fullname << " could not be opened" << std::endl;
919  throw;
920  }
921  if (! file.is_open())
922  DUNE_THROW(IOError, "Could not write to piecefile file " << fullname);
923  writeDataFile(file);
924  file.close();
925  gridView_.comm().barrier();
926 
927  // if we are rank 0, write .pvtu/.pvtp parallel header
928  fullname = getParallelHeaderName(name, path, commSize);
929  if( commRank ==0 )
930  {
931  file.open(fullname.c_str());
932  if (! file.is_open())
933  DUNE_THROW(IOError, "Could not write to parallel file " << fullname);
934  writeParallelHeader(file,name,relpiecepath, commSize );
935  file.close();
936  }
937  gridView_.comm().barrier();
938  return fullname;
939  }
940 
941  private:
943 
960  void writeParallelHeader(std::ostream& s, const std::string& piecename,
961  const std::string& piecepath, const int commSize)
962  {
963  VTK::FileType fileType =
964  (n == 1) ? VTK::polyData : VTK::unstructuredGrid;
965 
966  VTK::PVTUWriter writer(s, fileType);
967 
968  writer.beginMain();
969 
970  // PPointData
971  {
972  std::string scalars, vectors;
973  std::tie(scalars,vectors) = getDataNames(vertexdata);
974  writer.beginPointData(scalars, vectors);
975  }
976  for (auto it = vertexdata.begin(),
977  end = vertexdata.end();
978  it != end;
979  ++it)
980  {
981  unsigned writecomps = it->fieldInfo().size();
982  if(writecomps == 2) writecomps = 3;
983  writer.addArray<float>(it->name(), writecomps);
984  }
985  writer.endPointData();
986 
987  // PCellData
988  {
989  std::string scalars, vectors;
990  std::tie(scalars,vectors) = getDataNames(celldata);
991  writer.beginCellData(scalars, vectors);
992  }
993  for (auto it = celldata.begin(),
994  end = celldata.end();
995  it != end;
996  ++it)
997  {
998  unsigned writecomps = it->fieldInfo().size();
999  if(writecomps == 2) writecomps = 3;
1000  writer.addArray<float>(it->name(), writecomps);
1001  }
1002  writer.endCellData();
1003 
1004  // PPoints
1005  writer.beginPoints();
1006  writer.addArray<float>("Coordinates", 3);
1007  writer.endPoints();
1008 
1009  // Pieces
1010  for( int i = 0; i < commSize; ++i )
1011  {
1012  const std::string& fullname = getParallelPieceName(piecename,
1013  piecepath, i,
1014  commSize);
1015  writer.addPiece(fullname);
1016  }
1017 
1018  writer.endMain();
1019  }
1020 
1022  void writeDataFile (std::ostream& s)
1023  {
1024  VTK::FileType fileType =
1025  (n == 1) ? VTK::polyData : VTK::unstructuredGrid;
1026 
1027  VTK::VTUWriter writer(s, outputtype, fileType);
1028 
1029  // Grid characteristics
1030  vertexmapper = new VertexMapper( gridView_ );
1031  if (datamode == VTK::conforming)
1032  {
1033  number.resize(vertexmapper->size());
1034  for (std::vector<int>::size_type i=0; i<number.size(); i++) number[i] = -1;
1035  }
1036  countEntities(nvertices, ncells, ncorners);
1037 
1038  writer.beginMain(ncells, nvertices);
1039  writeAllData(writer);
1040  writer.endMain();
1041 
1042  // write appended binary data section
1043  if(writer.beginAppended())
1044  writeAllData(writer);
1045  writer.endAppended();
1046 
1047  delete vertexmapper; number.clear();
1048  }
1049 
1050  void writeAllData(VTK::VTUWriter& writer) {
1051  // PointData
1052  writeVertexData(writer);
1053 
1054  // CellData
1055  writeCellData(writer);
1056 
1057  // Points
1058  writeGridPoints(writer);
1059 
1060  // Cells
1061  writeGridCells(writer);
1062  }
1063 
1064  protected:
1065  std::string getFormatString() const
1066  {
1067  if (outputtype==VTK::ascii)
1068  return "ascii";
1069  if (outputtype==VTK::base64)
1070  return "binary";
1071  if (outputtype==VTK::appendedraw)
1072  return "appended";
1073  if (outputtype==VTK::appendedbase64)
1074  return "appended";
1075  DUNE_THROW(IOError, "VTKWriter: unsupported OutputType" << outputtype);
1076  }
1077 
1078  std::string getTypeString() const
1079  {
1080  if (n==1)
1081  return "PolyData";
1082  else
1083  return "UnstructuredGrid";
1084  }
1085 
1087  virtual void countEntities(int &nvertices, int &ncells, int &ncorners)
1088  {
1089  nvertices = 0;
1090  ncells = 0;
1091  ncorners = 0;
1092  for (CellIterator it=cellBegin(); it!=cellEnd(); ++it)
1093  {
1094  ncells++;
1095  // because of the use of vertexmapper->map(), this iteration must be
1096  // in the order of Dune's numbering.
1097  const int subEntities = it->subEntities(n);
1098  for (int i=0; i<subEntities; ++i)
1099  {
1100  ncorners++;
1101  if (datamode == VTK::conforming)
1102  {
1103  int alpha = vertexmapper->subIndex(*it,i,n);
1104  if (number[alpha]<0)
1105  number[alpha] = nvertices++;
1106  }
1107  else
1108  {
1109  nvertices++;
1110  }
1111  }
1112  }
1113  }
1114 
1115  template<typename T>
1116  std::tuple<std::string,std::string> getDataNames(const T& data) const
1117  {
1118  std::string scalars = "";
1119  for (auto it = data.begin(),
1120  end = data.end();
1121  it != end;
1122  ++it)
1123  if (it->fieldInfo().type() == VTK::FieldInfo::Type::scalar)
1124  {
1125  scalars = it->name();
1126  break;
1127  }
1128 
1129  std::string vectors = "";
1130  for (auto it = data.begin(),
1131  end = data.end();
1132  it != end;
1133  ++it)
1134  if (it->fieldInfo().type() == VTK::FieldInfo::Type::vector)
1135  {
1136  vectors = it->name();
1137  break;
1138  }
1139  return std::make_tuple(scalars,vectors);
1140  }
1141 
1142  template<typename Data, typename Iterator>
1143  void writeData(VTK::VTUWriter& writer, const Data& data, const Iterator begin, const Iterator end, int nentries)
1144  {
1145  for (auto it = data.begin(),
1146  iend = data.end();
1147  it != iend;
1148  ++it)
1149  {
1150  const auto& f = *it;
1151  VTK::FieldInfo fieldInfo = f.fieldInfo();
1152  std::size_t writecomps = fieldInfo.size();
1153  switch (fieldInfo.type())
1154  {
1156  break;
1158  // vtk file format: a vector data always should have 3 comps (with
1159  // 3rd comp = 0 in 2D case)
1160  if (writecomps > 3)
1161  DUNE_THROW(IOError,"Cannot write VTK vectors with more than 3 components (components was " << writecomps << ")");
1162  writecomps = 3;
1163  break;
1165  DUNE_THROW(NotImplemented,"VTK output for tensors not implemented yet");
1166  }
1167  std::shared_ptr<VTK::DataArrayWriter<float> > p
1168  (writer.makeArrayWriter<float>(f.name(), writecomps, nentries));
1169  if(!p->writeIsNoop())
1170  for (Iterator eit = begin; eit!=end; ++eit)
1171  {
1172  const Entity & e = *eit;
1173  f.bind(e);
1174  f.write(eit.position(),*p);
1175  f.unbind();
1176  // vtk file format: a vector data always should have 3 comps
1177  // (with 3rd comp = 0 in 2D case)
1178  for (std::size_t j=fieldInfo.size(); j < writecomps; ++j)
1179  p->write(0.0);
1180  }
1181  }
1182  }
1183 
1185  virtual void writeCellData(VTK::VTUWriter& writer)
1186  {
1187  if(celldata.size() == 0)
1188  return;
1189 
1190  std::string scalars, vectors;
1191  std::tie(scalars,vectors) = getDataNames(celldata);
1192 
1193  writer.beginCellData(scalars, vectors);
1194  writeData(writer,celldata,cellBegin(),cellEnd(),ncells);
1195  writer.endCellData();
1196  }
1197 
1199  virtual void writeVertexData(VTK::VTUWriter& writer)
1200  {
1201  if(vertexdata.size() == 0)
1202  return;
1203 
1204  std::string scalars, vectors;
1205  std::tie(scalars,vectors) = getDataNames(vertexdata);
1206 
1207  writer.beginPointData(scalars, vectors);
1208  writeData(writer,vertexdata,vertexBegin(),vertexEnd(),nvertices);
1209  writer.endPointData();
1210  }
1211 
1213  virtual void writeGridPoints(VTK::VTUWriter& writer)
1214  {
1215  writer.beginPoints();
1216 
1217  std::shared_ptr<VTK::DataArrayWriter<float> > p
1218  (writer.makeArrayWriter<float>("Coordinates", 3, nvertices));
1219  if(!p->writeIsNoop()) {
1220  VertexIterator vEnd = vertexEnd();
1221  for (VertexIterator vit=vertexBegin(); vit!=vEnd; ++vit)
1222  {
1223  int dimw=w;
1224  for (int j=0; j<std::min(dimw,3); j++)
1225  p->write((*vit).geometry().corner(vit.localindex())[j]);
1226  for (int j=std::min(dimw,3); j<3; j++)
1227  p->write(0.0);
1228  }
1229  }
1230  // free the VTK::DataArrayWriter before touching the stream
1231  p.reset();
1232 
1233  writer.endPoints();
1234  }
1235 
1237  virtual void writeGridCells(VTK::VTUWriter& writer)
1238  {
1239  writer.beginCells();
1240 
1241  // connectivity
1242  {
1243  std::shared_ptr<VTK::DataArrayWriter<int> > p1
1244  (writer.makeArrayWriter<int>("connectivity", 1, ncorners));
1245  if(!p1->writeIsNoop())
1246  for (CornerIterator it=cornerBegin(); it!=cornerEnd(); ++it)
1247  p1->write(it.id());
1248  }
1249 
1250  // offsets
1251  {
1252  std::shared_ptr<VTK::DataArrayWriter<int> > p2
1253  (writer.makeArrayWriter<int>("offsets", 1, ncells));
1254  if(!p2->writeIsNoop()) {
1255  int offset = 0;
1256  for (CellIterator it=cellBegin(); it!=cellEnd(); ++it)
1257  {
1258  offset += it->subEntities(n);
1259  p2->write(offset);
1260  }
1261  }
1262  }
1263 
1264  // types
1265  if (n>1)
1266  {
1267  {
1268  std::shared_ptr<VTK::DataArrayWriter<unsigned char> > p3
1269  (writer.makeArrayWriter<unsigned char>("types", 1, ncells));
1270 
1271  if(!p3->writeIsNoop())
1272  {
1273  for (CellIterator it=cellBegin(); it!=cellEnd(); ++it)
1274  {
1275  int vtktype = VTK::geometryType(it->type());
1276  p3->write(vtktype);
1277  }
1278  }
1279  }
1280 
1281 
1282  // if polyhedron cells found also cell faces need to be written
1283  if( polyhedralCellsPresent_ )
1284  {
1285  writeCellFaces( writer );
1286  }
1287  }
1288 
1289  writer.endCells();
1290  }
1291 
1292  protected:
1293  bool checkForPolyhedralCells() const
1294  {
1295  // check if polyhedron cells are present
1296  for( const auto& geomType : gridView_.indexSet().types( 0 ) )
1297  {
1298  if( VTK::geometryType( geomType ) == VTK::polyhedron )
1299  {
1300  return true;
1301  }
1302  }
1303  return false;
1304  }
1305 
1307  virtual void writeCellFaces(VTK::VTUWriter& writer)
1308  {
1309  if( ! faceVertices_ )
1310  {
1311  faceVertices_.reset( new std::pair< std::vector<int>, std::vector<int> > () );
1312  // fill face vertex structure
1313  fillFaceVertices( cornerBegin(), cornerEnd(), gridView_.indexSet(),
1314  faceVertices_->first, faceVertices_->second );
1315  }
1316 
1317  std::vector< int >& faces = faceVertices_->first;
1318  std::vector< int >& faceOffsets = faceVertices_->second;
1319  assert( int(faceOffsets.size()) == ncells );
1320 
1321  {
1322  std::shared_ptr<VTK::DataArrayWriter< int > > p4
1323  (writer.makeArrayWriter< int >("faces", 1, faces.size()));
1324  if(!p4->writeIsNoop())
1325  {
1326  for( const auto& face : faces )
1327  p4->write( face );
1328  }
1329  }
1330 
1331  {
1332  std::shared_ptr<VTK::DataArrayWriter< int > > p5
1333  (writer.makeArrayWriter< int >("faceoffsets", 1, ncells ));
1334  if(!p5->writeIsNoop())
1335  {
1336  for( const auto& offset : faceOffsets )
1337  p5->write( offset );
1338 
1339  // clear face vertex structure
1340  faceVertices_.reset();
1341  }
1342  }
1343  }
1344 
1345  template <class CornerIterator, class IndexSet, class T>
1346  inline void fillFaceVertices( CornerIterator it,
1347  const CornerIterator end,
1348  const IndexSet& indexSet,
1349  std::vector<T>& faces,
1350  std::vector<T>& faceOffsets )
1351  {
1352  if( n == 3 && it != end )
1353  {
1354  // clear output arrays
1355  faces.clear();
1356  faces.reserve( 15 * ncells );
1357  faceOffsets.clear();
1358  faceOffsets.reserve( ncells );
1359 
1360  int offset = 0;
1361 
1362  Cell element = *it;
1363  int elIndex = indexSet.index( element );
1364  std::vector< T > vertices;
1365  vertices.reserve( 30 );
1366  for( ; it != end; ++it )
1367  {
1368  const Cell& cell = *it ;
1369  const int cellIndex = indexSet.index( cell ) ;
1370  if( elIndex != cellIndex )
1371  {
1372  fillFacesForElement( element, indexSet, vertices, offset, faces, faceOffsets );
1373 
1374  vertices.clear();
1375  element = cell ;
1376  elIndex = cellIndex ;
1377  }
1378  vertices.push_back( it.id() );
1379  }
1380 
1381  // fill faces for last element
1382  fillFacesForElement( element, indexSet, vertices, offset, faces, faceOffsets );
1383  }
1384  }
1385 
1386  template <class Entity, class IndexSet, class T>
1387  static void fillFacesForElement( const Entity& element,
1388  const IndexSet& indexSet,
1389  const std::vector<T>& vertices,
1390  T& offset,
1391  std::vector<T>& faces,
1392  std::vector<T>& faceOffsets )
1393  {
1394  const int dim = n;
1395 
1396  std::map< T, T > vxMap;
1397 
1398  // get number of local faces
1399  const int nVertices = element.subEntities( dim );
1400  for( int vx = 0; vx < nVertices; ++ vx )
1401  {
1402  const int vxIdx = indexSet.subIndex( element, vx, dim );
1403  vxMap[ vxIdx ] = vertices[ vx ];
1404  }
1405 
1406  // get number of local faces
1407  const int nFaces = element.subEntities( 1 );
1408  // store number of faces for current element
1409  faces.push_back( nFaces );
1410  ++offset;
1411  // extract each face as a set of vertex indices
1412  for( int fce = 0; fce < nFaces; ++ fce )
1413  {
1414  // obtain face
1415  const auto face = element.template subEntity< 1 > ( fce );
1416 
1417  // get all vertex indices from current face
1418  const int nVxFace = face.subEntities( dim );
1419  faces.push_back( nVxFace );
1420  ++offset ;
1421  for( int i=0; i<nVxFace; ++i )
1422  {
1423  const T vxIndex = indexSet.subIndex( face, i, dim );
1424  assert( vxMap.find( vxIndex ) != vxMap.end() );
1425  faces.push_back( vxMap[ vxIndex ] );
1426  ++offset ;
1427  }
1428  }
1429 
1430  // store face offset for each element
1431  faceOffsets.push_back( offset );
1432  }
1433 
1434  protected:
1435  // the list of registered functions
1436  std::list<VTKLocalFunction> celldata;
1437  std::list<VTKLocalFunction> vertexdata;
1438 
1439  // the grid
1440  GridView gridView_;
1441 
1442  // temporary grid information
1443  int ncells;
1444  int nvertices;
1445  int ncorners;
1446  private:
1447  VertexMapper* vertexmapper;
1448  // in conforming mode, for each vertex id (as obtained by vertexmapper)
1449  // hold its number in the iteration order (VertexIterator)
1450  std::vector<int> number;
1451  VTK::DataMode datamode;
1452 
1453  // true if polyhedral cells are present in the grid
1454  const bool polyhedralCellsPresent_;
1455 
1456  // pointer holding face vertex connectivity if needed
1457  std::shared_ptr< std::pair< std::vector<int>, std::vector<int> > > faceVertices_;
1458 
1459  protected:
1460  VTK::OutputType outputtype;
1461  };
1462 
1463 }
1464 
1465 #endif
vector space out of a tensor product of fields.
Definition: fvector.hh:93
Base class for stl conformant forward iterators.
Definition: iteratorfacades.hh:144
Base class template for function classes.
Definition: function.hh:28
Grid view abstract base class.
Definition: gridview.hh:60
Default exception class for I/O errors.
Definition: exceptions.hh:229
Index Set Interface base class.
Definition: indexidset.hh:76
IndexType index(const typename Traits::template Codim< cc >::Entity &e) const
Map entity to index. The result of calling this method with an entity that is not in the index set is...
Definition: indexidset.hh:111
Implementation class for a multiple codim and multiple geometry type mapper.
Definition: mcmgmapper.hh:103
Index subIndex(const typename GV::template Codim< 0 >::Entity &e, int i, unsigned int codim) const
Map subentity of codim 0 entity to array index.
Definition: mcmgmapper.hh:160
int size() const
Return total number of entities in the entity set managed by the mapper.
Definition: mcmgmapper.hh:179
Default exception for dummy implementations.
Definition: exceptions.hh:261
Take a vector and interpret it as cell data for the VTKWriter.
Definition: function.hh:90
Take a vector and interpret it as point data for the VTKWriter.
Definition: function.hh:188
A base class for grid functions with any return type and dimension.
Definition: function.hh:39
Base class to write pvd-files which contains a list of all collected vtk-files.
Definition: vtksequencewriterbase.hh:32
Writer for the ouput of grid functions in the vtk format.
Definition: vtksequencewriter.hh:28
Iterator over the grids elements.
Definition: vtkwriter.hh:327
const FieldVector< DT, n > position() const
Definition: vtkwriter.hh:333
CellIterator(const GridCellIterator &x)
construct a CellIterator from the gridview's Iterator.
Definition: vtkwriter.hh:330
Iterate over the elements' corners.
Definition: vtkwriter.hh:481
int id() const
Process-local consecutive zero-starting vertex id.
Definition: vtkwriter.hh:539
Type erasure wrapper for VTK data sets.
Definition: vtkwriter.hh:148
void unbind() const
Unbind the data set from the currently bound entity.
Definition: vtkwriter.hh:302
std::string name() const
Returns the name of the data set.
Definition: vtkwriter.hh:284
const VTK::FieldInfo & fieldInfo() const
Returns the VTK::FieldInfo for the data set.
Definition: vtkwriter.hh:290
void bind(const Entity &e) const
Bind the data set to grid entity e.
Definition: vtkwriter.hh:296
VTKLocalFunction(const std::shared_ptr< const VTKFunction > &vtkFunctionPtr)
Construct a VTKLocalFunction for a legacy VTKFunction.
Definition: vtkwriter.hh:274
VTKLocalFunction(F &&f, VTK::FieldInfo fieldInfo, typename std::enable_if< detail::_has_local_context< F >::value, int >::type dummy=0)
Construct a VTKLocalFunction for a dune-functions style LocalFunction.
Definition: vtkwriter.hh:257
VTKLocalFunction(F &&f, VTK::FieldInfo fieldInfo, typename std::enable_if< not detail::_has_local_context< F >::value, int >::type dummy=0)
Construct a VTKLocalFunction for a dune-functions style Function.
Definition: vtkwriter.hh:265
void write(const Coordinate &pos, Writer &w) const
Write the value of the data set at local coordinate pos to the writer w.
Definition: vtkwriter.hh:308
Iterate over the grid's vertices.
Definition: vtkwriter.hh:366
const FieldVector< DT, n > & position() const
position of vertex inside the entity
Definition: vtkwriter.hh:443
int localindex() const
index of vertex within the entity, in Dune-numbering
Definition: vtkwriter.hh:438
Writer for the ouput of grid functions in the vtk format.
Definition: vtkwriter.hh:87
void clear()
clear list of registered functions
Definition: vtkwriter.hh:674
std::string write(const std::string &name, VTK::OutputType type=VTK::ascii)
write output (interface might change later)
Definition: vtkwriter.hh:697
std::string getParallelHeaderName(const std::string &name, const std::string &path, int commSize) const
return name of a parallel header file
Definition: vtkwriter.hh:779
void addVertexData(const std::shared_ptr< const VTKFunction > &p)
Add a grid function that lives on the vertices of the grid to the visualization.
Definition: vtkwriter.hh:632
void addVertexData(const Container &v, const std::string &name, int ncomps=1)
Add a grid function (represented by container) that lives on the vertices of the grid to the visualiz...
Definition: vtkwriter.hh:660
std::string getSerialPieceName(const std::string &name, const std::string &path) const
return name of a serial piece file
Definition: vtkwriter.hh:811
void addCellData(const std::shared_ptr< const VTKFunction > &p)
Add a grid function that lives on the cells of the grid to the visualization.
Definition: vtkwriter.hh:588
virtual void writeCellData(VTK::VTUWriter &writer)
write cell data
Definition: vtkwriter.hh:1185
VTKWriter(const GridView &gridView, VTK::DataMode dm=VTK::conforming)
Construct a VTKWriter working on a specific GridView.
Definition: vtkwriter.hh:577
std::string getParallelPieceName(const std::string &name, const std::string &path, int commRank, int commSize) const
return name of a parallel piece file
Definition: vtkwriter.hh:748
virtual void countEntities(int &nvertices, int &ncells, int &ncorners)
count the vertices, cells and corners
Definition: vtkwriter.hh:1087
void addCellData(const Container &v, const std::string &name, int ncomps=1)
Add a grid function (represented by container) that lives on the cells of the grid to the visualizati...
Definition: vtkwriter.hh:615
virtual void writeGridCells(VTK::VTUWriter &writer)
write the connectivity array
Definition: vtkwriter.hh:1237
virtual void writeCellFaces(VTK::VTUWriter &writer)
write the connectivity array
Definition: vtkwriter.hh:1307
std::string write(const std::string &name, VTK::OutputType type, const int commRank, const int commSize)
write output (interface might change later)
Definition: vtkwriter.hh:835
virtual void writeGridPoints(VTK::VTUWriter &writer)
write the positions of vertices
Definition: vtkwriter.hh:1213
virtual void writeVertexData(VTK::VTUWriter &writer)
write vertex data
Definition: vtkwriter.hh:1199
virtual ~VTKWriter()
destructor
Definition: vtkwriter.hh:681
std::string pwrite(const std::string &name, const std::string &path, const std::string &extendpath, VTK::OutputType ot, const int commRank, const int commSize)
write output; interface might change later
Definition: vtkwriter.hh:895
std::string pwrite(const std::string &name, const std::string &path, const std::string &extendpath, VTK::OutputType type=VTK::ascii)
write output (interface might change later)
Definition: vtkwriter.hh:729
base class for data array writers
Definition: dataarraywriter.hh:54
virtual void write(T data)=0
write one data element
Descriptor struct for VTK fields.
Definition: common.hh:315
@ tensor
tensor field (always 3x3)
@ vector
vector-valued field (always 3D, will be padded if necessary)
std::string name() const
The name of the data field.
Definition: common.hh:338
Dump a .vtu/.vtp files contents to a stream.
Definition: pvtuwriter.hh:60
Dump a .vtu/.vtp files contents to a stream.
Definition: vtuwriter.hh:96
DataArrayWriter< T > * makeArrayWriter(const std::string &name, unsigned ncomps, unsigned nitems)
acquire a DataArrayWriter
Definition: vtuwriter.hh:379
void endCellData()
finish CellData section
Definition: vtuwriter.hh:218
void beginCells()
start section for the grid cells/PolyData lines
Definition: vtuwriter.hh:272
void endPointData()
finish PointData section
Definition: vtuwriter.hh:180
void beginCellData(const std::string &scalars="", const std::string &vectors="")
start CellData section
Definition: vtuwriter.hh:203
void beginPointData(const std::string &scalars="", const std::string &vectors="")
start PointData section
Definition: vtuwriter.hh:165
void endPoints()
finish section for the point coordinates
Definition: vtuwriter.hh:247
void endCells()
start section for the grid cells/PolyData lines
Definition: vtuwriter.hh:283
void beginPoints()
start section for the point coordinates
Definition: vtuwriter.hh:236
Common stuff for the VTKWriter.
OutputType
How the bulk data should be stored in the file.
Definition: common.hh:40
FileType
which type of VTK file to write
Definition: common.hh:298
DataMode
Whether to produce conforming or non-conforming output.
Definition: common.hh:64
Data array writers for the VTKWriter.
A few common exception classes.
Functions for VTK output.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Traits ::IndexSet IndexSet
type of the index set
Definition: gridview.hh:81
Grid::ctype ctype
type used for coordinates in grid
Definition: gridview.hh:125
const CollectiveCommunication & comm() const
obtain collective communication object
Definition: gridview.hh:247
Traits ::Grid Grid
type of the grid
Definition: gridview.hh:78
const IndexSet & indexSet() const
obtain the index set
Definition: gridview.hh:173
@ dimensionworld
The dimension of the world the grid lives in.
Definition: gridview.hh:132
@ dimension
The dimension of the grid.
Definition: gridview.hh:128
PartitionIteratorType
Parameter to be used for the parallel level- and leaf iterators.
Definition: gridenums.hh:134
PartitionType
Attributes used in the generic overlap model.
Definition: gridenums.hh:28
@ All_Partition
all entities
Definition: gridenums.hh:139
@ InteriorBorder_Partition
interior and border entities
Definition: gridenums.hh:136
@ InteriorEntity
all interior entities
Definition: gridenums.hh:29
std::string relativePath(const std::string &newbase, const std::string &p)
compute a relative path between two paths
Definition: path.cc:151
std::string concatPaths(const std::string &base, const std::string &p)
concatenate two paths
Definition: path.cc:30
Utility class for handling nested indentation in output.
This file implements iterator facade classes for writing stl conformant iterators.
Mapper for multiple codim and multiple geometry types.
Dune namespace.
Definition: alignment.hh:11
Utilities for handling filesystem paths.
Static tag representing a codimension.
Definition: dimension.hh:22
static const ReferenceElement< ctype, dim > & general(const GeometryType &type)
get general reference elements
Definition: referenceelements.hh:758
Base class for polymorphic container of underlying data set.
Definition: vtkwriter.hh:156
virtual void write(const Coordinate &pos, Writer &w, std::size_t count) const =0
Evaluate data set at local position pos inside the current entity and write result to w.
virtual void unbind()=0
Unbind data set from current grid entity - mostly here for performance and symmetry reasons.
virtual void bind(const Entity &e)=0
Bind data set to grid entity - must be called before evaluating (i.e. calling write())
Type erasure implementation for functions conforming to the dune-functions LocalFunction interface.
Definition: vtkwriter.hh:179
virtual void write(const Coordinate &pos, Writer &w, std::size_t count) const
Evaluate data set at local position pos inside the current entity and write result to w.
Definition: vtkwriter.hh:197
virtual void unbind()
Unbind data set from current grid entity - mostly here for performance and symmetry reasons.
Definition: vtkwriter.hh:192
virtual void bind(const Entity &e)
Bind data set to grid entity - must be called before evaluating (i.e. calling write())
Definition: vtkwriter.hh:187
Type erasure implementation for legacy VTKFunctions.
Definition: vtkwriter.hh:226
virtual void unbind()
Unbind data set from current grid entity - mostly here for performance and symmetry reasons.
Definition: vtkwriter.hh:237
virtual void write(const Coordinate &pos, Writer &w, std::size_t count) const
Evaluate data set at local position pos inside the current entity and write result to w.
Definition: vtkwriter.hh:242
virtual void bind(const Entity &e)
Bind data set to grid entity - must be called before evaluating (i.e. calling write())
Definition: vtkwriter.hh:232
Definition: typetraits.hh:344
Traits for type conversions and type information.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 8, 22:30, 2024)