Commit 538e86fc authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Implemented MeshFunctionIO: reading and writing mesh functions using mesh readers and writers

parent e519d514
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -65,6 +65,8 @@ class MeshFunction :

      const MeshPointer& getMeshPointer() const;

      MeshPointer& getMeshPointer();

      static IndexType getDofs( const MeshPointer& meshPointer );

      __cuda_callable__ const VectorType& getData() const;
@@ -94,6 +96,7 @@ class MeshFunction :

      __cuda_callable__
      RealType& operator[]( const IndexType& meshEntityIndex );

      __cuda_callable__
      const RealType& operator[]( const IndexType& meshEntityIndex ) const;

@@ -120,8 +123,9 @@ class MeshFunction :

      void boundLoad( const String& fileName );

      bool write( const String& fileName,
                  const String& format = "vtk" ) const;
      bool write( const std::string& functionName,
                  const std::string& fileName,
                  const std::string& fileFormat = "auto" ) const;

      using Object::save;

+24 −43
Original line number Diff line number Diff line
@@ -8,16 +8,14 @@

/* See Copyright Notice in tnl/Copyright */

#pragma once

#include <TNL/Assert.h>
#include <TNL/Pointers/DevicePointer.h>
#include <TNL/Functions/MeshFunction.h>
#include <TNL/Functions/MeshFunctionEvaluator.h>
#include <TNL/Functions/MeshFunctionNormGetter.h>
#include <TNL/Functions/MeshFunctionGnuplotWriter.h>
#include <TNL/Meshes/Writers/VTKWriter.h>
#include <TNL/Meshes/Writers/VTUWriter.h>

#pragma once
#include <TNL/Functions/MeshFunctionIO.h>

