Commit 44bbad6f authored by Jakub Klinkovský's avatar Jakub Klinkovský
Browse files

Implemented VTIWriter and VTIReader, removed TNLReader

parent e9ff2175
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@ void export_MeshReaders( py::module & m )
        // bindings against the actual class, NOT the trampoline
        .def("reset", &MeshReader::reset)
        .def("detectMesh", &MeshReader::detectMesh)
        .def("loadMesh", &MeshReader::template loadMesh< Grid1D >)
        .def("loadMesh", &MeshReader::template loadMesh< Grid2D >)
        .def("loadMesh", &MeshReader::template loadMesh< Grid3D >)
        .def("loadMesh", &MeshReader::template loadMesh< MeshOfEdges >)
        .def("loadMesh", &MeshReader::template loadMesh< MeshOfTriangles >)
        .def("loadMesh", &MeshReader::template loadMesh< MeshOfQuadrangles >)
@@ -28,7 +31,7 @@ void export_MeshReaders( py::module & m )
        .def(py::init<std::string>())
    ;

    // base class for VTUReader and PVTUReader
    // base class for VTUReader, VTIReader and PVTUReader
    py::class_< XMLVTK, PyXMLVTK, MeshReader >( m, "XMLVTK" )
        .def(py::init<std::string>())
   ;
@@ -36,4 +39,8 @@ void export_MeshReaders( py::module & m )
    py::class_< TNL::Meshes::Readers::VTUReader, XMLVTK >( m, "VTUReader" )
        .def(py::init<std::string>())
    ;

    py::class_< TNL::Meshes::Readers::VTIReader, XMLVTK >( m, "VTIReader" )
        .def(py::init<std::string>())
    ;
}
+1 −0
Original line number Diff line number Diff line
#include <TNL/Meshes/Readers/VTKReader.h>
#include <TNL/Meshes/Readers/VTUReader.h>
#include <TNL/Meshes/Readers/VTIReader.h>

// trampoline classes needed for overriding virtual methods
// https://pybind11.readthedocs.io/en/stable/advanced/classes.html
+4 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@

#include <TNL/Meshes/Writers/VTKWriter.h>
#include <TNL/Meshes/Writers/VTUWriter.h>
#include <TNL/Meshes/Writers/VTIWriter.h>

