dune-grid  2.1.1
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/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