namespace TNL {
namespace Functions {
@@ -83,6 +81,7 @@ configSetup( Config::ConfigDescription& config,
             const String& prefix )
{
   config.addEntry< String >( prefix + "file", "Dataset for the mesh function." );
   config.addEntry< String >( prefix + "function-name", "Name of the mesh function in the input file.", "f" );
}

template< typename Mesh,
@@ -96,8 +95,8 @@ setup( const MeshPointer& meshPointer,
{
   this->setMesh( meshPointer );
   const String fileName = parameters.getParameter< String >( prefix + "file" );
   this->load( fileName );
   return true;
   const String functionName = parameters.getParameter< String >( prefix + "function-name" );
   return readMeshFunction( *this, functionName, fileName );
}

template< typename Mesh,
@@ -133,6 +132,16 @@ getMeshPointer() const
   return this->meshPointer;
}

template< typename Mesh,
          int MeshEntityDimension,
          typename Real >
typename MeshFunction< Mesh, MeshEntityDimension, Real >::MeshPointer&
MeshFunction< Mesh, MeshEntityDimension, Real >::
getMeshPointer()
{
   return this->meshPointer;
}

template< typename Mesh,
          int MeshEntityDimension,
          typename Real >
@@ -389,39 +398,11 @@ template< typename Mesh,
          typename Real >
bool
MeshFunction< Mesh, MeshEntityDimension, Real >::
write( const String& fileName,
       const String& format ) const
{
   std::fstream file;
   file.open( fileName.getString(), std::ios::out );
   if( ! file )
   {
      std::cerr << "Unable to open a file " << fileName << "." << std::endl;
      return false;
   }
   if( format == "vtk" ) {
      Meshes::Writers::VTKWriter< Mesh > writer( file );
      writer.template writeEntities< getEntitiesDimension() >( *meshPointer );
      if( MeshFunction::getEntitiesDimension() == 0 )
         writer.writePointData( getData(), "cellFunctionValues", 1 );
      else
         writer.writeCellData( getData(), "pointFunctionValues", 1 );
   }
   else if( format == "vtu" ) {
      Meshes::Writers::VTUWriter< Mesh > writer( file );
      writer.template writeEntities< getEntitiesDimension() >( *meshPointer );
      if( MeshFunction::getEntitiesDimension() == 0 )
         writer.writePointData( getData(), "cellFunctionValues", 1 );
      else
         writer.writeCellData( getData(), "pointFunctionValues", 1 );
   }
   else if( format == "gnuplot" )
      return MeshFunctionGnuplotWriter< MeshFunction >::write( *this, file );
   else {
      std::cerr << "Unknown output format: " << format << std::endl;
      return false;
   }
   return true;
write( const std::string& functionName,
       const std::string& fileName,
       const std::string& fileFormat ) const
{
   return writeMeshFunction( *this, functionName, fileName, fileFormat );
}

template< typename Mesh,
+160 −0
Original line number Diff line number Diff line
/***************************************************************************
                          MeshFunctionIO.h  -  description
                             -------------------
    begin                : Jun 22, 2021
    copyright            : (C) 2017 by Tomas Oberhuber et al.
    email                : tomas.oberhuber@fjfi.cvut.cz
 ***************************************************************************/

/* See Copyright Notice in tnl/Copyright */

#pragma once

#include <type_traits>
#include <experimental/filesystem>

#include <TNL/Meshes/Traits.h>
#include <TNL/Meshes/Readers/getMeshReader.h>
#include <TNL/Meshes/Writers/VTKWriter.h>
#include <TNL/Meshes/Writers/VTUWriter.h>
#include <TNL/Meshes/Writers/VTIWriter.h>
#include <TNL/Functions/MeshFunctionGnuplotWriter.h>

namespace TNL {
namespace Functions {

template< typename MeshFunction >
bool
readMeshFunction( MeshFunction& function,
                  const std::string& functionName,
                  const std::string& fileName,
                  const std::string& fileFormat = "auto" )
{
   std::shared_ptr< Meshes::Readers::MeshReader > reader = Meshes::Readers::getMeshReader( fileName, fileFormat );
   if( reader == nullptr )
      return false;

   reader->detectMesh();

   // load the mesh if the function does not have it yet
   if( function.getMesh() == typename MeshFunction::MeshType {} )
      reader->loadMesh( *function.getMeshPointer() );

   Meshes::Readers::MeshReader::VariantVector data;
   if( function.getEntitiesDimension() == 0 )
      data = reader->readPointData( functionName );
   else if( function.getEntitiesDimension() == function.getMeshDimension() )
      data = reader->readCellData( functionName );
   else {
      std::cerr << "The mesh function with entities dimension " << function.getEntitiesDimension() << " cannot be read from the file " << fileName << std::endl;
      return false;
   }

   visit( [&](auto&& array) {
            const auto entitiesCount = function.getMesh().template getEntitiesCount< MeshFunction::getEntitiesDimension() >();
            if( array.size() == (std::size_t) entitiesCount )
               Algorithms::MultiDeviceMemoryOperations< typename MeshFunction::VectorType::DeviceType, Devices::Host >
                  ::copy( function.getData().getData(), array.data(), array.size() );
            else
               throw Exceptions::FileDeserializationError( fileName, "mesh function data size does not match the mesh size (expected " + std::to_string(entitiesCount) + ", got " + std::to_string(array.size()) + ")." );
         },
         data
      );

   return true;
}

// specialization for grids
template< typename MeshFunction >
std::enable_if_t< Meshes::isGrid< typename MeshFunction::MeshType >::value, bool >
writeMeshFunction( const MeshFunction& function,
                   const std::string& functionName,
                   const std::string& fileName,
                   const std::string& fileFormat = "auto" )
{
   std::ofstream file;
   file.open( fileName );
   if( ! file )
   {
      std::cerr << "Unable to open a file " << fileName << "." << std::endl;
      return false;
   }

   namespace fs = std::experimental::filesystem;
   std::string format = fileFormat;
   if( format == "auto" ) {
      format = fs::path(fileName).extension();
      if( format.length() > 0 )
         // remove dot from the extension
         format = format.substr(1);
   }

   if( format == "vti" ) {
      Meshes::Writers::VTIWriter< typename MeshFunction::MeshType > writer( file );
      writer.writeImageData( function.getMesh() );
      if( MeshFunction::getEntitiesDimension() == 0 )
         writer.writePointData( function.getData(), functionName, 1 );
      else
         writer.writeCellData( function.getData(), functionName, 1 );
   }
   else if( format == "gnuplot" || format == "gplt" || format == "plt" )
      return MeshFunctionGnuplotWriter< MeshFunction >::write( function, file );
   else {
      std::cerr << "Unknown output format: " << format << std::endl;
      return false;
   }
   return true;
}

// specialization for meshes
template< typename MeshFunction >
std::enable_if_t< ! Meshes::isGrid< typename MeshFunction::MeshType >::value, bool >
writeMeshFunction( const MeshFunction& function,
                   const std::string& functionName,
                   const std::string& fileName,
                   const std::string& fileFormat = "auto" )
{
   std::ofstream file;
   file.open( fileName );
   if( ! file )
   {
      std::cerr << "Unable to open a file " << fileName << "." << std::endl;
      return false;
   }

   namespace fs = std::experimental::filesystem;
   std::string format = fileFormat;
   if( format == "auto" ) {
      format = fs::path(fileName).extension();
      if( format.length() > 0 )
         // remove dot from the extension
         format = format.substr(1);
   }

   if( format == "vtk" ) {
      Meshes::Writers::VTKWriter< typename MeshFunction::MeshType > writer( file );
      writer.template writeEntities< MeshFunction::getEntitiesDimension() >( function.getMesh() );
      if( MeshFunction::getEntitiesDimension() == 0 )
         writer.writePointData( function.getData(), functionName, 1 );
      else
         writer.writeCellData( function.getData(), functionName, 1 );
   }
   else if( format == "vtu" ) {
      Meshes::Writers::VTUWriter< typename MeshFunction::MeshType > writer( file );
      writer.template writeEntities< MeshFunction::getEntitiesDimension() >( function.getMesh() );
      if( MeshFunction::getEntitiesDimension() == 0 )
         writer.writePointData( function.getData(), functionName, 1 );
      else
         writer.writeCellData( function.getData(), functionName, 1 );
   }
   else if( format == "gnuplot" || format == "gplt" || format == "plt" )
      return MeshFunctionGnuplotWriter< MeshFunction >::write( function, file );
   else {
      std::cerr << "Unknown output format: " << format << std::endl;
      return false;
   }
   return true;
}

} // namespace Functions
} // namespace TNL
+6 −2
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ class MeshFunctionView :

      const MeshPointer& getMeshPointer() const;

      MeshPointer& getMeshPointer();

      static IndexType getDofs( const MeshPointer& meshPointer );

      __cuda_callable__ const VectorType& getData() const;
@@ -118,6 +120,7 @@ class MeshFunctionView :

      __cuda_callable__
      RealType& operator[]( const IndexType& meshEntityIndex );

      __cuda_callable__
      const RealType& operator[]( const IndexType& meshEntityIndex ) const;

@@ -144,8 +147,9 @@ class MeshFunctionView :

      void boundLoad( const String& fileName );

      bool write( const String& fileName,
                  const String& format = "vtk" ) const;
      bool write( const std::string& functionName,
                  const std::string& fileName,
                  const std::string& fileFormat = "auto" ) const;

      using Object::save;

+24 −43
Original line number Diff line number Diff line
@@ -8,16 +8,14 @@

/* See Copyright Notice in tnl/Copyright */

#pragma once

#include <TNL/Assert.h>
#include <TNL/Pointers/DevicePointer.h>
#include <TNL/Functions/MeshFunctionView.h>
#include <TNL/Functions/MeshFunctionEvaluator.h>
#include <TNL/Functions/MeshFunctionNormGetter.h>
#include <TNL/Functions/MeshFunctionGnuplotWriter.h>
#include <TNL/Meshes/Writers/VTKWriter.h>
#include <TNL/Meshes/Writers/VTUWriter.h>

#pragma once
#include <TNL/Functions/MeshFunctionIO.h>

namespace TNL {
namespace Functions {
@@ -108,6 +106,7 @@ configSetup( Config::ConfigDescription& config,
             const String& prefix )
{
   config.addEntry< String >( prefix + "file", "Dataset for the mesh function." );
   config.addEntry< String >( prefix + "function-name", "Name of the mesh function in the input file.", "f" );
}

template< typename Mesh,
@@ -121,8 +120,8 @@ setup( const MeshPointer& meshPointer,
{
   this->setMesh( meshPointer );
   const String fileName = parameters.getParameter< String >( prefix + "file" );
   this->load( fileName );
   return true;
   const String functionName = parameters.getParameter< String >( prefix + "function-name" );
   return readMeshFunction( *this, functionName, fileName );
}

template< typename Mesh,
@@ -218,6 +217,16 @@ getMeshPointer() const
   return this->meshPointer;
}

template< typename Mesh,
          int MeshEntityDimension,
          typename Real >
typename MeshFunctionView< Mesh, MeshEntityDimension, Real >::MeshPointer&
MeshFunctionView< Mesh, MeshEntityDimension, Real >::
getMeshPointer()
{
   return this->meshPointer;
}

template< typename Mesh,
          int MeshEntityDimension,
          typename Real >
@@ -474,39 +483,11 @@ template< typename Mesh,
          typename Real >
bool
MeshFunctionView< Mesh, MeshEntityDimension, Real >::
write( const String& fileName,
       const String& format ) const
{
   std::fstream file;
   file.open( fileName.getString(), std::ios::out );
   if( ! file )
   {
      std::cerr << "Unable to open a file " << fileName << "." << std::endl;
      return false;
   }
   if( format == "vtk" ) {
      Meshes::Writers::VTKWriter< Mesh > writer( file );
      writer.template writeEntities< getEntitiesDimension() >( *meshPointer );
      if( MeshFunctionView::getEntitiesDimension() == 0 )
         writer.writePointData( getData(), "cellFunctionValues", 1 );
      else
         writer.writeCellData( getData(), "pointFunctionValues", 1 );
   }
   else if( format == "vtu" ) {
      Meshes::Writers::VTUWriter< Mesh > writer( file );
      writer.template writeEntities< getEntitiesDimension() >( *meshPointer );
      if( MeshFunctionView::getEntitiesDimension() == 0 )
         writer.writePointData( getData(), "cellFunctionValues", 1 );
      else
         writer.writeCellData( getData(), "pointFunctionValues", 1 );
   }
   else if( format == "gnuplot" )
      return MeshFunctionGnuplotWriter< MeshFunctionView >::write( *this, file );
   else {
      std::cerr << "Unknown output format: " << format << std::endl;
      return false;
   }
   return true;
write( const std::string& functionName,
       const std::string& fileName,
       const std::string& fileFormat ) const
{
   return writeMeshFunction( *this, functionName, fileName, fileFormat );
}

template< typename Mesh,
Loading