diff --git a/dune/vtk/vtktimeserieswriter.hh b/dune/vtk/vtktimeserieswriter.hh index 929d0fd174f94b5ab18bda5cd38d4e2313f2ebe0..32a3e467308fe4a4059e1ad5655e7c59f4d77d8f 100644 --- a/dune/vtk/vtktimeserieswriter.hh +++ b/dune/vtk/vtktimeserieswriter.hh @@ -56,7 +56,7 @@ namespace Dune bool initialized_ = false; // block size of attached data - std::vector<std::uint64_t> blocksize_; + std::vector<std::uint64_t> blocks_; std::string filenameMesh_; std::vector<std::pair<double, std::string>> timesteps_; diff --git a/dune/vtk/vtktimeserieswriter.impl.hh b/dune/vtk/vtktimeserieswriter.impl.hh index 224e80f8445cf59faf79b249fed25adaa9192712..015f65bd1be1be10c6443d5af0ec336c2ff5b5b2 100644 --- a/dune/vtk/vtktimeserieswriter.impl.hh +++ b/dune/vtk/vtktimeserieswriter.impl.hh @@ -36,34 +36,14 @@ void VtkTimeseriesWriter<W> if (!initialized_) { // write points and cells only once filenameMesh_ = p.string() + ".mesh.vtkdata"; - std::ofstream file_mesh(filenameMesh_, std::ios_base::ate | std::ios::binary); - - if (vtkWriter_.datatype_ == Vtk::FLOAT32) - blocksize_.push_back( vtkWriter_.template writePointsAppended<float>(file_mesh) ); - else - blocksize_.push_back( vtkWriter_.template writePointsAppended<double>(file_mesh) ); - - auto bs = vtkWriter_.writeCellsAppended(file_mesh); - blocksize_.insert(blocksize_.end(), bs.begin(), bs.end()); + std::ofstream out(filenameMesh_, std::ios_base::ate | std::ios::binary); + vtkWriter_.writeGridAppended(out, blocks_); initialized_ = true; } std::string filenameData = p.string() + "_t" + std::to_string(timesteps_.size()) + ".vtkdata"; - std::ofstream file_data(filenameData, std::ios_base::ate | std::ios::binary); - - for (auto const& v : vtkWriter_.pointData_) { - if (v.type() == Vtk::FLOAT32) - blocksize_.push_back( vtkWriter_.template writeDataAppended<float>(file_data, v, W::POINT_DATA) ); - else - blocksize_.push_back( vtkWriter_.template writeDataAppended<double>(file_data, v, W::POINT_DATA) ); - } - for (auto const& v : vtkWriter_.cellData_) { - if (v.type() == Vtk::FLOAT32) - blocksize_.push_back( vtkWriter_.template writeDataAppended<float>(file_data, v, W::CELL_DATA) ); - else - blocksize_.push_back( vtkWriter_.template writeDataAppended<double>(file_data, v, W::CELL_DATA) ); - } - + std::ofstream out(filenameData, std::ios_base::ate | std::ios::binary); + vtkWriter_.writeDataAppended(out, blocks_); timesteps_.emplace_back(time, filenameData); } @@ -80,7 +60,7 @@ void VtkTimeseriesWriter<W> p.remove_filename(); p /= name.string(); std::string filename = p.string() + ".ts." + vtkWriter_.getFileExtension(); - vtkWriter_.writeTimeseriesFile(filename, filenameMesh_, timesteps_, blocksize_); + vtkWriter_.writeTimeseriesFile(filename, filenameMesh_, timesteps_, blocks_); // remove all temporary data files int ec = std::remove(filenameMesh_.c_str()); diff --git a/dune/vtk/vtkwriterinterface.hh b/dune/vtk/vtkwriterinterface.hh index 221a96d4356e3a8b80a5d8211bead7979336015f..d5ae604fe58169ef75cbb228b2810e880da69bf6 100644 --- a/dune/vtk/vtkwriterinterface.hh +++ b/dune/vtk/vtkwriterinterface.hh @@ -87,35 +87,35 @@ namespace Dune /// Return the file extension of the serial file (not including the dot) virtual std::string fileExtension () const = 0; + /// Write points and cells in raw/compressed format to output stream + virtual void writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const = 0; + // Write the point or cell values given by the grid function `fct` to the // output stream `out`. In case of binary format, stores the streampos of XML // attributes "offset" in the vector `offsets`. void writeData (std::ofstream& out, std::vector<pos_type>& offsets, VtkFunction const& fct, - PositionTypes type) const; + PositionTypes type, + Std::optional<std::size_t> timestep = {}) const; - // Collect point or cell data (depending on \ref PositionTypes) and pass - // the resulting vector to \ref writeAppended. - template <class T> - std::uint64_t writeDataAppended (std::ofstream& out, - VtkFunction const& fct, - PositionTypes type) const; + // Write points-data and cell-data in raw/compressed format to output stream + void writeDataAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const; // Write the coordinates of the vertices to the output stream `out`. In case // of binary format, stores the streampos of XML attributes "offset" in the // vector `offsets`. void writePoints (std::ofstream& out, - std::vector<pos_type>& offsets) const; + std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep = {}) const; - // Collect point positions and pass the resulting vector to \ref writeAppended. - template <class T> - std::uint64_t writePointsAppended (std::ofstream& out) const; + // Write Appended section and fillin offset values to XML attributes + void writeAppended (std::ofstream& out, std::vector<pos_type> const& offsets) const; // Write the `values` in blocks (possibly compressed) to the output // stream `out`. Return the written block size. template <class T> - std::uint64_t writeAppended (std::ofstream& out, std::vector<T> const& values) const; + std::uint64_t writeValuesAppended (std::ofstream& out, std::vector<T> const& values) const; /// Return PointData/CellData attributes for the name of the first scalar/vector/tensor DataArray std::string getNames (std::vector<VtkFunction> const& data) const; diff --git a/dune/vtk/vtkwriterinterface.impl.hh b/dune/vtk/vtkwriterinterface.impl.hh index d36dafc2502ea199572e20892df8eadb91e093f0..c5d4eccb6879bfd1cc46a09704841d2e94491dfa 100644 --- a/dune/vtk/vtkwriterinterface.impl.hh +++ b/dune/vtk/vtkwriterinterface.impl.hh @@ -52,12 +52,16 @@ void VtkWriterInterface<GV,DC> template <class GV, class DC> void VtkWriterInterface<GV,DC> ::writeData (std::ofstream& out, std::vector<pos_type>& offsets, - VtkFunction const& fct, PositionTypes type) const + VtkFunction const& fct, PositionTypes type, + Std::optional<std::size_t> timestep) const { out << "<DataArray Name=\"" << fct.name() << "\" type=\"" << to_string(fct.type()) << "\"" - << " NumberOfComponents=\"" << fct.ncomps() << "\" format=\"" << (format_ == Vtk::ASCII ? "ascii\">\n" : "appended\""); + << " NumberOfComponents=\"" << fct.ncomps() << "\" format=\"" << (format_ == Vtk::ASCII ? "ascii\"" : "appended\""); + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; if (format_ == Vtk::ASCII) { + out << ">\n"; std::size_t i = 0; if (type == POINT_DATA) { auto data = dataCollector_.template pointData<double>(fct); @@ -80,12 +84,16 @@ void VtkWriterInterface<GV,DC> template <class GV, class DC> void VtkWriterInterface<GV,DC> - ::writePoints (std::ofstream& out, std::vector<pos_type>& offsets) const + ::writePoints (std::ofstream& out, std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep) const { out << "<DataArray type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"3\" format=\"" << (format_ == Vtk::ASCII ? "ascii\">\n" : "appended\""); + << " NumberOfComponents=\"3\" format=\"" << (format_ == Vtk::ASCII ? "ascii\"" : "appended\""); + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; if (format_ == Vtk::ASCII) { + out << ">\n"; auto points = dataCollector_.template points<double>(); std::size_t i = 0; for (auto const& v : points) @@ -99,33 +107,44 @@ void VtkWriterInterface<GV,DC> } } - template <class GV, class DC> - template <class T> -std::uint64_t VtkWriterInterface<GV,DC> - ::writeDataAppended (std::ofstream& out, VtkFunction const& fct, PositionTypes type) const +void VtkWriterInterface<GV,DC> + ::writeDataAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const { - assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); - - if (type == POINT_DATA) { - auto data = dataCollector_.template pointData<T>(fct); - return this->writeAppended(out, data); - } else { - auto data = dataCollector_.template cellData<T>(fct); - return this->writeAppended(out, data); + for (auto const& v : pointData_) { + blocks.push_back( v.type() == Vtk::FLOAT32 + ? this->writeValuesAppended(out, dataCollector_.template pointData<float>(v)) + : this->writeValuesAppended(out, dataCollector_.template pointData<double>(v))); + } + for (auto const& v : cellData_) { + blocks.push_back( v.type() == Vtk::FLOAT32 + ? this->writeValuesAppended(out, dataCollector_.template cellData<float>(v)) + : this->writeValuesAppended(out, dataCollector_.template cellData<double>(v))); } } template <class GV, class DC> - template <class T> -std::uint64_t VtkWriterInterface<GV,DC> - ::writePointsAppended (std::ofstream& out) const +void VtkWriterInterface<GV,DC> + ::writeAppended (std::ofstream& out, std::vector<pos_type> const& offsets) const { - assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); + if (is_a(format_, Vtk::APPENDED)) { + out << "<AppendedData encoding=\"raw\">\n_"; + std::vector<std::uint64_t> blocks; + writeGridAppended(out, blocks); + writeDataAppended(out, blocks); + out << "</AppendedData>\n"; + pos_type appended_pos = out.tellp(); + + pos_type offset = 0; + for (std::size_t i = 0; i < offsets.size(); ++i) { + out.seekp(offsets[i]); + out << '"' << offset << '"'; + offset += pos_type(blocks[i]); + } - auto points = dataCollector_.template points<T>(); - return this->writeAppended(out, points); + out.seekp(appended_pos); + } } @@ -173,7 +192,7 @@ std::uint64_t writeCompressed (unsigned char const* buffer, unsigned char* buffe template <class GV, class DC> template <class T> std::uint64_t VtkWriterInterface<GV,DC> - ::writeAppended (std::ofstream& out, std::vector<T> const& values) const + ::writeValuesAppended (std::ofstream& out, std::vector<T> const& values) const { assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); pos_type begin_pos = out.tellp(); diff --git a/dune/vtk/writers/vtkimagedatawriter.hh b/dune/vtk/writers/vtkimagedatawriter.hh index 0db3f86cddff7f42d6096ab0d074c6b43d574627..cc6f04e772562b96bc617e8d16a9b3da6c61ede4 100644 --- a/dune/vtk/writers/vtkimagedatawriter.hh +++ b/dune/vtk/writers/vtkimagedatawriter.hh @@ -49,6 +49,8 @@ namespace Dune return "vti"; } + virtual void writeGridAppended (std::ofstream& /*out*/, std::vector<std::uint64_t>& /*blocks*/) const override {} + private: using Super::dataCollector_; using Super::format_; diff --git a/dune/vtk/writers/vtkimagedatawriter.impl.hh b/dune/vtk/writers/vtkimagedatawriter.impl.hh index 235b4ef89186a2e3f772c9a4b3d4c7246111d2c6..b976b428d85686ca7ff1c69f40b429290d594ac8 100644 --- a/dune/vtk/writers/vtkimagedatawriter.impl.hh +++ b/dune/vtk/writers/vtkimagedatawriter.impl.hh @@ -67,37 +67,8 @@ void VtkImageDataWriter<GV,DC> out << "</Piece>\n"; out << "</ImageData>\n"; - std::vector<std::uint64_t> blocks; // size of i'th appended block - pos_type appended_pos = 0; - if (is_a(format_, Vtk::APPENDED)) { - out << "<AppendedData encoding=\"raw\">\n_"; - appended_pos = out.tellp(); - for (auto const& v : pointData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::POINT_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::POINT_DATA) ); - } - for (auto const& v : cellData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::CELL_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::CELL_DATA) ); - } - out << "</AppendedData>\n"; - } - + this->writeAppended(out, offsets); out << "</VTKFile>"; - - // fillin offset values and block sizes - if (is_a(format_, Vtk::APPENDED)) { - pos_type offset = 0; - for (std::size_t i = 0; i < offsets.size(); ++i) { - out.seekp(offsets[i]); - out << '"' << offset << '"'; - offset += pos_type(blocks[i]); - } - } } diff --git a/dune/vtk/writers/vtkrectilineargridwriter.hh b/dune/vtk/writers/vtkrectilineargridwriter.hh index f7df76b54a5ce81e54b4fcfd215cb57f2f79a333..050e899bd9fc9dc3c2c9d518bce388c13b7586be 100644 --- a/dune/vtk/writers/vtkrectilineargridwriter.hh +++ b/dune/vtk/writers/vtkrectilineargridwriter.hh @@ -44,7 +44,8 @@ namespace Dune /// for [i] in [0,...,size). virtual void writeParallelFile (std::string const& pfilename, int size) const override; - void writeCoordinates (std::ofstream& out, std::vector<pos_type>& offsets) const; + void writeCoordinates (std::ofstream& out, std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep = {}) const; template <class T> std::array<std::uint64_t, 3> writeCoordinatesAppended (std::ofstream& out) const; @@ -54,6 +55,8 @@ namespace Dune return "vtr"; } + virtual void writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const override; + private: using Super::dataCollector_; using Super::format_; diff --git a/dune/vtk/writers/vtkrectilineargridwriter.impl.hh b/dune/vtk/writers/vtkrectilineargridwriter.impl.hh index 23b8f09a179abc27519e709217a687fcf8dab722..48a650ee3646ff6e7de7a23840fd560e4dfd180c 100644 --- a/dune/vtk/writers/vtkrectilineargridwriter.impl.hh +++ b/dune/vtk/writers/vtkrectilineargridwriter.impl.hh @@ -47,6 +47,11 @@ void VtkRectilinearGridWriter<GV,DC> out << "<Piece Extent=\"" << join(extent.begin(), extent.end()) << "\">\n"; }); + // Write point coordinates for x, y, and z ordinate + out << "<Coordinates>\n"; + writeCoordinates(out, offsets); + out << "</Coordinates>\n"; + // Write data associated with grid points out << "<PointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) @@ -59,53 +64,11 @@ void VtkRectilinearGridWriter<GV,DC> this->writeData(out, offsets, v, Super::CELL_DATA); out << "</CellData>\n"; - // Write point coordinates for x, y, and z ordinate - out << "<Coordinates>\n"; - writeCoordinates(out, offsets); - out << "</Coordinates>\n"; - out << "</Piece>\n"; out << "</RectilinearGrid>\n"; - std::vector<std::uint64_t> blocks; // size of i'th appended block - pos_type appended_pos = 0; - if (is_a(format_, Vtk::APPENDED)) { - out << "<AppendedData encoding=\"raw\">\n_"; - appended_pos = out.tellp(); - for (auto const& v : pointData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::POINT_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::POINT_DATA) ); - } - for (auto const& v : cellData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::CELL_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::CELL_DATA) ); - } - - if (datatype_ == Vtk::FLOAT32) { - auto bs = writeCoordinatesAppended<float>(out); - blocks.insert(blocks.end(), bs.begin(), bs.end()); - } else { - auto bs = writeCoordinatesAppended<double>(out); - blocks.insert(blocks.end(), bs.begin(), bs.end()); - } - out << "</AppendedData>\n"; - } - + this->writeAppended(out, offsets); out << "</VTKFile>"; - - // fillin offset values and block sizes - if (is_a(format_, Vtk::APPENDED)) { - pos_type offset = 0; - for (std::size_t i = 0; i < offsets.size(); ++i) { - out.seekp(offsets[i]); - out << '"' << offset << '"'; - offset += pos_type(blocks[i]); - } - } } @@ -131,6 +94,13 @@ void VtkRectilinearGridWriter<GV,DC> << " WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\"" << ">\n"; + // Write point coordinates for x, y, and z ordinate + out << "<PCoordinates>\n"; + out << "<PDataArray Name=\"x\" type=\"" << to_string(datatype_) << "\" />\n"; + out << "<PDataArray Name=\"y\" type=\"" << to_string(datatype_) << "\" />\n"; + out << "<PDataArray Name=\"z\" type=\"" << to_string(datatype_) << "\" />\n"; + out << "</PCoordinates>\n"; + // Write data associated with grid points out << "<PPointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) { @@ -153,13 +123,6 @@ void VtkRectilinearGridWriter<GV,DC> } out << "</PCellData>\n"; - // Write point coordinates for x, y, and z ordinate - out << "<PCoordinates>\n"; - out << "<PDataArray Name=\"x\" type=\"" << to_string(datatype_) << "\" />\n"; - out << "<PDataArray Name=\"y\" type=\"" << to_string(datatype_) << "\" />\n"; - out << "<PDataArray Name=\"z\" type=\"" << to_string(datatype_) << "\" />\n"; - out << "</PCoordinates>\n"; - // Write piece file references dataCollector_.writePieces([&out,pfilename,ext=this->fileExtension()](int p, auto const& extent, bool write_extent) { @@ -177,13 +140,17 @@ void VtkRectilinearGridWriter<GV,DC> template <class GV, class DC> void VtkRectilinearGridWriter<GV,DC> - ::writeCoordinates (std::ofstream& out, std::vector<pos_type>& offsets) const + ::writeCoordinates (std::ofstream& out, std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep) const { std::string names = "xyz"; if (format_ == Vtk::ASCII) { auto coordinates = dataCollector_.template coordinates<double>(); for (std::size_t d = 0; d < 3; ++d) { - out << "<DataArray type=\"" << to_string(datatype_) << "\" Name=\"" << names[d] << "\" format=\"ascii\">\n"; + out << "<DataArray type=\"" << to_string(datatype_) << "\" Name=\"" << names[d] << "\" format=\"ascii\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; + out << ">\n"; std::size_t i = 0; for (auto const& c : coordinates[d]) out << c << (++i % 6 != 0 ? ' ' : '\n'); @@ -193,6 +160,8 @@ void VtkRectilinearGridWriter<GV,DC> else { // Vtk::APPENDED format for (std::size_t j = 0; j < 3; ++j) { out << "<DataArray type=\"" << to_string(datatype_) << "\" Name=\"" << names[j] << "\" format=\"appended\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; out << " offset="; offsets.push_back(out.tellp()); out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); @@ -203,20 +172,23 @@ void VtkRectilinearGridWriter<GV,DC> template <class GV, class DC> - template <class T> -std::array<std::uint64_t,3> VtkRectilinearGridWriter<GV,DC> - ::writeCoordinatesAppended (std::ofstream& out) const +void VtkRectilinearGridWriter<GV,DC> + ::writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const { assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); - auto coordinates = dataCollector_.template coordinates<T>(); - - // write conncetivity, offsets, and types - std::uint64_t bs0 = this->writeAppended(out, coordinates[0]); - std::uint64_t bs1 = this->writeAppended(out, coordinates[1]); - std::uint64_t bs2 = this->writeAppended(out, coordinates[2]); - - return {bs0, bs1, bs2}; + // write coordinates along axis + if (datatype_ == Vtk::FLOAT32) { + auto coordinates = dataCollector_.template coordinates<float>(); + blocks.push_back(this->writeValuesAppended(out, coordinates[0])); + blocks.push_back(this->writeValuesAppended(out, coordinates[1])); + blocks.push_back(this->writeValuesAppended(out, coordinates[2])); + } else { + auto coordinates = dataCollector_.template coordinates<double>(); + blocks.push_back(this->writeValuesAppended(out, coordinates[0])); + blocks.push_back(this->writeValuesAppended(out, coordinates[1])); + blocks.push_back(this->writeValuesAppended(out, coordinates[2])); + } } } // end namespace Dune diff --git a/dune/vtk/writers/vtkstructuredgridwriter.hh b/dune/vtk/writers/vtkstructuredgridwriter.hh index b27d8901bf403b8173c9a7a7a20ac65271968bed..f6ebc6a5c2b70afe66f02ffbcffef8e1ebf2850c 100644 --- a/dune/vtk/writers/vtkstructuredgridwriter.hh +++ b/dune/vtk/writers/vtkstructuredgridwriter.hh @@ -49,6 +49,8 @@ namespace Dune return "vts"; } + virtual void writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const override; + private: using Super::dataCollector_; using Super::format_; diff --git a/dune/vtk/writers/vtkstructuredgridwriter.impl.hh b/dune/vtk/writers/vtkstructuredgridwriter.impl.hh index 61c69cb8f9936f9f784eb7b6e39283cf970a8b8b..1dcd7241622c62d7b0649dd828a31fa17bfe1c13 100644 --- a/dune/vtk/writers/vtkstructuredgridwriter.impl.hh +++ b/dune/vtk/writers/vtkstructuredgridwriter.impl.hh @@ -45,6 +45,11 @@ void VtkStructuredGridWriter<GV,DC> out << "<Piece Extent=\"" << join(extent.begin(), extent.end()) << "\">\n"; }); + // Write point coordinates + out << "<Points>\n"; + this->writePoints(out, offsets); + out << "</Points>\n"; + // Write data associated with grid points out << "<PointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) @@ -57,50 +62,11 @@ void VtkStructuredGridWriter<GV,DC> this->writeData(out, offsets, v, Super::CELL_DATA); out << "</CellData>\n"; - // Write point coordinates - out << "<Points>\n"; - this->writePoints(out, offsets); - out << "</Points>\n"; - out << "</Piece>\n"; out << "</StructuredGrid>\n"; - std::vector<std::uint64_t> blocks; // size of i'th appended block - pos_type appended_pos = 0; - if (is_a(format_, Vtk::APPENDED)) { - out << "<AppendedData encoding=\"raw\">\n_"; - appended_pos = out.tellp(); - for (auto const& v : pointData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::POINT_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::POINT_DATA) ); - } - for (auto const& v : cellData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::CELL_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::CELL_DATA) ); - } - - if (datatype_ == Vtk::FLOAT32) - blocks.push_back( this->template writePointsAppended<float>(out) ); - else - blocks.push_back( this->template writePointsAppended<double>(out) ); - out << "</AppendedData>\n"; - } - + this->writeAppended(out, offsets); out << "</VTKFile>"; - - // fillin offset values and block sizes - if (is_a(format_, Vtk::APPENDED)) { - pos_type offset = 0; - for (std::size_t i = 0; i < offsets.size(); ++i) { - out.seekp(offsets[i]); - out << '"' << offset << '"'; - offset += pos_type(blocks[i]); - } - } } @@ -126,6 +92,14 @@ void VtkStructuredGridWriter<GV,DC> << " WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\"" << ">\n"; + // Write points + out << "<PPoints>\n"; + out << "<PDataArray" + << " type=\"" << to_string(datatype_) << "\"" + << " NumberOfComponents=\"3\"" + << " />\n"; + out << "</PPoints>\n"; + // Write data associated with grid points out << "<PPointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) { @@ -148,14 +122,6 @@ void VtkStructuredGridWriter<GV,DC> } out << "</PCellData>\n"; - // Write points - out << "<PPoints>\n"; - out << "<PDataArray" - << " type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"3\"" - << " />\n"; - out << "</PPoints>\n"; - // Write piece file references dataCollector_.writePieces([&out,pfilename,ext=this->fileExtension()](int p, auto const& extent, bool write_extent) { @@ -170,4 +136,21 @@ void VtkStructuredGridWriter<GV,DC> out << "</VTKFile>"; } + +template <class GV, class DC> +void VtkStructuredGridWriter<GV,DC> + ::writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const +{ + assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); + + // write points + if (datatype_ == Vtk::FLOAT32) { + auto points = dataCollector_.template points<float>(); + blocks.push_back(this->writeValuesAppended(out, points)); + } else { + auto points = dataCollector_.template points<double>(); + blocks.push_back(this->writeValuesAppended(out, points)); + } +} + } // end namespace Dune diff --git a/dune/vtk/writers/vtkunstructuredgridwriter.hh b/dune/vtk/writers/vtkunstructuredgridwriter.hh index f513923c3ad55de7e6a87f74f0633adfffc17350..f5d557c45ab1ab78d3a4cf8b55f953a176dc7d6d 100644 --- a/dune/vtk/writers/vtkunstructuredgridwriter.hh +++ b/dune/vtk/writers/vtkunstructuredgridwriter.hh @@ -57,15 +57,14 @@ namespace Dune return "vtu"; } + virtual void writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const override; + // Write the element connectivity to the output stream `out`. In case // of binary format, stores the streampos of XML attributes "offset" in the // vector `offsets`. void writeCells (std::ofstream& oust, - std::vector<pos_type>& offsets) const; - - // Collect element connectivity, offsets and element types, and pass the - // resulting vectors to \ref writeAppended. - std::array<std::uint64_t,3> writeCellsAppended (std::ofstream& out) const; + std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep = {}) const; private: using Super::dataCollector_; diff --git a/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh b/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh index 8488ad254174df366f53f4722fdd86cd5a641a1a..752e3b5bf42172dc80b6b5c1d6b8225d9cf080b9 100644 --- a/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh +++ b/dune/vtk/writers/vtkunstructuredgridwriter.impl.hh @@ -45,6 +45,16 @@ void VtkUnstructuredGridWriter<GV,DC> << " NumberOfCells=\"" << dataCollector_.numCells() << "\"" << ">\n"; + // Write point coordinates + out << "<Points>\n"; + this->writePoints(out, offsets); + out << "</Points>\n"; + + // Write element connectivity, types and offsets + out << "<Cells>\n"; + writeCells(out, offsets); + out << "</Cells>\n"; + // Write data associated with grid points out << "<PointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) @@ -57,58 +67,11 @@ void VtkUnstructuredGridWriter<GV,DC> this->writeData(out, offsets, v, Super::CELL_DATA); out << "</CellData>\n"; - // Write point coordinates - out << "<Points>\n"; - this->writePoints(out, offsets); - out << "</Points>\n"; - - // Write element connectivity, types and offsets - out << "<Cells>\n"; - writeCells(out, offsets); - out << "</Cells>\n"; - out << "</Piece>\n"; out << "</UnstructuredGrid>\n"; - std::vector<std::uint64_t> blocks; // size of i'th appended block - pos_type appended_pos = 0; - if (is_a(format_, Vtk::APPENDED)) { - out << "<AppendedData encoding=\"raw\">\n_"; - appended_pos = out.tellp(); - for (auto const& v : pointData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::POINT_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::POINT_DATA) ); - } - for (auto const& v : cellData_) { - if (v.type() == Vtk::FLOAT32) - blocks.push_back( this->template writeDataAppended<float>(out, v, Super::CELL_DATA) ); - else - blocks.push_back( this->template writeDataAppended<double>(out, v, Super::CELL_DATA) ); - } - - if (datatype_ == Vtk::FLOAT32) - blocks.push_back( this->template writePointsAppended<float>(out) ); - else - blocks.push_back( this->template writePointsAppended<double>(out) ); - - auto bs = writeCellsAppended(out); - blocks.insert(blocks.end(), bs.begin(), bs.end()); - out << "</AppendedData>\n"; - } - + this->writeAppended(out, offsets); out << "</VTKFile>"; - - // fillin offset values and block sizes - if (is_a(format_, Vtk::APPENDED)) { - pos_type offset = 0; - for (std::size_t i = 0; i < offsets.size(); ++i) { - out.seekp(offsets[i]); - out << '"' << offset << '"'; - offset += pos_type(blocks[i]); - } - } } @@ -130,6 +93,14 @@ void VtkUnstructuredGridWriter<GV,DC> out << "<PUnstructuredGrid GhostLevel=\"0\">\n"; + // Write points + out << "<PPoints>\n"; + out << "<PDataArray" + << " type=\"" << to_string(datatype_) << "\"" + << " NumberOfComponents=\"3\"" + << " />\n"; + out << "</PPoints>\n"; + // Write data associated with grid points out << "<PPointData" << this->getNames(pointData_) << ">\n"; for (auto const& v : pointData_) { @@ -152,14 +123,6 @@ void VtkUnstructuredGridWriter<GV,DC> } out << "</PCellData>\n"; - // Write points - out << "<PPoints>\n"; - out << "<PDataArray" - << " type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"3\"" - << " />\n"; - out << "</PPoints>\n"; - // Write piece file references for (int p = 0; p < size; ++p) { std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + this->fileExtension(); @@ -176,7 +139,7 @@ void VtkUnstructuredGridWriter<GV,DC> ::writeTimeseriesFile (std::string const& filename, std::string const& filenameMesh, std::vector<std::pair<double, std::string>> const& timesteps, - std::vector<std::uint64_t> const& blocksize) const + std::vector<std::uint64_t> const& blocks) const { std::ofstream out(filename, std::ios_base::ate | std::ios::binary); assert(out.is_open()); @@ -212,43 +175,14 @@ void VtkUnstructuredGridWriter<GV,DC> // Write point coordinates out << "<Points>\n"; - for (std::size_t i = 0; i < timesteps.size(); ++i) { - out << "<DataArray" - << " type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"3\"" - << " TimeStep=\"" << i << "\"" - << " format=\"appended\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - } + for (std::size_t i = 0; i < timesteps.size(); ++i) + this->writePoints(out, offsets[i], i); out << "</Points>\n"; // Write element connectivity, types and offsets out << "<Cells>\n"; - for (std::size_t i = 0; i < timesteps.size(); ++i) { - out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"appended\"" - << " TimeStep=\"" << i << "\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - - out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"appended\"" - << " TimeStep=\"" << i << "\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - - out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"appended\"" - << " TimeStep=\"" << i << "\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - } + for (std::size_t i = 0; i < timesteps.size(); ++i) + writeCells(out, offsets[i], i); out << "</Cells>\n"; const std::size_t shift = offsets[0].size(); // number of blocks to write the grid @@ -256,43 +190,22 @@ void VtkUnstructuredGridWriter<GV,DC> // Write data associated with grid points out << "<PointData" << this->getNames(pointData_) << ">\n"; for (std::size_t i = 0; i < timesteps.size(); ++i) { - for (auto const& v : pointData_) { - out << "<DataArray" - << " Name=\"" << v.name() << "\"" - << " TimeStep=\"" << i << "\"" - << " type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\"" - << " format=\"appended\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - } + for (auto const& v : pointData_) + this->writeData(out, offsets[i], v, Super::POINT_DATA, i); } out << "</PointData>\n"; // Write data associated with grid cells out << "<CellData" << this->getNames(cellData_) << ">\n"; for (std::size_t i = 0; i < timesteps.size(); ++i) { - for (auto const& v : cellData_) { - out << "<DataArray" - << " Name=\"" << v.name() << "\"" - << " TimeStep=\"" << i << "\"" - << " type=\"" << to_string(datatype_) << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\"" - << " format=\"appended\"" - << " offset="; - offsets[i].push_back(out.tellp()); - out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); - out << "/>\n"; - } + for (auto const& v : cellData_) + this->writeData(out, offsets[i], v, Super::CELL_DATA, i); } out << "</CellData>\n"; out << "</Piece>\n"; out << "</UnstructuredGrid>\n"; - std::vector<std::uint64_t> blocks; // size of i'th appended block pos_type appended_pos = 0; out << "<AppendedData encoding=\"raw\">\n_"; appended_pos = out.tellp(); @@ -300,7 +213,7 @@ void VtkUnstructuredGridWriter<GV,DC> std::ifstream file_mesh(filenameMesh, std::ios_base::in | std::ios_base::binary); out << file_mesh.rdbuf(); file_mesh.close(); - assert( std::uint64_t(out.tellp()) == std::accumulate(blocksize.begin(), std::next(blocksize.begin(),shift), std::uint64_t(appended_pos)) ); + assert( std::uint64_t(out.tellp()) == std::accumulate(blocks.begin(), std::next(blocks.begin(),shift), std::uint64_t(appended_pos)) ); for (auto const& timestep : timesteps) { std::ifstream file(timestep.second, std::ios_base::in | std::ios_base::binary); @@ -320,7 +233,7 @@ void VtkUnstructuredGridWriter<GV,DC> for (std::size_t j = 0; j < shift; ++j) { out.seekp(off[j]); out << '"' << offset << '"'; - offset += pos_type(blocksize[j]); + offset += pos_type(blocks[j]); } } @@ -331,7 +244,7 @@ void VtkUnstructuredGridWriter<GV,DC> for (std::size_t k = shift; k < off.size(); ++k) { out.seekp(off[k]); out << '"' << offset << '"'; - offset += pos_type(blocksize[j++]); + offset += pos_type(blocks[j++]); } } } @@ -339,23 +252,33 @@ void VtkUnstructuredGridWriter<GV,DC> template <class GV, class DC> void VtkUnstructuredGridWriter<GV,DC> - ::writeCells (std::ofstream& out, std::vector<pos_type>& offsets) const + ::writeCells (std::ofstream& out, std::vector<pos_type>& offsets, + Std::optional<std::size_t> timestep) const { if (format_ == Vtk::ASCII) { auto cells = dataCollector_.cells(); - out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"ascii\">\n"; + out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"ascii\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; + out << ">\n"; std::size_t i = 0; for (auto const& c : cells.connectivity) out << c << (++i % 6 != 0 ? ' ' : '\n'); out << (i % 6 != 0 ? "\n" : "") << "</DataArray>\n"; - out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\">\n"; + out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"ascii\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; + out << ">\n"; i = 0; for (auto const& o : cells.offsets) out << o << (++i % 6 != 0 ? ' ' : '\n'); out << (i % 6 != 0 ? "\n" : "") << "</DataArray>\n"; - out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"; + out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; + out << ">\n"; i = 0; for (auto const& t : cells.types) out << int(t) << (++i % 6 != 0 ? ' ' : '\n'); @@ -363,18 +286,24 @@ void VtkUnstructuredGridWriter<GV,DC> } else { // Vtk::APPENDED format out << "<DataArray type=\"Int64\" Name=\"connectivity\" format=\"appended\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; out << " offset="; offsets.push_back(out.tellp()); out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); out << "/>\n"; out << "<DataArray type=\"Int64\" Name=\"offsets\" format=\"appended\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; out << " offset="; offsets.push_back(out.tellp()); out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); out << "/>\n"; out << "<DataArray type=\"UInt8\" Name=\"types\" format=\"appended\""; + if (timestep) + out << " TimeStep=\"" << *timestep << "\""; out << " offset="; offsets.push_back(out.tellp()); out << std::string(std::numeric_limits<std::uint64_t>::digits10 + 2, ' '); @@ -384,20 +313,25 @@ void VtkUnstructuredGridWriter<GV,DC> template <class GV, class DC> -std::array<std::uint64_t,3> VtkUnstructuredGridWriter<GV,DC> - ::writeCellsAppended (std::ofstream& out) const +void VtkUnstructuredGridWriter<GV,DC> + ::writeGridAppended (std::ofstream& out, std::vector<std::uint64_t>& blocks) const { assert(is_a(format_, Vtk::APPENDED) && "Function should by called only in appended mode!\n"); - auto cells = dataCollector_.cells(); + // write points + if (datatype_ == Vtk::FLOAT32) { + auto points = dataCollector_.template points<float>(); + blocks.push_back(this->writeValuesAppended(out, points)); + } else { + auto points = dataCollector_.template points<double>(); + blocks.push_back(this->writeValuesAppended(out, points)); + } // write conncetivity, offsets, and types - std::uint64_t bs0 = this->writeAppended(out, cells.connectivity); - std::uint64_t bs1 = this->writeAppended(out, cells.offsets); - std::uint64_t bs2 = this->writeAppended(out, cells.types); - - return {bs0, bs1, bs2}; + auto cells = dataCollector_.cells(); + blocks.push_back(this->writeValuesAppended(out, cells.connectivity)); + blocks.push_back(this->writeValuesAppended(out, cells.offsets)); + blocks.push_back(this->writeValuesAppended(out, cells.types)); } - } // end namespace Dune