template< typename Writer, TNL::Meshes::VTK::FileFormat default_format >
void export_MeshWriter( py::module & m, const char* name )
@@ -81,10 +82,13 @@ void export_MeshWriters( py::module & m )
{
    export_MeshWriter< TNL::Meshes::Writers::VTKWriter< Grid1D >, TNL::Meshes::VTK::FileFormat::binary          >( m, "VTKWriter_Grid1D" );
    export_MeshWriter< TNL::Meshes::Writers::VTUWriter< Grid1D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTUWriter_Grid1D" );
    export_MeshWriter< TNL::Meshes::Writers::VTIWriter< Grid1D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTIWriter_Grid1D" );
    export_MeshWriter< TNL::Meshes::Writers::VTKWriter< Grid2D >, TNL::Meshes::VTK::FileFormat::binary          >( m, "VTKWriter_Grid2D" );
    export_MeshWriter< TNL::Meshes::Writers::VTUWriter< Grid2D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTUWriter_Grid2D" );
    export_MeshWriter< TNL::Meshes::Writers::VTIWriter< Grid2D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTIWriter_Grid2D" );
    export_MeshWriter< TNL::Meshes::Writers::VTKWriter< Grid3D >, TNL::Meshes::VTK::FileFormat::binary          >( m, "VTKWriter_Grid3D" );
    export_MeshWriter< TNL::Meshes::Writers::VTUWriter< Grid3D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTUWriter_Grid3D" );
    export_MeshWriter< TNL::Meshes::Writers::VTIWriter< Grid3D >, TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTIWriter_Grid3D" );

    export_MeshWriter< TNL::Meshes::Writers::VTKWriter< MeshOfEdges >,        TNL::Meshes::VTK::FileFormat::binary          >( m, "VTKWriter_MeshOfEdges" );
    export_MeshWriter< TNL::Meshes::Writers::VTUWriter< MeshOfEdges >,        TNL::Meshes::VTK::FileFormat::zlib_compressed >( m, "VTUWriter_MeshOfEdges" );
+69 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <TNL/Meshes/MeshBuilder.h>
#include <TNL/Meshes/VTKTraits.h>
#include <TNL/Meshes/Traits.h>

namespace TNL {
namespace Meshes {
@@ -84,17 +85,75 @@ public:
    * \brief Method which loads the intermediate mesh representation into a
    * mesh object.
    *
    * This overload applies to structured grids, i.e. \ref TNL::Meshes::Grid.
    *
    * When the method exits, the intermediate mesh representation is destroyed
    * to save memory. However, depending on the specific file format, the mesh
    * file may remain open so that the user can load additional data.
    */
   template< typename MeshType >
   void loadMesh( MeshType& mesh )
   std::enable_if_t< isGrid< MeshType >::value >
   loadMesh( MeshType& mesh )
   {
      // check that detectMesh has been called
      if( meshType == "" )
         detectMesh();

      // check if we have a grid
      if( meshType != "Meshes::Grid" )
         throw MeshReaderError( "MeshReader", "the file does not contain a structured grid, it is " + meshType );

      if( getMeshDimension() != mesh.getMeshDimension() )
         throw MeshReaderError( "MeshReader", "cannot load a " + std::to_string(getMeshDimension()) + "-dimensional "
                                              "grid into a mesh of type " + std::string(getType(mesh)) );

      // check that the grid attributes were set
      if( gridExtent.size() != 6 )
         throw MeshReaderError( "MeshReader", "gridExtent has invalid size: " + std::to_string(gridExtent.size()) + " (should be 6)" );
      if( gridOrigin.size() != 3 )
         throw MeshReaderError( "MeshReader", "gridOrigin has invalid size: " + std::to_string(gridOrigin.size()) + " (should be 3)" );
      if( gridSpacing.size() != 3 )
         throw MeshReaderError( "MeshReader", "gridSpacing has invalid size: " + std::to_string(gridSpacing.size()) + " (should be 3)" );

      // split the extent into begin and end
      typename MeshType::CoordinatesType begin, end;
      for( int i = 0; i < begin.getSize(); i++ ) {
         begin[i] = gridExtent[2 * i];
         end[i] = gridExtent[2 * i + 1];
      }
      mesh.setDimensions(end - begin);

      // transform the origin and calculate proportions
      typename MeshType::PointType origin, proportions;
      for( int i = 0; i < origin.getSize(); i++ ) {
         origin[i] = gridOrigin[i] + begin[i] * gridSpacing[i];
         proportions[i] = (end[i] - begin[i]) * gridSpacing[i];
      }
      mesh.setDomain( origin, proportions );
   }

   /**
    * \brief Method which loads the intermediate mesh representation into a
    * mesh object.
    *
    * This overload applies to unstructured meshes, i.e. \ref TNL::Meshes::Mesh.
    *
    * When the method exits, the intermediate mesh representation is destroyed
    * to save memory. However, depending on the specific file format, the mesh
    * file may remain open so that the user can load additional data.
    */
   template< typename MeshType >
   std::enable_if_t< ! isGrid< MeshType >::value >
   loadMesh( MeshType& mesh )
   {
      // check that detectMesh has been called
      if( meshType == "" )
         detectMesh();

      // check if we have an unstructured mesh
      if( meshType != "Meshes::Mesh" )
         throw MeshReaderError( "MeshReader", "the file does not contain an unstructured mesh, it is " + meshType );

      // check that the cell shape mathes
      const VTK::EntityShape meshCellShape = VTK::TopologyToEntityShape< typename MeshType::template EntityTraits< MeshType::getMeshDimension() >::EntityTopology >::shape;
      if( meshCellShape != cellShape )
@@ -102,7 +161,6 @@ public:
                                            + "of cells used in the file (" + VTK::getShapeName(cellShape) + ")" );

      using MeshBuilder = MeshBuilder< MeshType >;
      using IndexType = typename MeshType::GlobalIndexType;
      using PointType = typename MeshType::PointType;
      using CellSeedType = typename MeshBuilder::CellSeedType;

@@ -147,7 +205,7 @@ public:
      pointsArray = connectivityArray = offsetsArray = typesArray = {};

      if( ! meshBuilder.build( mesh ) )
         throw MeshReaderError( "VTKReader", "MeshBuilder failed" );
         throw MeshReaderError( "MeshReader", "MeshBuilder failed" );
   }

   virtual VariantVector
@@ -218,6 +276,10 @@ protected:
   int meshDimension, worldDimension;
   VTK::EntityShape cellShape = VTK::EntityShape::Vertex;

   // intermediate representation of a grid (this is relevant only for TNL::Meshes::Grid)
   std::vector< std::int64_t > gridExtent;
   std::vector< double > gridOrigin, gridSpacing;

   // intermediate representation of the unstructured mesh (matches the VTU
   // file format, other formats have to be converted)
   VariantVector pointsArray, connectivityArray, offsetsArray, typesArray;
@@ -230,6 +292,10 @@ protected:
      NumberOfPoints = NumberOfCells = 0;
      meshDimension = worldDimension = 0;
      cellShape = VTK::EntityShape::Vertex;

      gridExtent = {};
      gridOrigin = gridSpacing = {};

      pointsArray = connectivityArray = offsetsArray = typesArray = {};
      pointsType = connectivityType = offsetsType = typesType = "";
   }
+0 −171
Original line number Diff line number Diff line
/***************************************************************************
                          TNL.h  -  description
                             -------------------
    begin                : Nov 20, 2016
    copyright            : (C) 2016 by Tomas Oberhuber et al.
    email                : tomas.oberhuber@fjfi.cvut.cz
 ***************************************************************************/

/* See Copyright Notice in tnl/Copyright */

#pragma once

#include <TNL/String.h>
#include <TNL/Object.h>
#include <TNL/Meshes/VTKTraits.h>

namespace TNL {
namespace Meshes {
namespace Readers {

class TNLReader
{
public:
   TNLReader() = delete;

   TNLReader( const String& fileName )
   : fileName( fileName )
   {}

   bool
   detectMesh()
   {
      this->reset();

      const String objectType = getObjectType( fileName );
      const std::vector< String > parsedMeshType = parseObjectType( objectType );
      if( ! parsedMeshType.size() ) {
         std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl;
         return false;
      }

      meshType = parsedMeshType[ 0 ];
      if( meshType == "Meshes::Grid" ) {
         // save parts necessary to determine the mesh type
         meshDimension = worldDimension = std::atoi( parsedMeshType[ 1 ].getString() );
         realType = parsedMeshType[ 2 ];
         globalIndexType = localIndexType = parsedMeshType[ 4 ];
         // populate entity types (not necessary for GridTypeResolver, but while we're at it...)
         if( meshDimension == 1 )
            cellShape = VTK::EntityShape::Line;
         else if( meshDimension == 2 )
            cellShape = VTK::EntityShape::Quad;
         else if( meshDimension == 3 )
            cellShape = VTK::EntityShape::Hexahedron;
      }
      else if( meshType == "Meshes::Mesh" ) {
         const std::vector< String > parsedMeshConfig = parseObjectType( parsedMeshType[ 1 ] );
         if( ! parsedMeshConfig.size() ) {
            std::cerr << "Unable to parse the mesh config type " << parsedMeshType[ 1 ] << "." << std::endl;
            return false;
         }
         if( parsedMeshConfig.size() != 6 ) {
            std::cerr << "The parsed mesh config type has wrong size (expected 6 elements):" << std::endl;
            std::cerr << "[ ";
            for( std::size_t i = 0; i < parsedMeshConfig.size() - 1; i++ )
               std::cerr << parsedMeshConfig[ i ] << ", ";
            std::cerr << parsedMeshConfig.back() << " ]" << std::endl;
            return false;
         }

         // save parts necessary to determine the mesh type
         const String topology = parsedMeshConfig[ 1 ];
         worldDimension = std::atoi( parsedMeshConfig[ 2 ].getString() );
         realType = parsedMeshConfig[ 3 ];
         globalIndexType = parsedMeshConfig[ 4 ];
         localIndexType = parsedMeshConfig[ 5 ];

         if( topology == "TNL::Meshes::Topologies::Edge" )
            cellShape = VTK::EntityShape::Line;
         else if( topology == "TNL::Meshes::Topologies::Triangle" )
            cellShape = VTK::EntityShape::Triangle;
         else if( topology == "TNL::Meshes::Topologies::Quadrangle" )
            cellShape = VTK::EntityShape::Quad;
         else if( topology == "TNL::Meshes::Topologies::Tetrahedron" )
            cellShape = VTK::EntityShape::Tetra;
         else if( topology == "TNL::Meshes::Topologies::Hexahedron" )
            cellShape = VTK::EntityShape::Hexahedron;
         else {
            std::cerr << "Detected topology '" << topology << "' is not supported." << std::endl;
            return false;
         }
      }
      else {
         std::cerr << "The mesh type " << meshType << " is not supported (yet)." << std::endl;
         return false;
      }

      return true;
   }

   template< typename MeshType >
   void
   loadMesh( MeshType& mesh )
   {
      mesh.load( fileName );
   }

   String
   getMeshType() const
   {
      return meshType;
   }

   int
   getMeshDimension() const
   {
      return meshDimension;
   }

   int
   getWorldDimension() const
   {
      return worldDimension;
   }

   VTK::EntityShape
   getCellShape() const
   {
      return cellShape;
   }

   String
   getRealType() const
   {
      return realType;
   }

   String
   getGlobalIndexType() const
   {
      return globalIndexType;
   }

   String
   getLocalIndexType() const
   {
      return localIndexType;
   }

protected:
   String fileName;
   String meshType;
   int meshDimension = 0;
   int worldDimension = 0;
   VTK::EntityShape cellShape = VTK::EntityShape::Vertex;
   String realType;
   String globalIndexType;
   String localIndexType;

   void reset()
   {
      meshType = "";
      meshDimension = worldDimension = 0;
      cellShape = VTK::EntityShape::Vertex;
      realType = localIndexType = globalIndexType = "";
   }
};

} // namespace Readers
} // namespace Meshes
} // namespace TNL
Loading