diff --git a/dune/vtk/gridcreator.hh b/dune/vtk/gridcreator.hh index 7399bdc08bca79c185eaadee0e504bd75142b7bb..ec44cad31d224de92439e9d3da22e202e1531ba3 100644 --- a/dune/vtk/gridcreator.hh +++ b/dune/vtk/gridcreator.hh @@ -28,9 +28,7 @@ namespace Dune { namespace experimental std::size_t idx = 0; for (std::size_t i = 0; i < types.size(); ++i) { - if (Vtk::Map::from_type.count(types[i]) == 0) - DUNE_THROW(Exception, "Unknown ElementType: " << types[i]); - auto type = Vtk::Map::from_type[types[i]]; + auto type = Vtk::to_geometry(types[i]); Vtk::CellType cellType{type}; auto refElem = referenceElement<double,Grid::dimension>(type); @@ -92,9 +90,7 @@ namespace Dune { namespace experimental idx = 0; for (std::size_t i = 0; i < types.size(); ++i) { - if (Vtk::Map::from_type.count(types[i]) == 0) - DUNE_THROW(Exception, "Unknown ElementType: " << types[i]); - auto type = Vtk::Map::from_type[types[i]]; + auto type = Vtk::to_geometry(types[i]); Vtk::CellType cellType{type}; std::size_t nNodes = offsets[i] - (i == 0 ? 0 : offsets[i-1]); diff --git a/dune/vtk/utility/string.hh b/dune/vtk/utility/string.hh index d0640a88203ca7264b3cbc93c05b97c124f444f6..7724911a9df42db7474b297b0f52424913242695 100644 --- a/dune/vtk/utility/string.hh +++ b/dune/vtk/utility/string.hh @@ -3,6 +3,7 @@ #include <algorithm> #include <cctype> #include <locale> +#include <sstream> #include <string> namespace Dune @@ -74,8 +75,8 @@ namespace Dune } } - template <class InputIter, class SeparaterIter, class Func> - void split(InputIter first, InputIter end, SeparaterIter s_first, SeparaterIter s_end, Func f) + template <class InputIter, class SeparatorIter, class Func> + void split(InputIter first, InputIter end, SeparatorIter s_first, SeparatorIter s_end, Func f) { if (first == end) return; @@ -102,4 +103,18 @@ namespace Dune } } + + template <class InputIter> + std::string join (InputIter first, InputIter end, std::string sep = " ") + { + if (first == end) + return ""; + + std::ostringstream os; + os << *first++; + while (first != end) + os << sep << *first++; + return os.str(); + } + } // end namspace Dune diff --git a/dune/vtk/vtkfunction.hh b/dune/vtk/vtkfunction.hh index 3220e0d7b979e9242691adeaaf0a4d096e0fc810..11a61ece0afd77e03ed6ede88d087a3f157de1c9 100644 --- a/dune/vtk/vtkfunction.hh +++ b/dune/vtk/vtkfunction.hh @@ -3,6 +3,7 @@ #include <type_traits> #include <dune/common/std/type_traits.hh> +#include <dune/functions/common/signature.hh> #include <dune/functions/common/typeerasure.hh> namespace Dune { namespace experimental @@ -162,14 +163,32 @@ namespace Dune { namespace experimental template <class F> using HasLocalFunction = decltype(localFunction(std::declval<F>())); - public: template <class F> - VTKFunction (F&& f, std::string name, int ncomps = 1) + using Signature = typename std::decay_t<F>::Signature; + + public: + template <class F, + class Range = typename Functions::SignatureTraits<Signature<F>>::Range> + VTKFunction (F&& f, std::string name, int ncomps = 1, + Vtk::DataTypes type = Vtk::Map::type<Range>) + : Super(std::forward<F>(f)) + , name_(std::move(name)) + , ncomps_(ncomps > 3 ? 9 : ncomps > 1 ? 3 : 1) // tensor, vector, or scalar + , type_(type) + { + static_assert(Std::is_detected<HasLocalFunction,F>::value, + "Requires A GridFunction to be passed to the VTKFunction."); + } + + template <class F, + std::enable_if_t<not Std::is_detected<Signature,F>::value,int> = 0> + VTKFunction (F&& f, std::string name, int ncomps = 1, + Vtk::DataTypes type = Vtk::FLOAT32) : Super(std::forward<F>(f)) , name_(std::move(name)) - , ncomps_(ncomps > 1 ? 3 : 1) + , ncomps_(ncomps > 3 ? 9 : ncomps > 1 ? 3 : 1) // tensor, vector, or scalar + , type_(type) { - assert(1 <= ncomps && ncomps <= 3); static_assert(Std::is_detected<HasLocalFunction,F>::value, "Requires A GridFunction to be passed to the VTKFunction."); } @@ -194,10 +213,16 @@ namespace Dune { namespace experimental return ncomps_; } + /// Return the VTK Datatype associated with the functions range type + Vtk::DataTypes type () const + { + return type_; + } + private: std::string name_; - int ncomps_ = 1; + Vtk::DataTypes type_; }; }} // end namespace Dune::experimental diff --git a/dune/vtk/vtkimagedatawriter.impl.hh b/dune/vtk/vtkimagedatawriter.impl.hh index b392047719f51071303a38a262ad2530cf6e3424..6ae03f06bf8bcdf0409d37e7371f032c98a98b16 100644 --- a/dune/vtk/vtkimagedatawriter.impl.hh +++ b/dune/vtk/vtkimagedatawriter.impl.hh @@ -29,56 +29,39 @@ void VtkImageDataWriter<GV,DC> } std::vector<pos_type> offsets; // pos => offset - out << "<VTKFile type=\"ImageData\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); - out << "<ImageData WholeExtent=\""; + out << "<VTKFile" + << " type=\"StructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; + auto const& wholeExtent = dataCollector_.wholeExtent(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << wholeExtent[2*i] << " " << wholeExtent[2*i+1]; - } - out << "\" Origin=\""; auto const& origin = dataCollector_.origin(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << origin[i]; - } - out << "\" Spacing=\""; auto const& spacing = dataCollector_.spacing(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << spacing[i]; - } - out << "\">\n"; - - dataCollector_.writeLocalPiece([&out](std::array<int,6> const& extent) - { - out << "<Piece Extent=\""; - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << extent[2*i] << " " << extent[2*i+1]; - } - out << "\">\n"; + out << "<ImageData" + << " WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\"" + << " Origin=\"" << join(origin.begin(), origin.end()) << "\"" + << " Spacing=\"" << join(spacing.begin(), spacing.end()) << "\"" + << ">\n"; + + dataCollector_.writeLocalPiece([&out](auto const& extent) { + out << "<Piece Extent=\"" << join(extent.begin(), extent.end()) << "\">\n"; }); - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) - this->writeData(out, offsets, v, Super::POINT_DATA); - out << "</PointData>\n"; - } + // Write data associated with grid points + out << "<PointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) + this->writeData(out, offsets, v, Super::POINT_DATA); + out << "</PointData>\n"; + + // Write data associated with grid cells + out << "<CellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) + this->writeData(out, offsets, v, Super::CELL_DATA); + out << "</CellData>\n"; - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<CellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) - this->writeData(out, offsets, v, Super::CELL_DATA); - out << "</CellData>\n"; - } out << "</Piece>\n"; out << "</ImageData>\n"; @@ -88,13 +71,13 @@ void VtkImageDataWriter<GV,DC> out << "<AppendedData encoding=\"raw\">\n_"; appended_pos = out.tellp(); for (auto const& v : pointData_) { - if (datatype_ == Vtk::FLOAT32) + 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 (datatype_ == Vtk::FLOAT32) + 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) ); @@ -123,63 +106,53 @@ void VtkImageDataWriter<GV,DC> std::string filename = pfilename + ".p" + this->fileExtension(); std::ofstream out(filename, std::ios_base::ate | std::ios::binary); - out << "<VTKFile type=\"PImageData\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); - out << "<PImageData GhostLevel=\"0\" WholeExtent=\""; + out << "<VTKFile" + << " type=\"StructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; + auto const& wholeExtent = dataCollector_.wholeExtent(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << wholeExtent[2*i] << " " << wholeExtent[2*i+1]; - } - out << "\" Origin=\""; auto const& origin = dataCollector_.origin(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << origin[i]; - } - out << "\" Spacing=\""; auto const& spacing = dataCollector_.spacing(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << spacing[i]; + out << "<PImageData" + << " GhostLevel=\"0\"" + << " WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\"" + << " Origin=\"" << join(origin.begin(), origin.end()) << "\"" + << " Spacing=\"" << join(spacing.begin(), spacing.end()) << "\"" + << ">\n"; + + // Write data associated with grid points + out << "<PPointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } - out << "\">\n"; - - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PPointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PPointData>\n"; - } - - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PCellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PCellData>\n"; + out << "</PPointData>\n"; + + // Write data associated with grid cells + out << "<PCellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } + out << "</PCellData>\n"; // Write piece file references - dataCollector_.writePieces([&out,pfilename,ext=this->fileExtension()](int p, std::array<int,6> const& extent, bool write_extent) + dataCollector_.writePieces([&out,pfilename,ext=this->fileExtension()](int p, auto const& extent, bool write_extent) { - out << "<Piece Source=\"" << pfilename << "_p" << std::to_string(p) << "." << ext << "\""; - if (write_extent) { - out << " Extent=\""; - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << extent[2*i] << " " << extent[2*i+1]; - } - out << "\""; - } + std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + ext; + out << "<Piece Source=\"" << piece_source << "\""; + if (write_extent) + out << " Extent=\"" << join(extent.begin(), extent.end()) << "\""; out << " />\n"; }); diff --git a/dune/vtk/vtkstructuredgridwriter.impl.hh b/dune/vtk/vtkstructuredgridwriter.impl.hh index d7f62943a4bd753578eb4a3d0592c8678508c451..60a9c989f345c9f26f229748c45a77b0033e97de 100644 --- a/dune/vtk/vtkstructuredgridwriter.impl.hh +++ b/dune/vtk/vtkstructuredgridwriter.impl.hh @@ -29,46 +29,32 @@ void VtkStructuredGridWriter<GV,DC> } std::vector<pos_type> offsets; // pos => offset - out << "<VTKFile type=\"StructuredGrid\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); - out << "<StructuredGrid WholeExtent=\""; + out << "<VTKFile" + << " type=\"StructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; + auto const& wholeExtent = dataCollector_.wholeExtent(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << wholeExtent[2*i] << " " << wholeExtent[2*i+1]; - } - out << "\">\n"; + out << "<StructuredGrid WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\">\n"; - dataCollector_.writeLocalPiece([&out](std::array<int,6> const& extent) - { - out << "<Piece Extent=\""; - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << extent[2*i] << " " << extent[2*i+1]; - } - out << "\">\n"; + dataCollector_.writeLocalPiece([&out](auto const& extent) { + out << "<Piece Extent=\"" << join(extent.begin(), extent.end()) << "\">\n"; }); - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) - this->writeData(out, offsets, v, Super::POINT_DATA); - out << "</PointData>\n"; - } + // Write data associated with grid points + out << "<PointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) + this->writeData(out, offsets, v, Super::POINT_DATA); + out << "</PointData>\n"; - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<CellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) - this->writeData(out, offsets, v, Super::CELL_DATA); - out << "</CellData>\n"; - } + // Write data associated with grid cells + out << "<CellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) + this->writeData(out, offsets, v, Super::CELL_DATA); + out << "</CellData>\n"; // Write point coordinates out << "<Points>\n"; @@ -84,17 +70,18 @@ void VtkStructuredGridWriter<GV,DC> out << "<AppendedData encoding=\"raw\">\n_"; appended_pos = out.tellp(); for (auto const& v : pointData_) { - if (datatype_ == Vtk::FLOAT32) + 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 (datatype_ == Vtk::FLOAT32) + 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 @@ -123,58 +110,57 @@ void VtkStructuredGridWriter<GV,DC> std::string filename = pfilename + ".p" + this->fileExtension(); std::ofstream out(filename, std::ios_base::ate | std::ios::binary); - out << "<VTKFile type=\"PStructuredGrid\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); - out << "<PStructuredGrid GhostLevel=\"0\" WholeExtent=\""; + out << "<VTKFile" + << " type=\"PStructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; + auto const& wholeExtent = dataCollector_.wholeExtent(); - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << wholeExtent[2*i] << " " << wholeExtent[2*i+1]; + out << "<PStructuredGrid" + << " GhostLevel=\"0\"" + << " WholeExtent=\"" << join(wholeExtent.begin(), wholeExtent.end()) << "\"" + << ">\n"; + + // Write data associated with grid points + out << "<PPointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } - out << "\">\n"; - - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PPointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PPointData>\n"; - } - - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PCellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PCellData>\n"; + out << "</PPointData>\n"; + + // Write data associated with grid cells + out << "<PCellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } + out << "</PCellData>\n"; // Write points out << "<PPoints>\n"; - out << "<PDataArray type=\"" << Vtk::Map::from_datatype[datatype_] << "\" NumberOfComponents=\"3\" />\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, std::array<int,6> const& extent, bool write_extent) + dataCollector_.writePieces([&out,pfilename,ext=this->fileExtension()](int p, auto const& extent, bool write_extent) { - out << "<Piece Source=\"" << pfilename << "_p" << std::to_string(p) << "." << ext << "\""; - if (write_extent) { - out << " Extent=\""; - for (int i = 0; i < 3; ++i) { - out << (i == 0 ? "" : " ") << extent[2*i] << " " << extent[2*i+1]; - } - out << "\""; - } + std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + ext; + out << "<Piece Source=\"" << piece_source << "\""; + if (write_extent) + out << " Extent=\"" << join(extent.begin(), extent.end()) << "\""; out << " />\n"; }); diff --git a/dune/vtk/vtktypes.cc b/dune/vtk/vtktypes.cc index feae2277b0bdaf2e4bd3163576351ab47a9d35f2..f14ffc5b09f6a3916584694a71c9f0c743be5823 100644 --- a/dune/vtk/vtktypes.cc +++ b/dune/vtk/vtktypes.cc @@ -5,16 +5,55 @@ namespace Dune { namespace experimental { namespace Vtk { -std::map<std::uint8_t, GeometryType> Map::from_type = { - {VERTEX, GeometryTypes::vertex }, - {LINE, GeometryTypes::line }, - {TRIANGLE, GeometryTypes::triangle }, - {QUAD, GeometryTypes::quadrilateral }, - {TETRA, GeometryTypes::tetrahedron }, - {HEXAHEDRON, GeometryTypes::hexahedron }, - {WEDGE, GeometryTypes::prism }, - {PYRAMID, GeometryTypes::pyramid }, -}; +std::string to_string (FormatTypes type) +{ + switch (type) { + case ASCII: return "ascii"; + case BINARY: return "binary"; + case COMPRESSED: return "compressed"; + case APPENDED: return "appended"; + default: + DUNE_THROW(RangeError, "FormatType not found."); + std::abort(); + } +} + +std::string to_string (DataTypes type) +{ + switch (type) { + case INT8: return "Int8"; + case UINT8: return "UInt8"; + case INT16: return "Int16"; + case UINT16: return "UInt16"; + case INT32: return "Int32"; + case UINT32: return "UInt32"; + case INT64: return "Int64"; + case UINT64: return "UInt64"; + case FLOAT32: return "Float32"; + case FLOAT64: return "Float64"; + default: + DUNE_THROW(RangeError, "DataType not found."); + std::abort(); + } +} + +GeometryType to_geometry (std::uint8_t cell) +{ + switch (cell) { + case VERTEX: return GeometryTypes::vertex; + case LINE: return GeometryTypes::line; + case TRIANGLE: return GeometryTypes::triangle; + case QUAD: return GeometryTypes::quadrilateral; + case TETRA: return GeometryTypes::tetrahedron; + case HEXAHEDRON: return GeometryTypes::hexahedron; + case WEDGE: return GeometryTypes::prism; + case PYRAMID: return GeometryTypes::pyramid; + default: + DUNE_THROW(RangeError, "CellType does not map to GeometryType."); + std::abort(); + } +} + std::map<std::string, DataTypes> Map::to_datatype = { {"Int8", INT8}, @@ -29,18 +68,7 @@ std::map<std::string, DataTypes> Map::to_datatype = { {"Float64", FLOAT64} }; -std::map<DataTypes, std::string> Map::from_datatype = { - {INT8, "Int8"}, - {UINT8, "UInt8"}, - {INT16, "Int16"}, - {UINT16, "UInt16"}, - {INT32, "Int32"}, - {UINT32, "UInt32"}, - {INT64, "Int64"}, - {UINT64, "UInt64"}, - {FLOAT32, "Float32"}, - {FLOAT64, "Float64"} -}; + CellType::CellType (GeometryType const& t, CellParametrization parametrization) : noPermutation_(true) diff --git a/dune/vtk/vtktypes.hh b/dune/vtk/vtktypes.hh index 68342ce56e749856cc5c80485230e7785fb4bde8..0415be700c92d19c67db0c15081a54fa11564d9f 100644 --- a/dune/vtk/vtktypes.hh +++ b/dune/vtk/vtktypes.hh @@ -17,6 +17,7 @@ namespace Dune { namespace experimental COMPRESSED = 1<<2, APPENDED = BINARY | COMPRESSED }; + std::string to_string (FormatTypes); enum DataTypes { UNKNOWN = 0, @@ -27,6 +28,7 @@ namespace Dune { namespace experimental FLOAT32 = 32, FLOAT64 = 64 }; + std::string to_string (DataTypes); enum CellParametrization { LINEAR, @@ -56,12 +58,28 @@ namespace Dune { namespace experimental QUADRATIC_TETRA = 24, QUADRATIC_HEXAHEDRON = 25 }; + GeometryType to_geometry (std::uint8_t); struct Map { - static std::map<std::uint8_t, GeometryType> from_type; // VTK Cell type -> Dune::GeometryType static std::map<std::string, DataTypes> to_datatype; // String -> DataTypes - static std::map<DataTypes, std::string> from_datatype; // DataTypes -> String + + template <class T> struct Type {}; + + static constexpr DataTypes typeImpl (Type<std::int8_t>) { return INT8; } + static constexpr DataTypes typeImpl (Type<std::uint8_t>) { return UINT8; } + static constexpr DataTypes typeImpl (Type<std::int16_t>) { return INT16; } + static constexpr DataTypes typeImpl (Type<std::uint16_t>) { return UINT16; } + static constexpr DataTypes typeImpl (Type<std::int32_t>) { return INT32; } + static constexpr DataTypes typeImpl (Type<std::uint32_t>) { return UINT32; } + static constexpr DataTypes typeImpl (Type<std::int64_t>) { return INT64; } + static constexpr DataTypes typeImpl (Type<std::uint64_t>) { return UINT64; } + static constexpr DataTypes typeImpl (Type<float>) { return FLOAT32; } + static constexpr DataTypes typeImpl (Type<double>) { return FLOAT64; } + static constexpr DataTypes typeImpl (Type<long double>) { return FLOAT64; } + + template <class T> + static constexpr DataTypes type = typeImpl(Type<T>{}); }; diff --git a/dune/vtk/vtkunstructuredgridwriter.impl.hh b/dune/vtk/vtkunstructuredgridwriter.impl.hh index 226f004e2b6dcc51d384e21135edce1bab3bbcad..41c602cf2c79461f792fb1b81d39fff7cf0454cf 100644 --- a/dune/vtk/vtkunstructuredgridwriter.impl.hh +++ b/dune/vtk/vtkunstructuredgridwriter.impl.hh @@ -29,34 +29,31 @@ void VtkUnstructuredGridWriter<GV,DC> } std::vector<pos_type> offsets; // pos => offset - out << "<VTKFile type=\"UnstructuredGrid\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); - out << "<UnstructuredGrid>\n"; - out << "<Piece NumberOfPoints=\"" << dataCollector_.numPoints() << "\" " - << "NumberOfCells=\"" << dataCollector_.numCells() << "\">\n"; - - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) - this->writeData(out, offsets, v, Super::POINT_DATA); - out << "</PointData>\n"; - } + out << "<VTKFile" + << " type=\"UnstructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<CellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) - this->writeData(out, offsets, v, Super::CELL_DATA); - out << "</CellData>\n"; - } + out << "<UnstructuredGrid>\n"; + out << "<Piece" + << " NumberOfPoints=\"" << dataCollector_.numPoints() << "\"" + << " NumberOfCells=\"" << dataCollector_.numCells() << "\"" + << ">\n"; + + // Write data associated with grid points + out << "<PointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) + this->writeData(out, offsets, v, Super::POINT_DATA); + out << "</PointData>\n"; + + // Write data associated with grid cells + out << "<CellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) + this->writeData(out, offsets, v, Super::CELL_DATA); + out << "</CellData>\n"; // Write point coordinates out << "<Points>\n"; @@ -77,17 +74,18 @@ void VtkUnstructuredGridWriter<GV,DC> out << "<AppendedData encoding=\"raw\">\n_"; appended_pos = out.tellp(); for (auto const& v : pointData_) { - if (datatype_ == Vtk::FLOAT32) + 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 (datatype_ == Vtk::FLOAT32) + 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 @@ -118,45 +116,50 @@ void VtkUnstructuredGridWriter<GV,DC> std::string filename = pfilename + ".pvtu"; std::ofstream out(filename, std::ios_base::ate | std::ios::binary); - out << "<VTKFile type=\"PUnstructuredGrid\" version=\"1.0\" " - << "byte_order=\"" << this->getEndian() << "\" header_type=\"UInt64\"" - << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\">\n" : ">\n"); + out << "<VTKFile" + << " type=\"PUnstructuredGrid\"" + << " version=\"1.0\"" + << " byte_order=\"" << this->getEndian() << "\"" + << " header_type=\"UInt64\"" + << (format_ == Vtk::COMPRESSED ? " compressor=\"vtkZLibDataCompressor\"" : "") + << ">\n"; + out << "<PUnstructuredGrid GhostLevel=\"0\">\n"; - { // Write data associated with grid points - auto scalar = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(pointData_.begin(), pointData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PPointData" << (scalar != pointData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != pointData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : pointData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PPointData>\n"; + // Write data associated with grid points + out << "<PPointData" << this->getNames(pointData_) << ">\n"; + for (auto const& v : pointData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } - - { // Write data associated with grid cells - auto scalar = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() == 1; }); - auto vector = std::find_if(cellData_.begin(), cellData_.end(), [](auto const& v) { return v.ncomps() > 1; }); - out << "<PCellData" << (scalar != cellData_.end() ? " Scalars=\"" + scalar->name() + "\"" : "") - << (vector != cellData_.end() ? " Vectors=\"" + vector->name() + "\"" : "") - << ">\n"; - for (auto const& v : cellData_) { - out << "<PDataArray Name=\"" << v.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" - << " NumberOfComponents=\"" << v.ncomps() << "\" />\n"; - } - out << "</PCellData>\n"; + out << "</PPointData>\n"; + + // Write data associated with grid cells + out << "<PCellData" << this->getNames(cellData_) << ">\n"; + for (auto const& v : cellData_) { + out << "<PDataArray" + << " Name=\"" << v.name() << "\"" + << " type=\"" << to_string(v.type()) << "\"" + << " NumberOfComponents=\"" << v.ncomps() << "\"" + << " />\n"; } + out << "</PCellData>\n"; // Write points out << "<PPoints>\n"; - out << "<PDataArray type=\"" << Vtk::Map::from_datatype[datatype_] << "\" NumberOfComponents=\"3\" />\n"; + out << "<PDataArray" + << " type=\"" << to_string(datatype_) << "\"" + << " NumberOfComponents=\"3\"" + << " />\n"; out << "</PPoints>\n"; // Write piece file references - for (int i = 0; i < size; ++i) { - out << "<Piece Source=\"" << pfilename << "_p" << std::to_string(i) << "." << this->fileExtension() << "\" />\n"; + for (int p = 0; p < size; ++p) { + std::string piece_source = pfilename + "_p" + std::to_string(p) + "." + this->fileExtension(); + out << "<Piece Source=\"" << piece_source << "\" />\n"; } out << "</PUnstructuredGrid>\n"; diff --git a/dune/vtk/vtkwriter.hh b/dune/vtk/vtkwriter.hh index 769cb9bc9827c392d8bb13dda2137b047f751a69..9e081812c7c7841c186709c51bc1272795b6cf50 100644 --- a/dune/vtk/vtkwriter.hh +++ b/dune/vtk/vtkwriter.hh @@ -4,6 +4,8 @@ #include <iosfwd> #include <map> +#include <dune/common/std/optional.hh> + #include "datacollector.hh" #include "filewriter.hh" #include "vtkfunction.hh" @@ -117,6 +119,35 @@ namespace Dune { namespace experimental template <class T> std::uint64_t writeAppended (std::ofstream& out, std::vector<T> const& values) const; + + Std::optional<std::string> getScalarName (std::vector<GlobalFunction> const& data) const + { + auto scalar = std::find_if(data.begin(), data.end(), [](auto const& v) { return v.ncomps() == 1; }); + return scalar != data.end() ? Std::optional<std::string>{scalar->name()} : Std::optional<std::string>{}; + } + + Std::optional<std::string> getVectorName (std::vector<GlobalFunction> const& data) const + { + auto vector = std::find_if(data.begin(), data.end(), [](auto const& v) { return v.ncomps() == 3; }); + return vector != data.end() ? Std::optional<std::string>{vector->name()} : Std::optional<std::string>{}; + } + + Std::optional<std::string> getTensorName (std::vector<GlobalFunction> const& data) const + { + auto tensor = std::find_if(data.begin(), data.end(), [](auto const& v) { return v.ncomps() == 9; }); + return tensor != data.end() ? Std::optional<std::string>{tensor->name()} : Std::optional<std::string>{}; + } + + std::string getNames (std::vector<GlobalFunction> const& data) const + { + auto n1 = getScalarName(data); + auto n2 = getVectorName(data); + auto n3 = getScalarName(data); + return (n1 ? " Scalars=\"" + *n1 + "\"" : "") + + (n2 ? " Vectors=\"" + *n2 + "\"" : "") + + (n3 ? " Tensors=\"" + *n3 + "\"" : ""); + } + // Returns endianness std::string getEndian () const { diff --git a/dune/vtk/vtkwriter.impl.hh b/dune/vtk/vtkwriter.impl.hh index 184e477e00c773f5be589cd80d248762be0271f5..7cb7f498463a94eb0b1534f512e8c0a85220240b 100644 --- a/dune/vtk/vtkwriter.impl.hh +++ b/dune/vtk/vtkwriter.impl.hh @@ -65,7 +65,7 @@ void VtkWriter<GV,DC> ::writeData (std::ofstream& out, std::vector<pos_type>& offsets, GlobalFunction const& fct, PositionTypes type) const { - out << "<DataArray Name=\"" << fct.name() << "\" type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" + out << "<DataArray Name=\"" << fct.name() << "\" type=\"" << to_string(fct.type()) << "\"" << " NumberOfComponents=\"" << fct.ncomps() << "\" format=\"" << (format_ == Vtk::ASCII ? "ascii\">\n" : "appended\""); if (format_ == Vtk::ASCII) { @@ -93,7 +93,7 @@ template <class GV, class DC> void VtkWriter<GV,DC> ::writePoints (std::ofstream& out, std::vector<pos_type>& offsets) const { - out << "<DataArray type=\"" << Vtk::Map::from_datatype[datatype_] << "\"" + out << "<DataArray type=\"" << to_string(datatype_) << "\"" << " NumberOfComponents=\"3\" format=\"" << (format_ == Vtk::ASCII ? "ascii\">\n" : "appended\""); if (format_ == Vtk::ASCII) {