Commit 197dee84 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Restructuring of vtk writers to remove redundency

parent be9d72e6
......@@ -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_;
......
......@@ -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());
......
......@@ -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;
......
......@@ -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();
......
......@@ -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_;
......
......@@ -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]);
}
}
}
......
......@@ -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_;
......
......@@ -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
......@@ -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_;
......
......@@ -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
......@@ -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;