Loading src/TNL/Functions/MeshFunction.hpp +4 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading src/TNL/Functions/MeshFunctionVTKWriter.h +24 −32 Original line number Diff line number Diff line Loading @@ -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 ); } }; Loading @@ -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." ); Loading src/TNL/Functions/VectorField.h +4 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading src/TNL/Functions/VectorFieldVTKWriter.h +24 −13 Original line number Diff line number Diff line Loading @@ -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 >; Loading @@ -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 ); } }; Loading src/TNL/Meshes/Writers/VTKWriter.h +41 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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
src/TNL/Functions/MeshFunction.hpp +4 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading
src/TNL/Functions/MeshFunctionVTKWriter.h +24 −32 Original line number Diff line number Diff line Loading @@ -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 ); } }; Loading @@ -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." ); Loading
src/TNL/Functions/VectorField.h +4 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading
src/TNL/Functions/VectorFieldVTKWriter.h +24 −13 Original line number Diff line number Diff line Loading @@ -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 >; Loading @@ -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 ); } }; Loading
src/TNL/Meshes/Writers/VTKWriter.h +41 −12 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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>