- Home
- About DUNE
- Download
- Documentation
- Community
- Development
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 // vi: set et ts=8 sw=2 sts=2: 00003 00004 #ifndef DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH 00005 #define DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH 00006 00007 #include <fstream> 00008 #include <iomanip> 00009 #include <iterator> 00010 #include <list> 00011 #include <sstream> 00012 #include <string> 00013 00014 #include <dune/common/mpiguard.hh> 00015 #include <dune/common/path.hh> 00016 #include <dune/common/shared_ptr.hh> 00017 00018 #include <dune/grid/common/genericreferenceelements.hh> 00019 #include <dune/grid/io/file/vtk/common.hh> 00020 #include <dune/grid/io/file/vtk/functionwriter.hh> 00021 #include <dune/grid/io/file/vtk/pvtuwriter.hh> 00022 #include <dune/grid/io/file/vtk/vtuwriter.hh> 00023 00024 namespace Dune 00025 { 00028 00029 namespace VTK { 00030 00031 template<typename IteratorFactory> 00032 class BasicWriter { 00033 typedef typename IteratorFactory::CellIterator CellIterator; 00034 typedef typename IteratorFactory::CornerIterator CornerIterator; 00035 typedef typename IteratorFactory::PointIterator PointIterator; 00036 00037 typedef typename IteratorFactory::Cell Cell; 00038 00039 public: 00040 typedef FunctionWriterBase<Cell> FunctionWriter; 00041 00042 private: 00043 typedef std::list<shared_ptr<FunctionWriter> > WriterList; 00044 typedef typename WriterList::const_iterator WIterator; 00045 00046 typedef typename Cell::ctype ctype; 00047 static const unsigned celldim = Cell::mydimension; 00048 typedef GenericReferenceElements<ctype, celldim> Refelems; 00049 00050 static const FileType fileType = celldim == 1 00051 ? polyData : unstructuredGrid; 00052 00053 const IteratorFactory& factory; 00054 00055 WriterList cellData; 00056 WriterList pointData; 00057 00058 CoordinatesWriter<Cell> coords; 00059 typename IteratorFactory::ConnectivityWriter connectivity; 00060 OffsetsWriter<Cell> offsets; 00061 TypesWriter<Cell> types; 00062 00063 public: 00064 BasicWriter(const IteratorFactory& factory_) 00065 : factory(factory_), connectivity(factory.makeConnectivity()) 00066 { } 00067 00069 // 00070 // Methods for adding data 00071 // 00072 00073 void addCellData(const shared_ptr<FunctionWriter>& writer) { 00074 cellData.push_back(writer); 00075 } 00076 00077 void addPointData(const shared_ptr<FunctionWriter>& writer) { 00078 pointData.push_back(writer); 00079 } 00080 00081 void clear() { 00082 cellData.clear(); 00083 pointData.clear(); 00084 } 00085 00086 protected: 00088 // 00089 // Methods for writing single functions 00090 // 00091 00092 void writeCellFunction(VTUWriter& vtuWriter, 00093 FunctionWriter& functionWriter, 00094 unsigned ncells) const 00095 { 00096 if(functionWriter.beginWrite(vtuWriter, ncells)) { 00097 const CellIterator& cellend = factory.endCells(); 00098 for(CellIterator cellit = factory.beginCells(); cellit != cellend; 00099 ++cellit) 00100 functionWriter.write(*cellit, Refelems::general(cellit->type()). 00101 position(0,0)); 00102 } 00103 functionWriter.endWrite(); 00104 } 00105 00106 void writePointFunction(VTUWriter& vtuWriter, 00107 FunctionWriter& functionWriter, 00108 unsigned npoints) const 00109 { 00110 if(functionWriter.beginWrite(vtuWriter, npoints)) { 00111 const PointIterator& pend = factory.endPoints(); 00112 for(PointIterator pit = factory.beginPoints(); pit != pend; ++pit) 00113 functionWriter.write(pit->cell(), pit->duneIndex()); 00114 } 00115 functionWriter.endWrite(); 00116 } 00117 00118 void writeCornerFunction(VTUWriter& vtuWriter, 00119 FunctionWriter& functionWriter, 00120 unsigned ncorners) const 00121 { 00122 if(functionWriter.beginWrite(vtuWriter, ncorners)) { 00123 const CornerIterator& cend = factory.endCorners(); 00124 for(CornerIterator cit = factory.beginCorners(); cit != cend; ++cit) 00125 functionWriter.write(cit->cell(), cit->duneIndex()); 00126 } 00127 functionWriter.endWrite(); 00128 } 00129 00131 // 00132 // Methods for writing whole sections 00133 // 00134 00135 static std::string getFirstScalar(const WriterList& data) { 00136 const WIterator& wend = data.end(); 00137 for(WIterator wit = data.begin(); wit != wend; ++wit) 00138 if((*wit)->ncomps() == 1) 00139 return (*wit)->name(); 00140 return ""; 00141 } 00142 00143 static std::string getFirstVector(const WriterList& data) { 00144 const WIterator& wend = data.end(); 00145 for(WIterator wit = data.begin(); wit != wend; ++wit) 00146 if((*wit)->ncomps() == 3) 00147 return (*wit)->name(); 00148 return ""; 00149 } 00150 00151 void writeCellData(VTUWriter& vtuWriter, unsigned ncells) const { 00152 if(cellData.empty()) return; 00153 00154 vtuWriter.beginCellData(getFirstScalar(cellData), 00155 getFirstVector(cellData)); 00156 const WIterator& wend = cellData.end(); 00157 for(WIterator wit = cellData.begin(); wit != wend; ++wit) 00158 writeCellFunction(vtuWriter, **wit, ncells); 00159 vtuWriter.endCellData(); 00160 } 00161 00162 void writePointData(VTUWriter& vtuWriter, unsigned npoints) const { 00163 if(pointData.empty()) return; 00164 00165 vtuWriter.beginPointData(getFirstScalar(pointData), 00166 getFirstVector(pointData)); 00167 const WIterator& wend = pointData.end(); 00168 for(WIterator wit = pointData.begin(); wit != wend; ++wit) 00169 writePointFunction(vtuWriter, **wit, npoints); 00170 vtuWriter.endPointData(); 00171 } 00172 00173 void writeGrid(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints, 00174 unsigned ncorners) { 00175 vtuWriter.beginPoints(); 00176 writePointFunction(vtuWriter, coords, npoints); 00177 vtuWriter.endPoints(); 00178 00179 vtuWriter.beginCells(); 00180 writeCornerFunction(vtuWriter, connectivity, ncorners); 00181 writeCellFunction(vtuWriter, offsets, ncells); 00182 if(fileType != polyData) 00183 writeCellFunction(vtuWriter, types, ncells); 00184 vtuWriter.endCells(); 00185 } 00186 00187 void writeAll(VTUWriter& vtuWriter, unsigned ncells, unsigned npoints, 00188 unsigned ncorners) { 00189 writeCellData(vtuWriter, ncells); 00190 writePointData(vtuWriter, npoints); 00191 writeGrid(vtuWriter, ncells, npoints, ncorners); 00192 } 00193 00194 public: 00195 void writePiece(const std::string& filename, OutputType outputType) { 00196 std::ofstream stream(filename.c_str(), std::ios::binary); 00197 stream.exceptions(std::ios_base::badbit | std::ios_base::failbit | 00198 std::ios_base::eofbit); 00199 00200 VTUWriter vtuWriter(stream, outputType, fileType); 00201 00202 unsigned ncells = std::distance(factory.beginCells(), 00203 factory.endCells()); 00204 unsigned npoints = std::distance(factory.beginPoints(), 00205 factory.endPoints()); 00206 unsigned ncorners = std::distance(factory.beginCorners(), 00207 factory.endCorners()); 00208 00209 vtuWriter.beginMain(ncells, npoints); 00210 writeAll(vtuWriter, ncells, npoints, ncorners); 00211 vtuWriter.endMain(); 00212 00213 if(vtuWriter.beginAppended()) 00214 writeAll(vtuWriter, ncells, npoints, ncorners); 00215 vtuWriter.endAppended(); 00216 00217 } 00218 00220 00236 void writeCollection(const std::string name, 00237 const std::string& piecename, 00238 const std::string& piecepath) 00239 { 00240 std::ofstream stream(name.c_str(), std::ios::binary); 00241 stream.exceptions(std::ios_base::badbit | std::ios_base::failbit | 00242 std::ios_base::eofbit); 00243 PVTUWriter writer(stream, fileType); 00244 00245 writer.beginMain(); 00246 00247 // PPointData 00248 writer.beginPointData(getFirstScalar(pointData), 00249 getFirstVector(pointData)); 00250 for(WIterator it=pointData.begin(); it!=pointData.end(); ++it) 00251 (*it)->addArray(writer); 00252 writer.endPointData(); 00253 00254 // PCellData 00255 writer.beginCellData(getFirstScalar(cellData), 00256 getFirstVector(cellData)); 00257 for(WIterator it=cellData.begin(); it!=cellData.end(); ++it) 00258 (*it)->addArray(writer); 00259 writer.endCellData(); 00260 00261 // PPoints 00262 writer.beginPoints(); 00263 coords.addArray(writer); 00264 writer.endPoints(); 00265 00266 // Pieces 00267 for( int i = 0; i < factory.comm().size(); ++i ) 00268 writer.addPiece(getParallelPieceName(piecename, piecepath, i)); 00269 00270 writer.endMain(); 00271 } 00272 00274 // 00275 // Filename generators 00276 // 00277 00279 00289 std::string getParallelPieceName(const std::string& name, 00290 const std::string& path, int rank) const 00291 { 00292 std::ostringstream s; 00293 if(path.size() > 0) { 00294 s << path; 00295 if(path[path.size()-1] != '/') 00296 s << '/'; 00297 } 00298 s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size() 00299 << ':'; 00300 s << 'p' << std::setw(4) << std::setfill('0') << rank << ':'; 00301 s << name; 00302 switch(fileType) { 00303 case polyData: s << ".vtp"; break; 00304 case unstructuredGrid: s << ".vtu"; break; 00305 } 00306 return s.str(); 00307 } 00308 00310 00319 std::string getParallelHeaderName(const std::string& name, 00320 const std::string& path) const 00321 { 00322 std::ostringstream s; 00323 if(path.size() > 0) { 00324 s << path; 00325 if(path[path.size()-1] != '/') 00326 s << '/'; 00327 } 00328 s << 's' << std::setw(4) << std::setfill('0') << factory.comm().size() 00329 << ':'; 00330 s << name; 00331 switch(fileType) { 00332 case polyData: s << ".pvtp"; break; 00333 case unstructuredGrid: s << ".pvtu"; break; 00334 } 00335 return s.str(); 00336 } 00337 00339 00351 std::string getSerialPieceName(const std::string& name, 00352 const std::string& path) const 00353 { 00354 switch(fileType) { 00355 case polyData: return concatPaths(path, name+".vtp"); 00356 case unstructuredGrid: return concatPaths(path, name+".vtu"); 00357 } 00358 } 00359 00361 // 00362 // User interface functions for writing 00363 // 00364 00366 00388 std::string pwrite(const std::string& name, const std::string& path, 00389 const std::string& extendpath, OutputType outputType) 00390 { 00391 MPIGuard guard(factory.comm()); 00392 00393 // do some magic because paraview can only cope with relative pathes to 00394 // piece files 00395 std::ofstream file; 00396 std::string piecepath = concatPaths(path, extendpath); 00397 std::string relpiecepath = relativePath(path, piecepath); 00398 00399 // write this processes .vtu/.vtp piece file 00400 std::string fullname = getParallelPieceName(name, piecepath, 00401 factory.comm().rank()); 00402 writePiece(fullname, outputType); 00403 00404 // if we are rank 0, write .pvtu/.pvtp parallel header 00405 fullname = getParallelHeaderName(name, path); 00406 if(factory.comm().rank() == 0) 00407 writeCollection(fullname, name, relpiecepath); 00408 00409 guard.finalize(); 00410 00411 return fullname; 00412 } 00413 00427 std::string write(const std::string &name, OutputType outputType) 00428 { 00429 // in the parallel case, just use pwrite, it has all the necessary 00430 // stuff, so we don't need to reimplement it here. 00431 if(factory.comm().size() > 1) 00432 return pwrite(name, "", "", outputType); 00433 00434 // generate filename for process data 00435 std::string pieceName = getSerialPieceName(name, ""); 00436 00437 writePiece(pieceName, outputType); 00438 00439 return pieceName; 00440 } 00441 00442 }; 00443 00444 } // namespace VTK 00445 00447 00448 } // namespace Dune 00449 00450 #endif // DUNE_GRID_IO_FILE_VTK_BASICWRITER_HH
Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].