dune-grid  2.2.0
basicwriter.hh
Go to the documentation of this file.
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