Commit f6fb8bd3 authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Refactoring VTKWriter

parent a234eefe
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -405,8 +405,10 @@ write( const String& fileName,
      std::cerr << "Unable to open a file " << fileName << "." << std::endl;
      return false;
   }
   if( format == "vtk" )
      return MeshFunctionVTKWriter< MeshFunction >::write( *this, file );
   if( format == "vtk" ) {
      MeshFunctionVTKWriter< MeshFunction > writer( file );
      writer.write( *this );
   }
   else if( format == "gnuplot" )
      return MeshFunctionGnuplotWriter< MeshFunction >::write( *this, file );
   else {
+24 −32
Original line number Diff line number Diff line
@@ -18,44 +18,36 @@ namespace Functions {
template< typename MeshFunction,
          bool = std::is_fundamental< typename MeshFunction::RealType >::value >
class MeshFunctionVTKWriter
: protected Meshes::Writers::VTKWriter< typename MeshFunction::MeshType >
{
   using MeshType = typename MeshFunction::MeshType;
   using MeshWriter = Meshes::Writers::VTKWriter< MeshType >;
   using EntityType = typename MeshType::template EntityType< MeshFunction::getEntitiesDimension() >;
   using GlobalIndex = typename MeshType::GlobalIndexType;

public:
   static bool write( const MeshFunction& function,
                      std::ostream& str,
                      const String& functionName = "cellFunctionValues",
   MeshFunctionVTKWriter( std::ostream& str,
                          Meshes::Writers::VTKFileFormat format = Meshes::Writers::VTKFileFormat::ASCII )
   : Meshes::Writers::VTKWriter< MeshType >( str, format )
   {}

   void write( const MeshFunction& function,
               const String& functionName = "cellFunctionValues" )
   {
      const MeshType& mesh = function.getMesh();
      MeshWriter::template writeEntities< MeshFunction::getEntitiesDimension() >( mesh, str, format );
      appendFunction( function, str, format, functionName );
      return true;
      this->template writeEntities< MeshFunction::getEntitiesDimension() >( mesh );
      appendFunction( function, functionName );
   }

   // VTK supports writing multiple functions into the same file.
   // You can call this after 'write', which initializes the mesh entities,
   // with different function name.
   static void appendFunction( const MeshFunction& function,
                               std::ostream& str,
                               Meshes::Writers::VTKFileFormat format,
   void appendFunction( const MeshFunction& function,
                        const String& functionName )
   {
      const MeshType& mesh = function.getMesh();
      const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
      str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
      str << "SCALARS " << functionName << " " << getType< typename MeshFunction::RealType >() << " 1" << std::endl;
      str << "LOOKUP_TABLE default" << std::endl;
      for( GlobalIndex i = 0; i < entitiesCount; i++ ) {
         const typename MeshFunction::RealType value = function.getData().getElement( i );
         using Meshes::Writers::__impl::writeReal;
         writeReal( format, str, value );
         if( format == Meshes::Writers::VTKFileFormat::ASCII )
            str << "\n";
      }
      if( MeshFunction::getEntitiesDimension() == 0 )
         this->writeDataArray( function.getData(), functionName, 1, Meshes::Writers::VTKDataType::PointData );
      else
         this->writeDataArray( function.getData(), functionName, 1, Meshes::Writers::VTKDataType::CellData );
   }
};

@@ -63,17 +55,17 @@ template< typename MeshFunction >
class MeshFunctionVTKWriter< MeshFunction, false >
{
public:
   static bool write( const MeshFunction& function,
                      std::ostream& str,
                      const String& functionName = "cellFunctionValues",
   MeshFunctionVTKWriter( std::ostream& str,
                          Meshes::Writers::VTKFileFormat format = Meshes::Writers::VTKFileFormat::ASCII )
   {}

   bool write( const MeshFunction& function,
               const String& functionName = "cellFunctionValues" )
   {
      throw std::logic_error( "Unsupported RealType - VTKWriter supports only fundamental types." );
   }

   static void appendFunction( const MeshFunction& function,
                               std::ostream& str,
                               Meshes::Writers::VTKFileFormat format,
   void appendFunction( const MeshFunction& function,
                        const String& functionName )
   {
      throw std::logic_error( "Unsupported RealType - VTKWriter supports only fundamental types." );
+4 −2
Original line number Diff line number Diff line
@@ -504,8 +504,10 @@ class VectorField< Size, MeshFunctionView< Mesh, MeshEntityDimension, Real > >
            std::cerr << "Unable to open a file " << fileName << "." << std::endl;
            return false;
         }
         if( format == "vtk" )
            return VectorFieldVTKWriter< VectorField >::write( *this, file );
         if( format == "vtk" ) {
            VectorFieldVTKWriter< VectorField > writer( file );
            writer.write( *this );
         }
         else if( format == "gnuplot" )
            return VectorFieldGnuplotWriter< VectorField >::write( *this, file );
         else {
+24 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ namespace Functions {

template< typename VectorField >
class VectorFieldVTKWriter
: protected Meshes::Writers::VTKWriter< typename VectorField::MeshType >
{
   using MeshType = typename VectorField::MeshType;
   using MeshWriter = Meshes::Writers::VTKWriter< MeshType >;
@@ -24,34 +25,44 @@ class VectorFieldVTKWriter
   using GlobalIndex = typename MeshType::GlobalIndexType;

public:
   static bool write( const VectorField& field,
                      std::ostream& str,
   VectorFieldVTKWriter( std::ostream& str,
                         Meshes::Writers::VTKFileFormat format = Meshes::Writers::VTKFileFormat::ASCII )
   : Meshes::Writers::VTKWriter< MeshType >( str, format )
   {}

   void write( const VectorField& field,
               const String& fieldName = "cellVectorFieldValues" )
   {
      const MeshType& mesh = field.getMesh();
      MeshWriter::template writeEntities< VectorField::getEntitiesDimension() >( mesh, str );
      appendField( field, str, fieldName );
      return true;
      this->template writeEntities< VectorField::getEntitiesDimension() >( mesh );
      appendField( field, fieldName );
   }

   // VTK supports writing multiple fields into the same file.
   // You can call this after 'write', which initializes the mesh entities,
   // with different field name.
   static void appendField( const VectorField& field,
                            std::ostream& str,
   void appendField( const VectorField& field,
                     const String& fieldName )
   {
      const MeshType& mesh = field.getMesh();
      const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
      str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
      str << "VECTORS " << fieldName << " " << getType< typename VectorField::RealType >() << " 1" << std::endl;

      // copy all values from the vector field into a contiguous array
      using BufferType = Containers::Array< typename VectorField::RealType, Devices::Host, GlobalIndex >;
      BufferType buffer( 3 * entitiesCount );
      GlobalIndex j = 0;
      for( GlobalIndex i = 0; i < entitiesCount; i++ ) {
         const typename VectorField::VectorType vector = field.getElement( i );
         static_assert( VectorField::getVectorDimension() <= 3, "The VTK format supports only up to 3D vector fields." );
         for( int i = 0; i < 3; i++ )
            str << ( i < vector.getSize() ? vector[ i ] : 0.0 ) << " ";
         str << "\n";
            buffer[ j++ ] = ( i < vector.getSize() ? vector[ i ] : 0 );
      }

      // write the buffer
      if( VectorField::getEntitiesDimension() == 0 )
         this->writeDataArray( buffer, fieldName, 3, Meshes::Writers::VTKDataType::PointData );
      else
         this->writeDataArray( buffer, fieldName, 3, Meshes::Writers::VTKDataType::CellData );
   }
};

+41 −12
Original line number Diff line number Diff line
@@ -25,13 +25,13 @@ enum class VTKFileFormat
   BINARY
};

namespace __impl {

// TODO: 64-bit integers are most likely not supported in the BINARY format
inline void writeInt( VTKFileFormat format, std::ostream& str, int value );
enum class VTKDataType
{
   CellData,
   PointData
};

template< typename Real >
void writeReal( VTKFileFormat format, std::ostream& str, Real value );
namespace __impl {

template< typename Mesh, int EntityDimension > struct MeshEntitiesVTKWriter;
template< typename Mesh, int EntityDimension > struct MeshEntityTypesVTKWriter;
@@ -52,21 +52,50 @@ class VTKWriter
   using EntityTypesWriter = __impl::MeshEntityTypesVTKWriter< Mesh, EntityDimension >;

public:
   using Index = typename Mesh::GlobalIndexType;
   using IndexType = typename Mesh::GlobalIndexType;

   VTKWriter() = delete;

   VTKWriter( std::ostream& str, VTKFileFormat format = VTKFileFormat::ASCII )
   : str(str), format(format)
   {}

   static void writeAllEntities( const Mesh& mesh, std::ostream& str, VTKFileFormat format = VTKFileFormat::ASCII );
   void writeAllEntities( const Mesh& mesh );

   template< int EntityDimension = Mesh::getMeshDimension() >
   static void writeEntities( const Mesh& mesh, std::ostream& str, VTKFileFormat format = VTKFileFormat::ASCII );
   void writeEntities( const Mesh& mesh );

   template< typename Array >
   void writeDataArray( const Array& array,
                        const String& name,
                        const int numberOfComponents = 1,
                        VTKDataType dataType = VTKDataType::CellData );

protected:
   static void writeHeader( const Mesh& mesh, std::ostream& str, VTKFileFormat format );
   void writeHeader( const Mesh& mesh );

   void writePoints( const Mesh& mesh );

   std::ostream& str;

   VTKFileFormat format;

   // number of cells (in the VTK sense) written to the file
   IndexType cellsCount = 0;

   // number of points written to the file
   IndexType pointsCount = 0;

   // number of data arrays written in each section
   int cellDataArrays = 0;
   int pointDataArrays = 0;

   static void writePoints( const Mesh& mesh, std::ostream& str, VTKFileFormat format );
   // indicator of the current section
   VTKDataType currentSection = VTKDataType::CellData;
};

} // namespace Writers
} // namespace Meshes
} // namespace TNL

#include <TNL/Meshes/Writers/VTKWriter_impl.h>
#include <TNL/Meshes/Writers/VTKWriter.hpp>
Loading