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