diff --git a/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp b/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
index 17bf57c128dabcb28793fa0bf831150929624abd..62bef5b26db192d9c48117d220d0e1b08d1d0401 100644
--- a/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
+++ b/src/Python/pytnl/tnl_mpi/DistributedMeshWriters.cpp
@@ -79,7 +79,7 @@ void export_DistributedMeshWriter( py::module & m, const char* name )
             py::arg("array"), py::arg("name"), py::arg("numberOfComponents") = 1)
         // NOTE: only the overload intended for sequential writing is exported, because we don't
         // have type casters for MPI_Comm (ideally, it would be compatible with the mpi4py objects)
-        .def("addPiece", static_cast< std::string (Writer::*)(const TNL::String&, unsigned) >( &Writer::addPiece ),
+        .def("addPiece", static_cast< std::string (Writer::*)(const std::string&, unsigned) >( &Writer::addPiece ),
               py::arg("mainFileName"), py::arg("subdomainIndex"))
     ;
 }
diff --git a/src/TNL/Matrices/SparseMatrix.h b/src/TNL/Matrices/SparseMatrix.h
index 1300a40d37caadff9a93dc27d4d22e54085430d8..0082e52f5b53a1d0bb56ad7b6443bb306e2d0ce5 100644
--- a/src/TNL/Matrices/SparseMatrix.h
+++ b/src/TNL/Matrices/SparseMatrix.h
@@ -365,6 +365,17 @@ class SparseMatrix : public Matrix< Real, Device, Index, RealAllocator >
       virtual void setDimensions( const IndexType rows,
                                   const IndexType columns ) override;
 
+      /**
+       * \brief Set number of columns of this matrix.
+       *
+       * Unlike \ref setDimensions, the storage is not reset in this operation.
+       * It is the user's responsibility to update the column indices stored in
+       * the matrix to be consistent with the new number of columns.
+       *
+       * \param columns is the number of matrix columns.
+       */
+      virtual void setColumnsWithoutReset( const IndexType columns );
+
       /**
        * \brief Set the number of matrix rows and columns by the given matrix.
        *
diff --git a/src/TNL/Matrices/SparseMatrix.hpp b/src/TNL/Matrices/SparseMatrix.hpp
index 4ae9990b567a40ea03cf14789fc59f65fec26784..a2ffcfcb6e3cff03c8a45a4fd785cd3b2d16f937 100644
--- a/src/TNL/Matrices/SparseMatrix.hpp
+++ b/src/TNL/Matrices/SparseMatrix.hpp
@@ -216,6 +216,22 @@ setDimensions( const IndexType rows,
    this->view = this->getView();
 }
 
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename MatrixType,
+          template< typename, typename, typename > class Segments,
+          typename ComputeReal,
+          typename RealAllocator,
+          typename IndexAllocator >
+void
+SparseMatrix< Real, Device, Index, MatrixType, Segments, ComputeReal, RealAllocator, IndexAllocator >::
+setColumnsWithoutReset( const IndexType columns )
+{
+   BaseType::setDimensions( this->getRows(), columns );
+   this->view = this->getView();
+}
+
 template< typename Real,
           typename Device,
           typename Index,
diff --git a/src/TNL/Meshes/EntityShapeGroup.h b/src/TNL/Meshes/EntityShapeGroup.h
index f9938068dc08d87cccfb2c5903eae278f8b4652b..8bca05fe367ef1ffabd77434677768b99e6e3ffc 100644
--- a/src/TNL/Meshes/EntityShapeGroup.h
+++ b/src/TNL/Meshes/EntityShapeGroup.h
@@ -13,7 +13,7 @@ struct EntityShapeGroup
 
 template < EntityShape GeneralShape, int index >
 struct EntityShapeGroupElement
-{ 
+{
 };
 
 template <>
@@ -34,6 +34,49 @@ struct EntityShapeGroupElement< EntityShape::Polygon, 1 >
    static constexpr EntityShape shape = EntityShape::Quad;
 };
 
+
+template <>
+struct EntityShapeGroup< EntityShape::Polyhedron >
+{
+   static constexpr int size = 6;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 0 >
+{
+   static constexpr EntityShape shape = EntityShape::Tetra;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 1 >
+{
+   static constexpr EntityShape shape = EntityShape::Hexahedron;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 2 >
+{
+   static constexpr EntityShape shape = EntityShape::Wedge;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 3 >
+{
+   static constexpr EntityShape shape = EntityShape::Pyramid;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 4 >
+{
+   static constexpr EntityShape shape = EntityShape::PentagonalPrism;
+};
+
+template <>
+struct EntityShapeGroupElement< EntityShape::Polyhedron, 5 >
+{
+   static constexpr EntityShape shape = EntityShape::HexagonalPrism;
+};
+
 } // namespace VTK
 } // namespace Meshes
-} // namespace TNL
\ No newline at end of file
+} // namespace TNL
diff --git a/src/TNL/Meshes/Geometry/EntityRefiner.h b/src/TNL/Meshes/Geometry/EntityRefiner.h
new file mode 100644
index 0000000000000000000000000000000000000000..081a35e5992e470946261f5e1e140320c5b6dbe5
--- /dev/null
+++ b/src/TNL/Meshes/Geometry/EntityRefiner.h
@@ -0,0 +1,239 @@
+#pragma once
+
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Quadrangle.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+#include <TNL/Meshes/Topologies/Hexahedron.h>
+
+namespace TNL {
+namespace Meshes {
+
+enum class EntityRefinerVersion
+{
+   EdgeBisection
+};
+
+template< typename MeshConfig,
+          typename Topology,
+          EntityRefinerVersion EntityRefinerVersion_ = EntityRefinerVersion::EdgeBisection >
+struct EntityRefiner;
+
+template< typename MeshConfig >
+struct EntityRefiner< MeshConfig, Topologies::Triangle, EntityRefinerVersion::EdgeBisection >
+{
+   using Device = Devices::Host;
+   using Topology = Topologies::Triangle;
+   using MeshEntityType = MeshEntity< MeshConfig, Device, Topology >;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   // returns: number of *new* points, number of *all* refined entities
+   static std::pair< GlobalIndexType, GlobalIndexType > getExtraPointsAndEntitiesCount( const MeshEntityType& entity )
+   {
+      return { 3, 4 };
+   }
+
+   template< typename AddPointFunctor,
+             typename AddCellFunctor >
+   static void decompose( const MeshEntityType& entity,
+                          AddPointFunctor&& addPoint,
+                          AddCellFunctor&& addCell )
+   {
+      const auto v0 = entity.template getSubentityIndex< 0 >( 0 );
+      const auto v1 = entity.template getSubentityIndex< 0 >( 1 );
+      const auto v2 = entity.template getSubentityIndex< 0 >( 2 );
+
+      const auto& mesh = entity.getMesh();
+      const auto v0_p = mesh.getPoint( v0 );
+      const auto v1_p = mesh.getPoint( v1 );
+      const auto v2_p = mesh.getPoint( v2 );
+
+      // add new points: midpoints of triangle edges
+      const auto w0 = addPoint( 0.5 * ( v1_p + v2_p ) );
+      const auto w1 = addPoint( 0.5 * ( v0_p + v2_p ) );
+      const auto w2 = addPoint( 0.5 * ( v0_p + v1_p ) );
+
+      // add refined triangles
+      addCell( v0, w1, w2 );
+      addCell( v1, w0, w2 );
+      addCell( v2, w0, w1 );
+      addCell( w0, w1, w2 );
+   }
+};
+
+template< typename MeshConfig >
+struct EntityRefiner< MeshConfig, Topologies::Quadrangle, EntityRefinerVersion::EdgeBisection >
+{
+   using Device = Devices::Host;
+   using Topology = Topologies::Quadrangle;
+   using MeshEntityType = MeshEntity< MeshConfig, Device, Topology >;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   // returns: number of *new* points, number of *all* refined entities
+   static std::pair< GlobalIndexType, GlobalIndexType > getExtraPointsAndEntitiesCount( const MeshEntityType& entity )
+   {
+      return { 5, 4 };
+   }
+
+   template< typename AddPointFunctor,
+             typename AddCellFunctor >
+   static void decompose( const MeshEntityType& entity,
+                          AddPointFunctor&& addPoint,
+                          AddCellFunctor&& addCell )
+   {
+      const auto v0 = entity.template getSubentityIndex< 0 >( 0 );
+      const auto v1 = entity.template getSubentityIndex< 0 >( 1 );
+      const auto v2 = entity.template getSubentityIndex< 0 >( 2 );
+      const auto v3 = entity.template getSubentityIndex< 0 >( 3 );
+
+      const auto& mesh = entity.getMesh();
+      const auto v0_p = mesh.getPoint( v0 );
+      const auto v1_p = mesh.getPoint( v1 );
+      const auto v2_p = mesh.getPoint( v2 );
+      const auto v3_p = mesh.getPoint( v3 );
+
+      // add new points
+      const auto w0 = addPoint( 0.5 * ( v0_p + v1_p ) );
+      const auto w1 = addPoint( 0.5 * ( v1_p + v2_p ) );
+      const auto w2 = addPoint( 0.5 * ( v2_p + v3_p ) );
+      const auto w3 = addPoint( 0.5 * ( v3_p + v0_p ) );
+      const auto c = addPoint( 0.25 * ( v0_p + v1_p + v2_p + v3_p ) );
+
+      // add refined quadrangles
+      addCell( v0, w0, c, w3 );
+      addCell( w0, v1, w1, c );
+      addCell( c, w1, v2, w2 );
+      addCell( w3, c, w2, v3 );
+   }
+};
+
+template< typename MeshConfig >
+struct EntityRefiner< MeshConfig, Topologies::Tetrahedron, EntityRefinerVersion::EdgeBisection >
+{
+   using Device = Devices::Host;
+   using Topology = Topologies::Tetrahedron;
+   using MeshEntityType = MeshEntity< MeshConfig, Device, Topology >;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   // returns: number of *new* points, number of *all* refined entities
+   static std::pair< GlobalIndexType, GlobalIndexType > getExtraPointsAndEntitiesCount( const MeshEntityType& entity )
+   {
+      return { 6, 8 };
+   }
+
+   template< typename AddPointFunctor,
+             typename AddCellFunctor >
+   static void decompose( const MeshEntityType& entity,
+                          AddPointFunctor&& addPoint,
+                          AddCellFunctor&& addCell )
+   {
+      const auto v0 = entity.template getSubentityIndex< 0 >( 0 );
+      const auto v1 = entity.template getSubentityIndex< 0 >( 1 );
+      const auto v2 = entity.template getSubentityIndex< 0 >( 2 );
+      const auto v3 = entity.template getSubentityIndex< 0 >( 3 );
+
+      const auto& mesh = entity.getMesh();
+      const auto v0_p = mesh.getPoint( v0 );
+      const auto v1_p = mesh.getPoint( v1 );
+      const auto v2_p = mesh.getPoint( v2 );
+      const auto v3_p = mesh.getPoint( v3 );
+
+      // add new points: midpoints of triangle edges
+      const auto w0 = addPoint( 0.5 * ( v1_p + v2_p ) );
+      const auto w1 = addPoint( 0.5 * ( v0_p + v2_p ) );
+      const auto w2 = addPoint( 0.5 * ( v0_p + v1_p ) );
+      const auto w3 = addPoint( 0.5 * ( v0_p + v3_p ) );
+      const auto w4 = addPoint( 0.5 * ( v1_p + v3_p ) );
+      const auto w5 = addPoint( 0.5 * ( v2_p + v3_p ) );
+
+      // add refined tetrahedrons
+      addCell( v0, w1, w2, w3 );
+      addCell( v1, w0, w2, w4 );
+      addCell( v2, w0, w1, w5 );
+      addCell( v3, w3, w4, w5 );
+
+      addCell( w5, w0, w1, w2 );
+      addCell( w5, w1, w2, w3 );
+      addCell( w5, w0, w2, w4 );
+      addCell( w5, w3, w4, w2 );
+   }
+};
+
+template< typename MeshConfig >
+struct EntityRefiner< MeshConfig, Topologies::Hexahedron, EntityRefinerVersion::EdgeBisection >
+{
+   using Device = Devices::Host;
+   using Topology = Topologies::Hexahedron;
+   using MeshEntityType = MeshEntity< MeshConfig, Device, Topology >;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   // returns: number of *new* points, number of *all* refined entities
+   static std::pair< GlobalIndexType, GlobalIndexType > getExtraPointsAndEntitiesCount( const MeshEntityType& entity )
+   {
+      return { 19, 8 };
+   }
+
+   template< typename AddPointFunctor,
+             typename AddCellFunctor >
+   static void decompose( const MeshEntityType& entity,
+                          AddPointFunctor&& addPoint,
+                          AddCellFunctor&& addCell )
+   {
+      const auto v0 = entity.template getSubentityIndex< 0 >( 0 );
+      const auto v1 = entity.template getSubentityIndex< 0 >( 1 );
+      const auto v2 = entity.template getSubentityIndex< 0 >( 2 );
+      const auto v3 = entity.template getSubentityIndex< 0 >( 3 );
+      const auto v4 = entity.template getSubentityIndex< 0 >( 4 );
+      const auto v5 = entity.template getSubentityIndex< 0 >( 5 );
+      const auto v6 = entity.template getSubentityIndex< 0 >( 6 );
+      const auto v7 = entity.template getSubentityIndex< 0 >( 7 );
+
+      const auto& mesh = entity.getMesh();
+      const auto v0_p = mesh.getPoint( v0 );
+      const auto v1_p = mesh.getPoint( v1 );
+      const auto v2_p = mesh.getPoint( v2 );
+      const auto v3_p = mesh.getPoint( v3 );
+      const auto v4_p = mesh.getPoint( v4 );
+      const auto v5_p = mesh.getPoint( v5 );
+      const auto v6_p = mesh.getPoint( v6 );
+      const auto v7_p = mesh.getPoint( v7 );
+
+      // add new points: centers of bottom edges
+      const auto b0 = addPoint( 0.5 * ( v0_p + v1_p ) );
+      const auto b1 = addPoint( 0.5 * ( v1_p + v2_p ) );
+      const auto b2 = addPoint( 0.5 * ( v2_p + v3_p ) );
+      const auto b3 = addPoint( 0.5 * ( v3_p + v0_p ) );
+      // add new points: centers of upper edges
+      const auto u0 = addPoint( 0.5 * ( v4_p + v5_p ) );
+      const auto u1 = addPoint( 0.5 * ( v5_p + v6_p ) );
+      const auto u2 = addPoint( 0.5 * ( v6_p + v7_p ) );
+      const auto u3 = addPoint( 0.5 * ( v7_p + v4_p ) );
+      // add new points: centers of middle (vertical) edges
+      const auto m0 = addPoint( 0.5 * ( v0_p + v4_p ) );
+      const auto m1 = addPoint( 0.5 * ( v1_p + v5_p ) );
+      const auto m2 = addPoint( 0.5 * ( v2_p + v6_p ) );
+      const auto m3 = addPoint( 0.5 * ( v3_p + v7_p ) );
+      // add new points: centers of faces
+      const auto f0 = addPoint( 0.25 * ( v0_p + v1_p + v2_p + v3_p ) );
+      const auto f1 = addPoint( 0.25 * ( v0_p + v1_p + v5_p + v4_p ) );
+      const auto f2 = addPoint( 0.25 * ( v1_p + v2_p + v6_p + v5_p ) );
+      const auto f3 = addPoint( 0.25 * ( v2_p + v3_p + v7_p + v6_p ) );
+      const auto f4 = addPoint( 0.25 * ( v3_p + v0_p + v4_p + v7_p ) );
+      const auto f5 = addPoint( 0.25 * ( v4_p + v5_p + v6_p + v7_p ) );
+      // add new points: center of the cell
+      const auto cc = addPoint( 0.125 * ( v0_p + v1_p + v2_p + v3_p + v4_p + v5_p + v6_p + v7_p) );
+
+      // add refined hexahedrons
+      addCell( v0, b0, f0, b3, m0, f1, cc, f4 );
+      addCell( b0, v1, b1, f0, f1, m1, f2, cc );
+      addCell( f0, b1, v2, b2, cc, f2, m2, f3 );
+      addCell( b3, f0, b2, v3, f4, cc, f3, m3 );
+      addCell( m0, f1, cc, f4, v4, u0, f5, u3 );
+      addCell( f1, m1, f2, cc, u0, v5, u1, f5 );
+      addCell( cc, f2, m2, f3, f5, u1, v6, u2 );
+      addCell( f4, cc, f3, m3, u3, f5, u2, v7 );
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Geometry/getRefinedMesh.h b/src/TNL/Meshes/Geometry/getRefinedMesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..a378b671dfe5ac781147b73b1fb30e0efd88edd0
--- /dev/null
+++ b/src/TNL/Meshes/Geometry/getRefinedMesh.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/MeshBuilder.h>
+#include <TNL/Meshes/Geometry/EntityRefiner.h>
+#include <TNL/Algorithms/ParallelFor.h>
+#include <TNL/Algorithms/scan.h>
+
+namespace TNL {
+namespace Meshes {
+
+// TODO: refactor to avoid duplicate points altogether - first split edges, then faces, then cells
+template< EntityRefinerVersion RefinerVersion,
+          typename MeshConfig,
+          std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Triangle >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Quadrangle >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Tetrahedron >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Hexahedron >::value, bool > = true >
+auto // returns MeshBuilder
+refineMesh( const Mesh< MeshConfig, Devices::Host >& inMesh )
+{
+   using namespace TNL;
+   using namespace TNL::Containers;
+   using namespace TNL::Algorithms;
+
+   using Mesh = Mesh< MeshConfig, Devices::Host >;
+   using MeshBuilder = MeshBuilder< Mesh >;
+   using GlobalIndexType = typename Mesh::GlobalIndexType;
+   using PointType = typename Mesh::PointType;
+   using EntityRefiner = EntityRefiner< MeshConfig, typename MeshConfig::CellTopology, RefinerVersion >;
+   constexpr int CellDimension = Mesh::getMeshDimension();
+
+   MeshBuilder meshBuilder;
+
+   const GlobalIndexType inPointsCount = inMesh.template getEntitiesCount< 0 >();
+   const GlobalIndexType inCellsCount = inMesh.template getEntitiesCount< CellDimension >();
+
+   // Find the number of output points and cells as well as
+   // starting indices at which every cell will start writing new refined points and cells
+   using IndexPair = std::pair< GlobalIndexType, GlobalIndexType >;
+   Array< IndexPair, Devices::Host > indices( inCellsCount + 1 );
+   auto setCounts = [&] ( GlobalIndexType i ) {
+      const auto cell = inMesh.template getEntity< CellDimension >( i );
+      indices[ i ] = EntityRefiner::getExtraPointsAndEntitiesCount( cell );
+   };
+   ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, setCounts );
+   indices[ inCellsCount ] = { 0, 0 }; // extend exclusive prefix sum by one element to also get result of reduce at the same time
+   auto reduction = [] ( const IndexPair& a, const IndexPair& b ) -> IndexPair {
+      return { a.first + b.first, a.second + b.second };
+   };
+   inplaceExclusiveScan( indices, 0, indices.getSize(), reduction, std::make_pair( 0, 0 ) );
+   const auto& reduceResult = indices[ inCellsCount ];
+   const GlobalIndexType outPointsCount = inPointsCount + reduceResult.first;
+   const GlobalIndexType outCellsCount = reduceResult.second;
+   meshBuilder.setEntitiesCount( outPointsCount, outCellsCount );
+
+   // Copy the points from inMesh to outMesh
+   auto copyPoint = [&] ( GlobalIndexType i ) mutable {
+      meshBuilder.setPoint( i, inMesh.getPoint( i ) );
+   };
+   ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inPointsCount, copyPoint );
+
+   // Refine each cell
+   auto refineCell = [&] ( GlobalIndexType i ) mutable {
+      const auto cell = inMesh.template getEntity< CellDimension >( i );
+      const auto& indexPair = indices[ i ];
+
+      // Lambda for adding new points
+      GlobalIndexType setPointIndex = inPointsCount + indexPair.first;
+      auto addPoint = [&] ( const PointType& point ) {
+         const auto pointIdx = setPointIndex++;
+         meshBuilder.setPoint( pointIdx, point );
+         return pointIdx;
+      };
+
+      // Lambda for adding new cells
+      GlobalIndexType setCellIndex = indexPair.second;
+      auto addCell = [&] ( auto... vertexIndices ) {
+         auto entitySeed = meshBuilder.getCellSeed( setCellIndex++ );
+         entitySeed.setCornerIds( vertexIndices... );
+      };
+
+      EntityRefiner::decompose( cell, addPoint, addCell );
+   };
+   ParallelFor< Devices::Host >::exec( GlobalIndexType{ 0 }, inCellsCount, refineCell );
+
+   return meshBuilder;
+}
+
+template< EntityRefinerVersion RefinerVersion,
+          typename MeshConfig,
+          std::enable_if_t< std::is_same< typename MeshConfig::CellTopology, Topologies::Triangle >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Quadrangle >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Tetrahedron >::value
+                         || std::is_same< typename MeshConfig::CellTopology, Topologies::Hexahedron >::value, bool > = true >
+auto // returns Mesh
+getRefinedMesh( const Mesh< MeshConfig, Devices::Host >& inMesh )
+{
+   using Mesh = Mesh< MeshConfig, Devices::Host >;
+
+   Mesh outMesh;
+   auto meshBuilder = refineMesh< RefinerVersion >( inMesh );
+   meshBuilder.deduplicatePoints();
+   meshBuilder.build( outMesh );
+   return outMesh;
+}
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
index 0ad33b103f5130413f446912e4fb551e8c3844e3..c46ed7175020d967cfcc4e0b58f7c262a45396de 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
@@ -12,7 +12,6 @@
 
 #include <fstream>
 #include <iomanip>
-#include <TNL/String.h>
 #include <TNL/Assert.h>
 #include <TNL/Meshes/GridDetails/GridEntityGetter_impl.h>
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h>
diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
index fc290d23d430fa53b909beb7cdb588f1e9174785..77c74437674bcdfbabcf833e8396638ec70aa7ac 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
@@ -12,7 +12,6 @@
 
 #include <fstream>
 #include <iomanip>
-#include <TNL/String.h>
 #include <TNL/Assert.h>
 #include <TNL/Meshes/GridDetails/GridEntityGetter_impl.h>
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter2D_impl.h>
diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
index 3dafeb2a3816004c90c14730fa6f2f7888fbd2de..7f66fbfc316f57a3126963a64855980f42e894d0 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
@@ -12,7 +12,6 @@
 
 #include <fstream>
 #include <iomanip>
-#include <TNL/String.h>
 #include <TNL/Assert.h>
 #include <TNL/Meshes/GridDetails/GridEntityGetter_impl.h>
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter3D_impl.h>
diff --git a/src/TNL/Meshes/MeshBuilder.h b/src/TNL/Meshes/MeshBuilder.h
index aa10a8a245bd886439a3b7d66f32129e88bcef01..eae805ef5e7f42ae8af1f4ae010ff5e99773ee71 100644
--- a/src/TNL/Meshes/MeshBuilder.h
+++ b/src/TNL/Meshes/MeshBuilder.h
@@ -16,6 +16,9 @@
 
 #pragma once
 
+#include <numeric>   // std::iota
+#include <vector>
+
 #include <TNL/Containers/Vector.h>
 #include <TNL/Meshes/Topologies/Polyhedron.h>
 
@@ -31,14 +34,16 @@ public:
    using GlobalIndexType    = typename MeshTraitsType::GlobalIndexType;
    using LocalIndexType     = typename MeshTraitsType::LocalIndexType;
    using PointType          = typename MeshTraitsType::PointType;
+   using PointArrayType     = typename MeshTraitsType::PointArrayType;
+   using BoolVector         = Containers::Vector< bool, Devices::Host, GlobalIndexType >;
    using CellTopology       = typename MeshTraitsType::CellTopology;
    using CellSeedMatrixType = typename MeshTraitsType::CellSeedMatrixType;
    using CellSeedType       = typename CellSeedMatrixType::EntitySeedMatrixSeed;
    using FaceSeedMatrixType = typename MeshTraitsType::FaceSeedMatrixType;
    using FaceSeedType       = typename FaceSeedMatrixType::EntitySeedMatrixSeed;
    using NeighborCountsArray = typename MeshTraitsType::NeighborCountsArray;
-   
-   void setEntitiesCount( const GlobalIndexType& points, 
+
+   void setEntitiesCount( const GlobalIndexType& points,
                           const GlobalIndexType& cells = 0,
                           const GlobalIndexType& faces = 0 )
    {
@@ -109,20 +114,237 @@ public:
       return this->cellSeeds.getSeed( index );
    }
 
+   void deduplicatePoints( const double numericalThreshold = 1e-9 )
+   {
+      // prepare vector with an identity permutationutation
+      std::vector< GlobalIndexType > permutation( points.getSize() );
+      std::iota( permutation.begin(), permutation.end(), (GlobalIndexType) 0 );
+
+      // workaround for lexicographical sorting
+      // FIXME: https://mmg-gitlab.fjfi.cvut.cz/gitlab/tnl/tnl-dev/-/issues/79
+      auto lexless = [numericalThreshold, this] (const GlobalIndexType& a, const GlobalIndexType& b) -> bool
+      {
+         const PointType& left = this->points[ a ];
+         const PointType& right = this->points[ b ];
+         for( LocalIndexType i = 0; i < PointType::getSize(); i++ )
+            if( TNL::abs( left[ i ] - right[ i ] ) > numericalThreshold )
+               return left[ i ] < right[ i ];
+         return false;
+      };
+
+      // sort points in lexicographical order
+      std::stable_sort( permutation.begin(), permutation.end(), lexless );
+
+      // old -> new index mapping for points
+      std::vector< GlobalIndexType > points_perm_to_new( points.getSize() );
+
+      // find duplicate points
+      GlobalIndexType uniquePointsCount = 0;
+      // first index is unique
+      points_perm_to_new[ permutation[ 0 ] ] = uniquePointsCount++;
+      for( GlobalIndexType i = 1; i < points.getSize(); i++ ) {
+         const PointType& curr = points[ permutation[ i ] ];
+         const PointType& prev = points[ permutation[ i - 1 ] ];
+         if( maxNorm( curr - prev ) > numericalThreshold )
+            // unique point
+            points_perm_to_new[ permutation[ i ] ] = uniquePointsCount++;
+         else
+            // duplicate point - use previous index
+            points_perm_to_new[ permutation[ i ] ] = uniquePointsCount - 1;
+      }
+
+      // if all points are unique, we are done
+      if( uniquePointsCount == points.getSize() )
+         return;
+
+      std::cout << "Found " << points.getSize() - uniquePointsCount << " duplicate points (total " << points.getSize() << ", unique " << uniquePointsCount << ")" << std::endl;
+
+      // copy this->points and this->pointsSet, drop duplicate points
+      // (trying to do this in-place is not worth it, since even Array::reallocate
+      // needs to allocate a temporary array and copy the elements)
+      PointArrayType newPoints( uniquePointsCount );
+      BoolVector newPointsSet( uniquePointsCount );
+      std::vector< GlobalIndexType > points_old_to_new( points.getSize() );
+      // TODO: this can almost be parallelized, except we have multiple writes for the duplicate points
+      for( std::size_t i = 0; i < points_perm_to_new.size(); i++ ) {
+         const GlobalIndexType oldIndex = permutation[ i ];
+         const GlobalIndexType newIndex = points_perm_to_new[ oldIndex ];
+         newPoints[ newIndex ] = points[ oldIndex ];
+         newPointsSet[ newIndex ] = pointsSet[ oldIndex ];
+         points_old_to_new[ oldIndex ] = newIndex;
+      }
+      points = std::move( newPoints );
+      pointsSet = std::move( newPointsSet );
+      // reset permutation and points_perm_to_new - we need just points_old_to_new further on
+      permutation.clear();
+      permutation.shrink_to_fit();
+      points_perm_to_new.clear();
+      points_perm_to_new.shrink_to_fit();
+
+      auto remap_matrix = [uniquePointsCount, &points_old_to_new] ( auto& seeds )
+      {
+         // TODO: parallelize (we have the IndexPermutationApplier)
+         for( GlobalIndexType i = 0; i < seeds.getEntitiesCount(); i++ ) {
+            auto seed = seeds.getSeed( i );
+            for( LocalIndexType j = 0; j < seed.getCornersCount(); j++ ) {
+               const GlobalIndexType newIndex = points_old_to_new[ seed.getCornerId( j ) ];
+               seed.setCornerId( j, newIndex );
+            }
+         }
+         // update the number of columns of the matrix
+         seeds.getMatrix().setColumnsWithoutReset( uniquePointsCount );
+      };
+
+      // remap points in this->faceSeeds or this->cellSeeds
+      if( faceSeeds.empty() )
+         remap_matrix( cellSeeds );
+      else
+         remap_matrix( faceSeeds );
+   }
+
+   void deduplicateFaces()
+   {
+      // prepare vector with an identity permutationutation
+      std::vector< GlobalIndexType > permutation( faceSeeds.getEntitiesCount() );
+      std::iota( permutation.begin(), permutation.end(), (GlobalIndexType) 0 );
+
+      // workaround for lexicographical sorting
+      // FIXME: https://mmg-gitlab.fjfi.cvut.cz/gitlab/tnl/tnl-dev/-/issues/79
+      auto lexless = [this] (const GlobalIndexType& a, const GlobalIndexType& b) -> bool
+      {
+         const auto& left = this->faceSeeds.getSeed( a );
+         const auto& right = this->faceSeeds.getSeed( b );
+         for( LocalIndexType i = 0; i < left.getCornersCount() && i < right.getCornersCount(); i++ ) {
+            if( left.getCornerId( i ) < right.getCornerId( i ) )
+               return true;
+            if( right.getCornerId( i ) < left.getCornerId( i ) )
+               return false;
+         }
+         return left.getCornersCount() < right.getCornersCount();
+      };
+
+      // TODO: here we just assume that all duplicate faces have the same ordering of vertices (which is the case for files
+      // produced by the VTUWriter), but maybe we should try harder (we would have to create a copy of faceSeeds and sort the
+      // vertex indices in each seed, all that *before* lexicographical sorting)
+      // (Just for the detection of duplicates, it does not matter that vertices of a polygon get sorted in an arbitrary order
+      // instead of clock-wise or counter-clockwise.)
+      auto equiv = [lexless] (const GlobalIndexType& a, const GlobalIndexType& b) -> bool
+      {
+         return ! lexless(a, b) && ! lexless(b, a);
+      };
+
+      // sort face seeds in lexicographical order
+      std::stable_sort( permutation.begin(), permutation.end(), lexless );
+
+      // old -> new index mapping for faces
+      std::vector< GlobalIndexType > faces_perm_to_new( faceSeeds.getEntitiesCount() );
+
+      // find duplicate faces
+      GlobalIndexType uniqueFacesCount = 0;
+      // first index is unique
+      faces_perm_to_new[ permutation[ 0 ] ] = uniqueFacesCount++;
+      for( GlobalIndexType i = 1; i < faceSeeds.getEntitiesCount(); i++ ) {
+         if( equiv( permutation[ i ], permutation[ i - 1 ] ) )
+            // duplicate face - use previous index
+            faces_perm_to_new[ permutation[ i ] ] = uniqueFacesCount - 1;
+         else
+            // unique face
+            faces_perm_to_new[ permutation[ i ] ] = uniqueFacesCount++;
+      }
+
+      // if all faces are unique, we are done
+      if( uniqueFacesCount == faceSeeds.getEntitiesCount() )
+         return;
+
+      std::cout << "Found " << faceSeeds.getEntitiesCount() - uniqueFacesCount << " duplicate faces (total " << faceSeeds.getEntitiesCount() << ", unique " << uniqueFacesCount << ")" << std::endl;
+
+      // get corners counts for unique faces
+      NeighborCountsArray cornersCounts( uniqueFacesCount );
+      std::vector< GlobalIndexType > faces_old_to_new( faceSeeds.getEntitiesCount() );
+      // TODO: this can almost be parallelized, except we have multiple writes for the duplicate faces
+      for( std::size_t i = 0; i < faces_perm_to_new.size(); i++ ) {
+         const GlobalIndexType oldIndex = permutation[ i ];
+         const GlobalIndexType newIndex = faces_perm_to_new[ oldIndex ];
+         cornersCounts[ newIndex ] = faceSeeds.getEntityCornerCounts()[ oldIndex ];
+         faces_old_to_new[ oldIndex ] = newIndex;
+      }
+      // reset permutation and faces_perm_to_new - we need just faces_old_to_new further on
+      permutation.clear();
+      permutation.shrink_to_fit();
+      faces_perm_to_new.clear();
+      faces_perm_to_new.shrink_to_fit();
+      // copy this->faceSeeds, drop duplicate faces
+      FaceSeedMatrixType newFaceSeeds;
+      newFaceSeeds.setDimensions( uniqueFacesCount, points.getSize() );
+      newFaceSeeds.setEntityCornersCounts( std::move( cornersCounts ) );
+      // TODO: this can almost be parallelized, except we have multiple writes for the duplicate faces
+      for( std::size_t i = 0; i < faces_old_to_new.size(); i++ ) {
+         const GlobalIndexType oldIndex = i;
+         const GlobalIndexType newIndex = faces_old_to_new[ oldIndex ];
+         const auto& oldSeed = faceSeeds.getSeed( oldIndex );
+         auto newSeed = newFaceSeeds.getSeed( newIndex );
+         for( LocalIndexType j = 0; j < newSeed.getCornersCount(); j++ )
+            newSeed.setCornerId( j, oldSeed.getCornerId( j ) );
+      }
+      faceSeeds = std::move( newFaceSeeds );
+
+      // TODO: refactoring - basically the same lambda as in deduplicatePoints
+      auto remap_matrix = [uniqueFacesCount, &faces_old_to_new] ( auto& seeds )
+      {
+         // TODO: parallelize (we have the IndexPermutationApplier)
+         for( GlobalIndexType i = 0; i < seeds.getEntitiesCount(); i++ ) {
+            auto seed = seeds.getSeed( i );
+            for( LocalIndexType j = 0; j < seed.getCornersCount(); j++ ) {
+               const GlobalIndexType newIndex = faces_old_to_new[ seed.getCornerId( j ) ];
+               seed.setCornerId( j, newIndex );
+            }
+         }
+         // update the number of columns of the matrix
+         seeds.getMatrix().setColumnsWithoutReset( uniqueFacesCount );
+      };
+
+      // remap cell seeds
+      remap_matrix( cellSeeds );
+   }
+
    bool build( MeshType& mesh )
    {
       if( ! this->validate() )
          return false;
+      pointsSet.reset();
       mesh.init( this->points, this->faceSeeds, this->cellSeeds );
       return true;
    }
 
 private:
-   using PointArrayType     = typename MeshTraitsType::PointArrayType;
-   using BoolVector         = Containers::Vector< bool, Devices::Host, GlobalIndexType >;
-
    bool validate() const
    {
+      // verify that matrix dimensions are consistent with points
+      if( faceSeeds.empty() ) {
+         // no face seeds - cell seeds refer to points
+         if( cellSeeds.getMatrix().getColumns() != points.getSize() ) {
+            std::cerr << "Mesh builder error: Inconsistent size of the cellSeeds matrix (it has "
+                      << cellSeeds.getMatrix().getColumns() << " columns, but there are " << points.getSize()
+                      << " points)." << std::endl;
+            return false;
+         }
+      }
+      else {
+         // cell seeds refer to faces and face seeds refer to points
+         if( cellSeeds.getMatrix().getColumns() != faceSeeds.getMatrix().getRows() ) {
+            std::cerr << "Mesh builder error: Inconsistent size of the cellSeeds matrix (it has "
+                      << cellSeeds.getMatrix().getColumns() << " columns, but there are " << faceSeeds.getMatrix().getRows()
+                      << " faces)." << std::endl;
+            return false;
+         }
+         if( faceSeeds.getMatrix().getColumns() != points.getSize() ) {
+            std::cerr << "Mesh builder error: Inconsistent size of the faceSeeds matrix (it has "
+                      << faceSeeds.getMatrix().getColumns() << " columns, but there are " << points.getSize()
+                      << " points)." << std::endl;
+            return false;
+         }
+      }
+
       if( min( pointsSet ) != true ) {
          std::cerr << "Mesh builder error: Not all points were set." << std::endl;
          return false;
diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h
deleted file mode 100644
index 13fec6787827ec6177815984096dbfe0ff10e59d..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
-                          MeshIntegrityChecker.h  -  description
-                             -------------------
-    begin                : Mar 20, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-/***
- * Authors:
- * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz
- * Zabka Vitezslav, zabkav@gmail.com
- */
-
-#pragma once
-
-#include <TNL/Meshes/Mesh.h>
-#include <TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshType >
-class MeshIntegrityChecker
-: public MeshIntegrityCheckerLayer< MeshType,
-                                    DimensionTag< MeshType::Config::CellType::dimension > >
-{
-      typedef Meshes::DimensionTag< MeshType::Config::CellType::dimension > DimensionTag;
-      typedef MeshIntegrityCheckerLayer< MeshType, DimensionTag > BaseType;
-
-   public:
-      static bool checkMesh( const MeshType& mesh )
-      {
-         if( ! BaseType::checkEntities( mesh ) )
-            return false;
-         return true;
-      }
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h
deleted file mode 100644
index 13e415d4567effbc8c8f5b735c7523045f718cad..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/***************************************************************************
-                          MeshIntegrityCheckerLayer.h  -  description
-                             -------------------
-    begin                : Mar 21, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-/***
- * Authors:
- * Oberhuber Tomas, tomas.oberhuber@fjfi.cvut.cz
- * Zabka Vitezslav, zabkav@gmail.com
- */
-
-#pragma once
-
-#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
-#include <TNL/Meshes/DimensionTag.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshType,
-          typename DimensionTag,
-          bool EntityStorageTag = MeshEntityTraits< typename MeshType::Config,
-                                                    DimensionTag::value >::storageEnabled >
-class MeshIntegrityCheckerLayer;
-
-template< typename MeshType,
-          typename DimensionTag >
-class MeshIntegrityCheckerLayer< MeshType,
-                                 DimensionTag,
-                                 true >
-   : public MeshIntegrityCheckerLayer< MeshType,
-                                       typename DimensionTag::Decrement >
-{
-   public:
-      typedef MeshIntegrityCheckerLayer< MeshType,
-                                         typename DimensionTag::Decrement >     BaseType;
-      enum { dimension = DimensionTag::value };
-
-      static bool checkEntities( const MeshType& mesh )
-      {
-         typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType;
-         typedef typename ContainerType::IndexType                                       GlobalIndexType;
-        std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl;
-         for( GlobalIndexType entityIdx = 0;
-              entityIdx < mesh.template getEntitiesCount< dimension >();
-              entityIdx++ )
-         {
-           std::cout << "Entity no. " << entityIdx << "               \r" << std::flush;
-         }
-        std::cout << std::endl;
-         if( ! BaseType::checkEntities( mesh ) )
-            return false;
-         return true;
-      }
-};
-
-template< typename MeshType >
-class MeshIntegrityCheckerLayer< MeshType,
-                                 DimensionTag< 0 >,
-                                 true >
-{
-   public:
-      enum { dimension = 0 };
-
-      static bool checkEntities( const MeshType& mesh )
-      {
-         typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType;
-         typedef typename ContainerType::IndexType                                       GlobalIndexType;
-        std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl;
-         for( GlobalIndexType entityIdx = 0;
-              entityIdx < mesh.template getEntitiesCount< dimension >();
-              entityIdx++ )
-         {
-           std::cout << "Entity no. " << entityIdx << "          \r" << std::flush;
-         }
-        std::cout << std::endl;
-         return true;
-      }
-};
-
-template< typename MeshType,
-          typename DimensionTag >
-class MeshIntegrityCheckerLayer< MeshType,
-                                 DimensionTag,
-                                 false >
-   : public MeshIntegrityCheckerLayer< MeshType,
-                                       typename DimensionTag::Decrement >
-{
-};
-
-template< typename MeshType >
-class MeshIntegrityCheckerLayer< MeshType,
-                                 DimensionTag< 0 >,
-                                 false >
-{
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/EntitySeedMatrix.h b/src/TNL/Meshes/MeshDetails/initializer/EntitySeedMatrix.h
index ae6ac5eeddba371f58d906dffd83f2cf213c05ad..fff6b8251ed92ce0ebb332a54c14fc601d4bbdd0 100644
--- a/src/TNL/Meshes/MeshDetails/initializer/EntitySeedMatrix.h
+++ b/src/TNL/Meshes/MeshDetails/initializer/EntitySeedMatrix.h
@@ -60,6 +60,13 @@ class EntitySeedMatrix< MeshConfig, EntityTopology, false >
                this->row.setColumnIndex( cornerIndex, pointIndex );
             }
 
+            template< typename... IndexTypes >
+            void setCornerIds( const IndexTypes&... pointIndices )
+            {
+               static_assert( sizeof...( pointIndices ) == getCornersCount(), "invalid number of indices" );
+               setCornerIds_impl( 0, pointIndices... );
+            }
+
             GlobalIndexType getCornerId( const LocalIndexType& cornerIndex ) const
             {
                return this->row.getColumnIndex( cornerIndex );
@@ -67,6 +74,17 @@ class EntitySeedMatrix< MeshConfig, EntityTopology, false >
 
          private:
             RowView row;
+
+            // empty overload to terminate recursion
+            void setCornerIds_impl( const LocalIndexType& cornerIndex )
+            {}
+
+            template< typename... IndexTypes >
+            void setCornerIds_impl( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex, const IndexTypes&... pointIndices )
+            {
+               setCornerId( cornerIndex, pointIndex );
+               setCornerIds_impl( cornerIndex + 1, pointIndices... );
+            }
       };
 
       class ConstEntitySeedMatrixSeed
diff --git a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
index 9417c244e313d88ae7b55444a044263ad24d4fde..76aff7010d88d6aa6c73fe7f05b0d23a28c236d4 100644
--- a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
+++ b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
@@ -70,7 +70,7 @@ class Initializer
    protected:
       // must be declared before its use in expression with decltype()
       Mesh< MeshConfig >* mesh = nullptr;
-      
+
    public:
       using MeshType          = Mesh< MeshConfig >;
       using MeshTraitsType    = MeshTraits< MeshConfig >;
@@ -92,14 +92,13 @@ class Initializer
                        CellSeedMatrixType& cellSeeds,
                        MeshType& mesh )
       {
-         // copy points
+         // move points
          mesh.template setEntitiesCount< 0 >( points.getSize() );
-         mesh.getPoints().swap( points );
-         points.reset();
+         mesh.getPoints() = std::move( points );
 
          this->mesh = &mesh;
          this->cellSeeds = &cellSeeds;
-         
+
          if( faceSeeds.empty() )
             BaseType::initEntities( *this, cellSeeds, mesh );
          else
@@ -227,7 +226,7 @@ protected:
          initializer.template setEntitiesCount< DimensionTag::value >( initializer.getCellSeeds().getEntitiesCount() );
          BaseType::initEntities( initializer, faceSeeds, mesh );
       }
-      
+
       using BaseType::findEntitySeedIndex;
 };
 
@@ -256,7 +255,7 @@ protected:
    using SeedIndexedSet        = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
    using SeedMatrixType        = typename EntityTraitsType::SeedMatrixType;
    using NeighborCountsArray   = typename MeshTraitsType::NeighborCountsArray;
-   
+
    public:
 
       void createSeeds( InitializerType& initializer, MeshType& mesh )
@@ -280,6 +279,12 @@ protected:
 
       void initEntities( InitializerType& initializer, MeshType& mesh )
       {
+         // skip initialization of entities which do not store their subvertices
+         // (and hence do not participate in any other incidence matrix)
+         if( ! MeshConfig::subentityStorage( DimensionTag::value, 0 ) ) {
+            BaseType::initEntities( initializer, mesh );
+            return;
+         }
          //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
 
          // create seeds and set entities count
diff --git a/src/TNL/Meshes/Readers/MeshReader.h b/src/TNL/Meshes/Readers/MeshReader.h
index e18e6577bf949f52f3b80c442c8dd913d5966e8c..537aed7408eddca59383050bc0d01ba4d4a3823b 100644
--- a/src/TNL/Meshes/Readers/MeshReader.h
+++ b/src/TNL/Meshes/Readers/MeshReader.h
@@ -174,7 +174,7 @@ public:
 
       MeshBuilder meshBuilder;
       meshBuilder.setEntitiesCount( NumberOfPoints, NumberOfCells, NumberOfFaces );
- 
+
       // assign points
       visit( [&meshBuilder](auto&& array) {
                PointType p;
@@ -196,7 +196,7 @@ public:
                // let's just assume that the connectivity and offsets arrays have the same type...
                using mpark::get;
                const auto& offsets = get< std::decay_t<decltype(connectivity)> >( faceOffsetsArray );
-               
+
                // Set corners counts
                NeighborCountsArray cornersCounts( NumberOfFaces );
                std::size_t offsetStart = 0;
@@ -252,6 +252,10 @@ public:
       // reset arrays since they are not needed anymore
       pointsArray = faceConnectivityArray = cellConnectivityArray = faceOffsetsArray = cellOffsetsArray = typesArray = {};
 
+      // deduplicate faces (important for VTK formats, not for FPMA)
+      if( NumberOfFaces > 0 )
+         meshBuilder.deduplicateFaces();
+
       if( ! meshBuilder.build( mesh ) )
          throw MeshReaderError( "MeshReader", "MeshBuilder failed" );
    }
@@ -295,20 +299,41 @@ public:
    std::string
    getRealType() const
    {
-      return pointsType;
+      if( forcedRealType.empty() )
+         return pointsType;
+      return forcedRealType;
    }
 
    std::string
    getGlobalIndexType() const
    {
-      return connectivityType;
+      if( forcedGlobalIndexType.empty() )
+         return connectivityType;
+      return forcedGlobalIndexType;
    }
 
    std::string
    getLocalIndexType() const
    {
-      // not stored in any file format
-      return "short int";
+      return forcedLocalIndexType;
+   }
+
+   void
+   forceRealType( std::string realType )
+   {
+      forcedRealType = std::move( realType );
+   }
+
+   void
+   forceGlobalIndexType( std::string globalIndexType )
+   {
+      forcedGlobalIndexType = std::move( globalIndexType );
+   }
+
+   void
+   forceLocalIndexType( std::string localIndexType )
+   {
+      forcedLocalIndexType = std::move( localIndexType );
    }
 
 protected:
@@ -324,6 +349,12 @@ protected:
    int meshDimension, spaceDimension;
    VTK::EntityShape cellShape = VTK::EntityShape::Vertex;
 
+   // string representation of mesh types (forced means specified by the user, otherwise
+   // the type detected by detectMesh takes precedence)
+   std::string forcedRealType = "";
+   std::string forcedGlobalIndexType = "";
+   std::string forcedLocalIndexType = "short int";  // not stored in any file format
+
    // intermediate representation of a grid (this is relevant only for TNL::Meshes::Grid)
    std::vector< std::int64_t > gridExtent;
    std::vector< double > gridOrigin, gridSpacing;
@@ -334,8 +365,6 @@ protected:
                  faceConnectivityArray, faceOffsetsArray,
                  typesArray;
 
-
-
    // string representation of each array's value type
    std::string pointsType, connectivityType, offsetsType, typesType;
 
@@ -346,12 +375,25 @@ protected:
       meshDimension = spaceDimension = 0;
       cellShape = VTK::EntityShape::Vertex;
 
-      gridExtent = {};
-      gridOrigin = gridSpacing = {};
+      reset_std_vectors( gridExtent, gridOrigin, gridSpacing );
 
       pointsArray = cellConnectivityArray = cellOffsetsArray = faceConnectivityArray = faceOffsetsArray = typesArray = {};
       pointsType = connectivityType = offsetsType = typesType = "";
    }
+
+   template< typename T >
+   void reset_std_vectors( std::vector< T >& v )
+   {
+      v.clear();
+      v.shrink_to_fit();
+   }
+
+   template< typename T, typename... Ts >
+   void reset_std_vectors( std::vector< T >& v, std::vector< Ts >&... vs )
+   {
+      reset_std_vectors( v );
+      reset_std_vectors( vs... );
+   }
 };
 
 } // namespace Readers
diff --git a/src/TNL/Meshes/Readers/PVTIReader.h b/src/TNL/Meshes/Readers/PVTIReader.h
index 3e9bf7200f1497654445db9ed229526c528ee8a9..5eae866dfb842d70c6b5b0b270034bd701dba742 100644
--- a/src/TNL/Meshes/Readers/PVTIReader.h
+++ b/src/TNL/Meshes/Readers/PVTIReader.h
@@ -312,7 +312,7 @@ public:
    {
       resetBase();
       ghostLevels = 0;
-      pieceSources = {};
+      reset_std_vectors( pieceSources );
       localReader.reset();
       pointTags = cellTags = {};
    }
diff --git a/src/TNL/Meshes/Readers/PVTUReader.h b/src/TNL/Meshes/Readers/PVTUReader.h
index 87379c732cf548ff4f83ce3789c65094e13e5023..6656deeb4adf19e8bf0b9bf911c739a1bc745e08 100644
--- a/src/TNL/Meshes/Readers/PVTUReader.h
+++ b/src/TNL/Meshes/Readers/PVTUReader.h
@@ -249,7 +249,7 @@ public:
    {
       resetBase();
       ghostLevels = 0;
-      pieceSources = {};
+      reset_std_vectors( pieceSources );
       localReader.reset();
       pointTags = cellTags = pointGlobalIndices = cellGlobalIndices = {};
    }
diff --git a/src/TNL/Meshes/Readers/VTKReader.h b/src/TNL/Meshes/Readers/VTKReader.h
index 966e4f4677c1dcbbe742c786f5038615aca88676..255b196ce4d8144b2666b4d2b6302b640f8143b0 100644
--- a/src/TNL/Meshes/Readers/VTKReader.h
+++ b/src/TNL/Meshes/Readers/VTKReader.h
@@ -67,15 +67,12 @@ public:
       if( pointsType != "float" && pointsType != "double" )
          throw MeshReaderError( "VTKReader", "unsupported data type for POINTS: " + pointsType );
 
-      // global index type is not stored in legacy VTK files
-      // (binary VTK files don't support int64)
-      connectivityType = offsetsType = "std::int32_t";
       // only std::uint8_t makes sense for entity types
       typesType = "std::uint8_t";
 
       // arrays holding the data from the VTK file
       std::vector< double > pointsArray;
-      std::vector< std::int32_t > connectivityArray, offsetsArray;
+      std::vector< std::int64_t > cellConnectivityArray, cellOffsetsArray;
       std::vector< std::uint8_t > typesArray;
 
       // read points
@@ -159,29 +156,20 @@ public:
 
       // validate cell types
       using PolygonShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polygon >;
-      //TODO: add EntityShapeGroup for polyhedrons and uncomment line below
-      //using PolyhedralShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polyhedral >;
+      using PolyhedronShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polyhedron >;
       cellShape = (VTK::EntityShape) cellTypes[0];
 
-      for( auto c : cellTypes )
-      {
+      for( auto c : cellTypes ) {
          auto entityShape = (VTK::EntityShape) c;
-         if( cellShape != entityShape )
-         {
-            //in case input mesh includes mixed shapes, use more general cellShape ( polygon for 2D, polyhedrals for 3D )
+         if( cellShape != entityShape ) {
+            // if the input mesh includes mixed shapes, use more general cellShape (polygon for 2D, polyhedron for 3D)
             if( PolygonShapeGroupChecker::bothBelong( cellShape, entityShape ) )
-            {
                cellShape = PolygonShapeGroupChecker::GeneralShape;
-            }
-            //TODO: add group check for polyhedrals later
-            /*else if( PolyhedralEntityShapeGroupChecker::bothBelong( cellShape, entityShape ) )
-            {
-               cellShape = PolyhedralEntityShapeGroupChecker::GeneralShape;
-            }*/
-            else
-            {
-               const std::string msg = "Mixed unstructured meshes are not supported. There are cells with type "
-                                  + VTK::getShapeName(cellShape) + " and " + VTK::getShapeName(entityShape) + ".";
+            else if( PolyhedronShapeGroupChecker::bothBelong( cellShape, entityShape ) )
+               cellShape = PolyhedronShapeGroupChecker::GeneralShape;
+            else {
+               const std::string msg = "Unsupported unstructured meshes with mixed entities: there are cells with type "
+                                     + VTK::getShapeName(cellShape) + " and " + VTK::getShapeName(entityShape) + ".";
                reset();
                throw MeshReaderError( "VTKReader", msg );
             }
@@ -194,38 +182,167 @@ public:
       inputFile.seekg( sectionPositions["CELLS"] );
       getline( inputFile, line );
 
-      // read entities
-      for( std::size_t entityIndex = 0; entityIndex < NumberOfEntities; entityIndex++ ) {
-         if( ! inputFile )
-            throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
-                                                " (entityIndex = " + std::to_string(entityIndex) + ")" );
-
-         VTK::EntityShape entityShape = (VTK::EntityShape) typesArray[ entityIndex ];
-
-         // TODO: Polyhedrons will require to create polygon subentity seeds from given entityShapes
-         //       and add their entries to faceConnectivityArray and faceOffsetsArray.
-         //       CellConnectivityArray and cellOffsetsArray will contain indices addressing created polygon subentities.
-         if( entityShape == cellShape ||
-             PolygonShapeGroupChecker::bothBelong( cellShape, entityShape ) ) {
-            iss.clear();
-            iss.str( line );
-            // read number of subvertices
-            const std::int32_t subvertices = readValue< std::int32_t >( dataFormat, inputFile );
-            for( int v = 0; v < subvertices; v++ ) {
-               // legacy VTK files do not support 64-bit integers, even in the BINARY format
-               const std::int32_t vid = readValue< std::int32_t >( dataFormat, inputFile );
-               if( ! inputFile )
-                  throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
-                                                      " (entityIndex = " + std::to_string(entityIndex) + ", subvertex = " + std::to_string(v) + ")" );
-               connectivityArray.push_back( vid );
+      if( formatVersion == "2.0" ) {
+         // read entities
+         for( std::size_t entityIndex = 0; entityIndex < NumberOfEntities; entityIndex++ ) {
+            if( ! inputFile )
+               throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
+                                                   " (entityIndex = " + std::to_string(entityIndex) + ")" );
+
+            const VTK::EntityShape entityShape = (VTK::EntityShape) typesArray[ entityIndex ];
+
+            if( entityShape == VTK::EntityShape::Polyhedron )
+               throw MeshReaderError( "VTKReader", "Reading polyhedrons from a DataFile version 2.0 is not supported. "
+                                                   "Convert the file to version 5.1 (e.g. using Paraview) and try again." );
+
+            if( entityShape == cellShape || PolygonShapeGroupChecker::bothBelong( cellShape, entityShape ) ) {
+               // read number of subvertices
+               const std::int32_t subvertices = readValue< std::int32_t >( dataFormat, inputFile );
+               for( int v = 0; v < subvertices; v++ ) {
+                  // legacy VTK files do not support 64-bit integers, even in the BINARY format
+                  const std::int32_t vid = readValue< std::int32_t >( dataFormat, inputFile );
+                  if( ! inputFile )
+                     throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
+                                                         " (entityIndex = " + std::to_string(entityIndex) + ", subvertex = " + std::to_string(v) + ")" );
+                  cellConnectivityArray.push_back( vid );
+               }
+               cellOffsetsArray.push_back( cellConnectivityArray.size() );
+            }
+            else {
+               // skip the entity
+               const std::int32_t subvertices = readValue< std::int32_t >( dataFormat, inputFile );
+               for( int v = 0; v < subvertices; v++ )
+                  skipValue( dataFormat, inputFile, "int" );
             }
-            offsetsArray.push_back( connectivityArray.size() );
          }
-         else {
-            // skip the entity
-            const std::int32_t subvertices = readValue< std::int32_t >( dataFormat, inputFile );
-            for( int v = 0; v < subvertices; v++ )
-               skipValue( dataFormat, inputFile, "int" );
+      }
+      else if( formatVersion == "5.1" ) {
+         // parse the rest of the line: CELLS <offsets_count> <connectivity_count>
+         std::int64_t offsets_count = 0;
+         std::int64_t connectivity_count = 0;
+         iss.clear();
+         iss.str( line );
+         iss >> aux >> offsets_count >> connectivity_count;
+         if( offsets_count < 1 )
+            throw MeshReaderError( "VTKReader", "invalid offsets count: " + std::to_string( offsets_count ) );
+
+         // find to the OFFSETS section
+         if( ! sectionPositions.count( "OFFSETS" ) )
+            throw MeshReaderError( "VTKReader", "unable to find the OFFSETS section, the file may be invalid or corrupted" );
+         inputFile.seekg( sectionPositions["OFFSETS"] );
+
+         // read all offsets into an auxiliary array
+         std::vector< std::int64_t > allOffsetsArray;
+         getline( inputFile, line );
+         iss.clear();
+         iss.str( line );
+         std::string aux, datatype;
+         iss >> aux >> datatype;
+         for( std::int64_t entityIndex = 0; entityIndex < offsets_count; entityIndex++ ) {
+            std::int64_t value;
+            if( datatype == "vtktypeint32" )
+               value = readValue< std::int32_t >( dataFormat, inputFile );
+            else if( datatype == "vtktypeint64" )
+               value = readValue< std::int64_t >( dataFormat, inputFile );
+            else
+               throw MeshReaderError( "VTKReader", "found data type which is not implemented in the reader: " + datatype );
+            if( ! inputFile )
+               throw MeshReaderError( "VTKReader", "unable to read enough offsets, the file may be invalid or corrupted"
+                                                   " (entityIndex = " + std::to_string(entityIndex) + ")" );
+            allOffsetsArray.push_back( value );
+         }
+
+         // find to the CONNECTIVITY section
+         if( ! sectionPositions.count( "CONNECTIVITY" ) )
+            throw MeshReaderError( "VTKReader", "unable to find the CONNECTIVITY section, the file may be invalid or corrupted" );
+         inputFile.seekg( sectionPositions["CONNECTIVITY"] );
+
+         // get datatype
+         getline( inputFile, line );
+         iss.clear();
+         iss.str( line );
+         iss >> aux >> datatype;
+
+         // arrays for polyhedral mesh
+         std::vector< std::int64_t > faceConnectivityArray, faceOffsetsArray;
+         std::int64_t faceIndex = 0;
+
+         // read connectivity
+         for( std::size_t entityIndex = 0; entityIndex < NumberOfEntities; entityIndex++ ) {
+            if( ! inputFile )
+               throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
+                                                   " (entityIndex = " + std::to_string(entityIndex) + ")" );
+
+            const VTK::EntityShape entityShape = (VTK::EntityShape) typesArray[ entityIndex ];
+            const std::int64_t offsetBegin = allOffsetsArray[ entityIndex ];
+            const std::int64_t offsetEnd = allOffsetsArray[ entityIndex + 1 ];
+
+            // TODO: Polyhedrons will require to create polygon subentity seeds from given entityShapes
+            //       and add their entries to faceConnectivityArray and faceOffsetsArray.
+            //       CellConnectivityArray and cellOffsetsArray will contain indices addressing created polygon subentities.
+            if( cellShape == VTK::EntityShape::Polyhedron && entityShape != cellShape && PolyhedronShapeGroupChecker::bothBelong( cellShape, entityShape ) )
+               throw MeshReaderError( "VTKReader", "Converting a mixed mesh to polyhedral mesh is not implemented yet." );
+
+            if( entityShape == cellShape && cellShape == VTK::EntityShape::Polyhedron ) {
+               // read connectivity for current cell into extra array
+               std::vector< std::int64_t > cell_connectivity;
+               for( int v = 0; v < offsetEnd - offsetBegin; v++ ) {
+                  std::int64_t value;
+                  if( datatype == "vtktypeint32" )
+                     value = readValue< std::int32_t >( dataFormat, inputFile );
+                  else if( datatype == "vtktypeint64" )
+                     value = readValue< std::int64_t >( dataFormat, inputFile );
+                  else
+                     throw MeshReaderError( "VTKReader", "found data type which is not implemented in the reader: " + datatype );
+                  if( ! inputFile )
+                     throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
+                                                         " (entityIndex = " + std::to_string(entityIndex) + ", subvertex = " + std::to_string(v) + ")" );
+                  cell_connectivity.push_back( value );
+               }
+               // connectivity[offsetBegin : offsetEnd] describes the faces of
+               // the cell in the following format (similar to VTU's faces array)
+               //    num_faces_cell_0,
+               //      num_nodes_face_0, node_ind_0, node_ind_1, ..
+               //      num_nodes_face_1, node_ind_0, node_ind_1, ..
+               //      ...
+               std::size_t i = 1;  // skip num_faces for the cell
+               while( i < cell_connectivity.size() ) {
+                  const std::int64_t num_nodes = cell_connectivity.at( i++ );
+                  for( std::int64_t n = 0; n < num_nodes; n++ )
+                     faceConnectivityArray.push_back( cell_connectivity.at( i++ ) );
+                  faceOffsetsArray.push_back( faceConnectivityArray.size() );
+                  cellConnectivityArray.push_back( faceIndex++ );
+               }
+               cellOffsetsArray.push_back( cellConnectivityArray.size() );
+            }
+            else if( entityShape == cellShape || PolygonShapeGroupChecker::bothBelong( cellShape, entityShape ) ) {
+               for( int v = 0; v < offsetEnd - offsetBegin; v++ ) {
+                  std::int64_t vid;
+                  if( datatype == "vtktypeint32" )
+                     vid = readValue< std::int32_t >( dataFormat, inputFile );
+                  else if( datatype == "vtktypeint64" )
+                     vid = readValue< std::int64_t >( dataFormat, inputFile );
+                  else
+                     throw MeshReaderError( "VTKReader", "found data type which is not implemented in the reader: " + datatype );
+                  if( ! inputFile )
+                     throw MeshReaderError( "VTKReader", "unable to read enough cells, the file may be invalid or corrupted"
+                                                         " (entityIndex = " + std::to_string(entityIndex) + ", subvertex = " + std::to_string(v) + ")" );
+                  cellConnectivityArray.push_back( vid );
+               }
+               cellOffsetsArray.push_back( cellConnectivityArray.size() );
+            }
+            else {
+               // skip the entity
+               for( int v = 0; v < offsetEnd - offsetBegin; v++ )
+                  skipValue( dataFormat, inputFile, datatype );
+            }
+         }
+
+         // set the arrays to the base class
+         if( faceIndex > 0 ) {
+            this->NumberOfFaces = faceIndex;
+            this->faceConnectivityArray = std::move( faceConnectivityArray );
+            this->faceOffsetsArray = std::move( faceOffsetsArray );
          }
       }
 
@@ -234,8 +351,8 @@ public:
 
       // set the arrays to the base class
       this->pointsArray = std::move(pointsArray);
-      this->cellConnectivityArray = std::move(connectivityArray);
-      this->cellOffsetsArray = std::move(offsetsArray);
+      this->cellConnectivityArray = std::move(cellConnectivityArray);
+      this->cellOffsetsArray = std::move(cellOffsetsArray);
       this->typesArray = std::move(typesArray);
 
       // indicate success by setting the mesh type
@@ -264,6 +381,7 @@ public:
 
 protected:
    // output of parseHeader
+   std::string formatVersion;
    VTK::FileFormat dataFormat = VTK::FileFormat::ascii;
    std::string dataset;
 
@@ -281,8 +399,12 @@ protected:
 
       // check header
       getline( str, line );
-      if( line != "# vtk DataFile Version 2.0" )
+      static const std::string prefix = "# vtk DataFile Version ";
+      formatVersion = line.substr( prefix.length() );
+      if( line.substr( 0, prefix.length() ) != prefix )
          throw MeshReaderError( "VTKReader", "failed to parse the VTK file header: unsupported VTK header '" + line + "'" );
+      if( formatVersion != "2.0" && formatVersion != "5.1" )
+         throw MeshReaderError( "VTKReader", "unsupported VTK DataFile Version: '" + formatVersion + "'" );
 
       // skip title
       if( ! str )
@@ -314,6 +436,22 @@ protected:
       iss >> dataset;
    }
 
+   void skip_meta( std::istream& str )
+   {
+      // skip possible metadata
+      // https://vtk.org/doc/nightly/html/IOLegacyInformationFormat.html
+      std::string line;
+      while( true ) {
+         getline( str, line );
+         if( ! str )
+            throw MeshReaderError( "VTKReader", "failed to parse a METADATA section: is it terminated by a blank line?" );
+         // strip whitespace
+         line.erase( std::remove_if( line.begin(), line.end(), isspace ), line.end() );
+         if( line.empty() )
+            break;
+      }
+   }
+
    void findSections( std::istream& str )
    {
       while( str ) {
@@ -349,7 +487,14 @@ protected:
                std::int32_t components = 0;
                std::int32_t tuples = 0;
                std::string datatype;
-               iss >> aux >> components >> tuples >> datatype;
+               iss >> aux;
+               if( aux == "METADATA" ) {
+                  // skip metadata and read again
+                  skip_meta( str );
+                  i--;
+                  continue;
+               }
+               iss >> components >> tuples >> datatype;
                if( ! iss )
                   throw MeshReaderError( "VTKReader", "failed to extract FieldData information from line '" + line + "'" );
                // skip the points coordinates
@@ -370,14 +515,74 @@ protected:
             // skip end of line (or any whitespace)
             str >> std::ws;
          }
+         // METADATA is a thing since version 5.1 of the file format (or something else newer than 2.0)
+         else if( name == "METADATA" ) {
+            sectionPositions.insert( {"METADATA", currentPosition} );
+            skip_meta( str );
+         }
          else if( name == "CELLS" ) {
             sectionPositions.insert( {"CELLS", currentPosition} );
-            // parse the rest of the line: CELLS <cells_count> <values_count>
-            std::int32_t values_count = 0;
-            iss >> cells_count >> values_count;
-            // skip the values
-            for( std::int32_t j = 0; j < values_count; j++ )
-               skipValue( dataFormat, str, "int" );
+            if( formatVersion == "2.0" ) {
+               // index type is not stored in legacy VTK DataFile version 2.0
+               // (binary files don't support int64)
+               connectivityType = offsetsType = "std::int32_t";
+               // parse the rest of the line: CELLS <cells_count> <values_count>
+               std::int32_t values_count = 0;
+               iss >> cells_count >> values_count;
+               // skip the values
+               for( std::int32_t j = 0; j < values_count; j++ )
+                  skipValue( dataFormat, str, "int" );
+            }
+            else if( formatVersion == "5.1" ) {
+               // parse the rest of the line: CELLS <offsets_count> <connectivity_count>
+               std::int32_t offsets_count = 0;
+               std::int32_t connectivity_count = 0;
+               iss >> offsets_count >> connectivity_count;
+               if( offsets_count < 1 )
+                  throw MeshReaderError( "VTKReader", "invalid offsets count: " + std::to_string( offsets_count ) );
+               cells_count = offsets_count - 1;
+               // drop all whitespace (empty lines etc) before saving a position and reading a line
+               str >> std::ws;
+               const std::ios::pos_type offsetsPosition = str.tellg();
+               // skip offsets
+               str >> std::ws;
+               getline( str, line );
+               iss.clear();
+               iss.str( line );
+               std::string aux, datatype;
+               iss >> aux >> datatype;
+               if( aux != "OFFSETS" )
+                  throw MeshReaderError( "VTKReader", "expected OFFSETS section, found '" + aux + "'" );
+               sectionPositions.insert( {"OFFSETS", offsetsPosition} );
+               if( datatype == "vtktypeint32" )
+                  offsetsType = "std::int32_t";
+               else if( datatype == "vtktypeint64" )
+                  offsetsType = "std::int64_t";
+               else
+                  throw MeshReaderError( "VTKReader", "unsupported datatype for OFFSETS: " + datatype );
+               for( std::int32_t j = 0; j < offsets_count; j++ )
+                  skipValue( dataFormat, str, datatype );
+               // drop all whitespace (empty lines etc) before saving a position and reading a line
+               str >> std::ws;
+               const std::ios::pos_type connectivityPosition = str.tellg();
+               // skip connectivity
+               str >> std::ws;
+               getline( str, line );
+               iss.clear();
+               iss.str( line );
+               iss >> aux >> datatype;
+               if( aux != "CONNECTIVITY" )
+                  throw MeshReaderError( "VTKReader", "expected CONNECTIVITY section, found '" + aux + "'" );
+               sectionPositions.insert( {"CONNECTIVITY", connectivityPosition} );
+               if( datatype == "vtktypeint32" )
+                  connectivityType = "std::int32_t";
+               else if( datatype == "vtktypeint64" )
+                  connectivityType = "std::int64_t";
+               else
+                  throw MeshReaderError( "VTKReader", "unsupported datatype for CONNECTIVITY: " + datatype );
+               for( std::int32_t j = 0; j < connectivity_count; j++ )
+                  skipValue( dataFormat, str, datatype );
+            }
             // skip end of line (or any whitespace)
             str >> std::ws;
          }
@@ -416,6 +621,12 @@ protected:
                std::string type;
                iss >> type;
 
+               // handle switching between CELL_DATA and POINT_DATA
+               if( ( name == "CELL_DATA" && type == "POINT_DATA" ) || ( name == "POINT_DATA" && type == "CELL_DATA" ) ) {
+                  name = type;
+                  continue;
+               }
+
                const std::int32_t elements = (name == "CELL_DATA") ? cells_count : points_count;
 
                // scalars: 1 value per cell/point
@@ -462,7 +673,14 @@ protected:
                      std::int32_t components = 0;
                      std::int32_t tuples = 0;
                      std::string datatype;
-                     iss >> array_name >> components >> tuples >> datatype;
+                     iss >> array_name;
+                     if( array_name == "METADATA" ) {
+                        // skip metadata and read again
+                        skip_meta( str );
+                        i--;
+                        continue;
+                     }
+                     iss >> components >> tuples >> datatype;
                      if( ! iss )
                         throw MeshReaderError( "VTKReader", "failed to extract FieldData information from line '" + line + "'" );
                      sectionPositions.insert( {name + "::" + array_name, currentPosition} );
@@ -474,6 +692,10 @@ protected:
                   }
                   continue;
                }
+               else if( type == "METADATA" ) {
+                  skip_meta( str );
+                  continue;
+               }
                else {
                   std::cerr << "VTKReader: encountered an unsupported CELL_DATA array type: " << type
                             << ". Ignoring the rest of the file." << std::endl;
@@ -491,6 +713,9 @@ protected:
             throw MeshReaderError( "VTKReader", "parsing error: unexpected section start at byte " + std::to_string(currentPosition)
                                     + " (section name is '" + name + "')" );
       }
+
+      // clear errors bits on the input stream
+      str.clear();
    }
 
    VariantVector
@@ -563,8 +788,12 @@ protected:
 
    static void skipValue( VTK::FileFormat format, std::istream& str, std::string datatype )
    {
-      if( datatype == "int" )
+      if( datatype == "int" )  // implicit in vtk DataFile Version 2.0
+         readValue< std::int32_t >( format, str );
+      else if( datatype == "vtktypeint32" )  // vtk DataFile Version 5.1
          readValue< std::int32_t >( format, str );
+      else if( datatype == "vtktypeint64" )  // vtk DataFile Version 5.1
+         readValue< std::int64_t >( format, str );
       else if( datatype == "float" )
          readValue< float >( format, str );
       else if( datatype == "double" )
diff --git a/src/TNL/Meshes/Readers/VTUReader.h b/src/TNL/Meshes/Readers/VTUReader.h
index 08450b0fee1701932937bc63cb2629c763a91997..27ee3a3aa83c9f64cd693983e160dda1bd01e9b8 100644
--- a/src/TNL/Meshes/Readers/VTUReader.h
+++ b/src/TNL/Meshes/Readers/VTUReader.h
@@ -96,28 +96,20 @@ class VTUReader
                cellShape = (VTK::EntityShape) array[0];
                meshDimension = getEntityDimension( cellShape );
                using PolygonShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polygon >;
-               //TODO: uncomment line below later for polyhedrals
-               //using PolyhedralShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polyhedral >;
+               using PolyhedronShapeGroupChecker = VTK::EntityShapeGroupChecker< VTK::EntityShape::Polyhedron >;
 
                // TODO: check only entities of the same dimension (edges, faces and cells separately)
-               for( auto c : array )
-               {
+               for( auto c : array ) {
                   VTK::EntityShape entityShape = (VTK::EntityShape) c;
-                  if( entityShape != cellShape )
-                  {
+                  if( entityShape != cellShape ) {
                      if( PolygonShapeGroupChecker::bothBelong( cellShape, entityShape ) )
-                     {
                         cellShape = PolygonShapeGroupChecker::GeneralShape;
-                     }
-                     //TODO: add group check for polyhedrals later
-                     /*else if( PolyhedralEntityShapeGroupChecker::bothBelong( cellShape, entityShape ) )
-                     {
-                        cellShape = PolyhedralEntityShapeGroupChecker::GeneralShape;
-                     }*/
-                     else
-                     {
-                        throw MeshReaderError( "VTUReader", "Mixed unstructured meshes are not supported. There are cells with type "
-                                                         + VTK::getShapeName(cellShape) + " and " + VTK::getShapeName(entityShape) + "." );
+                     else if( PolyhedronShapeGroupChecker::bothBelong( cellShape, entityShape ) )
+                        cellShape = PolyhedronShapeGroupChecker::GeneralShape;
+                     else {
+                        const std::string msg = "Unsupported unstructured meshes with mixed entities: there are cells with type "
+                                              + VTK::getShapeName(cellShape) + " and " + VTK::getShapeName(entityShape) + ".";
+                        throw MeshReaderError( "VTUReader", msg );
                      }
                   }
                }
@@ -148,6 +140,95 @@ class VTUReader
             },
             cellConnectivityArray
          );
+
+      if( cellShape == VTK::EntityShape::Polyhedron ) {
+         // NOTE: the data format for polyhedral meshes in VTK files is not documented well (almost not at all).
+         // Here are some references:
+         // - https://itk.org/Wiki/VTK/Polyhedron_Support
+         // - https://vtk.org/doc/nightly/html/classvtkPolyhedron.html
+         // - https://github.com/nschloe/meshio/pull/916
+         // - https://github.com/nschloe/meshio/blob/b358a88b7c1158d5ee2b2c873f67ba1cb0647686/src/meshio/vtu/_vtu.py#L33-L102
+
+         const XMLElement* faces = getDataArrayByName( cells, "faces" );
+         const XMLElement* faceOffsets = getDataArrayByName( cells, "faceoffsets" );
+         const VariantVector vtk_facesArray = readDataArray( faces, "faces" );
+         const VariantVector vtk_faceOffsetsArray = readDataArray( faceOffsets, "faceoffsets" );
+         const std::string facesType = VTKDataTypes.at( getAttributeString( faces, "type" ) );
+         const std::string faceOffsetsType = VTKDataTypes.at( getAttributeString( faceOffsets, "type" ) );
+         if( facesType != faceOffsetsType )
+            throw MeshReaderError( "VTUReader", "type of the faces array does not match the type of the faceoffsets array" );
+         if( faceOffsetsType != offsetsType )
+            throw MeshReaderError( "VTUReader", "type of the faceoffsets array does not match the type of the offsets array" );
+
+         // validate face offsets
+         std::size_t max_offset = 0;
+         visit( [this, &max_offset](auto&& array) mutable {
+                  if( array.size() != NumberOfCells )
+                     throw MeshReaderError( "VTUReader", "size of the faceoffsets data array does not match the NumberOfCells attribute" );
+                  for( auto c : array ) {
+                     // NOTE: VTK stores -1 for cells that are not a polyhedron. We would need to populate
+                     if( c < 0 )
+                        continue;
+                     if( c <= (decltype(c)) max_offset )
+                        throw MeshReaderError( "VTUReader", "the faceoffsets array is not monotonically increasing" );
+                     max_offset = c;
+                  }
+               },
+               vtk_faceOffsetsArray
+            );
+         // validate faces
+         visit( [this, max_offset, &vtk_faceOffsetsArray](auto&& vtk_faces) {
+                  if( vtk_faces.size() != max_offset )
+                     throw MeshReaderError( "VTUReader", "size of the faces data array does not match the faceoffsets array" );
+                  // let's just assume that the connectivity and offsets arrays have the same type...
+                  using mpark::get;
+                  const auto& vtk_faceOffsets = get< std::decay_t<decltype(vtk_faces)> >( vtk_faceOffsetsArray );
+
+                  // We need to translate the VTK faces and faceoffsets arrays
+                  // into the format suitable for MeshReader (which uses the
+                  // format from FPMA). The data format for the faces array is:
+                  //    num_faces_cell_0,
+                  //      num_nodes_face_0, node_ind_0, node_ind_1, ..
+                  //      num_nodes_face_1, node_ind_0, node_ind_1, ..
+                  //      ...
+                  //    num_faces_cell_1,
+                  //      ...
+                  // See https://vtk.org/Wiki/VTK/Polyhedron_Support for more.
+                  std::decay_t<decltype(vtk_faces)> cellOffsets, cellConnectivity, faceOffsets, faceConnectivity;
+                  std::make_signed_t< std::size_t > cell_off_begin = 0;
+                  std::size_t faceIndex = 0;
+                  for( std::size_t cell = 0; cell < vtk_faceOffsets.size(); cell++ ) {
+                     const std::make_signed_t< std::size_t > cell_off_end = vtk_faceOffsets[ cell ];
+                     // TODO: VTK stores -1 for cells that are not a polyhedron. We would need to populate
+                     // faceOffsetsArray and faceConnectivityArray with values based on the cell topology.
+                     if( cell_off_end < 0 )
+                        throw MeshReaderError( "VTUReader", "found invalid offset in the faceoffsets array: " + std::to_string(cell_off_end) );
+                     if( static_cast< std::size_t >( cell_off_end ) > vtk_faces.size() )
+                        throw MeshReaderError( "VTUReader", "not enough face indices for cell no " + std::to_string(cell) );
+                     // faces[cell_off_begin : cell_off_end] -> face data for cell
+                     const std::size_t num_faces = vtk_faces.at( cell_off_begin++ );
+                     for( std::size_t f = 0; f < num_faces; f++ ) {
+                        const std::size_t num_vertices = vtk_faces.at( cell_off_begin++ );
+                        for( std::size_t v = 0; v < num_vertices; v++ )
+                           faceConnectivity.push_back( vtk_faces.at( cell_off_begin++ ) );
+                        faceOffsets.push_back( faceConnectivity.size() );
+                        cellConnectivity.push_back( faceIndex++ );
+                     }
+                     cellOffsets.push_back( cellConnectivity.size() );
+
+                     if( cell_off_begin != cell_off_end )
+                        throw MeshReaderError( "VTUReader", "error while parsing the faces data array: did not reach the end offset for cell " + std::to_string(cell) );
+                  }
+
+                  this->NumberOfFaces = faceIndex;
+                  this->cellOffsetsArray = std::move( cellOffsets );
+                  this->cellConnectivityArray = std::move( cellConnectivity );
+                  this->faceOffsetsArray = std::move( faceOffsets );
+                  this->faceConnectivityArray = std::move( faceConnectivity );
+               },
+               vtk_facesArray
+            );
+      }
    }
 #endif
 
diff --git a/src/TNL/Meshes/Topologies/Hexahedron.h b/src/TNL/Meshes/Topologies/Hexahedron.h
index d1f9f9ee797419ff17203adc73e1de432a65e029..30292bcfc0400133be5b02c15ca5b3b438c3509c 100644
--- a/src/TNL/Meshes/Topologies/Hexahedron.h
+++ b/src/TNL/Meshes/Topologies/Hexahedron.h
@@ -108,72 +108,72 @@ struct Subtopology< Hexahedron, 2 >
  *
  */
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  0, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  0, 1> { static constexpr int index = 1; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  1, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  1, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  1, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  1, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  2, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  2, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  2, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  2, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  3, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  3, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  3, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  3, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  4, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  4, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  4, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  4, 1> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  5, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  5, 1> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  5, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  5, 1> { static constexpr int index = 5; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  6, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  6, 1> { enum { index = 6 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  6, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  6, 1> { static constexpr int index = 6; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  7, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  7, 1> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  7, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  7, 1> { static constexpr int index = 7; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  8, 0> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  8, 1> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  8, 0> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  8, 1> { static constexpr int index = 5; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge,  9, 0> { enum { index = 5 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge,  9, 1> { enum { index = 6 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  9, 0> { static constexpr int index = 5; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  9, 1> { static constexpr int index = 6; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 0> { enum { index = 6 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 1> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 0> { static constexpr int index = 6; };
+template<> struct SubentityVertexMap< Hexahedron, Edge, 10, 1> { static constexpr int index = 7; };
 
-template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 0> { enum { index = 7 }; };
-template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 0> { static constexpr int index = 7; };
+template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 1> { static constexpr int index = 4; };
 
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 2> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 3> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 2> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 0, 3> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 2> { enum { index = 5 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 3> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 2> { static constexpr int index = 5; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 1, 3> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 1> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 2> { enum { index = 6 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 3> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 1> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 2> { static constexpr int index = 6; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 2, 3> { static constexpr int index = 5; };
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 1> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 2> { enum { index = 7 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 3> { enum { index = 6 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 1> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 2> { static constexpr int index = 7; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 3, 3> { static constexpr int index = 6; };
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 1> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 2> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 3> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 1> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 2> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 4, 3> { static constexpr int index = 7; };
 
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 0> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 1> { enum { index = 5 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 2> { enum { index = 6 }; };
-template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 3> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 0> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 1> { static constexpr int index = 5; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 2> { static constexpr int index = 6; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrangle, 5, 3> { static constexpr int index = 7; };
 
 } // namespace Topologies
 } // namespace Meshes
diff --git a/src/TNL/Meshes/Topologies/IsDynamicTopology.h b/src/TNL/Meshes/Topologies/IsDynamicTopology.h
index 0cb52358a589c963c70f931ae57f69d06db6f8dc..47110449ac1c1ab1b8e34aa7f6dbdce0a1571c62 100644
--- a/src/TNL/Meshes/Topologies/IsDynamicTopology.h
+++ b/src/TNL/Meshes/Topologies/IsDynamicTopology.h
@@ -14,8 +14,8 @@ namespace Topologies {
 template< typename Topology, int D = Topology::dimension >
 struct IsDynamicTopology
 {
-   enum : bool { value = !HasCountMember< Subtopology< Topology, D - 1 > >::value ||
-                         IsDynamicTopology< Topology, D - 1 >::value };
+   static constexpr bool value = ! HasCountMember< Subtopology< Topology, D - 1 > >::value ||
+                                   IsDynamicTopology< Topology, D - 1 >::value;
 };
 
 /**
@@ -31,9 +31,9 @@ struct IsDynamicTopology< Vertex, 0 > : std::false_type
 template< typename Topology >
 struct IsDynamicTopology< Topology, 1 >
 {
-   enum : bool { value = !HasCountMember< Subtopology< Topology, 0 > >::value };
+   static constexpr bool value = ! HasCountMember< Subtopology< Topology, 0 > >::value;
 };
 
 } // namespace Topologies
 } // namespace Meshes
-} // namespace TNL
\ No newline at end of file
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Pyramid.h b/src/TNL/Meshes/Topologies/Pyramid.h
index 83edec19494f6d66d7be7cddb54faaa61ad05b42..38db2ee7b5b415d72f1ef36321646fe97fc71bd3 100644
--- a/src/TNL/Meshes/Topologies/Pyramid.h
+++ b/src/TNL/Meshes/Topologies/Pyramid.h
@@ -38,29 +38,29 @@ struct Subtopology< Pyramid, 2 >
 };
 
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 0, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 0, 1> { static constexpr int index = 1; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 1, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 1, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 1, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 1, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 2, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 2, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 2, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 2, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 3, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 3, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 3, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 3, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 4, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 4, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 4, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 4, 1> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 5, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 5, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 5, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 5, 1> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 6, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 6, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 6, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 6, 1> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Pyramid, Edge, 7, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Pyramid, Edge, 7, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 7, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Pyramid, Edge, 7, 1> { static constexpr int index = 4; };
 
 template <>
 struct SubentityVertexCount< Pyramid, Polygon, 0 >
@@ -68,10 +68,10 @@ struct SubentityVertexCount< Pyramid, Polygon, 0 >
    static constexpr int count = 4;
 };
 
-template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 2> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 3> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 2> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 0, 3> { static constexpr int index = 3; };
 
 template <>
 struct SubentityVertexCount< Pyramid, Polygon, 1 >
@@ -79,9 +79,9 @@ struct SubentityVertexCount< Pyramid, Polygon, 1 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 2> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 1, 2> { static constexpr int index = 4; };
 
 template <>
 struct SubentityVertexCount< Pyramid, Polygon, 2 >
@@ -89,9 +89,9 @@ struct SubentityVertexCount< Pyramid, Polygon, 2 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 1> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 2> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 1> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 2, 2> { static constexpr int index = 4; };
 
 template <>
 struct SubentityVertexCount< Pyramid, Polygon, 3 >
@@ -99,9 +99,9 @@ struct SubentityVertexCount< Pyramid, Polygon, 3 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 1> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 2> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 1> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 3, 2> { static constexpr int index = 4; };
 
 template <>
 struct SubentityVertexCount< Pyramid, Polygon, 4 >
@@ -109,10 +109,10 @@ struct SubentityVertexCount< Pyramid, Polygon, 4 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 1> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 2> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 1> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Pyramid, Polygon, 4, 2> { static constexpr int index = 4; };
 
 } // namespace Topologies
 } // namespace Meshes
-} // namespace TNL
\ No newline at end of file
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Quadrangle.h b/src/TNL/Meshes/Topologies/Quadrangle.h
index bc4885a8be583f51905f0ffc80360cfb58631bf7..aa881aadc7b875364a434204afeb02000c2651ac 100644
--- a/src/TNL/Meshes/Topologies/Quadrangle.h
+++ b/src/TNL/Meshes/Topologies/Quadrangle.h
@@ -72,17 +72,17 @@ struct Subtopology< Quadrangle, 1 >
  *
  */
 
-template<> struct SubentityVertexMap< Quadrangle, Edge, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Quadrangle, Edge, 0, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 0, 1> { static constexpr int index = 1; };
 
-template<> struct SubentityVertexMap< Quadrangle, Edge, 1, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Quadrangle, Edge, 1, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 1, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 1, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Quadrangle, Edge, 2, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Quadrangle, Edge, 2, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 2, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 2, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Quadrangle, Edge, 3, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Quadrangle, Edge, 3, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 3, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Quadrangle, Edge, 3, 1> { static constexpr int index = 0; };
 
 } // namespace Topologies
 } // namespace Meshes
diff --git a/src/TNL/Meshes/Topologies/Tetrahedron.h b/src/TNL/Meshes/Topologies/Tetrahedron.h
index 048daa1c3c3fe7cc112489e2d40411c4f4ad47b2..ed6e852f3288edad6064e3cfc935ef54ff672ddc 100644
--- a/src/TNL/Meshes/Topologies/Tetrahedron.h
+++ b/src/TNL/Meshes/Topologies/Tetrahedron.h
@@ -52,41 +52,41 @@ struct Subtopology< Tetrahedron, 2 >
 };
 
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 0, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 2, 1> { static constexpr int index = 1; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 4, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 1> { static constexpr int index = 3; };
 
 
 // i-th subvertex is the opposite vertex of i-th subface
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 1> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 2> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 1> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 0, 2> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 1> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 2> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 1> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 1, 2> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 2> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 2, 2> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 2> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Tetrahedron, Triangle, 3, 2> { static constexpr int index = 2; };
 
 } // namespace Topologies
 } // namespace Meshes
diff --git a/src/TNL/Meshes/Topologies/Triangle.h b/src/TNL/Meshes/Topologies/Triangle.h
index efe031059d1fa5e7705dc131d69de4a862743ed7..8494a6f4fdd9a6b505074380b93fdcb1d1004f00 100644
--- a/src/TNL/Meshes/Topologies/Triangle.h
+++ b/src/TNL/Meshes/Topologies/Triangle.h
@@ -45,14 +45,14 @@ struct Subtopology< Triangle, 1 >
 };
 
 
-template<> struct SubentityVertexMap< Triangle, Edge, 0, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Triangle, Edge, 0, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Triangle, Edge, 0, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Triangle, Edge, 0, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Triangle, Edge, 1, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Triangle, Edge, 1, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Triangle, Edge, 1, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Triangle, Edge, 1, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Triangle, Edge, 2, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Triangle, Edge, 2, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Triangle, Edge, 2, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Triangle, Edge, 2, 1> { static constexpr int index = 1; };
 
 } // namespace Topologies
 } // namespace Meshes
diff --git a/src/TNL/Meshes/Topologies/Vertex.h b/src/TNL/Meshes/Topologies/Vertex.h
index f90127624806c4acbfb8e0ee2aa01b5988f0c3f4..40d0e04d119f28d0883c3feeb1b9bbed1874809f 100644
--- a/src/TNL/Meshes/Topologies/Vertex.h
+++ b/src/TNL/Meshes/Topologies/Vertex.h
@@ -16,8 +16,6 @@
 
 #pragma once
 
-#include <TNL/String.h>
-
 namespace TNL {
 namespace Meshes {
 namespace Topologies {
diff --git a/src/TNL/Meshes/Topologies/Wedge.h b/src/TNL/Meshes/Topologies/Wedge.h
index 2cd3321944dd59fcf20a3230adb5ab1c9c7e3899..4aed46b0653450d2e970e5a5b590abd66530b146 100644
--- a/src/TNL/Meshes/Topologies/Wedge.h
+++ b/src/TNL/Meshes/Topologies/Wedge.h
@@ -37,32 +37,32 @@ struct Subtopology< Wedge, 2 >
    static constexpr int count = 5;
 };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 0, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Wedge, Edge, 0, 1> { static constexpr int index = 1; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 1, 0> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 1, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 1, 0> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Wedge, Edge, 1, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 2, 0> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 2, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 2, 0> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Wedge, Edge, 2, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 3, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 3, 1> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 3, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Wedge, Edge, 3, 1> { static constexpr int index = 4; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 4, 0> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 4, 1> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 4, 0> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Wedge, Edge, 4, 1> { static constexpr int index = 5; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 5, 0> { enum { index = 5 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 5, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 5, 0> { static constexpr int index = 5; };
+template<> struct SubentityVertexMap< Wedge, Edge, 5, 1> { static constexpr int index = 3; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 6, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 6, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 6, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Wedge, Edge, 6, 1> { static constexpr int index = 0; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 7, 0> { enum { index = 5 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 7, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 7, 0> { static constexpr int index = 5; };
+template<> struct SubentityVertexMap< Wedge, Edge, 7, 1> { static constexpr int index = 2; };
 
-template<> struct SubentityVertexMap< Wedge, Edge, 8, 0> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Wedge, Edge, 8, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Wedge, Edge, 8, 0> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Wedge, Edge, 8, 1> { static constexpr int index = 1; };
 
 
 template <>
@@ -71,9 +71,9 @@ struct SubentityVertexCount< Wedge, Polygon, 0 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Wedge, Polygon, 0, 0> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 0, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 0, 2> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 0, 0> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 0, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 0, 2> { static constexpr int index = 2; };
 
 template <>
 struct SubentityVertexCount< Wedge, Polygon, 1 >
@@ -81,9 +81,9 @@ struct SubentityVertexCount< Wedge, Polygon, 1 >
    static constexpr int count = 3;
 };
 
-template<> struct SubentityVertexMap< Wedge, Polygon, 1, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 1, 1> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 1, 2> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 1, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 1, 1> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 1, 2> { static constexpr int index = 5; };
 
 template <>
 struct SubentityVertexCount< Wedge, Polygon, 2 >
@@ -91,10 +91,10 @@ struct SubentityVertexCount< Wedge, Polygon, 2 >
    static constexpr int count = 4;
 };
 
-template<> struct SubentityVertexMap< Wedge, Polygon, 2, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 2, 1> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 2, 2> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 2, 3> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 2, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 2, 1> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 2, 2> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 2, 3> { static constexpr int index = 5; };
 
 template <>
 struct SubentityVertexCount< Wedge, Polygon, 3 >
@@ -102,10 +102,10 @@ struct SubentityVertexCount< Wedge, Polygon, 3 >
    static constexpr int count = 4;
 };
 
-template<> struct SubentityVertexMap< Wedge, Polygon, 3, 0> { enum { index = 4 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 3, 1> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 3, 2> { enum { index = 2 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 3, 3> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 3, 0> { static constexpr int index = 4; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 3, 1> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 3, 2> { static constexpr int index = 2; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 3, 3> { static constexpr int index = 5; };
 
 template <>
 struct SubentityVertexCount< Wedge, Polygon, 4 >
@@ -113,11 +113,11 @@ struct SubentityVertexCount< Wedge, Polygon, 4 >
    static constexpr int count = 4;
 };
 
-template<> struct SubentityVertexMap< Wedge, Polygon, 4, 0> { enum { index = 3 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 4, 1> { enum { index = 0 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 4, 2> { enum { index = 1 }; };
-template<> struct SubentityVertexMap< Wedge, Polygon, 4, 3> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 4, 0> { static constexpr int index = 3; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 4, 1> { static constexpr int index = 0; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 4, 2> { static constexpr int index = 1; };
+template<> struct SubentityVertexMap< Wedge, Polygon, 4, 3> { static constexpr int index = 4; };
 
 } // namespace Topologies
 } // namespace Meshes
-} // namespace TNL
\ No newline at end of file
+} // namespace TNL
diff --git a/src/TNL/Meshes/TypeResolver/BuildConfigTags.h b/src/TNL/Meshes/TypeResolver/BuildConfigTags.h
index 413e7538ada983726c23d002813e2431cff93988..c0b5c0fd5cb6e12e4ebd5ce80ceab55d3376ca4f 100644
--- a/src/TNL/Meshes/TypeResolver/BuildConfigTags.h
+++ b/src/TNL/Meshes/TypeResolver/BuildConfigTags.h
@@ -35,81 +35,80 @@ namespace BuildConfigTags {
 // Configuration for structured grids
 
 // 1, 2, and 3 dimensions are enabled by default
-template< typename ConfigTag, int Dimension > struct GridDimensionTag { enum { enabled = ( Dimension > 0 && Dimension <= 3 ) }; };
+template< typename ConfigTag, int Dimension > struct GridDimensionTag { static constexpr bool enabled = Dimension > 0 && Dimension <= 3; };
 
 // Grids are enabled only for the `float` and `double` real types by default.
-template< typename ConfigTag, typename Real > struct GridRealTag { enum { enabled = false }; };
-template< typename ConfigTag > struct GridRealTag< ConfigTag, float > { enum { enabled = true }; };
-template< typename ConfigTag > struct GridRealTag< ConfigTag, double > { enum { enabled = true }; };
+template< typename ConfigTag, typename Real > struct GridRealTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct GridRealTag< ConfigTag, float > { static constexpr bool enabled = true; };
+template< typename ConfigTag > struct GridRealTag< ConfigTag, double > { static constexpr bool enabled = true; };
 
 // Grids are enabled on all available devices by default.
-template< typename ConfigTag, typename Device > struct GridDeviceTag { enum { enabled = true }; };
+template< typename ConfigTag, typename Device > struct GridDeviceTag { static constexpr bool enabled = true; };
 #ifndef HAVE_CUDA
-template< typename ConfigTag > struct GridDeviceTag< ConfigTag, Devices::Cuda > { enum { enabled = false }; };
+template< typename ConfigTag > struct GridDeviceTag< ConfigTag, Devices::Cuda > { static constexpr bool enabled = false; };
 #endif
 
 // Grids are enabled only for the `int` and `long int` index types by default.
-template< typename ConfigTag, typename Index > struct GridIndexTag { enum { enabled = false }; };
-template< typename ConfigTag > struct GridIndexTag< ConfigTag, int > { enum { enabled = true }; };
-template< typename ConfigTag > struct GridIndexTag< ConfigTag, long int > { enum { enabled = true }; };
+template< typename ConfigTag, typename Index > struct GridIndexTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct GridIndexTag< ConfigTag, int > { static constexpr bool enabled = true; };
+template< typename ConfigTag > struct GridIndexTag< ConfigTag, long int > { static constexpr bool enabled = true; };
 
 // The Grid is enabled for allowed dimensions and Real, Device and Index types.
 //
 // By specializing this tag you can enable or disable custom combinations of
 // the grid template parameters. The default configuration is identical to the
 // individual per-type tags.
-template< typename ConfigTag, typename MeshType > struct GridTag { enum { enabled = false }; };
+template< typename ConfigTag, typename MeshType > struct GridTag { static constexpr bool enabled = false; };
 
 template< typename ConfigTag, int Dimension, typename Real, typename Device, typename Index >
 struct GridTag< ConfigTag, Grid< Dimension, Real, Device, Index > >
 {
-   enum { enabled = GridDimensionTag< ConfigTag, Dimension >::enabled  &&
+   static constexpr bool enabled = GridDimensionTag< ConfigTag, Dimension >::enabled  &&
                     GridRealTag< ConfigTag, Real >::enabled &&
                     GridDeviceTag< ConfigTag, Device >::enabled &&
-                    GridIndexTag< ConfigTag, Index >::enabled
-   };
+                    GridIndexTag< ConfigTag, Index >::enabled;
 };
 
 
 // Configuration for unstructured meshes
 
 // Meshes are enabled on all available devices by default.
-template< typename ConfigTag, typename Device > struct MeshDeviceTag { enum { enabled = false }; };
-template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Host > { enum { enabled = true }; };
+template< typename ConfigTag, typename Device > struct MeshDeviceTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Host > { static constexpr bool enabled = true; };
 #ifdef HAVE_CUDA
-template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Cuda > { enum { enabled = true }; };
+template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Cuda > { static constexpr bool enabled = true; };
 #endif
 
 // All available cell topologies are disabled by default.
-template< typename ConfigTag, typename CellTopology > struct MeshCellTopologyTag { enum { enabled = false }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Edge > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Quadrangle > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Polygon > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Wedge > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Pyramid > { enum { enabled = true }; };
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Polyhedron > { enum { enabled = true }; };
+template< typename ConfigTag, typename CellTopology > struct MeshCellTopologyTag { static constexpr bool enabled = false; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Wedge > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Pyramid > { static constexpr bool enabled = true; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 // TODO: Simplex has not been tested yet
-//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Simplex > { enum { enabled = true }; };
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Simplex > { static constexpr bool enabled = true; };
 
 // All sensible space dimensions are enabled by default.
-template< typename ConfigTag, typename CellTopology, int SpaceDimension > struct MeshSpaceDimensionTag { enum { enabled = ( SpaceDimension >= CellTopology::dimension && SpaceDimension <= 3 ) }; };
+template< typename ConfigTag, typename CellTopology, int SpaceDimension > struct MeshSpaceDimensionTag { static constexpr bool enabled = SpaceDimension >= CellTopology::dimension && SpaceDimension <= 3; };
 
 // Meshes are enabled only for the `float` and `double` real types by default.
-template< typename ConfigTag, typename Real > struct MeshRealTag { enum { enabled = false }; };
-template< typename ConfigTag > struct MeshRealTag< ConfigTag, float > { enum { enabled = true }; };
-template< typename ConfigTag > struct MeshRealTag< ConfigTag, double > { enum { enabled = true }; };
+template< typename ConfigTag, typename Real > struct MeshRealTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct MeshRealTag< ConfigTag, float > { static constexpr bool enabled = true; };
+template< typename ConfigTag > struct MeshRealTag< ConfigTag, double > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the `int` and `long int` global index types by default.
-template< typename ConfigTag, typename GlobalIndex > struct MeshGlobalIndexTag { enum { enabled = false }; };
-template< typename ConfigTag > struct MeshGlobalIndexTag< ConfigTag, int > { enum { enabled = true }; };
-template< typename ConfigTag > struct MeshGlobalIndexTag< ConfigTag, long int > { enum { enabled = true }; };
+template< typename ConfigTag, typename GlobalIndex > struct MeshGlobalIndexTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct MeshGlobalIndexTag< ConfigTag, int > { static constexpr bool enabled = true; };
+template< typename ConfigTag > struct MeshGlobalIndexTag< ConfigTag, long int > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the `short int` local index type by default.
-template< typename ConfigTag, typename LocalIndex > struct MeshLocalIndexTag { enum { enabled = false }; };
-template< typename ConfigTag > struct MeshLocalIndexTag< ConfigTag, short int > { enum { enabled = true }; };
+template< typename ConfigTag, typename LocalIndex > struct MeshLocalIndexTag { static constexpr bool enabled = false; };
+template< typename ConfigTag > struct MeshLocalIndexTag< ConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig to use.
 template< typename ConfigTag >
@@ -138,14 +137,13 @@ struct MeshConfigTemplateTag
 template< typename ConfigTag, typename Device, typename CellTopology, int SpaceDimension, typename Real, typename GlobalIndex, typename LocalIndex >
 struct MeshTag
 {
-   enum { enabled =
+   static constexpr bool enabled =
             MeshDeviceTag< ConfigTag, Device >::enabled &&
             MeshCellTopologyTag< ConfigTag, CellTopology >::enabled &&
             MeshSpaceDimensionTag< ConfigTag, CellTopology, SpaceDimension >::enabled &&
             MeshRealTag< ConfigTag, Real >::enabled &&
             MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled &&
-            MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled
-   };
+            MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled;
 };
 
 } // namespace BuildConfigTags
diff --git a/src/TNL/Meshes/TypeResolver/GridTypeResolver.hpp b/src/TNL/Meshes/TypeResolver/GridTypeResolver.hpp
index 0c284ca21757eeccd1efa605bf7df47173bab6b3..ef264339ef0720b2a5c1373b9a1fae90c00a2704 100644
--- a/src/TNL/Meshes/TypeResolver/GridTypeResolver.hpp
+++ b/src/TNL/Meshes/TypeResolver/GridTypeResolver.hpp
@@ -12,7 +12,6 @@
 
 #include <utility>
 
-#include <TNL/String.h>
 #include <TNL/Meshes/Grid.h>
 #include <TNL/Meshes/TypeResolver/GridTypeResolver.h>
 
diff --git a/src/TNL/Meshes/TypeResolver/MeshTypeResolver.hpp b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.hpp
index f6c991f41dde3692e0285262a38cd161a39dc678..fdaca73ec4fbf93008c62ea5bdea356d34db6a33 100644
--- a/src/TNL/Meshes/TypeResolver/MeshTypeResolver.hpp
+++ b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.hpp
@@ -12,7 +12,6 @@
 
 #include <utility>
 
-#include <TNL/String.h>
 #include <TNL/Meshes/Grid.h>
 #include <TNL/Meshes/TypeResolver/MeshTypeResolver.h>
 #include <TNL/Meshes/VTKTraits.h>
diff --git a/src/TNL/Meshes/TypeResolver/resolveMeshType.h b/src/TNL/Meshes/TypeResolver/resolveMeshType.h
index 2e8df25d8b5ba03c047dbc2f4e3e9e2f31e82d07..712c12c2dac7a6df5bfa58ab13482e4eb56a9e1c 100644
--- a/src/TNL/Meshes/TypeResolver/resolveMeshType.h
+++ b/src/TNL/Meshes/TypeResolver/resolveMeshType.h
@@ -40,7 +40,9 @@ template< typename ConfigTag,
 bool
 resolveMeshType( Functor&& functor,
                  const std::string& fileName,
-                 const std::string& fileFormat = "auto" );
+                 const std::string& fileFormat = "auto",
+                 const std::string& realType = "auto",
+                 const std::string& globalIndexType = "auto" );
 
 /**
  * This function dues the same as \ref resolveMeshType, but also reuses the mesh
@@ -63,7 +65,9 @@ template< typename ConfigTag,
 bool
 resolveAndLoadMesh( Functor&& functor,
                     const std::string& fileName,
-                    const std::string& fileFormat = "auto" );
+                    const std::string& fileFormat = "auto",
+                    const std::string& realType = "auto",
+                    const std::string& globalIndexType = "auto" );
 
 /**
  * This function takes a file name and a mesh instance and attempts to load the
diff --git a/src/TNL/Meshes/TypeResolver/resolveMeshType.hpp b/src/TNL/Meshes/TypeResolver/resolveMeshType.hpp
index 0f457a75d8422e0d1fc7d8f10000db49713e9ab0..c53f471683304cb9b9f0fd20d5e49dd823d90227 100644
--- a/src/TNL/Meshes/TypeResolver/resolveMeshType.hpp
+++ b/src/TNL/Meshes/TypeResolver/resolveMeshType.hpp
@@ -26,7 +26,9 @@ template< typename ConfigTag,
 bool
 resolveMeshType( Functor&& functor,
                  const std::string& fileName,
-                 const std::string& fileFormat )
+                 const std::string& fileFormat,
+                 const std::string& realType,
+                 const std::string& globalIndexType )
 {
    std::cout << "Detecting mesh from file " << fileName << " ..." << std::endl;
 
@@ -36,6 +38,11 @@ resolveMeshType( Functor&& functor,
 
    reader->detectMesh();
 
+   if( realType != "auto" )
+      reader->forceRealType( realType );
+   if( globalIndexType != "auto" )
+      reader->forceGlobalIndexType( globalIndexType );
+
    if( reader->getMeshType() == "Meshes::Grid" || reader->getMeshType() == "Meshes::DistributedGrid" )
       return GridTypeResolver< ConfigTag, Device >::run( *reader, functor );
    else if( reader->getMeshType() == "Meshes::Mesh" || reader->getMeshType() == "Meshes::DistributedMesh" )
@@ -52,7 +59,9 @@ template< typename ConfigTag,
 bool
 resolveAndLoadMesh( Functor&& functor,
                     const std::string& fileName,
-                    const std::string& fileFormat )
+                    const std::string& fileFormat,
+                    const std::string& realType,
+                    const std::string& globalIndexType )
 {
    auto wrapper = [&]( auto& reader, auto&& mesh ) -> bool
    {
@@ -67,7 +76,7 @@ resolveAndLoadMesh( Functor&& functor,
       }
       return functor( reader, std::forward<MeshType>(mesh) );
    };
-   return resolveMeshType< ConfigTag, Device >( wrapper, fileName, fileFormat );
+   return resolveMeshType< ConfigTag, Device >( wrapper, fileName, fileFormat, realType, globalIndexType );
 }
 
 template< typename Mesh >
diff --git a/src/TNL/Meshes/VTKTraits.h b/src/TNL/Meshes/VTKTraits.h
index 9f9de20ba1fd01defa0f5fc702f7d1b59433de37..65ecf7f1fde9663b5a98dc3be6ad6c530267c040 100644
--- a/src/TNL/Meshes/VTKTraits.h
+++ b/src/TNL/Meshes/VTKTraits.h
@@ -63,7 +63,9 @@ enum class EntityShape
    Hexahedron = 12,
    Wedge = 13,
    Pyramid = 14,
-   Polyhedron = 100
+   PentagonalPrism = 15,
+   HexagonalPrism = 16,
+   Polyhedron = 42
 };
 
 inline std::string getShapeName( EntityShape shape )
@@ -98,6 +100,10 @@ inline std::string getShapeName( EntityShape shape )
          return "Wedge";
       case EntityShape::Pyramid:
          return "Pyramid";
+      case EntityShape::PentagonalPrism:
+         return "PentagonalPrism";
+      case EntityShape::HexagonalPrism:
+         return "HexagonalPrism";
       case EntityShape::Polyhedron:
          return "Polyhedron";
    }
@@ -122,6 +128,8 @@ inline int getEntityDimension( EntityShape shape )
       case EntityShape::Hexahedron:     return 3;
       case EntityShape::Wedge:          return 3;
       case EntityShape::Pyramid:        return 3;
+      case EntityShape::PentagonalPrism:return 3;
+      case EntityShape::HexagonalPrism: return 3;
       case EntityShape::Polyhedron:     return 3;
    }
    // this can actually happen when an invalid uint8_t value is converted to EntityShape
diff --git a/src/TNL/Meshes/Writers/EntitiesListSize.h b/src/TNL/Meshes/Writers/EntitiesListSize.h
deleted file mode 100644
index 15e13d9d9f88c2764ba28a7e32bf46c3e4a752a3..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Writers/EntitiesListSize.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <TNL/Meshes/Writers/VerticesPerEntity.h>
-
-namespace TNL {
-namespace Meshes {
-namespace Writers {
-
-template< typename Mesh,
-          int EntityDimension,
-          typename EntityType = typename Mesh::template EntityType< EntityDimension > 
-        >
-struct EntitiesListSize
-{
-   using IndexType = typename Mesh::GlobalIndexType;
-
-   static IndexType getSize( const Mesh& mesh )
-   {
-      IndexType entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      IndexType verticesPerEntity = VerticesPerEntity< EntityType >::count;
-      return entitiesCount * ( verticesPerEntity + 1 );
-   }
-};
-
-template< typename Mesh,
-          int EntityDimension,
-          typename MeshConfig, 
-          typename Device >
-struct EntitiesListSize< Mesh, EntityDimension, MeshEntity< MeshConfig, Device, Topologies::Polygon > >
-{
-   using IndexType = typename Mesh::GlobalIndexType;
-
-   static IndexType getSize( const Mesh& mesh )
-   {
-      IndexType entitiesCount = mesh.template getEntitiesCount< EntityDimension >();
-      IndexType entitiesListSize = entitiesCount;
-      for(IndexType index = 0; index < entitiesCount; index++)
-         entitiesListSize += mesh.template getSubentitiesCount< EntityDimension, 0 >( index );
-      return entitiesListSize;
-   }
-};
-
-} // namespace Writers
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/NetgenWriter.h b/src/TNL/Meshes/Writers/NetgenWriter.h
index c247c0ff48a31ef300e4c467423fc0833894649e..afa2a97a0d95eb785c7643d10d9fd455c34f67c8 100644
--- a/src/TNL/Meshes/Writers/NetgenWriter.h
+++ b/src/TNL/Meshes/Writers/NetgenWriter.h
@@ -19,8 +19,6 @@
 #include <ostream>
 #include <iomanip>
 
-#include <TNL/String.h>
-
 namespace TNL {
 namespace Meshes {
 namespace Writers {
diff --git a/src/TNL/Meshes/Writers/PVTIWriter.h b/src/TNL/Meshes/Writers/PVTIWriter.h
index 4f391b142e972267eb67bad9415121c7e44c0e17..c37d40a5861b8e9f6f879d6af94d938c8d7fd3ba 100644
--- a/src/TNL/Meshes/Writers/PVTIWriter.h
+++ b/src/TNL/Meshes/Writers/PVTIWriter.h
@@ -57,27 +57,27 @@ public:
                        const unsigned MinCommonVertices = 0 );
 
    template< typename ValueType >
-   void writePPointData( const String& name,
+   void writePPointData( const std::string& name,
                          const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePCellData( const String& name,
+   void writePCellData( const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePDataArray( const String& name,
+   void writePDataArray( const std::string& name,
                          const int numberOfComponents = 1 );
 
    // add a single piece and return its source path
    // (useful for sequential writing, e.g. from tnl-decompose-grid)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const unsigned subdomainIndex,
                          const typename Grid::CoordinatesType& globalBegin,
                          const typename Grid::CoordinatesType& globalEnd );
 
    // add all pieces and return the source path for the current rank
    // (useful for parallel writing)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const DistributedMeshes::DistributedMesh< Grid >& distributedMesh );
 
    ~PVTIWriter();
diff --git a/src/TNL/Meshes/Writers/PVTIWriter.hpp b/src/TNL/Meshes/Writers/PVTIWriter.hpp
index fd3d9bfeb0f71a5742dd97fe9cdd2b0d87c80f0e..e28b1eed811dc34ed6e49f94e014ef5c7b078bb9 100644
--- a/src/TNL/Meshes/Writers/PVTIWriter.hpp
+++ b/src/TNL/Meshes/Writers/PVTIWriter.hpp
@@ -125,7 +125,7 @@ PVTIWriter< Grid >::writeEntities( const Grid& grid,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePPointData( const String& name,
+PVTIWriter< Grid >::writePPointData( const std::string& name,
                                      const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -137,7 +137,7 @@ PVTIWriter< Grid >::writePPointData( const String& name,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePCellData( const String& name,
+PVTIWriter< Grid >::writePCellData( const std::string& name,
                                     const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -149,7 +149,7 @@ PVTIWriter< Grid >::writePCellData( const String& name,
 template< typename Grid >
    template< typename ValueType >
 void
-PVTIWriter< Grid >::writePDataArray( const String& name,
+PVTIWriter< Grid >::writePDataArray( const std::string& name,
                                      const int numberOfComponents )
 {
    if( numberOfComponents != 0 && numberOfComponents != 1 && numberOfComponents != 3 )
@@ -162,12 +162,17 @@ PVTIWriter< Grid >::writePDataArray( const String& name,
 
 template< typename Grid >
 std::string
-PVTIWriter< Grid >::addPiece( const String& mainFileName,
+PVTIWriter< Grid >::addPiece( const std::string& mainFileName,
                               const unsigned subdomainIndex,
                               const typename Grid::CoordinatesType& globalBegin,
                               const typename Grid::CoordinatesType& globalEnd )
 {
-   if( ! mainFileName.endsWith( ".pvti" ) )
+   namespace fs = std::experimental::filesystem;
+
+   // get the basename of the main file (filename without extension)
+   const fs::path mainPath = mainFileName;
+   const fs::path basename = mainPath.stem();
+   if( mainPath.extension() != ".pvti" )
       throw std::logic_error("The mainFileName parameter must be the name of the "
                              ".pvti file (i.e., it must have the .pvti suffix).");
 
@@ -183,12 +188,6 @@ PVTIWriter< Grid >::addPiece( const String& mainFileName,
    for( int j = Grid::getMeshDimension(); j < 3; j++ )
       extent << "0 0 ";
 
-   namespace fs = std::experimental::filesystem;
-
-   // get the basename of the main file (filename without extension)
-   const fs::path mainPath = mainFileName.getString();
-   const fs::path basename = mainPath.stem();
-
    // create subdirectory for subdomains
    const fs::path subdirectory = mainPath.parent_path() / basename;
    fs::create_directory( subdirectory );
@@ -204,7 +203,7 @@ PVTIWriter< Grid >::addPiece( const String& mainFileName,
 
 template< typename Grid >
 std::string
-PVTIWriter< Grid >::addPiece( const String& mainFileName,
+PVTIWriter< Grid >::addPiece( const std::string& mainFileName,
                               const DistributedMeshes::DistributedMesh< Grid >& distributedMesh )
 {
    const MPI_Comm communicator = distributedMesh.getCommunicator();
diff --git a/src/TNL/Meshes/Writers/PVTUWriter.h b/src/TNL/Meshes/Writers/PVTUWriter.h
index 6d76781ff7ae68b33c05111186ae1276799b09ae..d53b5aa82ef7a4128336450c8ff4996aa2f180f7 100644
--- a/src/TNL/Meshes/Writers/PVTUWriter.h
+++ b/src/TNL/Meshes/Writers/PVTUWriter.h
@@ -45,25 +45,25 @@ public:
                        const unsigned MinCommonVertices = 0 );
 
    template< typename ValueType >
-   void writePPointData( const String& name,
+   void writePPointData( const std::string& name,
                          const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePCellData( const String& name,
+   void writePCellData( const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename ValueType >
-   void writePDataArray( const String& name,
+   void writePDataArray( const std::string& name,
                          const int numberOfComponents = 1 );
 
    // add a single piece and return its source path
    // (useful for sequential writing, e.g. from tnl-decompose-mesh)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const unsigned subdomainIndex );
 
    // add all pieces and return the source path for the current rank
    // (useful for parallel writing)
-   std::string addPiece( const String& mainFileName,
+   std::string addPiece( const std::string& mainFileName,
                          const MPI_Comm communicator );
 
    ~PVTUWriter();
diff --git a/src/TNL/Meshes/Writers/PVTUWriter.hpp b/src/TNL/Meshes/Writers/PVTUWriter.hpp
index 03b1e9aee795f5d6dd792ff800ad2ed1084dffbb..004cccd96751f746d3b1a1e3de8fab265185891a 100644
--- a/src/TNL/Meshes/Writers/PVTUWriter.hpp
+++ b/src/TNL/Meshes/Writers/PVTUWriter.hpp
@@ -69,7 +69,7 @@ PVTUWriter< Mesh >::writeEntities( const Mesh& mesh,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePPointData( const String& name,
+PVTUWriter< Mesh >::writePPointData( const std::string& name,
                                      const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -81,7 +81,7 @@ PVTUWriter< Mesh >::writePPointData( const String& name,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePCellData( const String& name,
+PVTUWriter< Mesh >::writePCellData( const std::string& name,
                                     const int numberOfComponents )
 {
    if( ! vtkfileOpen )
@@ -93,7 +93,7 @@ PVTUWriter< Mesh >::writePCellData( const String& name,
 template< typename Mesh >
    template< typename ValueType >
 void
-PVTUWriter< Mesh >::writePDataArray( const String& name,
+PVTUWriter< Mesh >::writePDataArray( const std::string& name,
                                      const int numberOfComponents )
 {
    if( numberOfComponents != 0 && numberOfComponents != 1 && numberOfComponents != 3 )
@@ -106,10 +106,15 @@ PVTUWriter< Mesh >::writePDataArray( const String& name,
 
 template< typename Mesh >
 std::string
-PVTUWriter< Mesh >::addPiece( const String& mainFileName,
+PVTUWriter< Mesh >::addPiece( const std::string& mainFileName,
                               const unsigned subdomainIndex )
 {
-   if( ! mainFileName.endsWith( ".pvtu" ) )
+   namespace fs = std::experimental::filesystem;
+
+   // get the basename of the main file (filename without extension)
+   const fs::path mainPath = mainFileName;
+   const fs::path basename = mainPath.stem();
+   if( mainPath.extension() != ".pvtu" )
       throw std::logic_error("The mainFileName parameter must be the name of the "
                              ".pvtu file (i.e., it must have the .pvtu suffix).");
 
@@ -117,12 +122,6 @@ PVTUWriter< Mesh >::addPiece( const String& mainFileName,
    closePCellData();
    closePPointData();
 
-   namespace fs = std::experimental::filesystem;
-
-   // get the basename of the main file (filename without extension)
-   const fs::path mainPath = mainFileName.getString();
-   const fs::path basename = mainPath.stem();
-
    // create subdirectory for subdomains
    const fs::path subdirectory = mainPath.parent_path() / basename;
    fs::create_directory( subdirectory );
@@ -138,7 +137,7 @@ PVTUWriter< Mesh >::addPiece( const String& mainFileName,
 
 template< typename Mesh >
 std::string
-PVTUWriter< Mesh >::addPiece( const String& mainFileName,
+PVTUWriter< Mesh >::addPiece( const std::string& mainFileName,
                               const MPI_Comm communicator )
 {
    std::string source;
diff --git a/src/TNL/Meshes/Writers/VTIWriter.h b/src/TNL/Meshes/Writers/VTIWriter.h
index 8772205718c859a031a16c5f73c1d88020a49888..367fc96520824abc8d18d23d83e8beed695f4be0 100644
--- a/src/TNL/Meshes/Writers/VTIWriter.h
+++ b/src/TNL/Meshes/Writers/VTIWriter.h
@@ -12,6 +12,8 @@
 
 #pragma once
 
+#include <ostream>
+#include <sstream>
 #include <type_traits>
 
 #include <TNL/Meshes/VTKTraits.h>
@@ -54,17 +56,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    ~VTIWriter();
diff --git a/src/TNL/Meshes/Writers/VTIWriter.hpp b/src/TNL/Meshes/Writers/VTIWriter.hpp
index 0744850d3e1a0760410a1dfad3394ba5cc37cbd2..9ea4684689eae86f01041349786e2e471c17b1b3 100644
--- a/src/TNL/Meshes/Writers/VTIWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTIWriter.hpp
@@ -121,7 +121,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -137,7 +137,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -153,7 +153,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTIWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible
diff --git a/src/TNL/Meshes/Writers/VTKWriter.h b/src/TNL/Meshes/Writers/VTKWriter.h
index fbff5c6428c46eadce16cecce8901f1a7f003657..947b438111b1e1b15e84365d066099dc72737297 100644
--- a/src/TNL/Meshes/Writers/VTKWriter.h
+++ b/src/TNL/Meshes/Writers/VTKWriter.h
@@ -10,6 +10,8 @@
 
 #pragma once
 
+#include <ostream>
+
 #include <TNL/Meshes/VTKTraits.h>
 
 namespace TNL {
@@ -17,13 +19,6 @@ namespace Meshes {
 //! \brief Namespace for mesh writers.
 namespace Writers {
 
-namespace details {
-
-template< typename Mesh, int EntityDimension > struct MeshEntitiesVTKWriter;
-template< typename Mesh, int EntityDimension > struct MeshEntityTypesVTKWriter;
-
-} // namespace details
-
 template< typename Mesh >
 class VTKWriter
 {
@@ -31,12 +26,6 @@ class VTKWriter
    // TODO: check also space dimension when grids allow it
 //   static_assert( Mesh::getSpaceDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." );
 
-   template< int EntityDimension >
-   using EntitiesWriter = details::MeshEntitiesVTKWriter< Mesh, EntityDimension >;
-
-   template< int EntityDimension >
-   using EntityTypesWriter = details::MeshEntityTypesVTKWriter< Mesh, EntityDimension >;
-
 public:
 
    VTKWriter() = delete;
@@ -57,17 +46,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
 protected:
diff --git a/src/TNL/Meshes/Writers/VTKWriter.hpp b/src/TNL/Meshes/Writers/VTKWriter.hpp
index ada849aefc9b8726fcd8171e0d2de99dab328420..0861f0ca6b0b2c1ed2d60304e6229eb2dae5122e 100644
--- a/src/TNL/Meshes/Writers/VTKWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTKWriter.hpp
@@ -13,399 +13,14 @@
 #include <limits>
 
 #include <TNL/Meshes/Writers/VTKWriter.h>
-#include <TNL/Meshes/Writers/VerticesPerEntity.h>
-#include <TNL/Meshes/Writers/EntitiesListSize.h>
+#include <TNL/Meshes/Writers/detail/VTKOffsetsCountGetter.h>
+#include <TNL/Meshes/Writers/detail/VTKMeshEntitiesWriter.h>
 #include <TNL/Meshes/Grid.h>
-#include <TNL/Endianness.h>
 
 namespace TNL {
 namespace Meshes {
 namespace Writers {
 
-namespace details {
-
-// legacy VTK files do not support 64-bit integers, even in the BINARY format
-inline void
-writeInt( VTK::FileFormat format, std::ostream& str, std::int32_t value )
-{
-   if( format == VTK::FileFormat::binary ) {
-      value = forceBigEndian( value );
-      str.write( reinterpret_cast<const char*>(&value), sizeof(std::int32_t) );
-   }
-   else {
-      str << value << " ";
-   }
-}
-
-template< typename Real >
-void
-writeReal( VTK::FileFormat format, std::ostream& str, Real value )
-{
-   if( format == VTK::FileFormat::binary ) {
-      value = forceBigEndian( value );
-      str.write( reinterpret_cast<const char*>(&value), sizeof(Real) );
-   }
-   else {
-      str.precision( std::numeric_limits< Real >::digits10 );
-      str << value << " ";
-   }
-}
-
-
-// TODO: specialization for disabled entities
-// Unstructured meshes, entities
-template< typename Mesh, int EntityDimension >
-struct MeshEntitiesVTKWriter
-{
-   static void exec( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      using EntityType = typename Mesh::template EntityType< EntityDimension >;
-      using Index = typename Mesh::GlobalIndexType;
-
-      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      for( Index i = 0; i < entitiesCount; i++ ) {
-         const auto& entity = mesh.template getEntity< EntityType >( i );
-         const int verticesPerEntity = entity.template getSubentitiesCount< 0 >();
-         writeInt( format, str, verticesPerEntity );
-         for( int j = 0; j < verticesPerEntity; j++ )
-            writeInt( format, str, entity.template getSubentityIndex< 0 >( j ) );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// Unstructured meshes, vertices
-template< typename Mesh >
-struct MeshEntitiesVTKWriter< Mesh, 0 >
-{
-   static void exec( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      using EntityType = typename Mesh::template EntityType< 0 >;
-      using Index = typename Mesh::GlobalIndexType;
-
-      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      const int verticesPerEntity = 1;
-      for( Index i = 0; i < entitiesCount; i++ )
-      {
-         writeInt( format, str, verticesPerEntity );
-         writeInt( format, str, i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 1D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1 >
-{
-   using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, i );
-         writeInt( format, str, i+1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 1D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0 >
-{
-   using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ )
-      {
-         writeInt( format, str, 1 );
-         writeInt( format, str, i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 2D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2 >
-{
-   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 4 );
-         writeInt( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 2D grids, faces
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1 >
-{
-   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-
-      for( MeshIndex j = 0; j < (mesh.getDimensions().y()+1); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 2D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0 >
-{
-   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
-      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
-      {
-         writeInt( format, str, 1 );
-         writeInt( format, str, j * mesh.getDimensions().x() + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 3D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3 >
-{
-   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 8 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 3D grids, faces
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2 >
-{
-   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 4 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 4 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 4 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 3D grids, edges
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1 >
-{
-   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         writeInt( format, str, 2 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         writeInt( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-// 3D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTKWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0 >
-{
-   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ )
-      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
-      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
-      {
-         writeInt( format, str, 1 );
-         writeInt( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-
-// TODO: specialization for disabled entities
-template< typename Mesh, int EntityDimension >
-struct MeshEntityTypesVTKWriter
-{
-   static void exec( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      using EntityType = typename Mesh::template EntityType< EntityDimension >;
-      using Index = typename Mesh::GlobalIndexType;
-
-      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      for( Index i = 0; i < entitiesCount; i++ ) {
-         const int type = (int) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
-         writeInt( format, str, type );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-template< int Dimension,
-          typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          int EntityDimension >
-struct MeshEntityTypesVTKWriter< Grid< Dimension, MeshReal, Device, MeshIndex >, EntityDimension >
-{
-   using MeshType = Grid< Dimension, MeshReal, Device, MeshIndex >;
-
-   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
-   {
-      using EntityType = typename MeshType::template EntityType< EntityDimension >;
-
-      const MeshIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      for( MeshIndex i = 0; i < entitiesCount; i++ ) {
-         const int type = (int) VTK::GridEntityShape< EntityType >::shape;
-         writeInt( format, str, type );
-         if( format == VTK::FileFormat::ascii )
-            str << "\n";
-      }
-   }
-};
-
-} // namespace details
-
 template< typename Mesh >
 void
 VTKWriter< Mesh >::writeMetadata( int cycle, double time )
@@ -422,12 +37,12 @@ VTKWriter< Mesh >::writeMetadata( int cycle, double time )
       str << "FIELD FieldData " << n_metadata << "\n";
    if( cycle >= 0 ) {
       str << "CYCLE 1 1 int\n";
-      details::writeInt( format, str, cycle );
+      detail::writeValue( format, str, cycle );
       str << "\n";
    }
    if( time >= 0 ) {
       str << "TIME 1 1 double\n";
-      details::writeReal( format, str, time );
+      detail::writeValue( format, str, time );
       str << "\n";
    }
 }
@@ -443,20 +58,26 @@ VTKWriter< Mesh >::writeEntities( const Mesh& mesh )
 
    using EntityType = typename Mesh::template EntityType< EntityDimension >;
    cellsCount = mesh.template getEntitiesCount< EntityType >();
-   const std::uint64_t cellsListSize = EntitiesListSize< Mesh, EntityDimension >::getSize( mesh );
+   const std::uint64_t offsetsCount = detail::VTKOffsetsCountGetter< Mesh, EntityDimension >::getOffsetsCount( mesh );
 
-   str << std::endl << "CELLS " << cellsCount << " " << cellsListSize << std::endl;
-   EntitiesWriter< EntityDimension >::exec( mesh, str, format );
+   // legacy VTK files always have fixed integer width, even in the BINARY format
+   // - DataFormat version 2.0: 32-bit
+   // - DataFormat version 5.1: 64-bit (vtktypeint64)
+   str << std::endl << "CELLS " << cellsCount + 1 << " " << offsetsCount << std::endl;
+   str << "OFFSETS vtktypeint64" << std::endl;
+   detail::VTKMeshEntitiesWriter< Mesh, EntityDimension >::template writeOffsets< std::int64_t >( mesh, str, format );
+   str << "CONNECTIVITY vtktypeint64" << std::endl;
+   detail::VTKMeshEntitiesWriter< Mesh, EntityDimension >::template writeConnectivity< std::int64_t >( mesh, str, format );
 
    str << std::endl << "CELL_TYPES " << cellsCount << std::endl;
-   EntityTypesWriter< EntityDimension >::exec( mesh, str, format );
+   detail::VTKMeshEntityTypesWriter< Mesh, EntityDimension >::exec( mesh, str, format );
 }
 
 template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( array.getSize() / numberOfComponents != typename Array::IndexType(pointsCount) )
@@ -480,7 +101,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( array.getSize() / numberOfComponents != typename Array::IndexType(cellsCount) )
@@ -504,7 +125,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTKWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible
@@ -522,16 +143,16 @@ VTKWriter< Mesh >::writeDataArray( const Array& array,
 
    // write DataArray header
    if( numberOfComponents == 1 ) {
-      str << "SCALARS " << name << " " << getType< typename Array::ValueType >() << " 1" << std::endl;
+      str << "SCALARS " << name << " " << getType< typename Array::ValueType >() << std::endl;
       str << "LOOKUP_TABLE default" << std::endl;
    }
    else {
-      str << "VECTORS " << name << " " << getType< typename Array::ValueType >() << " 1" << std::endl;
+      str << "VECTORS " << name << " " << getType< typename Array::ValueType >() << std::endl;
    }
 
-   using Meshes::Writers::details::writeReal;
+   using detail::writeValue;
    for( typename Array::IndexType i = 0; i < array.getSize(); i++ ) {
-      writeReal( format, str, array[i] );
+      writeValue( format, str, array[i] );
       if( format == VTK::FileFormat::ascii )
          str << "\n";
    }
@@ -541,17 +162,17 @@ template< typename Mesh >
 void
 VTKWriter< Mesh >::writePoints( const Mesh& mesh )
 {
-   using details::writeReal;
+   using detail::writeValue;
    pointsCount = mesh.template getEntitiesCount< typename Mesh::Vertex >();
    str << "POINTS " << pointsCount << " " << getType< typename Mesh::RealType >() << std::endl;
    for( std::uint64_t i = 0; i < pointsCount; i++ ) {
       const auto& vertex = mesh.template getEntity< typename Mesh::Vertex >( i );
       const auto& point = vertex.getPoint();
       for( int j = 0; j < point.getSize(); j++ )
-         writeReal( format, str, point[ j ] );
+         writeValue( format, str, point[ j ] );
       // VTK needs zeros for unused dimensions
       for( int j = point.getSize(); j < 3; j++ )
-         writeReal( format, str, (typename Mesh::PointType::RealType) 0 );
+         writeValue( format, str, (typename Mesh::PointType::RealType) 0 );
       if( format == VTK::FileFormat::ascii )
          str << "\n";
    }
@@ -561,11 +182,11 @@ template< typename Mesh >
 void
 VTKWriter< Mesh >::writeHeader()
 {
-    str << "# vtk DataFile Version 2.0\n"
-        << "TNL DATA\n"
-        << ((format == VTK::FileFormat::ascii) ? "ASCII\n" : "BINARY\n")
-        << "DATASET UNSTRUCTURED_GRID\n";
-    headerWritten = true;
+   str << "# vtk DataFile Version 5.1\n"
+       << "TNL DATA\n"
+       << ((format == VTK::FileFormat::ascii) ? "ASCII\n" : "BINARY\n")
+       << "DATASET UNSTRUCTURED_GRID\n";
+   headerWritten = true;
 }
 
 } // namespace Writers
diff --git a/src/TNL/Meshes/Writers/VTUWriter.h b/src/TNL/Meshes/Writers/VTUWriter.h
index 31a1175b8dfde2225fe3460ea6859a8af8bc90b7..047daebbed08d5aa726690d94a91c302f856a029 100644
--- a/src/TNL/Meshes/Writers/VTUWriter.h
+++ b/src/TNL/Meshes/Writers/VTUWriter.h
@@ -12,18 +12,14 @@
 
 #pragma once
 
+#include <ostream>
+
 #include <TNL/Meshes/VTKTraits.h>
 
 namespace TNL {
 namespace Meshes {
 namespace Writers {
 
-namespace details {
-
-template< typename Mesh, int EntityDimension > struct MeshEntitiesVTUCollector;
-
-} // namespace details
-
 template< typename Mesh >
 class VTUWriter
 {
@@ -31,9 +27,6 @@ class VTUWriter
    // TODO: check also space dimension when grids allow it
 //   static_assert( Mesh::getSpaceDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." );
 
-   template< int EntityDimension >
-   using EntitiesCollector = details::MeshEntitiesVTUCollector< Mesh, EntityDimension >;
-
    using HeaderType = std::uint64_t;
 public:
 
@@ -52,17 +45,17 @@ public:
 
    template< typename Array >
    void writePointData( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeCellData( const Array& array,
-                       const String& name,
+                       const std::string& name,
                        const int numberOfComponents = 1 );
 
    template< typename Array >
    void writeDataArray( const Array& array,
-                        const String& name,
+                        const std::string& name,
                         const int numberOfComponents = 1 );
 
    ~VTUWriter();
diff --git a/src/TNL/Meshes/Writers/VTUWriter.hpp b/src/TNL/Meshes/Writers/VTUWriter.hpp
index 385537a521bc1d8a2cd0147ee27632d6849f39de..8a2951b1ed843a14f6e95ae94f71ab26e0e00425 100644
--- a/src/TNL/Meshes/Writers/VTUWriter.hpp
+++ b/src/TNL/Meshes/Writers/VTUWriter.hpp
@@ -14,9 +14,10 @@
 
 #include <limits>
 
+#include <TNL/Containers/Array.h>
 #include <TNL/Meshes/Writers/VTUWriter.h>
-#include <TNL/Meshes/Writers/VerticesPerEntity.h>
-#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Writers/detail/VTUMeshEntitiesCollector.h>
+#include <TNL/Meshes/Writers/detail/VTUPolyhedralFacesWriter.h>
 #include <TNL/Endianness.h>
 #include <TNL/base64.h>
 #ifdef HAVE_ZLIB
@@ -27,345 +28,6 @@ namespace TNL {
 namespace Meshes {
 namespace Writers {
 
-namespace details {
-
-// TODO: specialization for disabled entities
-// Unstructured meshes, entities
-template< typename Mesh, int EntityDimension >
-struct MeshEntitiesVTUCollector
-{
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      using EntityType = typename Mesh::template EntityType< EntityDimension >;
-      using Index = typename Mesh::GlobalIndexType;
-
-      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      for( Index i = 0; i < entitiesCount; i++ ) {
-         const auto& entity = mesh.template getEntity< EntityType >( i );
-         const Index verticesPerEntity = entity.template getSubentitiesCount< 0 >();
-         for( Index j = 0; j < verticesPerEntity; j++ )
-            connectivity.push_back( entity.template getSubentityIndex< 0 >( j ) );
-         offsets.push_back( connectivity.size() );
-         const std::uint8_t type = (std::uint8_t) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
-         types.push_back( type );
-      }
-   }
-};
-
-// Unstructured meshes, vertices
-template< typename Mesh >
-struct MeshEntitiesVTUCollector< Mesh, 0 >
-{
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      using EntityType = typename Mesh::template EntityType< 0 >;
-      using Index = typename Mesh::GlobalIndexType;
-
-      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
-      for( Index i = 0; i < entitiesCount; i++ ) {
-         connectivity.push_back( i );
-         offsets.push_back( connectivity.size() );
-         const std::uint8_t type = (std::uint8_t) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
-         types.push_back( type );
-      }
-   }
-};
-
-// 1D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1 >
-{
-   using Mesh = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 1 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( i );
-         connectivity.push_back( i+1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 1D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0 >
-{
-   using Mesh = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 0 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ )
-      {
-         connectivity.push_back( i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 2D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2 >
-{
-   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 2 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 2D grids, faces
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1 >
-{
-   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 1 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < (mesh.getDimensions().x() + 1); i++ )
-      {
-         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-
-      for( MeshIndex j = 0; j < (mesh.getDimensions().y() + 1); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 2D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0 >
-{
-   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 0 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
-      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
-      {
-         connectivity.push_back( j * mesh.getDimensions().x() + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 3D grids, cells
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3 >
-{
-   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 3 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 3D grids, faces
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2 >
-{
-   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 2 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 3D grids, edges
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1 >
-{
-   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 1 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-
-      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-
-      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
-      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
-      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-// 3D grids, vertices
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex >
-struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0 >
-{
-   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
-   using Entity = typename Mesh::template EntityType< 0 >;
-
-   static void exec( const Mesh& mesh,
-                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
-                     std::vector< typename Mesh::GlobalIndexType > & offsets,
-                     std::vector< std::uint8_t > & types )
-   {
-      for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ )
-      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
-      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
-      {
-         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
-         offsets.push_back( connectivity.size() );
-         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
-      }
-   }
-};
-
-} // namespace details
-
 template< typename Mesh >
 void
 VTUWriter< Mesh >::writeMetadata( int cycle, double time )
@@ -413,7 +75,7 @@ VTUWriter< Mesh >::writeEntities( const Mesh& mesh )
    using IndexType = typename Mesh::GlobalIndexType;
    std::vector< IndexType > connectivity, offsets;
    std::vector< std::uint8_t > types;
-   EntitiesCollector< EntityDimension >::exec( mesh, connectivity, offsets, types );
+   detail::MeshEntitiesVTUCollector< Mesh, EntityDimension >::exec( mesh, connectivity, offsets, types );
 
    // create array views that can be passed to writeDataArray
    Containers::ArrayView< IndexType, Devices::Host, std::uint64_t > connectivity_v( connectivity.data(), connectivity.size() );
@@ -425,6 +87,8 @@ VTUWriter< Mesh >::writeEntities( const Mesh& mesh )
    writeDataArray( connectivity_v, "connectivity", 0 );
    writeDataArray( offsets_v, "offsets", 0 );
    writeDataArray( types_v, "types", 0 );
+   // write faces if the mesh is polyhedral
+   detail::VTUPolyhedralFacesWriter< Mesh >::exec( *this, mesh );
    str << "</Cells>\n";
 }
 
@@ -432,7 +96,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writePointData( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -448,7 +112,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writeCellData( const Array& array,
-                                  const String& name,
+                                  const std::string& name,
                                   const int numberOfComponents )
 {
    if( ! pieceOpen )
@@ -464,7 +128,7 @@ template< typename Mesh >
    template< typename Array >
 void
 VTUWriter< Mesh >::writeDataArray( const Array& array,
-                                   const String& name,
+                                   const std::string& name,
                                    const int numberOfComponents )
 {
    // use a host buffer if direct access to the array elements is not possible
diff --git a/src/TNL/Meshes/Writers/detail/VTKMeshEntitiesWriter.h b/src/TNL/Meshes/Writers/detail/VTKMeshEntitiesWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..456c7263b910daf5dd13c29c2713fd150e1951a1
--- /dev/null
+++ b/src/TNL/Meshes/Writers/detail/VTKMeshEntitiesWriter.h
@@ -0,0 +1,636 @@
+#pragma once
+
+#include <limits>
+#include <ostream>
+
+#include <TNL/Endianness.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/VTKTraits.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+namespace detail {
+
+template< typename T >
+void
+writeValue( VTK::FileFormat format, std::ostream& str, T value )
+{
+   if( format == VTK::FileFormat::binary ) {
+      value = forceBigEndian( value );
+      str.write( reinterpret_cast<const char*>(&value), sizeof(T) );
+   }
+   else {
+      // precision affects only floating-point types, not integers
+      str.precision( std::numeric_limits< T >::digits10 );
+      str << value << " ";
+   }
+}
+
+
+// TODO: specialization for disabled entities
+// Unstructured meshes, entities
+template< typename Mesh,
+          int EntityDimension,
+          typename EntityType = typename Mesh::template EntityType< EntityDimension > >
+struct VTKMeshEntitiesWriter
+{
+   template< typename Index >
+   static void writeOffsets( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const auto& entity = mesh.template getEntity< EntityType >( i );
+         offset += entity.template getSubentitiesCount< 0 >();
+         writeValue< Index >( format, str, offset );
+      }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const auto& entity = mesh.template getEntity< EntityType >( i );
+         const Index verticesPerEntity = entity.template getSubentitiesCount< 0 >();
+         for( Index j = 0; j < verticesPerEntity; j++ )
+            writeValue< Index >( format, str, entity.template getSubentityIndex< 0 >( j ) );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// Unstructured meshes, polyhedrons
+template< typename Mesh >
+struct VTKMeshEntitiesWriter< Mesh, 3, MeshEntity< typename Mesh::Config, typename Mesh::DeviceType, Topologies::Polyhedron > >
+{
+   template< typename Index >
+   static void writeOffsets( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      const Index entitiesCount = mesh.template getEntitiesCount< 3 >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const Index num_faces = mesh.template getSubentitiesCount< 3, 2 >( i );
+         // one value (num_faces) for each cell
+         offset++;
+         // one value (num_vertices) for each face
+         offset += num_faces;
+         // list of vertex indices for each face
+         for( Index f = 0; f < num_faces; f++ ) {
+            const Index face = mesh.template getSubentityIndex< 3, 2 >( i, f );
+            offset += mesh.template getSubentitiesCount< 2, 0 >( face );
+         }
+         writeValue< Index >( format, str, offset );
+      }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      const Index entitiesCount = mesh.template getEntitiesCount< 3 >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const Index num_faces = mesh.template getSubentitiesCount< 3, 2 >( i );
+         writeValue< Index >( format, str, num_faces );
+
+         for( Index f = 0; f < num_faces; f++ ) {
+            const Index face = mesh.template getSubentityIndex< 3, 2 >( i, f );
+            const Index num_vertices = mesh.template getSubentitiesCount< 2, 0 >( face );
+            writeValue< Index >( format, str, num_vertices );
+            for( Index v = 0; v < num_vertices; v++ ) {
+               const Index vertex = mesh.template getSubentityIndex< 2, 0 >( face, v );
+               writeValue< Index >( format, str, vertex );
+            }
+         }
+
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// Unstructured meshes, vertices
+template< typename Mesh >
+struct VTKMeshEntitiesWriter< Mesh, 0, MeshEntity< typename Mesh::Config, typename Mesh::DeviceType, Topologies::Vertex > >
+{
+   template< typename Index >
+   static void writeOffsets( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      using EntityType = typename Mesh::template EntityType< 0 >;
+
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ )
+         writeValue< Index >( format, str, ++offset );
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      using EntityType = typename Mesh::template EntityType< 0 >;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         writeValue< Index >( format, str, i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 1D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1 >
+{
+   using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+         offset += 2;
+         writeValue< Index >( format, str, offset );
+      }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+         writeValue< Index >( format, str, i );
+         writeValue< Index >( format, str, i+1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 1D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0 >
+{
+   using MeshType = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ )
+         writeValue< Index >( format, str, ++offset );
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ ) {
+         writeValue< Index >( format, str, i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 2D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2 >
+{
+   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+         for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+            offset += 4;
+            writeValue< Index >( format, str, offset );
+         }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 2D grids, faces
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1 >
+{
+   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+         for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ ) {
+            offset += 2;
+            writeValue< Index >( format, str, offset );
+         }
+
+      for( MeshIndex j = 0; j < (mesh.getDimensions().y()+1); j++ )
+         for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+            offset += 2;
+            writeValue< Index >( format, str, offset );
+         }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+      {
+         writeValue< Index >( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+
+      for( MeshIndex j = 0; j < (mesh.getDimensions().y()+1); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 2D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0 >
+{
+   using MeshType = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+         for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+            writeValue< Index >( format, str, ++offset );
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+      {
+         writeValue< Index >( format, str, j * mesh.getDimensions().x() + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 3D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3 >
+{
+   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+               offset += 8;
+               writeValue< Index >( format, str, offset );
+            }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 3D grids, faces
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2 >
+{
+   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) {
+               offset += 4;
+               writeValue< Index >( format, str, offset );
+            }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+               offset += 4;
+               writeValue< Index >( format, str, offset );
+            }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+               offset += 4;
+               writeValue< Index >( format, str, offset );
+            }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 3D grids, edges
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1 >
+{
+   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ ) {
+               offset += 2;
+               writeValue< Index >( format, str, offset );
+            }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) {
+               offset += 2;
+               writeValue< Index >( format, str, offset );
+            }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+         for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+            for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ ) {
+               offset += 2;
+               writeValue< Index >( format, str, offset );
+            }
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         writeValue< Index >( format, str, (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+// 3D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTKMeshEntitiesWriter< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0 >
+{
+   using MeshType = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+
+   template< typename Index >
+   static void writeOffsets( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      Index offset = 0;
+      writeValue< Index >( format, str, offset );
+
+      for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ )
+         for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+            for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+               writeValue< Index >( format, str, ++offset );
+
+      if( format == VTK::FileFormat::ascii )
+         str << "\n";
+   }
+
+   template< typename Index >
+   static void writeConnectivity( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ )
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+      {
+         writeValue< Index >( format, str, k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+
+// TODO: specialization for disabled entities
+template< typename Mesh, int EntityDimension >
+struct VTKMeshEntityTypesWriter
+{
+   static void exec( const Mesh& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      using EntityType = typename Mesh::template EntityType< EntityDimension >;
+      using Index = typename Mesh::GlobalIndexType;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const int type = (int) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
+         writeValue( format, str, type );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+template< int Dimension,
+          typename MeshReal,
+          typename Device,
+          typename MeshIndex,
+          int EntityDimension >
+struct VTKMeshEntityTypesWriter< Grid< Dimension, MeshReal, Device, MeshIndex >, EntityDimension >
+{
+   using MeshType = Grid< Dimension, MeshReal, Device, MeshIndex >;
+
+   static void exec( const MeshType& mesh, std::ostream& str, VTK::FileFormat format )
+   {
+      using EntityType = typename MeshType::template EntityType< EntityDimension >;
+
+      const MeshIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( MeshIndex i = 0; i < entitiesCount; i++ ) {
+         const int type = (int) VTK::GridEntityShape< EntityType >::shape;
+         writeValue( format, str, type );
+         if( format == VTK::FileFormat::ascii )
+            str << "\n";
+      }
+   }
+};
+
+} // namespace detail
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/detail/VTKOffsetsCountGetter.h b/src/TNL/Meshes/Writers/detail/VTKOffsetsCountGetter.h
new file mode 100644
index 0000000000000000000000000000000000000000..abe89c91a32be7ffc7db3e918cc5d14176774c35
--- /dev/null
+++ b/src/TNL/Meshes/Writers/detail/VTKOffsetsCountGetter.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <TNL/Meshes/Writers/detail/VerticesPerEntity.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+namespace detail {
+
+template< typename Mesh,
+          int EntityDimension,
+          typename EntityType = typename Mesh::template EntityType< EntityDimension > >
+struct VTKOffsetsCountGetter
+{
+   using IndexType = typename Mesh::GlobalIndexType;
+
+   static IndexType getOffsetsCount( const Mesh& mesh )
+   {
+      const IndexType entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      const IndexType verticesPerEntity = VerticesPerEntity< EntityType >::count;
+      return entitiesCount * verticesPerEntity;
+   }
+};
+
+template< typename Mesh, int EntityDimension >
+struct VTKOffsetsCountGetter< Mesh, EntityDimension, MeshEntity< typename Mesh::Config, typename Mesh::DeviceType, Topologies::Polygon > >
+{
+   using IndexType = typename Mesh::GlobalIndexType;
+
+   static IndexType getOffsetsCount( const Mesh& mesh )
+   {
+      const IndexType entitiesCount = mesh.template getEntitiesCount< EntityDimension >();
+      IndexType offsetsCount = 0;
+      for( IndexType index = 0; index < entitiesCount; index++ )
+         offsetsCount += mesh.template getSubentitiesCount< EntityDimension, 0 >( index );
+      return offsetsCount;
+   }
+};
+
+template< typename Mesh, int EntityDimension >
+struct VTKOffsetsCountGetter< Mesh, EntityDimension, MeshEntity< typename Mesh::Config, typename Mesh::DeviceType, Topologies::Polyhedron > >
+{
+   using IndexType = typename Mesh::GlobalIndexType;
+
+   static IndexType getOffsetsCount( const Mesh& mesh )
+   {
+      const IndexType entitiesCount = mesh.template getEntitiesCount< EntityDimension >();
+      IndexType offsetsCount = 0;
+      for( IndexType index = 0; index < entitiesCount; index++ ) {
+         const IndexType num_faces = mesh.template getSubentitiesCount< EntityDimension, EntityDimension - 1 >( index );
+         // one value (num_faces) for each cell
+         offsetsCount++;
+         // one value (num_vertices) for each face
+         offsetsCount += num_faces;
+         // list of vertex indices for each face
+         for( IndexType f = 0; f < num_faces; f++ ) {
+            const IndexType face = mesh.template getSubentityIndex< EntityDimension, EntityDimension - 1 >( index, f );
+            offsetsCount += mesh.template getSubentitiesCount< EntityDimension - 1, 0 >( face );
+         }
+      }
+      return offsetsCount;
+   }
+};
+
+} // namespace detail
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/detail/VTUMeshEntitiesCollector.h b/src/TNL/Meshes/Writers/detail/VTUMeshEntitiesCollector.h
new file mode 100644
index 0000000000000000000000000000000000000000..b631c50870c7e5e6708938ec5b700bc22db353d5
--- /dev/null
+++ b/src/TNL/Meshes/Writers/detail/VTUMeshEntitiesCollector.h
@@ -0,0 +1,349 @@
+#pragma once
+
+#include <TNL/Meshes/VTKTraits.h>
+#include <TNL/Meshes/Grid.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+namespace detail {
+
+// TODO: specialization for disabled entities
+// Unstructured meshes, entities
+template< typename Mesh, int EntityDimension >
+struct MeshEntitiesVTUCollector
+{
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      using EntityType = typename Mesh::template EntityType< EntityDimension >;
+      using Index = typename Mesh::GlobalIndexType;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const auto& entity = mesh.template getEntity< EntityType >( i );
+         const Index verticesPerEntity = entity.template getSubentitiesCount< 0 >();
+         for( Index j = 0; j < verticesPerEntity; j++ )
+            connectivity.push_back( entity.template getSubentityIndex< 0 >( j ) );
+         offsets.push_back( connectivity.size() );
+         const std::uint8_t type = (std::uint8_t) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
+         types.push_back( type );
+      }
+   }
+};
+
+// Unstructured meshes, vertices
+template< typename Mesh >
+struct MeshEntitiesVTUCollector< Mesh, 0 >
+{
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      using EntityType = typename Mesh::template EntityType< 0 >;
+      using Index = typename Mesh::GlobalIndexType;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         connectivity.push_back( i );
+         offsets.push_back( connectivity.size() );
+         const std::uint8_t type = (std::uint8_t) VTK::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
+         types.push_back( type );
+      }
+   }
+};
+
+// 1D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1 >
+{
+   using Mesh = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 1 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( i );
+         connectivity.push_back( i+1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 1D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0 >
+{
+   using Mesh = Meshes::Grid< 1, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 0 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ )
+      {
+         connectivity.push_back( i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 2D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2 >
+{
+   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 2 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 2D grids, faces
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1 >
+{
+   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 1 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < (mesh.getDimensions().x() + 1); i++ )
+      {
+         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+
+      for( MeshIndex j = 0; j < (mesh.getDimensions().y() + 1); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 2D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0 >
+{
+   using Mesh = Meshes::Grid< 2, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 0 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+      {
+         connectivity.push_back( j * mesh.getDimensions().x() + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 3D grids, cells
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3 >
+{
+   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 3 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 3D grids, faces
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2 >
+{
+   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 2 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 3D grids, edges
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1 >
+{
+   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 1 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+
+      for( MeshIndex k = 0; k <= mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+
+      for( MeshIndex k = 0; k < mesh.getDimensions().z(); k++ )
+      for( MeshIndex j = 0; j <= mesh.getDimensions().y(); j++ )
+      for( MeshIndex i = 0; i <= mesh.getDimensions().x(); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         connectivity.push_back( (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+// 3D grids, vertices
+template< typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct MeshEntitiesVTUCollector< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0 >
+{
+   using Mesh = Meshes::Grid< 3, MeshReal, Device, MeshIndex >;
+   using Entity = typename Mesh::template EntityType< 0 >;
+
+   static void exec( const Mesh& mesh,
+                     std::vector< typename Mesh::GlobalIndexType > & connectivity,
+                     std::vector< typename Mesh::GlobalIndexType > & offsets,
+                     std::vector< std::uint8_t > & types )
+   {
+      for( MeshIndex k = 0; k < ( mesh.getDimensions().z() + 1 ); k++ )
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+      for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+      {
+         connectivity.push_back( k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i );
+         offsets.push_back( connectivity.size() );
+         types.push_back( (std::uint8_t) VTK::GridEntityShape< Entity >::shape );
+      }
+   }
+};
+
+} // namespace detail
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/detail/VTUPolyhedralFacesWriter.h b/src/TNL/Meshes/Writers/detail/VTUPolyhedralFacesWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2267b97d2d96a50223a045fed63d58e0e19c592
--- /dev/null
+++ b/src/TNL/Meshes/Writers/detail/VTUPolyhedralFacesWriter.h
@@ -0,0 +1,72 @@
+#pragma once
+
+#include <type_traits>  // std::enable_if_t
+
+#include <TNL/Containers/ArrayView.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Topologies/Polyhedron.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+namespace detail {
+
+// specialization for meshes
+template< typename Mesh >
+struct VTUPolyhedralFacesWriter
+{
+   // specialization for all meshes except polyhedral
+   template< typename W, typename M >
+   static std::enable_if_t< ! std::is_same< typename M::Config::CellTopology, Topologies::Polyhedron >::value >
+   exec( W& writer, const M& mesh )
+   {}
+
+   // specialization for polyhedral meshes
+   template< typename W, typename M >
+   static std::enable_if_t< std::is_same< typename M::Config::CellTopology, Topologies::Polyhedron >::value >
+   exec( W& writer, const M& mesh )
+   {
+      // build the "face stream" for VTK
+      using IndexType = typename Mesh::GlobalIndexType;
+      std::vector< IndexType > faces, faceoffsets;
+      for( IndexType c = 0; c < mesh.template getEntitiesCount< M::getMeshDimension() >(); c++ ) {
+         const IndexType num_faces = mesh.template getSubentitiesCount< M::getMeshDimension(), M::getMeshDimension() - 1 >( c );
+         faces.push_back( num_faces );
+         for( IndexType f = 0; f < num_faces; f++ ) {
+            const auto& face = mesh.template getEntity< M::getMeshDimension() - 1 >( mesh.template getSubentityIndex< M::getMeshDimension(), M::getMeshDimension() - 1 >( c, f ) );
+            const IndexType num_vertices = face.template getSubentitiesCount< 0 >();
+            faces.push_back( num_vertices );
+            for( IndexType v = 0; v < num_vertices; v++ ) {
+               const IndexType vertex = face.template getSubentityIndex< 0 >( v );
+               faces.push_back( vertex );
+            }
+         }
+         faceoffsets.push_back( faces.size() );
+      }
+
+      // create array views that can be passed to writeDataArray
+      Containers::ArrayView< IndexType, Devices::Host, std::uint64_t > faces_v( faces.data(), faces.size() );
+      Containers::ArrayView< IndexType, Devices::Host, std::uint64_t > faceoffsets_v( faceoffsets.data(), faceoffsets.size() );
+
+      // write cells
+      writer.writeDataArray( faces_v, "faces", 0 );
+      writer.writeDataArray( faceoffsets_v, "faceoffsets", 0 );
+   }
+};
+
+// specialization for grids
+template< int Dimension,
+          typename MeshReal,
+          typename Device,
+          typename MeshIndex >
+struct VTUPolyhedralFacesWriter< Meshes::Grid< Dimension, MeshReal, Device, MeshIndex > >
+{
+   template< typename W, typename M >
+   static void exec( W& writer, const M& mesh )
+   {}
+};
+
+} // namespace detail
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/VerticesPerEntity.h b/src/TNL/Meshes/Writers/detail/VerticesPerEntity.h
similarity index 64%
rename from src/TNL/Meshes/Writers/VerticesPerEntity.h
rename to src/TNL/Meshes/Writers/detail/VerticesPerEntity.h
index 5ae5e356e25739bf3e17da877e16a055cddd3df8..608557e2117ef556f83e3c3f0880535079e3e959 100644
--- a/src/TNL/Meshes/Writers/VerticesPerEntity.h
+++ b/src/TNL/Meshes/Writers/detail/VerticesPerEntity.h
@@ -1,15 +1,3 @@
-/***************************************************************************
-                          VerticesPerEntity.h  -  description
-                             -------------------
-    begin                : Mar 18, 2020
-    copyright            : (C) 2020 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-// Implemented by: Jakub Klinkovský
-
 #pragma once
 
 #include <TNL/TypeTraits.h>
@@ -18,8 +6,7 @@
 namespace TNL {
 namespace Meshes {
 namespace Writers {
-
-namespace details {
+namespace detail {
 
 template< typename T, typename Enable = void >
 struct has_entity_topology : std::false_type {};
@@ -29,10 +16,8 @@ struct has_entity_topology< T, typename enable_if_type< typename T::EntityTopolo
 : std::true_type
 {};
 
-} // namespace details
-
 template< typename Entity,
-          bool _is_mesh_entity = details::has_entity_topology< Entity >::value >
+          bool _is_mesh_entity = has_entity_topology< Entity >::value >
 struct VerticesPerEntity
 {
    static constexpr int count = Topologies::Subtopology< typename Entity::EntityTopology, 0 >::count;
@@ -59,6 +44,7 @@ public:
                    8;
 };
 
+} // namespace detail
 } // namespace Writers
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Solvers/BuildConfigTags.h b/src/TNL/Solvers/BuildConfigTags.h
index e75dcfddb0b37df8cdfd8e1eba38ae2e49e46cc4..a6f20396eded5bb037c936af1bbf88b7cb60cd06 100644
--- a/src/TNL/Solvers/BuildConfigTags.h
+++ b/src/TNL/Solvers/BuildConfigTags.h
@@ -22,26 +22,26 @@ class DefaultBuildConfigTag {};
  * All devices are enabled by default. Those which are not available
  * are disabled.
  */
-template< typename ConfigTag, typename Device > struct ConfigTagDevice{ enum { enabled = true }; };
+template< typename ConfigTag, typename Device > struct ConfigTagDevice{ static constexpr bool enabled = true; };
 #ifndef HAVE_CUDA
-template< typename ConfigTag > struct ConfigTagDevice< ConfigTag, Devices::Cuda >{ enum { enabled = false }; };
+template< typename ConfigTag > struct ConfigTagDevice< ConfigTag, Devices::Cuda >{ static constexpr bool enabled = false; };
 #endif
 
 /****
  * All real types are enabled by default.
  */
-template< typename ConfigTag, typename Real > struct ConfigTagReal{ enum { enabled = true }; };
+template< typename ConfigTag, typename Real > struct ConfigTagReal{ static constexpr bool enabled = true; };
 
 /****
  * All index types are enabled by default.
  */
-template< typename ConfigTag, typename Index > struct ConfigTagIndex{ enum { enabled = true }; };
+template< typename ConfigTag, typename Index > struct ConfigTagIndex{ static constexpr bool enabled = true; };
 
 /****
  * The mesh type will be resolved by the Solver by default.
  * (The detailed mesh configuration is in TNL/Meshes/TypeResolver/BuildConfigTags.h)
  */
-template< typename ConfigTag > struct ConfigTagMeshResolve{ enum { enabled = true }; };
+template< typename ConfigTag > struct ConfigTagMeshResolve{ static constexpr bool enabled = true; };
 
 /****
  * All time discretisations (explicit, semi-impicit and implicit ) are
@@ -51,7 +51,7 @@ class ExplicitTimeDiscretisationTag{};
 class SemiImplicitTimeDiscretisationTag{};
 class ImplicitTimeDiscretisationTag{};
 
-template< typename ConfigTag, typename TimeDiscretisation > struct ConfigTagTimeDiscretisation{ enum { enabled = true }; };
+template< typename ConfigTag, typename TimeDiscretisation > struct ConfigTagTimeDiscretisation{ static constexpr bool enabled = true; };
 
 /****
  * All explicit solvers are enabled by default
@@ -70,7 +70,7 @@ public:
     using Template = ODE::Merson< Problem, SolverMonitor >;
 };
 
-template< typename ConfigTag, typename ExplicitSolver > struct ConfigTagExplicitSolver{ enum { enabled = true }; };
+template< typename ConfigTag, typename ExplicitSolver > struct ConfigTagExplicitSolver{ static constexpr bool enabled = true; };
 
 } // namespace Solvers
 } // namespace TNL
diff --git a/src/TNL/Solvers/FastBuildConfigTag.h b/src/TNL/Solvers/FastBuildConfigTag.h
index d4a43df06a2d6e9fb9b685381d421c70419c4ff5..f737d6b67127c89bc679e1c7c80a6cb0ccaa93c2 100644
--- a/src/TNL/Solvers/FastBuildConfigTag.h
+++ b/src/TNL/Solvers/FastBuildConfigTag.h
@@ -21,26 +21,26 @@ class FastBuildConfigTag {};
 /****
  * Turn off support for float and long double.
  */
-template<> struct ConfigTagReal< FastBuildConfigTag, float > { enum { enabled = false }; };
-template<> struct ConfigTagReal< FastBuildConfigTag, long double > { enum { enabled = false }; };
+template<> struct ConfigTagReal< FastBuildConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct ConfigTagReal< FastBuildConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct ConfigTagIndex< FastBuildConfigTag, short int >{ enum { enabled = false }; };
-template<> struct ConfigTagIndex< FastBuildConfigTag, long int >{ enum { enabled = false }; };
+template<> struct ConfigTagIndex< FastBuildConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct ConfigTagIndex< FastBuildConfigTag, long int >{ static constexpr bool enabled = false; };
 
 /****
  * Please, chose your preferred time discretisation  here.
  */
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; };
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ enum { enabled = true }; };
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ExplicitTimeDiscretisationTag >{ static constexpr bool enabled = true; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ static constexpr bool enabled = true; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ImplicitTimeDiscretisationTag >{ static constexpr bool enabled = false; };
 
 /****
  * Only the Runge-Kutta-Merson solver is enabled by default.
  */
-//template<> struct ConfigTagExplicitSolver< FastBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = false }; };
+//template<> struct ConfigTagExplicitSolver< FastBuildConfigTag, ExplicitEulerSolverTag >{ static constexpr bool enabled = false; };
 
 } // namespace Solvers
 
@@ -50,14 +50,14 @@ namespace BuildConfigTags {
 /****
  * Turn off support for float and long double.
  */
-template<> struct GridRealTag< Solvers::FastBuildConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< Solvers::FastBuildConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< Solvers::FastBuildConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< Solvers::FastBuildConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct GridIndexTag< Solvers::FastBuildConfigTag, short int >{ enum { enabled = false }; };
-template<> struct GridIndexTag< Solvers::FastBuildConfigTag, long int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< Solvers::FastBuildConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct GridIndexTag< Solvers::FastBuildConfigTag, long int >{ static constexpr bool enabled = false; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
diff --git a/src/Tools/CMakeLists.txt b/src/Tools/CMakeLists.txt
index 8af2438fdf675656e6c89d7b51d9152d8bb4890e..8bfc42752c5e0daf73f57423c52b8748fb650dc2 100644
--- a/src/Tools/CMakeLists.txt
+++ b/src/Tools/CMakeLists.txt
@@ -1,49 +1,44 @@
 add_subdirectory(tnl-quickstart)
 
-ADD_EXECUTABLE(tnl-decompose-grid tnl-decompose-grid.cpp )
-ADD_EXECUTABLE(tnl-grid-setup tnl-grid-setup.cpp )
-ADD_EXECUTABLE(tnl-grid-to-mesh tnl-grid-to-mesh.cpp )
-ADD_EXECUTABLE(tnl-mesh-converter tnl-mesh-converter.cpp )
-ADD_EXECUTABLE(tnl-triangulate-mesh tnl-triangulate-mesh.cpp )
-ADD_EXECUTABLE(tnl-planar-correct-mesh tnl-planar-correct-mesh.cpp )
-ADD_EXECUTABLE(tnl-game-of-life tnl-game-of-life.cpp )
+set( MESH_TOOLS
+         tnl-init
+         tnl-diff
+         tnl-decompose-grid
+         tnl-grid-to-mesh
+         tnl-mesh-converter
+         tnl-triangulate-mesh
+         tnl-planar-correct-mesh
+         tnl-refine-mesh
+         tnl-game-of-life
+)
+set( CUDA_MESH_TOOLS )
 if( BUILD_CUDA )
-   CUDA_ADD_EXECUTABLE(tnl-test-distributed-mesh tnl-test-distributed-mesh.cu )
+   set( CUDA_MESH_TOOLS  ${CUDA_MESH_TOOLS} tnl-test-distributed-mesh )
 else()
-   ADD_EXECUTABLE(tnl-test-distributed-mesh tnl-test-distributed-mesh.cpp )
+   set( MESH_TOOLS  ${MESH_TOOLS} tnl-test-distributed-mesh )
 endif()
-ADD_EXECUTABLE(tnl-init tnl-init.cpp )
-ADD_EXECUTABLE(tnl-diff tnl-diff.cpp )
 
-ADD_EXECUTABLE(tnl-image-converter tnl-image-converter.cpp )
-if( PNG_FOUND )
-   target_link_libraries(tnl-image-converter ${PNG_LIBRARIES} )
-endif()
-if( JPEG_FOUND )
-   target_link_libraries(tnl-image-converter ${JPEG_LIBRARIES} )
-endif()
-
-ADD_EXECUTABLE(tnl-dicom-reader tnl-dicom-reader.cpp )
-if( DCMTK_FOUND )
-   target_link_libraries(tnl-dicom-reader ${DCMTK_LIBRARIES} )
-endif()
+foreach( target IN ITEMS ${MESH_TOOLS} )
+   add_executable( ${target} ${target}.cpp )
+endforeach()
+foreach( target IN ITEMS ${CUDA_MESH_TOOLS} )
+   cuda_add_executable( ${target} ${target}.cu )
+endforeach()
 
 find_package( ZLIB )
-if( ZLIB_FOUND )
-   foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh )
-      target_compile_definitions(${target} PUBLIC "-DHAVE_ZLIB")
-      target_include_directories(${target} PUBLIC ${ZLIB_INCLUDE_DIRS})
-      target_link_libraries(${target} ${ZLIB_LIBRARIES})
-   endforeach()
-endif()
-
 find_package( tinyxml2 QUIET )
-if( tinyxml2_FOUND )
-   foreach( target IN ITEMS tnl-init tnl-diff tnl-decompose-grid tnl-grid-to-mesh tnl-mesh-converter tnl-triangulate-mesh tnl-planar-correct-mesh tnl-game-of-life tnl-test-distributed-mesh )
-      target_compile_definitions(${target} PUBLIC "-DHAVE_TINYXML2")
-      target_link_libraries(${target} tinyxml2::tinyxml2)
-   endforeach()
-endif()
+foreach( target IN ITEMS ${MESH_TOOLS} ${CUDA_MESH_TOOLS} )
+   if( ZLIB_FOUND )
+      target_compile_definitions( ${target} PUBLIC "-DHAVE_ZLIB" )
+      target_include_directories( ${target} PUBLIC ${ZLIB_INCLUDE_DIRS} )
+      target_link_libraries( ${target} ${ZLIB_LIBRARIES} )
+   endif()
+   if( tinyxml2_FOUND )
+      target_compile_definitions( ${target} PUBLIC "-DHAVE_TINYXML2" )
+      target_link_libraries( ${target} tinyxml2::tinyxml2 )
+   endif()
+   install( TARGETS ${target} DESTINATION bin )
+endforeach()
 
 find_package( METIS QUIET )
 if( METIS_FOUND )
@@ -62,27 +57,33 @@ if( METIS_FOUND )
    install( TARGETS tnl-decompose-mesh DESTINATION bin )
 endif()
 
+
+add_executable( tnl-grid-setup tnl-grid-setup.cpp )
+
+add_executable( tnl-image-converter tnl-image-converter.cpp )
+if( PNG_FOUND )
+   target_link_libraries( tnl-image-converter ${PNG_LIBRARIES} )
+endif()
+if( JPEG_FOUND )
+   target_link_libraries( tnl-image-converter ${JPEG_LIBRARIES} )
+endif()
+
+add_executable( tnl-dicom-reader tnl-dicom-reader.cpp )
+if( DCMTK_FOUND )
+   target_link_libraries( tnl-dicom-reader ${DCMTK_LIBRARIES} )
+endif()
+
 IF( BUILD_CUDA )
-   CUDA_ADD_EXECUTABLE( tnl-cuda-arch tnl-cuda-arch.cu )
-   INSTALL( TARGETS tnl-cuda-arch
-            DESTINATION bin )
+   cuda_add_executable( tnl-cuda-arch tnl-cuda-arch.cu )
+   install( TARGETS tnl-cuda-arch DESTINATION bin )
 ENDIF()
 
-INSTALL( TARGETS tnl-init
-                 tnl-diff
-                 tnl-decompose-grid
-                 tnl-grid-setup
-                 tnl-grid-to-mesh
-                 tnl-mesh-converter
-                 tnl-triangulate-mesh
-                 tnl-planar-correct-mesh
-                 tnl-game-of-life
-                 tnl-test-distributed-mesh
-                 tnl-dicom-reader
+install( TARGETS tnl-grid-setup
                  tnl-image-converter
+                 tnl-dicom-reader
          DESTINATION bin )
 
-INSTALL( PROGRAMS tnl-err2eoc
+install( PROGRAMS tnl-err2eoc
                   tnl-benchmark-to-html.py
                   tnl-log-to-html.py
          DESTINATION bin )
diff --git a/src/Tools/tnl-decompose-grid.cpp b/src/Tools/tnl-decompose-grid.cpp
index b57558cc5b74f6bcf6097467c51ad6810129d216..c47055b3201a4875d3074df41a94eaad9e6eaed4 100644
--- a/src/Tools/tnl-decompose-grid.cpp
+++ b/src/Tools/tnl-decompose-grid.cpp
@@ -26,12 +26,12 @@ namespace BuildConfigTags {
 /****
  * Turn on all grids.
  */
-template<> struct GridRealTag< DecomposeGridConfigTag, float > { enum { enabled = true }; };
-template<> struct GridRealTag< DecomposeGridConfigTag, double > { enum { enabled = true }; };
-template<> struct GridRealTag< DecomposeGridConfigTag, long double > { enum { enabled = true }; };
+template<> struct GridRealTag< DecomposeGridConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct GridRealTag< DecomposeGridConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct GridRealTag< DecomposeGridConfigTag, long double > { static constexpr bool enabled = true; };
 
-template<> struct GridIndexTag< DecomposeGridConfigTag, int > { enum { enabled = true }; };
-template<> struct GridIndexTag< DecomposeGridConfigTag, long int > { enum { enabled = true }; };
+template<> struct GridIndexTag< DecomposeGridConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct GridIndexTag< DecomposeGridConfigTag, long int > { static constexpr bool enabled = true; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
diff --git a/src/Tools/tnl-decompose-mesh.cpp b/src/Tools/tnl-decompose-mesh.cpp
index 97383e9f3791af5ff52b88739b23deb2a2a266b0..b85d01dd016c96d1529fd002974ec89dbb929e3f 100644
--- a/src/Tools/tnl-decompose-mesh.cpp
+++ b/src/Tools/tnl-decompose-mesh.cpp
@@ -38,30 +38,30 @@ namespace BuildConfigTags {
 /****
  * Turn off all grids.
  */
-template<> struct GridRealTag< DecomposeMeshConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< DecomposeMeshConfigTag, double > { enum { enabled = false }; };
-template<> struct GridRealTag< DecomposeMeshConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< DecomposeMeshConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< DecomposeMeshConfigTag, double > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< DecomposeMeshConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Unstructured meshes.
  */
-template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Quadrangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< DecomposeMeshConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to the cell dimension.
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< DecomposeMeshConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == CellTopology::dimension ) }; };
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< DecomposeMeshConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< DecomposeMeshConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< DecomposeMeshConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< DecomposeMeshConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< DecomposeMeshConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< DecomposeMeshConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< DecomposeMeshConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< DecomposeMeshConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< DecomposeMeshConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< DecomposeMeshConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
diff --git a/src/Tools/tnl-diff.cpp b/src/Tools/tnl-diff.cpp
index c946dc80b5481314b8fa7a2d304d83c2ecc1500b..ce7fe42d4b19d23f72d80ceb975c5b8f8a7116c3 100644
--- a/src/Tools/tnl-diff.cpp
+++ b/src/Tools/tnl-diff.cpp
@@ -22,14 +22,14 @@ namespace BuildConfigTags {
 /****
  * Turn off support for float and long double.
  */
-//template<> struct GridRealTag< TNLDiffBuildConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< TNLDiffBuildConfigTag, long double > { enum { enabled = false }; };
+//template<> struct GridRealTag< TNLDiffBuildConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< TNLDiffBuildConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct GridIndexTag< TNLDiffBuildConfigTag, short int >{ enum { enabled = false }; };
-template<> struct GridIndexTag< TNLDiffBuildConfigTag, long int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< TNLDiffBuildConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct GridIndexTag< TNLDiffBuildConfigTag, long int >{ static constexpr bool enabled = false; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
diff --git a/src/Tools/tnl-game-of-life.cpp b/src/Tools/tnl-game-of-life.cpp
index e2f19c2ea6abb0fffcdb99c1339a6f61b62f9294..e570cd10c75e00224d3aa696b959bbc3a5e3c5eb 100644
--- a/src/Tools/tnl-game-of-life.cpp
+++ b/src/Tools/tnl-game-of-life.cpp
@@ -29,26 +29,26 @@ namespace BuildConfigTags {
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
 struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >
-{ enum { enabled = false }; };
+{ static constexpr bool enabled = false; };
 
 // Meshes are enabled only for topologies explicitly listed below.
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { enum { enabled = true }; };
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to the cell dimension.
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< MyConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == CellTopology::dimension ) }; };
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< MyConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< MyConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MyConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MyConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< MyConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< MyConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MyConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MyConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MyConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MyConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
diff --git a/src/Tools/tnl-grid-to-mesh.cpp b/src/Tools/tnl-grid-to-mesh.cpp
index 193f606206644340fecb791ca1d4df3bb25ae0d8..34d917838807d3db7016b56045d28fbc0ca16127 100644
--- a/src/Tools/tnl-grid-to-mesh.cpp
+++ b/src/Tools/tnl-grid-to-mesh.cpp
@@ -25,14 +25,14 @@ namespace BuildConfigTags {
 /****
  * Turn off support for float and long double.
  */
-template<> struct GridRealTag< GridToMeshConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< GridToMeshConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< GridToMeshConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< GridToMeshConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct GridIndexTag< GridToMeshConfigTag, short int >{ enum { enabled = false }; };
-template<> struct GridIndexTag< GridToMeshConfigTag, long int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< GridToMeshConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct GridIndexTag< GridToMeshConfigTag, long int >{ static constexpr bool enabled = false; };
 
 /****
  * Unstructured meshes are disabled, only grids can be on input.
@@ -175,7 +175,7 @@ struct MeshCreator< Meshes::Grid< 3, Real, Device, Index > >
 };
 
 template< typename Grid >
-bool convertGrid( Grid& grid, const String& outputFileName, const String& outputFormat )
+bool convertGrid( Grid& grid, const std::string& outputFileName, const std::string& outputFormat )
 {
    using MeshCreator = MeshCreator< Grid >;
    using Mesh = typename MeshCreator::MeshType;
@@ -186,37 +186,55 @@ bool convertGrid( Grid& grid, const String& outputFileName, const String& output
       return false;
    }
 
-   if( outputFormat == "vtk" ) {
+   std::string format = outputFormat;
+   if( outputFormat == "auto" ) {
+      namespace fs = std::experimental::filesystem;
+      format = fs::path( outputFileName ).extension();
+      if( format.length() > 0 )
+         // remove dot from the extension
+         format = format.substr(1);
+   }
+
+   if( format == "vtk" ) {
       using VTKWriter = Meshes::Writers::VTKWriter< Mesh >;
-      std::ofstream file( outputFileName.getString() );
+      std::ofstream file( outputFileName );
       VTKWriter writer( file );
       writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
    }
-   else if( outputFormat == "vtu" ) {
+   if( format == "vtu" ) {
       using VTKWriter = Meshes::Writers::VTUWriter< Mesh >;
-      std::ofstream file( outputFileName.getString() );
+      std::ofstream file( outputFileName );
       VTKWriter writer( file );
       writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
    }
-   else if( outputFormat == "netgen" ) {
+   if( format == "ng" ) {
       using NetgenWriter = Meshes::Writers::NetgenWriter< Mesh >;
-      std::fstream file( outputFileName.getString() );
+      std::fstream file( outputFileName );
       NetgenWriter::writeMesh( mesh, file );
+      return true;
    }
 
-   return true;
+   if( outputFormat == "auto" )
+      std::cerr << "File '" << outputFileName << "' has unsupported format (based on the file extension): " << format << ".";
+   else
+      std::cerr << "Unsupported output file format: " << outputFormat << ".";
+   std::cerr << " Supported formats are 'vtk', 'vtu' and 'ng'." << std::endl;
+   return false;
 }
 
 void configSetup( Config::ConfigDescription& config )
 {
    config.addDelimiter( "General settings:" );
-   config.addRequiredEntry< String >( "input-file", "Input file with the mesh." );
-   config.addRequiredEntry< String >( "output-file", "Output mesh file path." );
-   config.addRequiredEntry< String >( "output-file-format", "Output mesh file format." );
-   config.addEntryEnum( "tnl" );
+   config.addRequiredEntry< std::string >( "input-file", "Input file with the mesh." );
+   config.addEntry< std::string >( "input-file-format", "Input mesh file format.", "auto" );
+   config.addRequiredEntry< std::string >( "output-file", "Output mesh file path." );
+   config.addEntry< std::string >( "output-file-format", "Output mesh file format.", "auto" );
+   config.addEntryEnum( "auto" );
    config.addEntryEnum( "vtk" );
    config.addEntryEnum( "vtu" );
-   config.addEntryEnum( "netgen" );
+   config.addEntryEnum( "ng" );
 }
 
 int
@@ -230,13 +248,15 @@ main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-   const String inputFileName = parameters.getParameter< String >( "input-file" );
-   const String outputFileName = parameters.getParameter< String >( "output-file" );
-   const String outputFileFormat = parameters.getParameter< String >( "output-file-format" );
+   const std::string inputFileName = parameters.getParameter< std::string >( "input-file" );
+   const std::string inputFileFormat = parameters.getParameter< std::string >( "input-file-format" );
+   const std::string outputFileName = parameters.getParameter< std::string >( "output-file" );
+   const std::string outputFileFormat = parameters.getParameter< std::string >( "output-file-format" );
 
    auto wrapper = [&] ( const auto& reader, auto&& grid )
    {
       return convertGrid( grid, outputFileName, outputFileFormat );
    };
-   return ! Meshes::resolveAndLoadMesh< GridToMeshConfigTag, Devices::Host >( wrapper, inputFileName );
+   const bool status = Meshes::resolveAndLoadMesh< GridToMeshConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat );
+   return static_cast< int >( ! status );
 }
diff --git a/src/Tools/tnl-init.cpp b/src/Tools/tnl-init.cpp
index b1f2626d9c880587fb9db952f7aa25daf027ed09..645451bc68a1ccbb1e6f14be34bd6beb0045d857 100644
--- a/src/Tools/tnl-init.cpp
+++ b/src/Tools/tnl-init.cpp
@@ -27,14 +27,14 @@ namespace Meshes {
 namespace BuildConfigTags {
 
 // Configure real types
-template<> struct GridRealTag< TnlInitConfigTag, float > { enum { enabled = true }; };
-template<> struct GridRealTag< TnlInitConfigTag, double > { enum { enabled = true }; };
-template<> struct GridRealTag< TnlInitConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< TnlInitConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct GridRealTag< TnlInitConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct GridRealTag< TnlInitConfigTag, long double > { static constexpr bool enabled = false; };
 
 // Configure index types
-template<> struct GridIndexTag< TnlInitConfigTag, short int >{ enum { enabled = false }; };
-template<> struct GridIndexTag< TnlInitConfigTag, int >{ enum { enabled = true }; };
-template<> struct GridIndexTag< TnlInitConfigTag, long int >{ enum { enabled = true }; };
+template<> struct GridIndexTag< TnlInitConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct GridIndexTag< TnlInitConfigTag, int >{ static constexpr bool enabled = true; };
+template<> struct GridIndexTag< TnlInitConfigTag, long int >{ static constexpr bool enabled = true; };
 
 // Unstructured meshes are disabled, only grids can be on input.
 
diff --git a/src/Tools/tnl-mesh-converter.cpp b/src/Tools/tnl-mesh-converter.cpp
index b97639118b740e8db9169c872ca44d6706d225e3..6275e1e8e63e5bea30eb42b4b1857857919097be 100644
--- a/src/Tools/tnl-mesh-converter.cpp
+++ b/src/Tools/tnl-mesh-converter.cpp
@@ -10,10 +10,11 @@
 
 #include <TNL/Config/parseCommandLine.h>
 #include <TNL/Meshes/TypeResolver/resolveMeshType.h>
+#include <TNL/Meshes/Writers/FPMAWriter.h>
 #include <TNL/Meshes/Writers/VTKWriter.h>
 #include <TNL/Meshes/Writers/VTUWriter.h>
-//#include <TNL/Meshes/Writers/VTIWriter.h>
-//#include <TNL/Meshes/Writers/NetgenWriter.h>
+#include <TNL/Meshes/Writers/VTIWriter.h>
+#include <TNL/Meshes/Writers/NetgenWriter.h>
 
 using namespace TNL;
 
@@ -26,38 +27,39 @@ namespace BuildConfigTags {
 /****
  * Turn off support for float and long double.
  */
-template<> struct GridRealTag< MeshConverterConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< MeshConverterConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< MeshConverterConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshConverterConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct GridIndexTag< MeshConverterConfigTag, short int >{ enum { enabled = false }; };
-template<> struct GridIndexTag< MeshConverterConfigTag, long int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< MeshConverterConfigTag, short int >{ static constexpr bool enabled = false; };
+template<> struct GridIndexTag< MeshConverterConfigTag, long int >{ static constexpr bool enabled = false; };
 
 /****
  * Unstructured meshes.
  */
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Quadrangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Polygon > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Wedge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Pyramid > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Wedge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Pyramid > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to the cell dimension.
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< MeshConverterConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == CellTopology::dimension ) }; };
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< MeshConverterConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< MeshConverterConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< MeshConverterConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< MeshConverterConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MeshConverterConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MeshConverterConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
@@ -68,19 +70,18 @@ struct MeshConfigTemplateTag< MeshConverterConfigTag >
              typename Real = double,
              typename GlobalIndex = int,
              typename LocalIndex = GlobalIndex >
-   struct MeshConfig
+   struct MeshConfig : public DefaultConfig< Cell, SpaceDimension, Real, GlobalIndex, LocalIndex >
    {
-      using CellTopology = Cell;
-      using RealType = Real;
-      using GlobalIndexType = GlobalIndex;
-      using LocalIndexType = LocalIndex;
-
-      static constexpr int spaceDimension = SpaceDimension;
-      static constexpr int meshDimension = Cell::dimension;
-
       static constexpr bool subentityStorage( int entityDimension, int subentityDimension )
       {
-         return subentityDimension == 0 && entityDimension == meshDimension;
+         // faces must be stored for polyhedral meshes
+         if( std::is_same< Cell, TNL::Meshes::Topologies::Polyhedron >::value ) {
+            if( subentityDimension == 0 && entityDimension == Cell::dimension - 1 )
+               return true;
+            if( subentityDimension == Cell::dimension - 1 && entityDimension == Cell::dimension )
+               return true;
+         }
+         return subentityDimension == 0 && entityDimension == Cell::dimension;
       }
 
       static constexpr bool superentityStorage( int entityDimension, int superentityDimension )
@@ -104,50 +105,130 @@ struct MeshConfigTemplateTag< MeshConverterConfigTag >
 } // namespace Meshes
 } // namespace TNL
 
+// specialization for polyhedral meshes
+template< typename Mesh,
+          std::enable_if_t< std::is_same< typename Mesh::Cell::EntityTopology, TNL::Meshes::Topologies::Polyhedron >::value, bool > = true >
+bool writeMesh( const Mesh& mesh, std::ostream& out, const std::string& format )
+{
+   if( format == "fpma" ) {
+      using Writer = Meshes::Writers::FPMAWriter< Mesh >;
+      Writer writer( out );
+      writer.writeEntities( mesh );
+      return true;
+   }
+   if( format == "vtk" ) {
+      using Writer = Meshes::Writers::VTKWriter< Mesh >;
+      Writer writer( out );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   if( format == "vtu" ) {
+      using Writer = Meshes::Writers::VTUWriter< Mesh >;
+      Writer writer( out );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   return false;
+}
 
-template< typename Mesh >
-bool convertMesh( const Mesh& mesh, const String& inputFileName, const String& outputFileName, const String& outputFormat )
+// specialization for unstructured meshes except polyhedral
+template< typename Mesh,
+          std::enable_if_t< ! std::is_same< typename Mesh::Cell::EntityTopology, TNL::Meshes::Topologies::Polyhedron >::value, bool > = true >
+bool writeMesh( const Mesh& mesh, std::ostream& out, const std::string& format )
+{
+   if( format == "vtk" ) {
+      using Writer = Meshes::Writers::VTKWriter< Mesh >;
+      Writer writer( out );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   if( format == "vtu" ) {
+      using Writer = Meshes::Writers::VTUWriter< Mesh >;
+      Writer writer( out );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   if( format == "ng" ) {
+      using NetgenWriter = Meshes::Writers::NetgenWriter< Mesh >;
+      NetgenWriter::writeMesh( mesh, out );
+      return true;
+   }
+   return false;
+}
+
+// specialization for grids
+template< int Dimension, typename Real, typename Device, typename Index >
+bool writeMesh( const TNL::Meshes::Grid< Dimension, Real, Device, Index >& mesh,
+                std::ostream& out,
+                const std::string& format )
 {
-   if( outputFormat == "vtk" ) {
+   using Mesh = TNL::Meshes::Grid< Dimension, Real, Device, Index >;
+   if( format == "vtk" ) {
       using Writer = Meshes::Writers::VTKWriter< Mesh >;
-      std::ofstream file( outputFileName );
-      Writer writer( file );
+      Writer writer( out );
       writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
    }
-   else if( outputFormat == "vtu" ) {
+   if( format == "vtu" ) {
       using Writer = Meshes::Writers::VTUWriter< Mesh >;
-      std::ofstream file( outputFileName );
-      Writer writer( file );
+      Writer writer( out );
       writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   if( format == "vti" ) {
+      using Writer = Meshes::Writers::VTIWriter< Mesh >;
+      Writer writer( out );
+      writer.writeImageData( mesh );
+      return true;
    }
-   // FIXME: VTIWriter is not specialized for meshes
-//   else if( outputFormat == "vti" ) {
-//      using Writer = Meshes::Writers::VTIWriter< Mesh >;
-//      std::ofstream file( outputFileName );
-//      Writer writer( file );
-//      writer.writeImageData( mesh );
-//   }
-   // FIXME: NetgenWriter is not specialized for grids
-//   else if( outputFormat == "netgen" ) {
-//      using NetgenWriter = Meshes::Writers::NetgenWriter< Mesh >;
-//      std::fstream file( outputFileName );
-//      NetgenWriter::writeMesh( mesh, file );
-//   }
-
-   return true;
+   return false;
+}
+
+template< typename Mesh >
+bool convertMesh( const Mesh& mesh, const std::string& inputFileName, const std::string& outputFileName, const std::string& outputFormat )
+{
+   std::string format = outputFormat;
+   if( outputFormat == "auto" ) {
+      namespace fs = std::experimental::filesystem;
+      format = fs::path( outputFileName ).extension();
+      if( format.length() > 0 )
+         // remove dot from the extension
+         format = format.substr(1);
+   }
+
+   std::ofstream file( outputFileName );
+   if( writeMesh( mesh, file, format ) )
+      return true;
+
+   if( outputFormat == "auto" )
+      std::cerr << "File '" << outputFileName << "' has unsupported format (based on the file extension): " << format << ".";
+   else
+      std::cerr << "Unsupported output file format: " << outputFormat << ".";
+   std::cerr << " Supported formats are 'vtk', 'vtu', 'vti' (only grids), 'ng' (only static unstructured meshes) and 'fpma' (only polyhedral meshes)." << std::endl;
+   return false;
 }
 
 void configSetup( Config::ConfigDescription& config )
 {
    config.addDelimiter( "General settings:" );
-   config.addRequiredEntry< String >( "input-file", "Input file with the mesh." );
-   config.addEntry< String >( "input-file-format", "Input mesh file format.", "auto" );
-   config.addRequiredEntry< String >( "output-file", "Output mesh file path." );
-   config.addRequiredEntry< String >( "output-file-format", "Output mesh file format." );
+   config.addRequiredEntry< std::string >( "input-file", "Input file with the mesh." );
+   config.addEntry< std::string >( "input-file-format", "Input mesh file format.", "auto" );
+   config.addEntry< std::string >( "real-type", "Type to use for the representation of spatial coordinates in the output mesh. When 'auto', the real type from the input mesh is used.", "auto" );
+   config.addEntryEnum( "auto" );
+   config.addEntryEnum( "float" );
+   config.addEntryEnum( "double" );
+   config.addEntry< std::string >( "global-index-type", "Type to use for the representation of global indices in the output mesh. When 'auto', the global index type from the input mesh is used.", "auto" );
+   config.addEntryEnum( "auto" );
+   config.addEntryEnum( "std::int32_t" );
+   config.addEntryEnum( "std::int64_t" );
+   config.addRequiredEntry< std::string >( "output-file", "Output mesh file path." );
+   config.addEntry< std::string >( "output-file-format", "Output mesh file format.", "auto" );
+   config.addEntryEnum( "auto" );
    config.addEntryEnum( "vtk" );
    config.addEntryEnum( "vtu" );
-//   config.addEntryEnum( "vti" );
-//   config.addEntryEnum( "netgen" );
+   config.addEntryEnum( "vti" );
+   config.addEntryEnum( "ng" );
+   config.addEntryEnum( "fpma" );
 }
 
 int main( int argc, char* argv[] )
@@ -160,14 +241,17 @@ int main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-   const String inputFileName = parameters.getParameter< String >( "input-file" );
-   const String inputFileFormat = parameters.getParameter< String >( "input-file-format" );
-   const String outputFileName = parameters.getParameter< String >( "output-file" );
-   const String outputFileFormat = parameters.getParameter< String >( "output-file-format" );
+   const std::string inputFileName = parameters.getParameter< std::string >( "input-file" );
+   const std::string inputFileFormat = parameters.getParameter< std::string >( "input-file-format" );
+   const std::string realType = parameters.getParameter< std::string >( "real-type" );
+   const std::string globalIndexType = parameters.getParameter< std::string >( "global-index-type" );
+   const std::string outputFileName = parameters.getParameter< std::string >( "output-file" );
+   const std::string outputFileFormat = parameters.getParameter< std::string >( "output-file-format" );
 
    auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool
    {
       return convertMesh( mesh, inputFileName, outputFileName, outputFileFormat );
    };
-   return ! Meshes::resolveAndLoadMesh< MeshConverterConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat );
+   const bool status = Meshes::resolveAndLoadMesh< MeshConverterConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat, realType, globalIndexType );
+   return static_cast< int >( ! status );
 }
diff --git a/src/Tools/tnl-planar-correct-mesh.cpp b/src/Tools/tnl-planar-correct-mesh.cpp
index c4802b66ada8ee204cca6c25bf75c5756a53612c..9ad689b92812b3bd23a2036450dc1f790b87f8f7 100644
--- a/src/Tools/tnl-planar-correct-mesh.cpp
+++ b/src/Tools/tnl-planar-correct-mesh.cpp
@@ -1,6 +1,7 @@
 #include <TNL/Config/parseCommandLine.h>
 #include <TNL/Meshes/TypeResolver/resolveMeshType.h>
 #include <TNL/Meshes/Writers/VTKWriter.h>
+#include <TNL/Meshes/Writers/VTUWriter.h>
 #include <TNL/Meshes/Writers/FPMAWriter.h>
 #include <TNL/Meshes/Geometry/getPlanarMesh.h>
 
@@ -15,27 +16,27 @@ namespace BuildConfigTags {
 /****
  * Turn off all grids.
  */
-template<> struct GridRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = false }; };
-template<> struct GridRealTag< MeshPlanarCorrectConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< MeshPlanarCorrectConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshPlanarCorrectConfigTag, double > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshPlanarCorrectConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Unstructured meshes.
  */
-template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polygon > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polyhedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshPlanarCorrectConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to 3
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< MeshPlanarCorrectConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == 3 ) }; };
+{ static constexpr bool enabled = SpaceDimension == 3; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< MeshPlanarCorrectConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MeshPlanarCorrectConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshPlanarCorrectConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MeshPlanarCorrectConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
@@ -87,7 +88,7 @@ struct MeshConfigTemplateTag< MeshPlanarCorrectConfigTag >
 using namespace TNL::Meshes;
 
 template< typename Mesh >
-auto getPlanarMeshHelper( const Mesh& mesh, const String& decompositionType )
+auto getPlanarMeshHelper( const Mesh& mesh, const std::string& decompositionType )
 {
    using namespace TNL::Meshes;
 
@@ -106,12 +107,38 @@ template<>
 struct PlanarMeshWriter< Topologies::Polygon >
 {
    template< typename Mesh >
-   static void exec( const Mesh& mesh, const String& outputFileName )
+   static bool exec( const Mesh& mesh, const std::string& outputFileName, const std::string& outputFormat )
    {
-      using Writer = Meshes::Writers::VTKWriter< Mesh >;
-      std::ofstream file( outputFileName );
-      Writer writer( file );
-      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      std::string format = outputFormat;
+      if( outputFormat == "auto" ) {
+         namespace fs = std::experimental::filesystem;
+         format = fs::path( outputFileName ).extension();
+         if( format.length() > 0 )
+            // remove dot from the extension
+            format = format.substr(1);
+      }
+
+      if( format == "vtk" ) {
+         using Writer = Meshes::Writers::VTKWriter< Mesh >;
+         std::ofstream file( outputFileName );
+         Writer writer( file );
+         writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+         return true;
+      }
+      if( format == "vtu" ) {
+         using Writer = Meshes::Writers::VTUWriter< Mesh >;
+         std::ofstream file( outputFileName );
+         Writer writer( file );
+         writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+         return true;
+      }
+
+      if( outputFormat == "auto" )
+         std::cerr << "File '" << outputFileName << "' has unsupported format (based on the file extension): " << format << ".";
+      else
+         std::cerr << "Unsupported output file format: " << outputFormat << ".";
+      std::cerr << " Supported formats are 'vtk' and 'vtu'." << std::endl;
+      return false;
    }
 };
 
@@ -119,31 +146,38 @@ template<>
 struct PlanarMeshWriter< Topologies::Polyhedron >
 {
    template< typename Mesh >
-   static void exec( const Mesh& mesh, const String& outputFileName )
+   static bool exec( const Mesh& mesh, const std::string& outputFileName, const std::string& outputFormat )
    {
+      if( outputFormat != "auto" && outputFormat != "fpma" ) {
+         std::cerr << "Unsupported output file format: " << outputFormat << ". Only 'fpma' is supported for polyhedral meshes." << std::endl;
+         return false;
+      }
+
       using Writer = Meshes::Writers::FPMAWriter< Mesh >;
       std::ofstream file( outputFileName );
       Writer writer( file );
       writer.writeEntities( mesh );
+      return true;
    }
 };
 
 template< typename Mesh >
-bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& decompositionType )
+bool triangulateMesh( const Mesh& mesh, const std::string& outputFileName, const std::string& outputFormat, const std::string& decompositionType )
 {
    const auto planarMesh = getPlanarMeshHelper( mesh, decompositionType );
    using PlanarMesh = decltype( planarMesh );
    using CellTopology = typename PlanarMesh::Cell::EntityTopology;
-   PlanarMeshWriter< CellTopology >::exec( planarMesh, outputFileName );
-   return true;
+   return PlanarMeshWriter< CellTopology >::exec( planarMesh, outputFileName, outputFormat );
 }
 
 void configSetup( Config::ConfigDescription& config )
 {
    config.addDelimiter( "General settings:" );
-   config.addRequiredEntry< String >( "input-file", "Input file with the mesh." );
-   config.addRequiredEntry< String >( "output-file", "Output mesh file path." );
-   config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use for non-planar polygons." );
+   config.addRequiredEntry< std::string >( "input-file", "Input file with the mesh." );
+   config.addEntry< std::string >( "input-file-format", "Input mesh file format.", "auto" );
+   config.addRequiredEntry< std::string >( "output-file", "Output mesh file path." );
+   config.addEntry< std::string >( "output-file-format", "Output mesh file format.", "auto" );
+   config.addRequiredEntry< std::string >( "decomposition-type", "Type of decomposition to use for non-planar polygons." );
    config.addEntryEnum( "c" );
    config.addEntryEnum( "p" );
 }
@@ -158,14 +192,15 @@ int main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-   const String inputFileName = parameters.getParameter< String >( "input-file" );
-   const String inputFileFormat = "auto";
-   const String outputFileName = parameters.getParameter< String >( "output-file" );
-   const String decompositionType = parameters.getParameter< String >( "decomposition-type" );
+   const std::string inputFileName = parameters.getParameter< std::string >( "input-file" );
+   const std::string inputFileFormat = parameters.getParameter< std::string >( "input-file-format" );
+   const std::string outputFileName = parameters.getParameter< std::string >( "output-file" );
+   const std::string outputFileFormat = parameters.getParameter< std::string >( "output-file-format" );
+   const std::string decompositionType = parameters.getParameter< std::string >( "decomposition-type" );
 
    auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool
    {
-      return triangulateMesh( mesh, outputFileName, decompositionType );
+      return triangulateMesh( mesh, outputFileName, outputFileFormat, decompositionType );
    };
    return ! Meshes::resolveAndLoadMesh< MeshPlanarCorrectConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat );
 }
diff --git a/src/Tools/tnl-refine-mesh.cpp b/src/Tools/tnl-refine-mesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b69bc1f78fb56b805c943046b07042f24b7ad84e
--- /dev/null
+++ b/src/Tools/tnl-refine-mesh.cpp
@@ -0,0 +1,174 @@
+#include <TNL/Config/parseCommandLine.h>
+#include <TNL/Meshes/TypeResolver/resolveMeshType.h>
+#include <TNL/Meshes/Writers/VTKWriter.h>
+#include <TNL/Meshes/Writers/VTUWriter.h>
+#include <TNL/Meshes/Geometry/getRefinedMesh.h>
+
+using namespace TNL;
+
+struct MeshRefineConfigTag {};
+
+namespace TNL {
+namespace Meshes {
+namespace BuildConfigTags {
+
+/****
+ * Turn off all grids.
+ */
+template<> struct GridRealTag< MeshRefineConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshRefineConfigTag, double > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshRefineConfigTag, long double > { static constexpr bool enabled = false; };
+
+/****
+ * Unstructured meshes.
+ */
+template<> struct MeshCellTopologyTag< MeshRefineConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshRefineConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshRefineConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshRefineConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
+
+// Meshes are enabled only for the space dimension equal to the cell dimension.
+template< typename CellTopology, int SpaceDimension >
+struct MeshSpaceDimensionTag< MeshRefineConfigTag, CellTopology, SpaceDimension >
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
+
+// Meshes are enabled only for types explicitly listed below.
+template<> struct MeshRealTag< MeshRefineConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MeshRefineConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshRefineConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshRefineConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MeshRefineConfigTag, short int > { static constexpr bool enabled = true; };
+
+// Config tag specifying the MeshConfig template to use.
+template<>
+struct MeshConfigTemplateTag< MeshRefineConfigTag >
+{
+   template< typename Cell,
+             int SpaceDimension = Cell::dimension,
+             typename Real = float,
+             typename GlobalIndex = int,
+             typename LocalIndex = short int >
+   struct MeshConfig : public DefaultConfig< Cell, SpaceDimension, Real, GlobalIndex, LocalIndex >
+   {
+      static constexpr bool subentityStorage( int entityDimension, int subentityDimension )
+      {
+         return subentityDimension == 0 && entityDimension == Cell::dimension;
+      }
+
+      static constexpr bool superentityStorage( int entityDimension, int superentityDimension )
+      {
+         return false;
+      }
+
+      static constexpr bool entityTagsStorage( int entityDimension )
+      {
+         return false;
+      }
+
+      static constexpr bool dualGraphStorage()
+      {
+         return false;
+      }
+   };
+};
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
+
+template< typename Mesh >
+Mesh getRefinedMeshHelper( const Mesh& mesh, const std::string& decompositionType )
+{
+   using namespace TNL::Meshes;
+   return getRefinedMesh< EntityRefinerVersion::EdgeBisection >( mesh );
+}
+
+template< typename Mesh >
+bool refineMesh( Mesh& mesh, const std::string& outputFileName, const std::string& outputFormat, const std::string& decompositionType, int iterations )
+{
+   for( int i = 1; i <= iterations; i++ ) {
+      std::cout << "Refining mesh (iteration " << i << ")" << std::endl;
+      mesh = getRefinedMeshHelper( mesh, decompositionType );
+   }
+
+   std::string format = outputFormat;
+   if( outputFormat == "auto" ) {
+      namespace fs = std::experimental::filesystem;
+      format = fs::path( outputFileName ).extension();
+      if( format.length() > 0 )
+         // remove dot from the extension
+         format = format.substr(1);
+   }
+
+   if( format == "vtk" ) {
+      using Writer = Meshes::Writers::VTKWriter< Mesh >;
+      std::ofstream file( outputFileName );
+      Writer writer( file );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+   if( format == "vtu" ) {
+      using Writer = Meshes::Writers::VTUWriter< Mesh >;
+      std::ofstream file( outputFileName );
+      Writer writer( file );
+      writer.template writeEntities< Mesh::getMeshDimension() >( mesh );
+      return true;
+   }
+
+   if( outputFormat == "auto" )
+      std::cerr << "File '" << outputFileName << "' has unsupported format (based on the file extension): " << format << ".";
+   else
+      std::cerr << "Unsupported output file format: " << outputFormat << ".";
+   std::cerr << " Supported formats are 'vtk' and 'vtu'." << std::endl;
+   return false;
+}
+
+void configSetup( Config::ConfigDescription& config )
+{
+   config.addDelimiter( "General settings:" );
+   config.addRequiredEntry< std::string >( "input-file", "Input file with the mesh." );
+   config.addEntry< std::string >( "input-file-format", "Input mesh file format.", "auto" );
+   config.addEntry< std::string >( "real-type", "Type to use for the representation of spatial coordinates in the output mesh. When 'auto', the real type from the input mesh is used.", "auto" );
+   config.addEntryEnum( "auto" );
+   config.addEntryEnum( "float" );
+   config.addEntryEnum( "double" );
+   config.addEntry< std::string >( "global-index-type", "Type to use for the representation of global indices in the output mesh. When 'auto', the global index type from the input mesh is used.", "auto" );
+   config.addEntryEnum( "auto" );
+   config.addEntryEnum( "std::int32_t" );
+   config.addEntryEnum( "std::int64_t" );
+   config.addRequiredEntry< std::string >( "output-file", "Output mesh file path." );
+   config.addEntry< std::string >( "output-file-format", "Output mesh file format.", "auto" );
+   config.addEntryEnum( "auto" );
+   config.addEntryEnum( "vtk" );
+   config.addEntryEnum( "vtu" );
+   config.addEntry< std::string >( "decomposition-type", "Type of decomposition to use.", "edge-bisection" );
+   config.addEntryEnum( "edge-bisection" );
+   config.addEntry< int >( "iterations", "Number of mesh refinement iterations.", 1 );
+}
+
+int main( int argc, char* argv[] )
+{
+   Config::ParameterContainer parameters;
+   Config::ConfigDescription conf_desc;
+
+   configSetup( conf_desc );
+
+   if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
+      return EXIT_FAILURE;
+
+   const std::string inputFileName = parameters.getParameter< std::string >( "input-file" );
+   const std::string inputFileFormat = parameters.getParameter< std::string >( "input-file-format" );
+   const std::string realType = parameters.getParameter< std::string >( "real-type" );
+   const std::string globalIndexType = parameters.getParameter< std::string >( "global-index-type" );
+   const std::string outputFileName = parameters.getParameter< std::string >( "output-file" );
+   const std::string outputFileFormat = parameters.getParameter< std::string >( "output-file-format" );
+   const std::string decompositionType = parameters.getParameter< std::string >( "decomposition-type" );
+   const int iterations = parameters.getParameter< int >( "iterations" );
+
+   auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool
+   {
+      return refineMesh( mesh, outputFileName, outputFileFormat, decompositionType, iterations );
+   };
+   const bool status = Meshes::resolveAndLoadMesh< MeshRefineConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat, realType, globalIndexType );
+   return static_cast< int >( ! status );
+}
diff --git a/src/Tools/tnl-test-distributed-mesh.h b/src/Tools/tnl-test-distributed-mesh.h
index 47e3266767035b8f6288d994852bb18f671e95e6..ddbe71100694285db0f45f7df19b06450c4b0393 100644
--- a/src/Tools/tnl-test-distributed-mesh.h
+++ b/src/Tools/tnl-test-distributed-mesh.h
@@ -31,26 +31,26 @@ namespace BuildConfigTags {
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
 struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >
-{ enum { enabled = false }; };
+{ static constexpr bool enabled = false; };
 
 // Meshes are enabled only for topologies explicitly listed below.
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to the cell dimension.
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< MyConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == CellTopology::dimension ) }; };
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< MyConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< MyConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MyConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MyConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< MyConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< MyConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MyConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MyConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MyConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MyConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
diff --git a/src/Tools/tnl-triangulate-mesh.cpp b/src/Tools/tnl-triangulate-mesh.cpp
index 4c83b97944ae3fd01f9387ed21643457795ab746..5dbfe4c5f402619c46c8883505162d8ee95792c7 100644
--- a/src/Tools/tnl-triangulate-mesh.cpp
+++ b/src/Tools/tnl-triangulate-mesh.cpp
@@ -15,32 +15,32 @@ namespace BuildConfigTags {
 /****
  * Turn off all grids.
  */
-template<> struct GridRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = false }; };
-template<> struct GridRealTag< MeshTriangulatorConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< MeshTriangulatorConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshTriangulatorConfigTag, double > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MeshTriangulatorConfigTag, long double > { static constexpr bool enabled = false; };
 
 /****
  * Unstructured meshes.
  */
-template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polygon > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polyhedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MeshTriangulatorConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 // Meshes are enabled only for the space dimension equal to the cell dimension.
 template< typename CellTopology, int SpaceDimension >
 struct MeshSpaceDimensionTag< MeshTriangulatorConfigTag, CellTopology, SpaceDimension >
-{ enum { enabled = ( SpaceDimension == CellTopology::dimension ) }; };
+{ static constexpr bool enabled = SpaceDimension == CellTopology::dimension; };
 
 // Polygonal Meshes are enable for the space dimension equal to 2 or 3
 template< int SpaceDimension >
 struct MeshSpaceDimensionTag< MeshTriangulatorConfigTag, Topologies::Polygon, SpaceDimension >
-{ enum { enabled = ( SpaceDimension >= 2 && SpaceDimension <= 3 ) }; };
+{ static constexpr bool enabled = SpaceDimension >= 2 && SpaceDimension <= 3; };
 
 // Meshes are enabled only for types explicitly listed below.
-template<> struct MeshRealTag< MeshTriangulatorConfigTag, float > { enum { enabled = true }; };
-template<> struct MeshRealTag< MeshTriangulatorConfigTag, double > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, long int > { enum { enabled = true }; };
-template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, int > { enum { enabled = true }; };
-template<> struct MeshLocalIndexTag< MeshTriangulatorConfigTag, short int > { enum { enabled = true }; };
+template<> struct MeshRealTag< MeshTriangulatorConfigTag, float > { static constexpr bool enabled = true; };
+template<> struct MeshRealTag< MeshTriangulatorConfigTag, double > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, long int > { static constexpr bool enabled = true; };
+template<> struct MeshGlobalIndexTag< MeshTriangulatorConfigTag, int > { static constexpr bool enabled = true; };
+template<> struct MeshLocalIndexTag< MeshTriangulatorConfigTag, short int > { static constexpr bool enabled = true; };
 
 // Config tag specifying the MeshConfig template to use.
 template<>
@@ -90,7 +90,7 @@ struct MeshConfigTemplateTag< MeshTriangulatorConfigTag >
 } // namespace TNL
 
 template< typename Mesh >
-auto getDecomposedMeshHelper( const Mesh& mesh, const String& decompositionType )
+auto getDecomposedMeshHelper( const Mesh& mesh, const std::string& decompositionType )
 {
    using namespace TNL::Meshes;
 
@@ -117,35 +117,52 @@ auto getDecomposedMeshHelper( const Mesh& mesh, const String& decompositionType
 }
 
 template< typename Mesh >
-bool triangulateMesh( const Mesh& mesh, const String& outputFileName, const String& outputFormat, const String& decompositionType )
+bool triangulateMesh( const Mesh& mesh, const std::string& outputFileName, const std::string& outputFormat, const std::string& decompositionType )
 {
    const auto decomposedMesh = getDecomposedMeshHelper( mesh, decompositionType );
 
-   if( outputFormat == "vtk" ) {
+   std::string format = outputFormat;
+   if( outputFormat == "auto" ) {
+      namespace fs = std::experimental::filesystem;
+      format = fs::path( outputFileName ).extension();
+      if( format.length() > 0 )
+         // remove dot from the extension
+         format = format.substr(1);
+   }
+
+   if( format == "vtk" ) {
       using Writer = Meshes::Writers::VTKWriter< decltype( decomposedMesh ) >;
       std::ofstream file( outputFileName );
       Writer writer( file );
       writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh );
+      return true;
    }
-   else if( outputFormat == "vtu" ) {
+   if( format == "vtu" ) {
       using Writer = Meshes::Writers::VTUWriter< decltype( decomposedMesh ) >;
       std::ofstream file( outputFileName );
       Writer writer( file );
       writer.template writeEntities< Mesh::getMeshDimension() >( decomposedMesh );
+      return true;
    }
 
-   return true;
+   if( outputFormat == "auto" )
+      std::cerr << "File '" << outputFileName << "' has unsupported format (based on the file extension): " << format << ".";
+   else
+      std::cerr << "Unsupported output file format: " << outputFormat << ".";
+   std::cerr << " Supported formats are 'vtk' and 'vtu'." << std::endl;
+   return false;
 }
 
 void configSetup( Config::ConfigDescription& config )
 {
    config.addDelimiter( "General settings:" );
-   config.addRequiredEntry< String >( "input-file", "Input file with the mesh." );
-   config.addRequiredEntry< String >( "output-file", "Output mesh file path." );
-   config.addRequiredEntry< String >( "output-file-format", "Output mesh file format." );
+   config.addRequiredEntry< std::string >( "input-file", "Input file with the mesh." );
+   config.addEntry< std::string >( "input-file-format", "Input mesh file format.", "auto" );
+   config.addRequiredEntry< std::string >( "output-file", "Output mesh file path." );
+   config.addRequiredEntry< std::string >( "output-file-format", "Output mesh file format." );
    config.addEntryEnum( "vtk" );
    config.addEntryEnum( "vtu" );
-   config.addRequiredEntry< String >( "decomposition-type", "Type of decomposition to use." );
+   config.addRequiredEntry< std::string >( "decomposition-type", "Type of decomposition to use." );
    config.addEntryEnum( "cc" );
    config.addEntryEnum( "cp" );
    config.addEntryEnum( "pc" );
@@ -162,15 +179,16 @@ int main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-   const String inputFileName = parameters.getParameter< String >( "input-file" );
-   const String inputFileFormat = "auto";
-   const String outputFileName = parameters.getParameter< String >( "output-file" );
-   const String outputFileFormat = parameters.getParameter< String >( "output-file-format" );
-   const String decompositionType = parameters.getParameter< String >( "decomposition-type" );
+   const std::string inputFileName = parameters.getParameter< std::string >( "input-file" );
+   const std::string inputFileFormat = parameters.getParameter< std::string >( "input-file-format" );
+   const std::string outputFileName = parameters.getParameter< std::string >( "output-file" );
+   const std::string outputFileFormat = parameters.getParameter< std::string >( "output-file-format" );
+   const std::string decompositionType = parameters.getParameter< std::string >( "decomposition-type" );
 
    auto wrapper = [&] ( auto& reader, auto&& mesh ) -> bool
    {
       return triangulateMesh( mesh, outputFileName, outputFileFormat, decompositionType );
    };
-   return ! Meshes::resolveAndLoadMesh< MeshTriangulatorConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat );
+   const bool status = Meshes::resolveAndLoadMesh< MeshTriangulatorConfigTag, Devices::Host >( wrapper, inputFileName, inputFileFormat );
+   return static_cast< int >( ! status );
 }
diff --git a/src/UnitTests/Meshes/FPMAReaderTest.cpp b/src/UnitTests/Meshes/FPMAReaderTest.cpp
index bedfb05f7aa3d522c4873f876a8218da36b1ccc0..e2126a10317095294e1abca79d24e68c4482ab9e 100644
--- a/src/UnitTests/Meshes/FPMAReaderTest.cpp
+++ b/src/UnitTests/Meshes/FPMAReaderTest.cpp
@@ -20,16 +20,33 @@ namespace BuildConfigTags {
 
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
-struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ enum { enabled = false }; };
+struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ static constexpr bool enabled = false; };
 
 // enable meshes used in the tests
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polyhedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
 } // namespace TNL
 
-TEST( FPMAReaderTest, polyhedrons )
+TEST( FPMAReaderTest, two_polyhedra )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::FPMAReader >( "polyhedrons/two_polyhedra.fpma" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto faces = mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 22 );
+   EXPECT_EQ( faces, 16 );
+   EXPECT_EQ( cells, 2 );
+
+   test_reader< Readers::FPMAReader, Writers::FPMAWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::FPMAWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+}
+
+TEST( FPMAReaderTest, cube1m_1 )
 {
    using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
    const MeshType mesh = loadMeshFromFile< MeshType, Readers::FPMAReader >( "polyhedrons/cube1m_1.fpma" );
diff --git a/src/UnitTests/Meshes/MeshGeometryTest.h b/src/UnitTests/Meshes/MeshGeometryTest.h
index 146e04eaaf72015306acf786f29ccbe82f340d91..01c2430a9009c9df3179b594033469e43ca8a450 100644
--- a/src/UnitTests/Meshes/MeshGeometryTest.h
+++ b/src/UnitTests/Meshes/MeshGeometryTest.h
@@ -20,6 +20,7 @@
 #include <TNL/Meshes/Geometry/isPlanar.h>
 #include <TNL/Meshes/Geometry/getDecomposedMesh.h>
 #include <TNL/Meshes/Geometry/getPlanarMesh.h>
+#include <TNL/Meshes/Geometry/getRefinedMesh.h>
 
 #include <TNL/Meshes/Writers/VTKWriter.h>
 
@@ -28,41 +29,41 @@ namespace MeshGeometryTest {
 using namespace TNL;
 using namespace TNL::Meshes;
 
-class TestPolygon2DMeshConfig : public DefaultConfig< Topologies::Polygon >
+template< typename... Ts >
+struct TestMeshConfigBase : public DefaultConfig< Ts... >
 {
-public:
    static constexpr bool subentityStorage( int entityDimension, int subentityDimension ) { return true; }
    static constexpr bool superentityStorage( int entityDimension, int superentityDimension ) { return true; }
 };
 
-class TestPolygon3DMeshConfig : public DefaultConfig< Topologies::Polygon >
+struct TestTriangleMeshConfig : public TestMeshConfigBase< Topologies::Triangle >
+{};
+
+struct TestQuadrangleMeshConfig : public TestMeshConfigBase< Topologies::Quadrangle >
+{};
+
+struct TestTetrahedronMeshConfig : public TestMeshConfigBase< Topologies::Tetrahedron >
+{};
+
+struct TestHexahedronMeshConfig : public TestMeshConfigBase< Topologies::Hexahedron >
+{};
+
+struct TestPolygon2DMeshConfig : public TestMeshConfigBase< Topologies::Polygon >
+{};
+
+struct TestPolygon3DMeshConfig : public TestMeshConfigBase< Topologies::Polygon >
 {
-public:
    static constexpr int spaceDimension = 3;
-   static constexpr bool subentityStorage( int entityDimension, int subentityDimension ) { return true; }
-   static constexpr bool superentityStorage( int entityDimension, int superentityDimension ) { return true; }
 };
 
-class TestWedgeMeshConfig : public DefaultConfig< Topologies::Wedge >
-{
-public:
-   static constexpr bool subentityStorage( int entityDimension, int subentityDimension ) { return true; }
-   static constexpr bool superentityStorage( int entityDimension, int superentityDimension ) { return true; }
-};
+struct TestWedgeMeshConfig : public TestMeshConfigBase< Topologies::Wedge >
+{};
 
-class TestPyramidMeshConfig : public DefaultConfig< Topologies::Pyramid >
-{
-public:
-   static constexpr bool subentityStorage( int entityDimension, int subentityDimension ) { return true; }
-   static constexpr bool superentityStorage( int entityDimension, int superentityDimension ) { return true; }
-};
+struct TestPyramidMeshConfig : public TestMeshConfigBase< Topologies::Pyramid >
+{};
 
-class TestPolyhedronMeshConfig : public DefaultConfig< Topologies::Polyhedron >
-{
-public:
-   static constexpr bool subentityStorage( int entityDimension, int subentityDimension ) { return true; }
-   static constexpr bool superentityStorage( int entityDimension, int superentityDimension ) { return true; }
-};
+struct TestPolyhedronMeshConfig : public TestMeshConfigBase< Topologies::Polyhedron >
+{};
 
 TEST( MeshGeometryTest, Polygon2DAreaTest )
 {
@@ -1107,6 +1108,199 @@ TEST( MeshGeometryTest, PolyhedronGetPlanarMeshTest )
    }
 }
 
+TEST( MeshGeometryTest, TriangleGetRefinedMeshTest )
+{
+   using TriangleTestMesh = Mesh< TestTriangleMeshConfig >;
+   using PointType = typename TriangleTestMesh::PointType;
+
+   /****
+    * We set-up the following situation
+            point2   edge3       point3
+               |\-------------------|
+               | \                  |
+               |  \   triangle1     |
+               |   \                |
+
+                      ....
+            edge1     edge0        edge4
+                      ....
+
+
+               |   triangle0     \  |
+               |                  \ |
+               ---------------------|
+            point0   edge2        point1
+    */
+
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 ),
+             point3( 1.0, 1.0 );
+
+   MeshBuilder< TriangleTestMesh > meshBuilder;
+   meshBuilder.setEntitiesCount( 4, 2 );
+
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+
+   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 1 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 2 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 3 );
+
+   TriangleTestMesh mesh;
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+   const TriangleTestMesh refinedMesh = getRefinedMesh< EntityRefinerVersion::EdgeBisection >( mesh );
+
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 2 >(),  8 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 1 >(), 16 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 0 >(),  9 );
+};
+
+TEST( MeshGeometryTest, QuadrangleGetRefinedMeshTest )
+{
+   using QuadrangleTestMesh = Mesh< TestQuadrangleMeshConfig >;
+   using PointType = typename QuadrangleTestMesh::PointType;
+
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 ),
+             point3( 1.0, 1.0 ),
+             point4( 0.0, 2.0 ),
+             point5( 1.0, 2.0 );
+
+   MeshBuilder< QuadrangleTestMesh > meshBuilder;
+   meshBuilder.setEntitiesCount( 6, 2 );
+
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+   meshBuilder.setPoint( 4, point4 );
+   meshBuilder.setPoint( 5, point5 );
+
+   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 3 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 3, 2 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 2 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 3 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 5 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 3, 4 );
+
+   QuadrangleTestMesh mesh;
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+   const QuadrangleTestMesh refinedMesh = getRefinedMesh< EntityRefinerVersion::EdgeBisection >( mesh );
+
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 2 >(),  8 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 1 >(), 22 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 0 >(), 15 );
+};
+
+TEST( MeshGeometryTest, TetrahedronGetRefinedMeshTest )
+{
+   using TetrahedronTestMesh = Mesh< TestTetrahedronMeshConfig >;
+   using PointType = typename TetrahedronTestMesh::PointType;
+
+   PointType point0( 0.0, 0.0, 0.0 ),
+             point1( 1.0, 0.0, 0.0 ),
+             point2( 0.0, 1.0, 0.0 ),
+             point3( 0.0, 0.0, 1.0 ),
+             point4( 1.0, 1.0, 1.0 );
+
+   MeshBuilder< TetrahedronTestMesh > meshBuilder;
+   meshBuilder.setEntitiesCount( 5, 2 );
+
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+   meshBuilder.setPoint( 4, point4 );
+
+   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 3, 3 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 1 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 2 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 3 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 3, 4 );
+
+   TetrahedronTestMesh mesh;
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+   const TetrahedronTestMesh refinedMesh = getRefinedMesh< EntityRefinerVersion::EdgeBisection >( mesh );
+
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 3 >(), 16 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 2 >(), 44 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 1 >(), 41 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 0 >(), 14 );
+};
+
+TEST( MeshGeometryTest, HexahedronGetRefinedMeshTest )
+{
+   using HexahedronTestMesh = Mesh< TestHexahedronMeshConfig >;
+   using PointType = typename HexahedronTestMesh::PointType;
+
+   PointType point0( 0.0, 0.0, 0.0 ),
+             point1( 1.0, 0.0, 0.0 ),
+             point2( 1.0, 1.0, 0.0 ),
+             point3( 0.0, 1.0, 0.0 ),
+             point4( 0.0, 0.0, 1.0 ),
+             point5( 1.0, 0.0, 1.0 ),
+             point6( 1.0, 1.0, 1.0 ),
+             point7( 0.0, 1.0, 1.0 ),
+             point8( 0.0, 0.0, 2.0 ),
+             point9( 1.0, 0.0, 2.0 ),
+             point10( 1.0, 1.0, 2.0 ),
+             point11( 0.0, 1.0, 2.0 );
+
+   MeshBuilder< HexahedronTestMesh > meshBuilder;
+   meshBuilder.setEntitiesCount( 12, 2 );
+
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+   meshBuilder.setPoint( 4, point4 );
+   meshBuilder.setPoint( 5, point5 );
+   meshBuilder.setPoint( 6, point6 );
+   meshBuilder.setPoint( 7, point7 );
+   meshBuilder.setPoint( 8, point8 );
+   meshBuilder.setPoint( 9, point9 );
+   meshBuilder.setPoint( 10, point10 );
+   meshBuilder.setPoint( 11, point11 );
+
+   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 0 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 1 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 2 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 3, 3 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 4, 4 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 5, 5 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 6, 6 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 7, 7 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 4 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 5 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 6 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 3, 7 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 4, 8 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 5, 9 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 6, 10 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 7, 11 );
+
+   HexahedronTestMesh mesh;
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+   const HexahedronTestMesh refinedMesh = getRefinedMesh< EntityRefinerVersion::EdgeBisection >( mesh );
+
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 3 >(), 16 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 2 >(), 68 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 1 >(), 96 );
+   EXPECT_EQ( refinedMesh.getEntitiesCount< 0 >(), 45 );
+};
+
 } // namespace MeshTest
 
 #endif
diff --git a/src/UnitTests/Meshes/MeshReaderTest.h b/src/UnitTests/Meshes/MeshReaderTest.h
index 9290057ddc490d3645e3d6c270aff4dfff5f83df..0ee553d8554778f3cf3848efe25a1b620a87dd09 100644
--- a/src/UnitTests/Meshes/MeshReaderTest.h
+++ b/src/UnitTests/Meshes/MeshReaderTest.h
@@ -30,7 +30,7 @@ void test_reader( const MeshType& mesh, std::string outputFileName )
 // 1. resolveMeshType resolves the mesh type correctly
 // 2. resolveAndLoadMesh loads the mesh
 template< template<typename> class WriterType, typename ConfigTag, typename MeshType >
-void test_resolveAndLoadMesh( const MeshType& mesh, std::string outputFileName )
+void test_resolveAndLoadMesh( const MeshType& mesh, std::string outputFileName, std::string globalIndexType = "auto" )
 {
    // write the mesh into the file (new scope is needed to properly close the file)
    {
@@ -57,7 +57,7 @@ void test_resolveAndLoadMesh( const MeshType& mesh, std::string outputFileName )
       return true;
    };
 
-   const bool status = TNL::Meshes::resolveAndLoadMesh< ConfigTag, TNL::Devices::Host >( wrapper, outputFileName );
+   const bool status = TNL::Meshes::resolveAndLoadMesh< ConfigTag, TNL::Devices::Host >( wrapper, outputFileName, "auto", "auto", globalIndexType );
    EXPECT_TRUE( status );
 
    EXPECT_EQ( std::remove( outputFileName.c_str() ), 0 );
diff --git a/src/UnitTests/Meshes/NetgenReaderTest.cpp b/src/UnitTests/Meshes/NetgenReaderTest.cpp
index d7caa9957b0c908109e3d055ee66a72652848686..71c755525c2bf3847c4ec4c9832e36884075d309 100644
--- a/src/UnitTests/Meshes/NetgenReaderTest.cpp
+++ b/src/UnitTests/Meshes/NetgenReaderTest.cpp
@@ -19,12 +19,12 @@ namespace BuildConfigTags {
 
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
-struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ enum { enabled = false }; };
+struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ static constexpr bool enabled = false; };
 
 // enable meshes used in the tests
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
diff --git a/src/UnitTests/Meshes/VTIReaderTest.cpp b/src/UnitTests/Meshes/VTIReaderTest.cpp
index 3b41a3b7020c5c42b437fa42e7162f7151614a9d..b0c6847ba48997ddd98b62135b52cb66ce59cafc 100644
--- a/src/UnitTests/Meshes/VTIReaderTest.cpp
+++ b/src/UnitTests/Meshes/VTIReaderTest.cpp
@@ -5,6 +5,7 @@
 #include <TNL/Meshes/Writers/VTIWriter.h>
 #include <TNL/Meshes/TypeResolver/resolveMeshType.h>
 
+#include "data/loader.h"
 #include "MeshReaderTest.h"
 
 using namespace TNL::Meshes;
@@ -18,13 +19,13 @@ namespace Meshes {
 namespace BuildConfigTags {
 
 // enable all index types in the GridTypeResolver
-template<> struct GridIndexTag< MyConfigTag, short int >{ enum { enabled = true }; };
-template<> struct GridIndexTag< MyConfigTag, int >{ enum { enabled = true }; };
-template<> struct GridIndexTag< MyConfigTag, long int >{ enum { enabled = true }; };
+template<> struct GridIndexTag< MyConfigTag, short int >{ static constexpr bool enabled = true; };
+template<> struct GridIndexTag< MyConfigTag, int >{ static constexpr bool enabled = true; };
+template<> struct GridIndexTag< MyConfigTag, long int >{ static constexpr bool enabled = true; };
 
 // disable float and long double (RealType is not stored in VTI and double is the default)
-template<> struct GridRealTag< MyConfigTag, float > { enum { enabled = false }; };
-template<> struct GridRealTag< MyConfigTag, long double > { enum { enabled = false }; };
+template<> struct GridRealTag< MyConfigTag, float > { static constexpr bool enabled = false; };
+template<> struct GridRealTag< MyConfigTag, long double > { static constexpr bool enabled = false; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
@@ -77,6 +78,42 @@ TEST( VTIReaderTest, Grid3D )
    test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( grid, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( grid, TEST_FILE_NAME, "CellData" );
 }
+
+// ASCII data, produced by TNL writer
+TEST( VTIReaderTest, Grid2D_vti )
+{
+   using GridType = Grid< 2, double, TNL::Devices::Host, int >;
+   const GridType mesh = loadMeshFromFile< GridType, Readers::VTIReader >( "quadrangles/grid_2x3.vti" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< GridType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 12 );
+   EXPECT_EQ( cells, 6 );
+
+   test_reader< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTIWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// ASCII data, produced by TNL writer
+TEST( VTIReaderTest, Grid3D_vti )
+{
+   using GridType = Grid< 3, double, TNL::Devices::Host, long int >;
+   const GridType mesh = loadMeshFromFile< GridType, Readers::VTIReader >( "hexahedrons/grid_2x3x4.vti" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< GridType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 60 );
+   EXPECT_EQ( cells, 24 );
+
+   test_reader< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTIWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTIReader, Writers::VTIWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
 #endif
 
 #include "../main.h"
diff --git a/src/UnitTests/Meshes/VTKReaderTest.cpp b/src/UnitTests/Meshes/VTKReaderTest.cpp
index 9d2df309bb762d2f3c0a26298165d238392f25df..a1fafba52ac4401a0209a564a20af9b3d4b622e4 100644
--- a/src/UnitTests/Meshes/VTKReaderTest.cpp
+++ b/src/UnitTests/Meshes/VTKReaderTest.cpp
@@ -20,13 +20,16 @@ namespace BuildConfigTags {
 
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
-struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ enum { enabled = false }; };
+struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ static constexpr bool enabled = false; };
 
 // enable meshes used in the tests
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polygon > { enum { enabled = true }; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
@@ -47,7 +50,7 @@ TEST( VTKReaderTest, mrizka_1 )
    EXPECT_EQ( cells, 242 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
@@ -65,7 +68,7 @@ TEST( VTKReaderTest, tetrahedrons )
    EXPECT_EQ( cells, 1312 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
@@ -83,7 +86,7 @@ TEST( VTKReaderTest, triangles_2x2x2_original_with_metadata_and_cell_data )
    EXPECT_EQ( cells, 8 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
@@ -101,7 +104,7 @@ TEST( VTKReaderTest, triangles_2x2x2_minimized_ascii )
    EXPECT_EQ( cells, 8 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
@@ -119,7 +122,80 @@ TEST( VTKReaderTest, triangles_2x2x2_minimized_binary )
    EXPECT_EQ( cells, 8 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// ASCII data, produced by Paraview (DataFile version 5.1)
+TEST( VTKReaderTest, triangles_2x2x2_ascii_51 )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Triangle > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "triangles_2x2x2/version_5.1_ascii.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 9 );
+   EXPECT_EQ( cells, 8 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// binary data, produced by Paraview (DataFile version 5.1)
+TEST( VTKReaderTest, triangles_2x2x2_binary_51 )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Triangle > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "triangles_2x2x2/version_5.1_binary.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 9 );
+   EXPECT_EQ( cells, 8 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+
+// binary data, produced by TNL writer
+TEST( VTKReaderTest, quadrangles )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Quadrangle > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "quadrangles/grid_2x3.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 12 );
+   EXPECT_EQ( cells, 6 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// binary data, produced by TNL writer
+TEST( VTKReaderTest, hexahedrons )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Hexahedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "hexahedrons/grid_2x3x4.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 60 );
+   EXPECT_EQ( cells, 24 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
@@ -137,12 +213,51 @@ TEST( VTKReaderTest, polygons )
    EXPECT_EQ( cells, 90 );
 
    test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
-   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// ASCII data, produced by Paraview
+TEST( VTKReaderTest, two_polyhedra )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "polyhedrons/two_polyhedra.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto faces = mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 22 );
+   EXPECT_EQ( faces, 16 );
+   EXPECT_EQ( cells, 2 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// binary data, produced by Paraview
+TEST( VTKReaderTest, cube1m_1 )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTKReader >( "polyhedrons/cube1m_1.vtk" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto faces = mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 2358 );
+   EXPECT_EQ( faces, 2690 );
+   EXPECT_EQ( cells, 395 );
+
+   test_reader< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTKWriter, MyConfigTag >( mesh, TEST_FILE_NAME, "int" );  // force GlobalIndex to int (VTK DataFormat 2.0 uses int32, but 5.1 uses int64)
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "PointData" );
    test_meshfunction< Readers::VTKReader, Writers::VTKWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
 
-// TODO: test case for DataFile version 5.1: triangles_2x2x2/DataFile_version_5.1_exported_from_paraview.vtk
 #endif
 
 #include "../main.h"
diff --git a/src/UnitTests/Meshes/VTUReaderTest.cpp b/src/UnitTests/Meshes/VTUReaderTest.cpp
index 9a37f765db40706dbb3d2dc551555802fa406248..8bead316c45b8802a8b777d0bd24186ade00313d 100644
--- a/src/UnitTests/Meshes/VTUReaderTest.cpp
+++ b/src/UnitTests/Meshes/VTUReaderTest.cpp
@@ -20,13 +20,16 @@ namespace BuildConfigTags {
 
 // disable all grids
 template< int Dimension, typename Real, typename Device, typename Index >
-struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ enum { enabled = false }; };
+struct GridTag< MyConfigTag, Grid< Dimension, Real, Device, Index > >{ static constexpr bool enabled = false; };
 
 // enable meshes used in the tests
-//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
-template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polygon > { enum { enabled = true }; };
+//template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Edge > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Triangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Quadrangle > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Tetrahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Hexahedron > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polygon > { static constexpr bool enabled = true; };
+template<> struct MeshCellTopologyTag< MyConfigTag, Topologies::Polyhedron > { static constexpr bool enabled = true; };
 
 } // namespace BuildConfigTags
 } // namespace Meshes
@@ -177,6 +180,42 @@ TEST( VTUReaderTest, triangles_2x2x2_minimized_compressed_paraview )
    test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
 
+// encoded data, produced by Paraview
+TEST( VTUReaderTest, quadrangles )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Quadrangle > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTUReader >( "quadrangles/grid_2x3.vtu" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 12 );
+   EXPECT_EQ( cells, 6 );
+
+   test_reader< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTUWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// encoded data, produced by Paraview
+TEST( VTUReaderTest, hexahedrons )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Hexahedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTUReader >( "hexahedrons/grid_2x3x4.vtu" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 60 );
+   EXPECT_EQ( cells, 24 );
+
+   test_reader< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTUWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
 // ASCII data, produced by TNL writer
 TEST( VTUReaderTest, polygons )
 {
@@ -195,7 +234,48 @@ TEST( VTUReaderTest, polygons )
    test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
 }
 
+// ASCII data, hand-converted from the FPMA format
+TEST( VTUReaderTest, two_polyhedra )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTUReader >( "polyhedrons/two_polyhedra.vtu" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto faces = mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 22 );
+   EXPECT_EQ( faces, 16 );
+   EXPECT_EQ( cells, 2 );
+
+   test_reader< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTUWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
+// compressed data, produced by TNL writer
+TEST( VTUReaderTest, cube1m_1 )
+{
+   using MeshType = Mesh< DefaultConfig< Topologies::Polyhedron > >;
+   const MeshType mesh = loadMeshFromFile< MeshType, Readers::VTUReader >( "polyhedrons/cube1m_1.vtu" );
+
+   // test that the mesh was actually loaded
+   const auto vertices = mesh.template getEntitiesCount< 0 >();
+   const auto faces = mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >();
+   const auto cells = mesh.template getEntitiesCount< MeshType::getMeshDimension() >();
+   EXPECT_EQ( vertices, 2358 );
+   EXPECT_EQ( faces, 2690 );
+   EXPECT_EQ( cells, 395 );
+
+   test_reader< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME );
+   test_resolveAndLoadMesh< Writers::VTUWriter, MyConfigTag >( mesh, TEST_FILE_NAME );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "PointData" );
+   test_meshfunction< Readers::VTUReader, Writers::VTUWriter >( mesh, TEST_FILE_NAME, "CellData" );
+}
+
 // TODO: test cases for the appended data block: minimized_appended_binary_compressed.vtu, minimized_appended_binary.vtu, minimized_appended_encoded_compressed.vtu, minimized_appended_encoded.vtu
+// TODO: test case for mixed 3D mesh: data/polyhedrons/hexahedron_and_two_polyhedra.vtu
 #endif
 
 #include "../main.h"
diff --git a/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vti b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vti
new file mode 100644
index 0000000000000000000000000000000000000000..c11d52388a04e0e872f8356b833a4e9ec88cf513
--- /dev/null
+++ b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vti
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<VTKFile type="ImageData" version="1.0" byte_order="LittleEndian" header_type="UInt32">
+<ImageData WholeExtent="0 2 0 3 0 4 " Origin="0.000000e+00 0.000000e+00 0.000000e+00 " Spacing="1.000000e+00 1.000000e+00 1.000000e+00 ">
+<Piece Extent="0 2 0 3 0 4 ">
+</Piece>
+</ImageData>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtk b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtk
new file mode 100644
index 0000000000000000000000000000000000000000..fb9809e9d28f4e66d11449d2aef37d4957ce0b67
Binary files /dev/null and b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtk differ
diff --git a/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtu b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..2747da2660ca24b23d4eff0e24026839530b1927
--- /dev/null
+++ b/src/UnitTests/Meshes/data/hexahedrons/grid_2x3x4.vtu
@@ -0,0 +1,22 @@
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="60" NumberOfCells="24">
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="binary">
+          oAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAQAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAADwPwAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8D8AAAAAAADwPwAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAAAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAQAAAAAAAAPA/AAAAAAAA8D8AAAAAAAAAAAAAAAAAAABAAAAAAAAA8D8AAAAAAADwPwAAAAAAAABAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAABAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAAhAAAAAAAAA8D8AAAAAAADwPwAAAAAAAAhAAAAAAAAA8D8AAAAAAAAAQAAAAAAAAAhAAAAAAAAA8D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAADwPwAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAEAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAEAAAAAAAAAAQAAAAAAAAPA/AAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAAAADwPwAAAAAAAABAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAhAAAAAAAAAAEAAAAAAAADwPwAAAAAAAAhAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAhAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAAAAAAADwPwAAAAAAAAAAAAAAAAAACEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAACEAAAAAAAAAAAAAAAAAAAPA/AAAAAAAACEAAAAAAAADwPwAAAAAAAPA/AAAAAAAACEAAAAAAAAAAQAAAAAAAAPA/AAAAAAAACEAAAAAAAAAAAAAAAAAAAABAAAAAAAAACEAAAAAAAADwPwAAAAAAAABAAAAAAAAACEAAAAAAAAAAQAAAAAAAAABAAAAAAAAACEAAAAAAAAAAAAAAAAAAAAhAAAAAAAAACEAAAAAAAADwPwAAAAAAAAhAAAAAAAAACEAAAAAAAAAAQAAAAAAAAAhAAAAAAAAACEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEAAAAAAAADwPwAAAAAAAAAAAAAAAAAAEEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAEEAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAEEAAAAAAAADwPwAAAAAAAPA/AAAAAAAAEEAAAAAAAAAAQAAAAAAAAPA/AAAAAAAAEEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAEEAAAAAAAADwPwAAAAAAAABAAAAAAAAAEEAAAAAAAAAAQAAAAAAAAABAAAAAAAAAEEAAAAAAAAAAAAAAAAAAAAhAAAAAAAAAEEAAAAAAAADwPwAAAAAAAAhAAAAAAAAAEEAAAAAAAAAAQAAAAAAAAAhAAAAAAAAAEEA=
+        </DataArray>
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="binary">
+          AAYAAAAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAADAAAAAAAAAAwAAAAAAAAADQAAAAAAAAAQAAAAAAAAAA8AAAAAAAAAAQAAAAAAAAACAAAAAAAAAAUAAAAAAAAABAAAAAAAAAANAAAAAAAAAA4AAAAAAAAAEQAAAAAAAAAQAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAHAAAAAAAAAAYAAAAAAAAADwAAAAAAAAAQAAAAAAAAABMAAAAAAAAAEgAAAAAAAAAEAAAAAAAAAAUAAAAAAAAACAAAAAAAAAAHAAAAAAAAABAAAAAAAAAAEQAAAAAAAAAUAAAAAAAAABMAAAAAAAAABgAAAAAAAAAHAAAAAAAAAAoAAAAAAAAACQAAAAAAAAASAAAAAAAAABMAAAAAAAAAFgAAAAAAAAAVAAAAAAAAAAcAAAAAAAAACAAAAAAAAAALAAAAAAAAAAoAAAAAAAAAEwAAAAAAAAAUAAAAAAAAABcAAAAAAAAAFgAAAAAAAAAMAAAAAAAAAA0AAAAAAAAAEAAAAAAAAAAPAAAAAAAAABgAAAAAAAAAGQAAAAAAAAAcAAAAAAAAABsAAAAAAAAADQAAAAAAAAAOAAAAAAAAABEAAAAAAAAAEAAAAAAAAAAZAAAAAAAAABoAAAAAAAAAHQAAAAAAAAAcAAAAAAAAAA8AAAAAAAAAEAAAAAAAAAATAAAAAAAAABIAAAAAAAAAGwAAAAAAAAAcAAAAAAAAAB8AAAAAAAAAHgAAAAAAAAAQAAAAAAAAABEAAAAAAAAAFAAAAAAAAAATAAAAAAAAABwAAAAAAAAAHQAAAAAAAAAgAAAAAAAAAB8AAAAAAAAAEgAAAAAAAAATAAAAAAAAABYAAAAAAAAAFQAAAAAAAAAeAAAAAAAAAB8AAAAAAAAAIgAAAAAAAAAhAAAAAAAAABMAAAAAAAAAFAAAAAAAAAAXAAAAAAAAABYAAAAAAAAAHwAAAAAAAAAgAAAAAAAAACMAAAAAAAAAIgAAAAAAAAAYAAAAAAAAABkAAAAAAAAAHAAAAAAAAAAbAAAAAAAAACQAAAAAAAAAJQAAAAAAAAAoAAAAAAAAACcAAAAAAAAAGQAAAAAAAAAaAAAAAAAAAB0AAAAAAAAAHAAAAAAAAAAlAAAAAAAAACYAAAAAAAAAKQAAAAAAAAAoAAAAAAAAABsAAAAAAAAAHAAAAAAAAAAfAAAAAAAAAB4AAAAAAAAAJwAAAAAAAAAoAAAAAAAAACsAAAAAAAAAKgAAAAAAAAAcAAAAAAAAAB0AAAAAAAAAIAAAAAAAAAAfAAAAAAAAACgAAAAAAAAAKQAAAAAAAAAsAAAAAAAAACsAAAAAAAAAHgAAAAAAAAAfAAAAAAAAACIAAAAAAAAAIQAAAAAAAAAqAAAAAAAAACsAAAAAAAAALgAAAAAAAAAtAAAAAAAAAB8AAAAAAAAAIAAAAAAAAAAjAAAAAAAAACIAAAAAAAAAKwAAAAAAAAAsAAAAAAAAAC8AAAAAAAAALgAAAAAAAAAkAAAAAAAAACUAAAAAAAAAKAAAAAAAAAAnAAAAAAAAADAAAAAAAAAAMQAAAAAAAAA0AAAAAAAAADMAAAAAAAAAJQAAAAAAAAAmAAAAAAAAACkAAAAAAAAAKAAAAAAAAAAxAAAAAAAAADIAAAAAAAAANQAAAAAAAAA0AAAAAAAAACcAAAAAAAAAKAAAAAAAAAArAAAAAAAAACoAAAAAAAAAMwAAAAAAAAA0AAAAAAAAADcAAAAAAAAANgAAAAAAAAAoAAAAAAAAACkAAAAAAAAALAAAAAAAAAArAAAAAAAAADQAAAAAAAAANQAAAAAAAAA4AAAAAAAAADcAAAAAAAAAKgAAAAAAAAArAAAAAAAAAC4AAAAAAAAALQAAAAAAAAA2AAAAAAAAADcAAAAAAAAAOgAAAAAAAAA5AAAAAAAAACsAAAAAAAAALAAAAAAAAAAvAAAAAAAAAC4AAAAAAAAANwAAAAAAAAA4AAAAAAAAADsAAAAAAAAAOgAAAAAAAAA=
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary">
+          wAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAGAAAAAAAAAAgAAAAAAAAACgAAAAAAAAAMAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAASAAAAAAAAABQAAAAAAAAAFgAAAAAAAAAYAAAAAAAAABoAAAAAAAAAHAAAAAAAAAAeAAAAAAAAACAAAAAAAAAAIgAAAAAAAAAkAAAAAAAAACYAAAAAAAAAKAAAAAAAAAAqAAAAAAAAACwAAAAAAAAALgAAAAAAAAAwAAAAAAAAAA=
+        </DataArray>
+        <DataArray type="UInt8" Name="types" format="binary">
+          GAAAAAAAAAAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw=
+        </DataArray>
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtk b/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtk
new file mode 100644
index 0000000000000000000000000000000000000000..3683bc542fb29403af0df455d911c2f6cf6f8271
Binary files /dev/null and b/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtk differ
diff --git a/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtu b/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..5baa036db153fdbf3d262731952b2f7bc04ca88b
--- /dev/null
+++ b/src/UnitTests/Meshes/data/polyhedrons/cube1m_1.vtu
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64" compressor="vtkZLibDataCompressor">
+<UnstructuredGrid>
+<Piece NumberOfPoints="2358" NumberOfCells="395">
+<Points>
+<DataArray type="Float64" Name="Points" NumberOfComponents="3" format="binary">
+AQAAAAAAAAAQ3QAAAAAAABDdAAAAAAAAIHQAAAAAAAA=eJykvHk8lN/7P46khUpKKpTShkp7KD0rJNKiSHtalBZJi0hFpaKkBa0oChHJvm/Z933fZphhZsyMFxWp5Dvv5p7bN71f38/n9/jNP/djnvc1z3Od61znOtd1zn2Px7vjxsbGmRD6/fmHuP798fhD7n/7+ZuvXto/KCiINaS9f/Bv/FEqBjy88i98Nms3D6cPwf9u77/zDrY7lP///f3f7EP5/6if4Er5H/vv8V/HZ/D6pz3/rZ3B6596/d3//6l//709yv9gn6HtDO3/3/KCfg/V99/k/992oPxL///mGXr/3/z1v7f3P/kL5V9+/3e//nu/h17/Z/8Yev9/52eD9vhT7/+pn//uT/8d/7ff/Vu7/zZ+f4/zf7/+3e7Q3/2bf/zbeP//G6ehn7/n51D5oXYa6kf/5q//u6vg8/d8/jd/Fej7b/PPOHgD774HKgP38a5+xH0uOow+8ORjyfu/4VQucT+YxH/znuQQ3x8RVy++nAKDxN/viOPxveDja0tInM/3jn91yCG+B5H8v8elMoPQz+dPfYTiye/S7w1516gh94PJfqnsfMNr/8N/75fQW+LqDg9txirXIyV/6iuU+aeepHw+KcdvPwKbKiJ43wd/z2/X9y89+ePSidF3L8sdCn4P1VAR+a81YXDf8cBWawQHzUurraKFfXCp9qzrZfYnnDmxfBZ38SDOl4+Ann190TO5DpJnimhY9qubiXx8Hxf/PO9Qq3eIxtKRhx9gRCCfx4pN8oy5UdNavC6N366ugCeQkA/hy5cyETei+rE2PZCQz+HzN3AI/ihIHr2aqxTnycevsNC9MMm7Vzccvspr1Wc/TSf61QlOX3TXJ49UUp/feDaHwLP+5PFkk+MhGJ/fdqvkQubmnRPN+zKI/oaR/Hw8DyPDk2nu+96Reo6o1Phi4JVC2DODlA9W6UxeFp6JznCq3NeaZBLnt+dPjuPvcWWVDxnXD3z/Z9FIeYH//8b120h5vh+GEP5RNcS/XhP9avkL58eTOtzwnaY7+VTaEDsz+XhHNonzx5GFRcfn3w168greAXeTZmhkIWmqwTWzyW0oPZCzqD4hEtImfutbe2NhvWv55l8VDFL+/M4EqUsPcjGic2CepBYDiRHW9beOfYRDjVvPhtJ0bDtT3/vuFRPnRRS1no1Mw9qQjZz7vmFQcbzuu+MkAxaN514EKYRg/C+dkme5cQQPHQVT7vkG0cMJPIyPv2lD10HRn/byqej1Y3y9zXjL11OtjZwv/HnCIb//iXeS80kwz/lxjkt+Hzrf/pj3lPa/4pNrUZ+S65vBcRi19dxTK7mnMKeuzJbM9UO//hyrSWWpeP0roi37YCC8dfTHLn0QjvjnKi3z34ZB893ErboL0nF5kpJ6weonhHwWNIxGervuiSB43oDeWeRSvSUW7waC+7qqs6B5z13u2DQ/PFJ54NaoVYA8I5NH50YHE/KhBJ4F1rYZNhonvYh2I1CsfXXljb5obBvY/bk1NJrAI0FbkiAvziwhefj+9AEfqfUPgpTLh/jZW8IvK7DmtOKLVrVwQp9QXJvtpiZ+ogw2qSpq59ziyH4VNa988NygBAErP2QduTC0v5/4dgjJJPGyvp1Zp+bm8PtrkopZTxfaGlc+x5S5FzavRA4eVZnNDXlaSeL7G/q2jlldhg0i4VdEODUk7nhN4huVWYCfC36VmqyvRXtv43ihtUEYfX/STsqLJBwsmxzy5mQ10S9v9CqI0jbNayDn05/9rcaESQ6daq4RxPoThv2P37dIvagl5QXzmT8/2wm7PUZE7A771m8Ucl4L/KQ0B4FWns3k72/NjctXc31PfB+qx2tMCV9t9yEmBRL+72+9uRgF/1vtK67o5yDefIKF3bxYvJkspMvxDcXAeq9pOrZlML+z8RAjOR1bTsd1Pd3si1+3NDTvdhdCQ22R6qrx5SSuL2OY29kqkP9E4u4dohdeFBH4mrxBfKHv4+bsPAIvINv9zX8uDQt3xZcMGxODFb2XF21RSERpVTR1ztd8RGq9XXThVekQnkLs/rCf169wiJVXfiqNz+D3Ky8PHw4utLbbGA8rTNwanJaMA9LR+Yw3FbhYOqeuZ1sQcuLapy0YnoMrst5afZIluDn2YH6JVwQ2C33W8yrLwcMpwzZ0l5Rh0r0715feq4Fjt23SuqW+cDnQpTW6LQPXW6bPb1peTeKTk1ruTCyIA8tQMjxAuQxGohtvyHTEQuG+WxUzJJWQr8P6vsSm11PCMEzGbEmK9UcCr8Buzyqpp06hqElN4/GEweH7pRH99hU4Efq8+vTacIInh7Tn8fD+b/lzkjB3v/bslAdxRD6fRcShONL/NC4nLdbuTkW2mfWqSWXF5Lwes9tbs3pvBqyUz1hcMUvj2/liKnKfTIlrVE/C8boUxpLn2aQ8v1+liKouOLVCIR3KFwJNronF8vnPpRLxIZmIP2E4pjO/Ju1MDYzHaRbVBiRCbGHe0Wuc1wTOiwt3prWzd2QMwSthbyph67g9gcQF6x9/XtDJeSHw699xWJlK9DuMwENhJynSPXsi5a958JvHg0bmbUPXRUEe9YPjtkAmo5bQM4vUh79O1g/h7eTPx4ZGEv89bydzERkwsE4u+xExPsVkXvHH+uDAJfrR8de6M3RdEnwX3B+6HgmuQ9cjwVWgD78f5YQ8h+h3EKF/JannmxN3f3rpRaCm+95GI5diLGcedk1pZ+D6tuMiW0ekY+kWxosz10qxg5YYLxrPRUT5yTceO2MxIlvSUsS9ABIz/Z29nrDxeJj1ctu8BNAvHJ0/qygX3DkG+3dps6CdtvnK18pPaLy4LsOEmY/2lQbLNqZxwP6+LXRjXCzBXwHbokmSex5w8OHVfxZEf8iEfdmwPaaK364Gk8T58uV8+XEsOJ3/VXHhfSgYtsv+SS8vg3fsWbPQo2x0iRYuPKGRjWETz8/ymZqNdG578a4PTFT2DNzqZBWg40ujRKfVR7gOv7XueRYT7sKj9J8EVaJ4Zf8yvTu+UPDcKv9+IguLP3jOn7o0B+0G/neWtMVDX6E05Zc3A0pBZ191DJSR8t/DvmYbpzAQ6v3TK9yqAu0vr714qxVB8LChvsCi65VDPmGHHNIOsl6fd8hl1xDjEv6nv8lVkvOcP14cct0VrMOCceytaauboVKEY6cZx+wpWaAy1/30EmJjc9KZ8ZM7iiG6++A5/YXRZB7Lxwv5eXhaGpmvrsrAaeajEqh0/eLZJx4RnU1PuLJsNPUwrjSy8gn7l5H+8H4gX2X7wlJ811a7t2R7MYlP3nutROzpS5w/OEfo8ogSpBwYI/5gWyveHjgVUvMkBI7HqpOk9QrhcySiSe8XDSd+VH48qBoP5QUKxVtsSjF1SR73zZh2kqe2pPDX2r5yXDmafe+9SSuJjxzpalzcUEXgdHi1TRsbpReOu5KyugXJlVBbMEuWeXCQJ8qoyfXs1DrQNh43pfnRSPyW/DS1lhX1BN6CQwpWW+VMeHmPms+p+D4/JObse6D5rg6Vozw7J0UnYIbErmGq53IxKzzhR9LcVtxJvLvYuDKQsE8mId+MKWN6OAOIH8LTDAnR8b0DByMwk33vrHNPDj5qNT5aYd6AvibbEW7P07Ezc7RFp3MajoZnDS/tqcb3gl/0gcsJ8Omgf1SwSsLaE0Yva4VbsTDivJaxRwTMPEuWN/4MJ/gbsErKtkHYPA9Od45uyoxMxq3O/jF1p+jo3e/mEzQ6nmg3FWaWSu33kupwX+xHz8D0zL/0nBl62MD4Ys5fdmAkPfVSNs/Aoc4Mnj5RhD40pJ59bGy9vhgu20MWBipGYjglZNcClyrSPnw940n+ofofOPohe5oRFQfp9SJuo7L/4hmqD1++BaO/0gxOl0RA64DohjFqBVgfIj1v2GUqPw9PH8yv+HGbiJfLB/cVBPPo97QybSPrsD9woVYy3xXgv/meUUncnPaqQo3LIeI9ncQFcfg3TSqb3IcQxG3NPV8yuBurcNdtg5QVJQyn1sr29c6sROed3sfrZBuwIZa5RP+8D1ZnJd2cJVaNm3KrvT7y4mPBHdWu8d/jcUzW9Oz2jhJCvoqUv+dwuC6c2QSz9cvpxa7lcLLR2XojOgINXXNSdNobcGTP/VRuTRlCl/bobmlMxJxRNk7L82vgrnFSYiC1HDeXK5k+MUzApkfzLGfMpGCaw/z4s5urMO35LuU4o4+Qkqn4aaJIRfOTxZlUXv7Vuuvw+9imj7gSSQtWSm/DsSVyxcdTK8H57Kq17bQ3AtgbNZR20/Fosr/1JucSmO6O3ND1NByUY17B3SYtGP40L5W6tBQj+8ZTPeoToF/9+sLGpzTIHjCflSRdPoSnFY6LDjKenG0cYp96wg51f9mBr3/dX/pHHJCga9vVk/xjtnseGHaxBb+WpD7onF03BKdhyQ8FjROHsxBz8UHL04BSKL33yFj6so23bi39EqldgPGKtsePrCzEXUZ11dbmdpiLONZmzM5GqY63/aQ5xVimcqd0c1QrNsc+cZMcWYjIm2kz9Mfmwt08t/VEHw0LOZpyzJtlWLai+HS4TzZ2bzutXzOL9lf9+Ue+ID24rybIE/j+NrgPJ/g93z87/9yX+M9+U+lATOxnCvYJNV/8x/0DvMvvOB86HAUXXeOi2FYqLBcYLZsUlgargWDXiRbeWH19n5fm6DbECSV3UJS84HW9d5Hp9lyUL9zeam9GI3FPrbuKOi9T8G1ysFrlHjoWOnRq2OiHkzy32/0OH5nWgt1Vj+kzv0ZBM2DchPSMIJj2bxozNneQx3neimUSYyJhNdHGy0mlGWdtg6dMORqLV8ayO0WlYqFjuiuua92gPt+CPEaluKfz29VoIfG+c+6rN9ukEvq04c7OGwovEQBXpQjP5nvBRLutCA+ena/Dek/qU1HlZConx4B415uLodxABG4w2hz1Iw0NSQ1zdX06cIDqPHA14gnqZz1IkFqYhejyG2Vdm1gkvuHK3GNJNakQfrfiqudOJvZoXws6IfoW63XXab0e84HgGZS33txvPXtfJMHDGcKTgb7Uliir0na8fKMoGWIQBs2WnTrSvtF8/h4OHF/MMJ4Y+o6Qz/sr/gj86Df/vQ5CPhgyXV7Pvh5+z9dnHQu7bFrsm4PDwX7xnaMf+5qPz+AS+vvD5duWgsthSXycyibkI+Dz5vWMErGIv/z2j/z1//JbQb77W598LsETRvZ3qD//sX+szB2yH1FB5lN/7ptVkrggn+fny7VkuxbTTCuXiaSQ47jzZP3L9uBXmFlrd1zVqRL3nAuzo3ya8Kq4fql/QgLS+1pitneUIkF52700LQo209/YuczLxotJYtYbMsvgF5cm/tOOCs1hlnenpQXDPSKt/OL2cgzvq825uKMeMS3zV/T6hGCc9qQTLfK1uKX4hXtiBnVIu7Vku3/KV5Lyvq31jeqbEvBYc33hQ/0SiD9hiRzwbyDbbVLsObpbvAKceeefVVRWk/yGwYlve/qqoHXDf+1tXrwW4CxJyjUdw3r8aPpVJh9WT+JG5jZK//yoJfDqv8aBb9dPeGdhbulR4A3H6huKAVcYSM7S318Yl42KFZEx+sdCCZyOROfo+BfnY2CfpRJ2eWQMH09sw5ak3Ly7q4Mx4GJy+KtkEA5y5hUZHmeDKTN1pM3RNJL/Nz6XhR2W4eEzx6UR8h8IHgbJ86c+bYR85p/4TyahTwTZrsawYpufjzqgeHyOAuVRCIzPOomV7I/k44Ys2E6wuLi83ZfAw/n6tLMR0HTUTGdaJGkPgX0E9lIwu7VL0zGN0GeQh4+nkv0VtCuoXwX+K9jXFeCCOoF/v4rQJ5qv53gO0d+sIfJcnDJ5xvteRMyr8CF5Tzk5f/6Uz4L76UAefzzJH7Ry9+5HvHyfr/8nEr9y34NnzySiTs4Zwk/soymXkLhgH4DfTjaJC+b9735XDta3f+wbOFQN4Q8m4hgTK8Z9PDlVOJWMY/LDxFyVP9KhpbLuYeGrFHI9+sBeKJ7t346Pej5mIr7J8JtquLySG0qsg614cU2xOfU/+yuEvKC9oecMe+y0u4qt8jE3QzTlMa/OVdmns7w+3x/HK1oWBhRmwmhv89remELULxgZKj8vDVfv+768Kp+AvdI0g8+rK3BEfmBu1JZkaBaeKavlxsHY99XlyxYVSHxXHPh9dwWadXfd1x+bBPUbP3u+W9RB+oPvC45ZBA7vjNklOz8FZ7JbjlDbeXnW84Mmk41L8WrTyvv6rlGEPjUwT9W6O+dLMjoVgzfMzi7AY1mvE5pKtaSeuyP1v2dGx0Jl1v4tStdLULM6OXCNciHRbgKcV/tsdjZsIttd8/TMVA+5AKw/9E0qVKcR4iaGhT3huSSexm30F5WtxrC1RrSSawX8du9k4W2tu4/f5HqyXT6eiQpJ429LfzaRuIBHYu74U9YxtVhGmaEz4XI2LsxVvOBoG4F3AdfjZfZVY4LIsO3B2mWD8umPDEMzy2HxlO1qp5QPJe8TNifUM2AdXv16nGgZtom8V7uSGo5vfe4j+3SSyXHZcOv17pyybGg+us4blzC8L3Z6c12hDA3NRWuGl2XijfKnpoNXciFDbZD+WF4C/ZKDjPGtpRh26t6MznvZuJ19VlKrswSNP28eiY6uhUdoKO2Bch40a49/3lGeBwfOhPEVYVUoFa0WVxWqxJimpGsWWVlYeaOvJOhHKUqaK2RTGrPwK+H5fD3eeAc0F2t8aa+AcH/BrR88vZMX7AoSj83Geu1MN7Xb1cDNlml6DpFICtx4K2x4Cwyzu110zyXghO/Ly2eWJqI3WOZXCC+fLjJy0m2hJ8JeLFPzsVAgNtmsDwWTisAjtlmKcZlD8FZckwqStR2bj0DvRB5PJMFDx88yFdsNOdloKpoS7DY2FgfqMsY6z6PA+cQPhmVaFizbJar0RqSiVDyf9l2bAqnyntLmG0kEnoPbK2U0tr2gwLBYpqz5RhT0o42GMRbm8ONGKYOMh3m2UY8lLLMh99RqxzALOmIDV3S7PIxA1BhOyOPaDH6cDGgj5etVNrHseeue9ptVTl6BkQi1TRCiHMpBt+iZZ+u/U3FW5QjtQl04dGRUrZCQidzQ85O7jVshatS/vW96AC6YjBE5plsKndSLoycrU0j80tcTzZ6cXJS5Wi7zH0Ml8aqn79JZSSVYuEy1PyuDV2/dYXzy0YtEYfnMw+MyePN08ziHpU31CLAr9Vl/JAla8fV1vlNLsWBFEDdsTh1+VI+tHv4jGxNnXFz1Q5mX93+fPVed00rqaf/kG2d5UR7En6vcPKlIQfh0g3TpLwnQ9Ih5fEM1AyI31C//9KZCr9F8do59Fk7Z7JGV3hdK4K2IWCZcck45l8Rz+4/VvPFqhtQrygiXujxEfBtWcXf2a8SoeC6UNGnEov1uUdUfc7BvwnFPR+ePcN6zwS/cjoLjL2XLJ+zk5Z2G8qm5s2KxlxlVu2sUFU5nOuZKTcvCCbdYXbpaBqIPqMj4WdXggJzEIZWEfLQ67+2fdiEUy6+Id2Stqoaz18rLx2bz8qWYmYvXjfGCGi1hdoV4MWR/aHyn2ZXgSYPM7WtyaTjnuXSyt2gD3nbEqE6aXIRNaaGMioIYDNygVCUplsK2QZixLr8U6kH6uqqa+RBe2py2Va4Szhb14lVmeWS7/Tt9VuavKoWsvFH/SV5dK7qvo00zMBwO21I8rNrKMW3Dq+KEyyWkPreQ/nI5ry52S3J+OH1JLmpnl74p0ktBhvDz9S6etdC8bJ5hNbwQo57pMdRm5cF5R9DBUdYV2Oogc7q2JB9b92yf8CwzF4dds1Q88hoxPHOb40RKPsqLKPUsiQzUrfFz+BJWDNOZTRoD1s2k/4do+n5rjy2FtNiYO8pbB+Phb/0TymFZMiwjV6SG1D8zTNG1w6oIldmd8yyn0mCznnWGpv4Wi0Ylqj2RK8SPML1rGZYtJL55UZDV6yO8fPSeD/XzQyqJswJM1soZ1uKSVsrezLkVpB1mdJWv33KuEcuPOvc/eF+Gh0Yep1WCP/DH0a4GDjMTLtmmVJPyWqPqaxs6mjE/SXvG0h2lpF/Rri1ll45txZnwn6FKc0pI3MeRc5q7nIp9X0Rt0qLLSJy/ftaR6+rQ/Oa/749y/9ofFeQFgnqXfz7QTv7uT5w5JL/iEryUv/IuwXmCIF8S4Pz6ogllMsH0Bdo+0Lj4qL/wGhMbxGdZjPJvxa/ouRtP94Yh6pZb5+duDipq5Z8+VaKR8o56Ou9sAln4ueLspwN2dDDFq7on8eo5vjwXzsNPstlr6Lz1u1vj5vMgCO3RfeEtL8DbSB4+LuCn48R/thXWNeP1o3kyNnnvkJ3qqu36vY04Z2xEyUZ38dVmkdhzvfAL24ANpVN0S5extQj36Yn+opWE2NlZl5wM2vH93MeN+xuq0UtZ6k95l4Lx6lc1D57vwDGrgF9Zi+shqRPF40mGzJ07F0ct48DLQ8J6zSjefL+bVk3l5X2+kSu/fXJsQ6tHwaryaQ3IH24jt00oEr+4uddiyun8/XDdBlJPvj4s/j6bDRU/vFdGt42LgP2pufrrZ7LBNlvaf/9I8xB5JnH+TkGC7ySefAKBc9AT/pynJ5WU5/OwsOjrZ/+Z0oP4xJGrMoOE29BcmfhlrXQtYmhSvP5GEf1l8sc/ioL9huJ7P/PyFH5/uYQdGuHkWzfce0k2iQvOuQ7ohzF+Xu9Al+cChchpXEw8bOuVZhAD9XjvBRv02Xjt0nWoJ3zQP5O3GvtcV2PiaNHSntkvGYQ/hPPWd89VClVMcMq9WqReDMq3qof2VN1vI+RZhH9GYqJ1v+b2ajZfnwscUv6Z2Y9N81vb4Rx7f5PdP0xST3VTE7eAYDYKwsvzDuh1kPK/9RfuIHDWEJxF4EP4j9D5/GeZJM7nZ/Lt4C3gJ/Q04fD1jGSSdcdv+dMMPv6FQ+K/201rI3A2Od8F8/zPfS4iDrDoQ+rUSD4/m8nXP5dL7gvwr/VkfBmQLPW+rptInDdVk+dWAvkXrruE1YsayX3geWml2q6tH4k6rYbkEZxnPpM1Vcl+RCH3pQVxhq9fKxlXBPhm3WAHuXYqef7Ivx9L2IFO6M8h654/nyvqhIOTeXGqYhauzvTUmaJUQ57XRPpNKVuytpDoVyWJ8+u1NL595nOJcWHBvn7CrOgfn8Cls268nM4h/JZBnlPz/YFDjougXhT0X2B/Pp5GjDubnBeCdn/jMqwh4zJYRwv2lQT1q4D/j/15np0Mb7xxlst+Q9SHjaQ9+OMTBtWVqTtd3xDnvmu5f8b7VBo5ngJcsO8/dH3i87aS48l/DobY//KgEM85dv5ZZ0u3DTnvDSH07CD3u/7wCxaT5PkTb4fwKpPexm1voaeS7PNPHBWyFcpRseosEv90f/ULS15+tzbZcfTYcSw4eL3/cWZeJDoso0aVVrTirUus0DIev0CeumFaYYwKheAZxDNXpbpNGkvgU9oJnnBsvJHzbEWugJ8NF7w8ln8zG9aPjV86Dq/GdIeKOVvGtuMpM9/4sEsSKOt2LTltWwfDdz90VD92IP8LXXkxr/55YvH2TlpRHf7Tjdo6Nkw4QTz5KNiVfFzqN0Igz1tXl+WHLhobhv4q/7kBig2YPYJ9sntiG+Qd80bNOpeIouDupdPH1WJ512H/CVXtcJVRvqh9rxw7bJ0uVmwrQ+hsNY0xBzh4rhXkrRteg3s31G5JXi0F+4aF/ci3XPyKNPQaS6uDd8AmyZT5xRg2+uuX8TVsjFT0tr46hVd/lSgo2NtVkTz9dhrmqcpFOJ3xMOaKdS1k1o0723KtA3ILpyYuq6mDgsrrOrOyCpL/su0/ubYXi9EnIZSf6VeNc66u/8jFMOAWvaf9rWs1Hn+9u/9RUT76E1iJx2U64HS3LsknoAwv1m5Ts9MqRlD1ApEjXh1Ic1c6u7L+P/WK6p4wXt3ofuzVDa9KBvJTA59rfKqCz1PG6dXrSmAy6qSm71YG9leGpZYdq4X/9Pm187VrSH2MeqLeTiuuxOoct4U3ptSS+OZHveZTN/kjb0VG0q5MCmZ49jo7fW0icTr3/JXIGirWjdZ3wSwaTh98ydgiHo5ddcKbB+wbMWdHGFtRvwUL+o7Tknh1qFiRFe3n5Ub8mv9kZt9JGsnz6HDF9+vfqFBi+zKuj2vB8eNyi35u5tWFMbPPpcVR8KWv4nSKJR1X3h6XzZaMwLzZ+9aMyWzEt19inMoRg/pMX1w0S7KBgmEiem7zNahYvyKi2KknDi1C368OHKvHCvYmu0BePyZ+Z+54djQb7bkPk9+eroNfWpritiAavJ89yO3XyUK8vPzqz2troGCX9KO1n4reDcZee85W4KLT3di75wux06FzhaUnFSNDg+7X36nj15nUQhg2VVbPsquGsmjh+idCJSg0k1jaJ1+Dq4wb35/w+tHlcbdabFcVejXG5V6Uy8GRIwd05cKbgaSPF2mGlXDgjtbd9qwQWRbXl86UrMc+hr5oUEoJ3m2U6x5tUQbhpxkX1o2rxw3l6peNViW4Xy9pYeBbBpG5d0aHrqTAqcaUOut+K9yKn8jZnoiEZvyBXPvXlZCz69nn39aMbedmRKoPz0XjNOvLFwJqMar/9flGKg0zNi1q+xbug9TpVY+8efVH/dJNIhVGdBK/vld5LWtlDcqMtrZNlx/Et6/rmrZOlIrFez57v93RRuLGOZrtn982ITb8mfzIFVREf2xePk0xCSp2+8xihAQ8raQ8a5+h/khrCqFPyxCeBoiPvbkmpp+CSOH7LjPcwnh11YPFlzj1SD9cEdVzjYOGJxYGX5pSscd0VfnsnVwwDRaKGyxj4hwqeeV4GvyWdV4t4cV9vnwH4hbUP2MkhQ2RZ6GoZj5Xc0I0Ke9tc9nUh8mCZ9juBrs5vnDQ95hnp8Ih231zw1nLzTycL7+Wxce9mdAdPuHOnNIgPn8Vh88T2PEnTwch/4tJ4nweJl+fCjahTwxf/j2Hj0/kEvrHEPwdfH69dqK/qX/qn9tO8ESS+hxhON6L7m/DtOeL13SlJuHBwM5e7j42sixHq0h/oULyTnTIJeccNBz3eF4Wz0bH7qMOJ5l0bGo6qT9eLBisvOO20xqYsJl3IOibAY3EMyljZuWKMeFc1kQRL2/HF93DbhsmxeCkdL/P8xEsfFEz9Zy2blB+/0+LrQ/V2hF4NLjrvHULehK9Pmqbx0MpdN3UzrR2vL71sTIlmbeuLn+/3VE4l89/m4uFRkEDm28Mygtv7+TOfcjk65nbQuifSuAd/P5ebcN3xTA9xXuZfH3ucPj9nUjHtsyarREhkZCMSis6v5jNt7MRm/CrLNKefB4GHhRMfmVDySN5BOP42/7Lckh58VkV2fKjqLg7vGn++SehOEH5fO1qdgu+GL6QsuTFxf7GJ4opUzLhPvaGXn5CG9pWHzkYXkpBkqj5owWhqTA9P9Z71BgKn4dJgce2ap+LixJhf9zuy+0fNAwcXXbloU0TUlO2B2w+FoP0Ww/V7j5vwcnbRoaJ+o2QMrhg2jcuFbtc4quadKk4u3K6jKRiPXatdzMOfp7Pq0NuHNQDHRzpWS0y32uRqc5ixNYV46jdde/5n1qwarvS4kCjFuycd2dU9NtYmF92DjN4RYX7yc/aK+QpCPd+rlwzMx+uc5X92Hea+fqoNfHPvelpOLFl9Ae3QhqyqRfkMqj10GWf6XtzMw8p89fdy/9FwcINE5oqrGsg9UN0m0tBBdIspqiI27bD+7SY1z9ry2HndYem8aEWN1OtO6rM2iGndEL5q1M9zH8YLdL/VIZ1+uy6piI6bB2dv/48WIdpl4Qul7RU4NGRjimfDFtxsPH4JoldJVDSqzs3ll0PyyMRipUyPD+W8jD5drQCT/za57Yp1+KXkrEvO6SFP47JXGLcM4h52kHiutzhvd7OmfzxTSXmozuHwPP58qcG81D+eUUJmbcJ9jH45x4VJD7hkKV80gUmdssmUxbufAt50ZOmlTa8/ilnumZd52JdU/bhFanZYL30KhB9UYH9yxVzjk8flC9TjY5SLqrEP5O+PL+fw8ASscUqljNjEFh84NGJumw0jrx3V+0qHY2rfYxchieBtebFOMVVRejt1z0Uu5mDFm1Jmx8dadAZviTIKqaAbLfqtmrsPel0LD9reClUu4wvX8jCSImbFE5oKCl/aNrtl+EOdNjXTrr/0D0ZEnEj15ufryB4OHh6eIzsp8pYOGgPn7mnk8B59aRAfwG/3NpT6la8+pMv/5HAy7Fv5qnti87SIN/vcbbQPwuNSaW6DxbnItL2bOKhje3QXHqp1U00AouqO2PLRlfDeEuxkCavPq6/v+X9g4thGKn8fPvmlAKsL/shfsSGjc66zhc+N6IJ/YtQfmxjiXo4F/Yyl+JyZuRihcK7r0c8U3GD5qU1hdWGgD3iESWuOViUa+MgX5aJirH2m6sYTMRwZ5tY3c7EyuWpMetZYfi2zXf2A148OFs6SWxnSCkc2grXyrvG8vnPceDQfJG9c3gGVBQxn54VgjHb/5l4bjYTovH+89XXpaOpU+xOYU8m5EquHeyXasNqlQt+nYp5iJ5pVzR3dRyfp5sJaafGdcF78iFc+PK6htwbfru6bII/j8QF/Qoy33D0fEE2njya/uRcawQ0FL0Xdw904FsBJy5gQxbsZte9qizPIfXnyxcSPCEkD79fJcjPGbcprusT+r7V+KqsYRN2SINEs9yYZ4hBgGbpop1bGNjluGH6rqoMlJ+3rr9zK44vz1s3Xbx2BmfVp2O8zsowa/1PuHNGP1mtiY3qffb75u+MQdL5eVrGBQ3gzbo1xpkcAk8BO4jxvLWzjsC5OP0BCye9z4aJyHVt1xf1kKYkFMrqcvDBSCyjrigb3a228aKPagh+Jg6s3Ku6mh6Ed7V717Z2NhE4B1XDa2pSjVMhOovbY7+KgtOzRn2SPsuA9fHH/c9WpWLbvYik4MJagp+NfYESTlFeKQgYlzVuT1s1gbMIPIZsV+W71tKt3HasTcu8O9UgGitijV9M2SZol0XqUyMp99SqvB6Soheman1ug8vAfO2bN/xw4EsaJ2gPDc3Zs8uzmRyEVWQYsE8l8fE6Oh8/wRoiT4ezjsQqFyYN33o43DTdDGzSyEs77UuHwsYl/4gsaQObu0lXPyMW8f+oaq7i5W2+yt+dkt+xcULkNb1CKQmNa0wmzRFjAKKBu7PKaRhbUVT5IzwNmWc2veqNa4H7Z6t58ilsvFQ63/tkUiTe5Vx8ZnyLhvUfgw5cm8tAEv391IyOVEg1ndPoNGDw5QcYpJ4rnlp+ap1Hw9W1r5ee2MGCkcmWh/YVEfx2b7cjhRO197QFA0d890/6cDsVO9oemx3mUHBviezRx1ZtMPFbKJ38IgJLwmO1jba04PST6f3GFoN2SDc7wbY6LcAH9ZQMkbZwjWiB7OHENuP9LFyUzYhrXhqLK1Fv1HQ1qQTO5uUZr++8yEhF7s+tcUccqaRftVjFZBl0FBHjW42Jj8YcFFrGgcL85J+BLkV4LbSJ9smviIyfy7+Gmr1rKCLidjk5j8QzuAo7F5Tx55FVHunPtsvpoctfl0F//UyL1nF1mJn9UlSpLwATrQ2/pLZTkWDzVLhFtg6XQpKjZ/Di+0OphOiYVVS0Fx88N6+qAWN43rd3TArcdpstyg9rQvISy8qLjHqkXJY1S4osgOnV7mPpixrAbrvbsKu1geS/nMoI2curH46l7tZ/sqMCkb8qQw745OLx26iIPudapJ8+la8TUYGziy6Pa74bgymc56EyjU3Y1Cy5VTa+hOTpKWG9uv6eioLFwnr7daowXNyqZ7J1CphcDdnuB/XoHl52kuNbDhMTbRn34Z+g91p6v+YXCqRL8+NCbxThWIr6iaL2CPgN3M9+NKMREu1Tj5mvrib5uQd3n9g+mgZZtt+rjnf1JD71gX9Kkk0rnv4MeDT+agVKji3yabwSi73zONv17rZi2/guhTtSpUjZGHVtlmMJZGs9njx6UQNxkZLCN7q1mBSZt9G0OAz2N3tYrTOYeK6/uf3L5FJ4vM1qNkwOh8I/E2MW7WLBoFXmgN4SKlT2bPSOmpUAP4tta9UvdYA2Tfjxq/QyeAsL6boYpIHbmaqz+RAdlQUGomtty2G8pPZ44NZkrF6Asx5zeevStwkeYzqKoXlljWXx5GgcvpE1QsaPjtLWrXnT1evwhOP9lJ6ViB/vz2evNuPgH6kv94+Mb8T19ZvXP7SKgMKTQrnHGmwCryZ5gndeDk/bSods7LCLea1V2LWYWntR7S02OMw91z6OCY32ALWxibUkD5+fDZtR37PCRlJI+UuJF+MO17bB2PGli/KwWhL/LU9n4lbC3tbYY5V/4mYsAm/CyR29ywImJBJ2Y8Oq0CrCewSvrlft3XMqIB9rpXxXRlu148JHzasZ+akorlM4qupZBj2zu+oj97BRP64s3D8sHFNCK8bWbajELLtFtHBHnh3iFUf+FEvE1Ym/FDwTC3DTfHe46GkmgrXrPj25HAOvqHU5B9QKSfnWZUEf5n1I5fNklfFxURYoF3Ulv40JRkSL2dO4vExwy+ps1xl2wFh9JzPiRRlytiy8stQ0G6bvLI02zmcgeUGy1ornhWCcepK/4Xgmv102Gyve7ju0KakY29MXWneNz8G77REj9qR1oMAgI/q1VDoOmqhx1StzCPtwSfs8jqKKcw8X4OQPk50vJnLQU/lRo1CzhrBDOc5spbnuD+VizG3b3eW7sjFlk/FXKeMSEk/kjhRJuV6FHLHx50e15pH4iPTE4BPzywg7FJO4TeN40WvD8oY8P/T3+y5D30tYrjS88UA3BzW+IRVq3MH3YDIVDYLbUYUd1v73uBNYKLTUDJUPi/kTd+OgPca72rUmF4dep3cf3lILn/lXroZ0MBB/YukWLaM3JG5EL/75kMbLL3zvib2KLYDkt4Gdj1nVsDEVomqdYMNw3Mob6jdTiX32hr/2ZR9W39Tr6qpHYq5laW4ZG90HT/20HgjHhmEl3huyGzB6vNz2tt0ssl1+Xt70135t9vhTXUpCjaQ+Z+pcyiWNcxB84ZLXmL5GPG2WvnKhn4P6WXLrhrcm4omo0eeeqWzMfswwmyhehZ3coGApw3BIi4yxE1JjYXOnxqP6hjq8bzDePdv3Nag1I7x9MhlIUVh3fPPzChKXgNorjUl0bBgx61Dz2HKEsoIn1Rz5iFqloPRFhR14GWK5WLq1HJNKn3NUmxOIdln4z7bkN61qkkfp8rKp05e247S5WJXhzVJYFr40+doVh4jfb96yYS95pfGbbCXuMQp6nnZmE3qy0fLUt23RkgZC/498+UtM5NFUnd5klaKqwobXbhhf/1ttUJ8fZX47oPLPfunw8t5jnpIpUbUETzx+ZdVlBM6qxKSuryqTD9dBe4P30baOSqx/67H4y68KHEkoXrF/HxWXSh4J6xjGwmSSXpWwSB32eDGNFMvL4XdsXKTIsEI8vyrptcyqFK6J0noOhvX4+VH9sJNJKbryXHqnmVTC0GeExRHxOqTedN+VcyYVDjq0J6tWF0N1wZNGi8UUlPmzptV6FuLIrpOH5zypg6zi2aO7d1fgbY7Ix9vTKnBowhqhLRfK0HBdg146phkbMHXL8/o0fG06n9B9oQL7iqe5H5pcjSOG2VNsH+TBz5x+wLSqDcKvNc0NcsvxIUZCpMM9C+JVLob9i+iQXpArzXDIA+tQ+kJ6TAUovZYHPJ/R8MPmxszFakXQOT9RonGgCEvaLcKEk9uRP7ekQO0cr36cPn3N93+qIRbvu/WWVDuOnDFdMlWyBLtsurVPvc7HSFn9d/Hfqbiwwb1HrLkYHGeZ/Lh71Qh+2O12cjoF220pI3u3VuLMZovLcxrKEf9+jGgMrRxhp+YOj2HQgLlH5KvkIuFgutTM4Fg55Hb7haZ5tCB3+0PtCmYBjm7SmWJaWQn3W6GhF0e1QrMj5bz7vDSM8VmYNvZtEXLdvs3wUKVD/PLEHa5bSnHovNzb8ZYlENGriXEzb4fwyZO1e5oLYebz9djWzmrca1zzvsCdjuESDfnZA2/QnvfDbccTXnwQVUu6F8MAI94jz6EmFY9MPd1CHpeBGj76pfCHNvR2h0sxx6fhpu75uqK3tfCNHxOq/6AdzfEj7g8PisBa/Wezzl6jwXxvoUbrqiqkLnEQLvLMxJWKCLPpVi3o3Lp2B6u+DK1zM6QyX+Ti8nEJ5qn0RmixSkNH2lbi4q3sx1phWehylpfZw8uHPp20nVhjV4N3YzQnH/8UgldW9+/WZrbCIpwbOEO0Cu7pN3YmCMei/sQp7UULqZggdHlPnGkVzg9QP917X4DorI0O0+fx4k+zmU/S/DpsXbJv523pJDxWXpKx4kozxq96/XJuTwUW3FTo+fY5Gjsj6TIDhlSIqWyJmuRfiatBoTsMD4XigHeRtN8sCqZpPHun/qUUtJDAliuv03FjPZ1JbaqFw9wF+3Zep+DSAXV3P/Ng/Ofnx9IoCLVTkZrgXgv3IyYDLpe88ZbpXro5qg7hXRKVZxa2YE3U6I8rlsXiu97+xLfa9QjLfiY0k9VKjotZiN661bMbcVja8ug020YoOHWPWlEWBZ+z02qsFzTBSfF4tVpOPckfU6y81O8rFeOF/rOzPIjH+yit6qfw6o/ukOfCwoNx79m7JaUbVvHytq+S97mva3HRVbi2ozEU15xnLXc9xcUkP0dTY6/B9zoTQ62L946jwLKMYqUSM6inmKPyZbF4AT7oV/w438yP245MMs4Xyc69Zbu1CSZtu0Vf0wb95/f6wbPL0PNA/jkg9a/zQ/453eC5rEBPwfs+f54rC+Ihl4jPtVC5ZLzTeV4+ifPjZD2BZ0LPdPouVdtOfAmgvm4tGfz/AAFenHRnk6sdlTwn5F8DMbH93ZvWk3TY6wp1DyRRifPFaEQ8evrP7HY6TnUz7rVatCP6x6RylxOpEPM0/JC3i4bbWRPWeba3o3Ta9OaVJTG4NXqsqpN5K6h6Bzdn8OoyAT/n8Ial/1TRYHzq0KQ6WzoqzHZ5pRmkwFX41nJLVQamtgQXzv7URspLbX7tpDO/jZBvRcpXj7s/zVOwSi5sr3IDAztGFH4Wu8WrY9S75iMgFuaPnmeVZNCw51TJjK9hzcRzEVEw9lngmy3CQNPZfJHsb61YfD160bG2NNyad7BkfUsLbu99vFFYlYLINrExSYfSYHBuopnHwTZIHrlsoLS+CVVm1+9GxhdC+1PvL7ExVBwf69Uq0kiD0gEzix0/U8EsS5nlodcCN3XWAu0LdNIOi6+dCTF2asUui6BAsYktYC0JLjL1zyCfw/nQmb5uPS+eTXS0sxU3zB6Ct+N+3ZSVJT+ycWdrW12XLRvBn6TyPIVbEKvCpF72z4Wv3Q37jn4maktmRIUqtYAdOWXSSK0CuLw5NyFqIhfL4iYP67ChoXDRGso9uSKU5m7v6L/Nwa+yLU57QiiIdrrZTF3MW4/lmxXTZnTidq5R2rtZrWig6E5N1Kz8Cw+9oCc37HUhZHuKJ0u87IBQYB/dYqADC7ftXxv3MhdZSX4mb1czUe9fIJVu1w6x6z8aou4X4YjdAkbSYhZmD2DUGBM6bqZe5dZllWDj1kdaGSFsuD5/dn6raBvSv2V4jO0qwrnF4dOHuXCQ9OPBiJ/LGAR/Ht4/GhURFNuBD8+S5n7cweT5k0vrTr9yJL2ftmjcc15/e2bLjotmwkZhdMPysU3IXd09Yti4KrA/jSsK2MLBC+0kSrlnA1Q/PBfLc6gl8Q06nlvCPXhx+/TWlOWqVaiapt9nycsrsfOfeslWKgIc5FOu5JZAd4SNzJaDDNxzPNzW4EBFVr/77g9VJagPWMmwMuvAsnndL8oCmjHZ4tWrz7Mq0LZ6XKDWunZYrhuben1FE2zol6J+bi+HiP5TrbAbHfCoGXXBYBgVu01CqsbWVmIAvlteBXHJc4qgIx5lS71KyHOKsDOJq5ZYt8BL72WQnWM5MhU+njNfzEHWR1vxuj05cA3VjJjlQIPJ9ISskT8YsJP40dL7Mg1p57WeCVfQMCbPaVt+AxuLR0pFO/Lq5fM3fcaq/GzFRfrB26/7WVC+rj3wfVUhLhx6KxMl245f4z7u5Ggw8SijqG/U8hLoeTnM+bShCR5RfRr6NR3omdyT2bkyDh/Prlk0I64FjuN/iG6bz8FhyVmnR4nHo3RNkL8+lYp9Hc0aszd3EO3m8vONV80IXOKSsG4Zh9AzFT+0u+vyj1AJHi4hn4Zgo22GX+9RCB42PNb62vfLl2Dppg/yx9a3Q7bKaNItTTYRL3PI53wEz3sI/k+Lj7eRON+fi9Ejbp0ercOE/tWQh5OVOZCMOqy2uSsPns7M9cHX6ITdOEjIb0gMXlKJrs/NN6u5DeS59pWKPunb9nlYA7U9oYlUlO4KuHV6Qie231Q+VV9RTOCtJD5DZK9RFK8+NazcR5syoxkLXswcfjGGQ8gX8uVXU0j5P/2klvQTYeEJ611YTcj4oHM97mY9iQveT/rjOZkgDkziZ7kKb6tEi4fNraNnONhNsT97VFxgt8H3IAS/E8yv3/JcJsZKFGTGmQrwMjxNy6iL02Lz590KwfNCdX89P8P3Zzq+rtS72qRbPsSfaWDIbzWew5t3An/my7fjQZbPNZmqUlJesK8l5PpPdvqwMgidOfNJjd5I4hbWaw69dS3k7+taNpF4TWGV+Fb1PFgbfynoiqHgRKD58XPaHIwINY+f9y4PqxfufFAp1AKTnRuaJqzhIC9wZQ5Y2Zg3QTyt5J92/n6jPRcZzn3DVLUL+fuTw2lDznHyyXNbgTxXKs9uk3gOXz6TDkvDtNUpb0oQGjNDvLe3BcZ3GiRWvmZgi6OscYx1HRgrlkuPzKEgbyovsTnDxbCXsvuV9ZrwacdZkV29vHi25+nB+VM48GzK/GH1ox6bq97dMf/SgKhG0eZlSR1I+i6vqje6HNfdLChj3anYNYyx2vlrGwyTX98SLajHEnbN47oDDXAOj3H/PJuJBXYH741wq0QjY5xTWDMFvZEyk0TmsNHRpqrY9qgSuwzrf2rIN+GwwXc7JU8GsrSpn3/Nq8Gef3xDFe43I9rr8EMPKZ4+muWL9qmUo7ZgRuCtcxQcLOFuqt7Awus4/+itE8vhccLJ8o4bHT8ulXrKUhgozXz2QKOpiozbv/2Khz+WcLcc71ZDrjvvIz5M+mVLhXDwCueskBqEpJcax9dTYamStEK2gwZ1sysZUw7WYISa7Kl43SZeHrT/yL6Rtdjarvmq2qEClt17L4QbUXFtxblG97IWWLzctLhAoRRCuRcYX/a14L7dZ9k5eyhwpXjvV2c0YtMH6TWLee17VC3N5aq2oGxJ0I2CH83Iav1oatDD8+uXE/0jv1bDfmasodL9CtCcF1bkdzRBMUNTwXhuEw6dCUpZxqlGesPPjg31DRjm5WU4xYWKbub+S+797di3/6T0szEFsFddbHjAm4JZcdvWHCng1SchVc75XSVIburvOlBZj9LhXxecf0HHiAf1FXT1QkgYNzaN66ZiYN6am8G8/uwXpiy1uFwNY9WU8qNiVNhdH95Re6wFSdEWRZfmlEJa2NfP0JUCqanSV4+ubUEWtS6KO5Nnl5HyF0a1N8D1XAPt0fZWzHlqvq2vqAxF71tkWnvq0Z4S8Y3rzIL8cKcbU9zq+M9PHOJC3sjV0WQ4G/Ej7Adm8PiddVd47ipkY/od6QjHljbMmLP658NzZTh+jbrteRQNnj5HFzRzGEiNqriUzKu3S8VMh80UZeLkcpu3CrcYqBdhmaS4VKCo8cNTfwYb5vPWq4os4tX7S/ONLtmV4uj+hg3DbFjY0xVXZMrzI2Fz94X94tWkPq2yB4zlLtCgM5HCUk4sh8bVR9Iz7zMIeTZi3Cg3t1N54yOlO82pgAMXyWkWco/acO2I+Jwm1RI8WxwWuaC/DQueGeyR0WYicnbcPNqcEpyX8pa+xOzAot8v4LShiNGpOuJCFYrkDdt03DrwUzbSZHpoB3znPbr8wKQYbau+OQ+bx+CfL2ymQPhbgJHzuSY07U7grP/cDq5W07mvb+h4sSOrbqCsGvqRD1dtkKBD8WTPrWi9Vnjh5EITwzq8uhTTW5zaAv8NjOOsizT4OYaMnGdQg6isL7kfL7XjQ51ztawIBary2UYKphQUypYXjT5Ix+mwO2FzmBScPJGgJnuyHpam0zi7eXUY50ba8kvLqBg7t7L1iByvzvMWk3h8rQ1vMy1sxa04hH2q+Pb0YRPjzsbx2lULMjTrkDKPk7NkJYesT/jrSe1fz0Pyn1NuGPKeHCGvXEU+B8lvl8sfx3uV/HExYGGEqUnNEjE2lOa9pp0wKkPckyWLYh5XEf/HwEScbVuew6EyLBsw3BvKq49/pq83b+L5UcvBgxskeHW/Xzbt/npaIYxPK/j2RtBBE/JlNWTXwW3LFZX7s+tx+IXHu1hRDhq6H7l/+ViHgPVP831SS5C1/LHeaUcOwt4qLe67VonxX+taPMbXoqB8zO5h65jQWnhDsq6hDHO1zcypl0qxbcUjI4fDDORPMOaqvqjEueRF4ybq1MEvpcOmO7oD28dOMf3qVIXQHr+V2zcWQWx84AmZzx2IaFilnF5chuB6HU1mYClmrL5947McC3b+tPzltCo4OWml+vs0YemZk6/7GpiY9Uw+4lNUGaZcDEna6kHFsGvUulAnJjSeZ+2dbFYJbbX4ByKGNMxPzNe5coe3fkk0d8ksKcc+9blhOpmtKLmunnLnWwdGSn4R22JQgbsKMy/bJNIhdO6TY6kBG++8JxVOpJXi4H7pd5mpVJy+tm1fZCEHdULT709hVkDxWI+tyxIKuGg6lu/CxngJ2hfpqiq8mTsmRWF1I8o0gl4o6PPitNZpjTuZdZh75sTl0AAanubslj84shPc50tHnHOphc78wzWHXCiYcrd9rnU2B3P8vp05Y1uPtgiaXX5nI7rtX46WSeHi09gEM5GOBhj4Rt904dSRuF7d/TVt6Q0Y9e6saGBFBYmvnqp6fJVtHSFfjasD9yRk1lSC1dH3gr6EA9Xdk0dcWl6FD7NOvWv3qYedp7SE000ulL7Xna/4XoeOrRoj9HvLsfmYee+t0bx4RjNNlYlrRLu/RJtlUzGyxypbybe2Qb2v0n/FpgZkGn0fdXxlHYqv00dOMecgP1ndaYQkb3yuDNvxmDc/Bfzuhuen2ftVQ6nmRnrHvGqsKc19ai3Dm09ZTWcHXpVgwYO58nZTy0F/anF45rMOnFybiltd1ViQ/WnbJ49KFLmUsUan0/B4HXemwfgmCG3fcmvL2XIc9jy1Y1JNG76IvZx+sKQCCV3cnF28dUdccjdz4ngmWGmr1K9ZlaEjIk5hPLMU5o9FPe1dmbi2S2YdI6IZVce+m50Sq4XVw6MvL49uxXu1bKOHb6pR2zT8rptjNWYrzKGuX0PDlugibnxPKaKr8oxFlGvx5W7AtBMPmVBvN7B/ySpAibmYwaqztdge/0VVz4/D38ff3oyB9Q8ma/LyEoEdaLvVBszu12JPDGeF3hzKELwSkkofIse3NJH2PHTcp3GfWSlanaK+TRSikPvkoje/zDsWlA9FqcUUMV683XwsMeTL1GZU3KFNNV6diA+SQVNs9nbgiWkm99BPKn4tOd/gWBUAqdvCmz58akem84jRK283EvKRKND1d1ri04Y8WdO2VbsopLy/yvz+oFwGqqW61xX710NU8e6sSqli/OcYxb2FjU0u47VjxlNh/1z9zPqOCHztupK2sYUJ39jWzdfeD/JkLzRMWv4PB8P9Jqr+00lFIGvkFI5HPPYemZU6biKDL39qUM+rRYvNxC5xsbe0TS1Gjwrji44uPfqZRH+ZeKZxdterzEH9KebZY1LsOhCyZMcee/EmjN2+qYhmXQguQ2XYu0Q2LqaPrU2Y3wyW1rn7ytOykERlJfwUbsXBFzNTmY28+bSXLh+mlQXVCV2Pzvzi5U0fc066j+RAqa+6p/xNONiT30vdo7dAaoc1CntY2N4dygnQ9cOtwmDTr98p6LFVW32gno0zp2gtNxcnoyVfe/x2EwE/B4+i81YdvpOI+rzPJ4ebNoNWSd/6NZkJa8cY6xHq+ej9Fb7i+CUqwcOC2Icur6+bI3G5/e3qKScE7bJhGB/I44lEw3jftAJRKhbKjcwV4a3nF66n3pRWL4LabSFKjRsVEfbdiZc/8dax5ee60iZnY9W9pkCHBF5er16iZbGKiY0fhRxrNydjZ2V+5zLbFoScPR+per4ZV9ft7P8VH4XoRQffiK+kwjpjhuzGp+1Yalp33fFcIVZ+KL9flUxDjJl51tyYRrgtpQSOl0jGhBOWy8drtYJ+8NJF801ULCoVslupEQwFW7cXMvF03B0utTsvhYrq4c9VDoyMx3LdoGVOchTMzDt1cmBbK340R+9dqV8JCzHT+2oxTajcveBjtiMNmglXOtI1iuHnnL/iiWYLnr1eEtfNpuHFmTNvBuRisSdKxqXjMZXAW0jcsSr9qfP6FvyYKzEudUI7WpYqFp4wTYN9fYqFbj4VT5NV365Z0Ywt4ZfnzxxXgdryw8sTxej859vf1COVtVClzycHVRd/7nOrb8ObD1G9gcoUTPo+43Ts/DTYvLwnaqvYjlObMreVr2uCRL7pp3c5eeiO3HYpY2wLfz+jpwHb9b6pP3fLx9310624nu2I29iX4t3QhGGLz1Wd/lkCax+zZ5Gr6dhRJGOneq0J14tMXpxcWIUdcxoVmm2asSdJ5i2EW9DhmrkicF465nd33KlJpUDnkGXN4r3N2GcT1/quNw3+16dXfkxhQbnlwuMQXt26Tdj/Z6/MMxj167en8/KyrbY5tS/qWsn55fA0037vSQ62FhS1i2SwSPnfPGBi+LepmrumcLHdSCLQP/oD3w8DaeR8mV420d/9ZyZRDw++//Pn+xltJC54D6fSXfL4dF7devSxZv+6Xja2z1uyae5AHF/Pcjox77hY81bJQKkvAe7LykXq3nD5+7H1dPJ/pAS8v5v5v/4X1ke79zhlKoff3+80uGvfS3+69iMZf/h4KxGvov/c760f/F/g/FO2ymLSXL4dbJmEHd7CTv9yeRFvHVKTfDzcgEIj/TzP2GHZpxza/6nsOsOiSJowYhYD5hwOIwbEnO4sxUwwY0RUUMwBVETlVNTDhFlBEQOCWRQ9DKgoJlSCICA5bE7sLisqZvlGenr6pmf3vG/+8EzRW91dqd+q7pmBLtmzZjatqoRHc6dFFcfeQe892K+A5R9bqSMmSzn7r5no+rUTkzenfYxLWL2F6CWmskd8RKmawePxtyJOyzh6uXwmKZD8ZxVx8QfpUcPqsYjTY7mcB6tgp2/QxCDHIvhzXYXS1xcjkR6t5bBtm29D6EXiWJfxhWt7VlZATkS0atcpFUdHdlXE2hWxExyfk8x1ta2ZvArF5wQo2/dwRcu+Ohg+vs/6PmZi8NJ9udft/GsOn5S/Z+q2iMMtmM+FJoei0yxl8DCxRb/QDy85+uZ7Q/bWLJNB53Y3xQ5tHrP2qUfjuVrE7uNEIDlo9EgO8zQwebN12ffK5H046Pke8j4ejLvxe3Hwc0Llen9ThPgM17N8ItnnfrR8fmbhqN/OrB8xOBreZF68EHkH8XFm/VHP4KvO/pMnzYyGffcmiq4uzAKx67HbmoE6GHior/PHTkp4GbmrX89kJn/4e/323FA9iG/ckh08IYeEEHFmq40ZcMfXJ/eyixZiXXY3Op0khz9Hxp+ebZMDIZ7Lp62rIwff6o/mF5+SofY/0iHtQoPNZ0VqeLF5yJVZbeQQNW2XrItfAce//P2N4RLICnw357fGeeC9bMXtdqO0sGHUgEmP40Qg3Wc/6O68fKq9DJZ8D4z1+poBU96tHOXqrgSLVNHXoRoFVD7YtPsZWSZ8TZl+OeSJDhb4WpwbZCeD3RGjMzy8cyDm7Oh12/UKeB79uYK6jxiG6XdbJA7NhAPHLFxaJajB1e/woc5PxRA80G/bxwG5HJ8Aj/lf9wdJ0DmJqvnU++B0EPl8uP3f6/KBgX5JxUzee0zr8PaglwZOdH7drUZhJuzZ7Pr9x3o1zP/xut8iRt7Nn+XW6HAzF0Lyq6ycPFQFlol/dtsZp4L9ecGrZ255AwkPA6deZfLJvlPXxbxx0gJsDersdiYXbvTK3pYTUgQjr+9o8W2qCib4FZlVfJUJOZNaHf3TUwFlnstfud3XwJY9+dm6xjmo3y9a2KXqsudBHQ00GqAdvZ7B8f5mAVYjmLwRjVMLVbcsyoramQ12Vy5NnJxSxLbXQkJXu+sNe0tgSuquFZ2+5cHI9mvMgy/ooOXakzHTLeWw9sLYAy8m5MN+x+1jkzeo4Yfuxuy1zSTQPn5XyOxRIhi/OLdoI5MXdd20eK06WwSfzKt+LhssAsshi+t3ZHB3brP5diWDpGC1d41nc6dCGCVP/fvLdz1LZ/JmN+sWcR/zOToajwxCzw1ulsbgQDwe+2oMgkiWw3bPwvd/F+XCOKtG3muZvOFaSb0XU9Jy4LL35wPfGH5v55+pdnGmFoZuvuORuFaEnl/aJgFLsxdPty/VweBXved+XSSCuoU7p3dXyGBBSVLffgyued9wzJwmDP5vJJHbqOxlXL23Zv7W8U1VufDYMffhDS8JVw/UOz0edG17FhyXeE7oZqeAjg4RH5vrdBB195j2oYjB8z8NfbgUgleFBH7208HX45/ez5LlgGvYgI9/jlDBlJLKXtey9eDkuKTJvCZSuPGokVn1SDEnh4mzA70XXxVDwyXz6iUnSjh6+bwyZVDY70Fp4g1CR/ueIq5ujN6TqGf7LYQB0YWhnVaquX7L3+PXRgSXNfK1wTW1IIstO/7HCR33nCpdRyjnV1HC0RF/Hbxoe+fAjb8U0G391zsu9hKo+6S2e2qZDmadW792l0QFz4Z0WVNcWwQJ+YOuZVYohqqb6o8LUauh36mDaoeQfJjXItnqpruOpRfBllUjD5eOzIddVax9agzQgsRncEVNLSWsObpVblNHBDM1ba5VTWP8rMesYfZxCrjV/XRjfYiI67dOjdJmLklK+PI5yGbMnQJoHnst49pcLTyxeHV8niuzTqX2DFofJuHGUz81LrHwthqNc6+Yo7tHn32z30cHiuKe1VK9RHD2nXj6lita2BFW1lnB+Gts5ewbvi0lsLn6jkrdMnWUvIj88Hkm+vlSfD4JvYe4kNMbrz5jkQ1BCcEnljD2gvP6ETYjdz73y4KA+rN1nWqTfD83I6KgRWYuXP9+x26juwQSk6MDF69j8v1r3ie/H88Gh98db81k1l3cvrLzx1pe7URwpGRG9Xwm37j3QZ++RSaCNc/6D9zB+H1eUGG78zvlUDBVbid/KIJhK13inLopYfiOLgt+nvst3NXkXliiGFRjK926WFUOl+6O6ju1mwbmHemg6dJHAvqgcVNqrpXA73WCmyzNl0Phiiipf5kcyWOvBO1bTVPDzcuyC+bNpXCzzDmg6VUJVLoeG1L2lMEFbSxGWXwvhA/b705OqKiDfmfvT7H7qITC5sPMVnYVcetF+fPaTFzIcrc6m/27iIvPyJ7VEN1DfalZpliwvrjaSAb16CKFuY8bnB7VWg2DxlR6X9MhHfJdvi0bZyuGgHrvG6/fpoO/9jscdIvIA/sOk2IbM/Et8tnyU84dtDAyodvCrwxOL81oUMvnHGP33gUWJYyf9N9o9mLbiAJwzQuOVhyXcvSAjO+tAueIwe3RhH7e3hImb59+KOmMDoor3x10IEICxfsc5laaIebo5flxlhiKLh2Wrt5E+Gdeuv5yyM/9tz1HD7tkSaCVZNVS92MyiPSMrJZeMQfyh/ttbTFXDZWS57/vdC0fZtcNzzMPKYTIi6dKdq5QgE3kiusdJxfCZYl89siTBTAlevznTC8pjHQfei53kxxmfb36xGuwFGSbTj7aPE0F5r7uT1ZHidF6tiYdDhx1TDF7K4MmHc7fqztMBH8GDvJx1IihzCs7rO45GcgMH1aGDVLBg5GDF+tspfBo6VVnl2timPVI0mXmRqb/H26e2TNFUDZtR20/Bt+OXWv/eLZCAve9Ft3ud1AKayp3h0ALGcSs6NSvi7MSVldLdn6pyoZc2XCzQIkEltQ6W2o1UA37x5Q0njyWie8nSlQjP8kh+UFJmz/+EsMxt0ev2p7Phge9bOYekiihypLhd9uJC2BBccCtzkx++9avZVllcxUssFy1d46ByfOe2JW8Z+xqXqvPW/2q6mHW5MLBr83FUCj3Xr1lqwz+apX/pMxSC01CGgaebCSB40eGfnFk8k83v2uqjMtKCHdsdOPwJik0npdQsqapHKrLPL4H+GghIPugc92rBXC36WPvKcz4PJvXEnVbyeCVg5Fyy1YF8PM1fh79VfBbi9l9c5OLwO1ihuOwjoWQ9nm49FqGGtV9LNVQscqYU1M8RVA8wMXjhpcKkpxPeViV6WFamdJ2doEIbmTeg4LLKtA1KLuf7KoDD8dl8z65iaFY8f1pR3sNLD0cKm8WrYY42c2QlAcFsGzNgPZtqihg2p72V/ZMUEPLKqNq91smhohSl7nHn0vhwbczY3bMLoZPzz6Lcn+TQM+VRwvW1cnj6PKoSTY2FyQQJIb8IY8KIdN/l+ePDgxeGJraY+n5QvAJ2v1pbOLP58VtJ59qxcjT2b7B5gARxJivM7OMz+Hoyf7jNW8viFl6Jng/E52b76mFEY75OSprCVxOtq41s42Y63fJx7JbToxdovFkg7xKsYdygR52VTq/tXkjxq8mzJ9l/p3BH/7Lr/vaFsGYha1XblWKoObhBtPM6hdATIBb9NkjWnhZJisueCuGDqMr3jkckg4FASM/tz2lgXqNGnoOVIvh7vCAxiOlmSgOREq4OHC6Gyg2rs5B79mxlHD1tB8Hrwy455YBwYOV1o6M/Rb9PN7ppoUhFqenSXZloPjQQcb576Tm75uH1syDucsCThhKJJDTt3+i51wdnFxZ60qrdalsXUjO5b9R632/qicksHkxoYt62H+71+w1vDjRwWeRrRpOavYfF/troPWA5wPmLIqFV63u33ufpwbD1lPv3s/TwxzfuMFrGySg9pEqWGfWb2RADy3s3D9bVqPBM/jeI8LJvbkKxrV6/HeBnQ6cv1sMnOuRAHXjxxVX662EnlNvtDraVwkbIjOCP6ozodMtG8MtuQJ2N7cYV3upEoZGlDQpXv0ULvR28zj1XA+Nln8ebZ+jgoQ0V/Vv8AyyRk36VCtOyfG3XBlx/GO719C3YrWcB3cVMOfw6Ycpw7SwoG/ACcuAdKjQdKD3+EVaCLQemDklWgG7Tm9o86R3LMw4ERJ6p60GDvjt9yz6qgS/b0v+1HeKhBt+q68vGqGB0I1Pyj42UwAcjCuybXAfvpSYa8OYfDbj4sntUWZqsHtrMWCQYypYJ3ZUfPHUQDOPBv5nJungTUOpqs3jp4jeowjmD3xh67RRDem+R3y1Nrdg1enc/WdDtKh9fS2Uedw4lLD0KXSoeDjh7GAdSFcqpq46LUfjjHrF0R2c/bte2auADx/rJywrjIMuJ+41Ce+lAreFa7z8zeXgWHZw8rkmz2Bn5J5eHa1UEN9jet6mSmq49KXx6seJd2H1UOuGNie1sLeGwcpLKYP5Wwr6rvqSChbvvFpWn6uCOP/lpVUvyWCAb+rOSmmpUNmsufOV8xrIaNMmPKlABp82LghsNzQDzeu6Ds2rlQYWP7Af7B30CM0rj51XL6bfLnGvh267y+kxYuf01XW7KsF2sPupQTXSwKNH5ciOHfWgmucMlqsUMN5QcaTTpQzOT7vvrJqdVU8Of7UdfTbrQDbHp9wOZSqQL7r2fv/sVESvqkV2wuRLyD6TYat9tbr2N3SI/qWIpcfz+YSrkV09TGDzZTa/PqJjz5c85+j4fRsZV20Zegz7PnByHgJ9Ryyeff+PlqK/gssDp47b3kkKf3RND1bEMPgSLm+vPkvB5G1Jq4b/EEOtCg0WZrRm8o1RU8PdGX2o8nTrF9lLocm66fUtWhRD0MrDa68xuOhxyaH2DdYwfNz/XjjnrY6la0HeefGao79LQOV0TPTlTx3o3ILVrlU1sAe+W9ndkkAFv/X6Ama+W+u8Dts6WgWT4x/mSpg47XTmxrmsB1qYE/B+VtF8GdQP2je7KYMH7ayadhMP04C+k1W1W2vlEDvEss2wBRI4uU7eZ/wkLcufyZuGn/5S1VMGnc78XfdqhArCXJo9NHQugkPnpxl8j0nA3MG86RytHE5kZrW/xODb/QuCVvzZRA5limc7rzWScXlHtzW//9ZwuhTmQJOYdWsJvfe83+3bf5PCom/L1+TUUoDo1MT28Q+KoP67K+ENT6ngkt/AzrOqyji83cQiKNidwfNjrSs6wlUph+envml9LmyRAhr1epy71VYGk3fvcCtRFMF3J98vNkw+RudTPb0alUZJpUie39VsXNHBjNrvx+dWkSO9uOig+plgp98W6/jv0xlC8p0+7YK//nVdDu/2lsXcrFLEttfz3ze0uJg7H4r4K1B7fz1M9h77KeGwlv/eosXkPd3l/D3lnJ3YBLw/4/1QDZs/OZ2zDVFw9PJ+NRp4e2vjzeFMHlN+fra7DCIee2y2mKiBQ6vc6uieqOFrxQNmdQplEH/av3OGuxrazS0cayVRw9VtdmPOf5XB1bAfDy0LdTDGYUD42n5M3A9WvZvArEvuyfYNPaK08PNpvTUrGByR5bJ+xmUmj17i89A2rgg6B2Q7xU/VwAYn99g7oQqQPntsOYBZfzpMvf7JyU8JO0a2nZFop4Lutpmz1tuw7Rl7KW8/V47at9Rx9Cnu1Ze4B6ggJnfhPekoPf9clIaSEz7/1FBBPWeN/ZrobZx3r7DWEVrose5aw9q3FRz/wm/+O6ss0kGYekjzwm0y8GqRuMShsxhcGxw4d7qaDrwHrMs4zPjBXIl02h9OBP/ssPnWvtpTOTz1Chs8PCWfo0fuHjsheY0Mlhx1GpSxScTHY65SyHzU8EgvRi5Db3WdHVRBDzt9gkYuc5ZDt+iCDQVfCH4LrKq29qomh5J1zybtS5fB6jl7Pq02L0bj78eO/7mGa59gq6/yeqAURKfrXlcelcPFx++Cfk/QwsFXDTYN7KKEM7d9fJJDGfnFvnwrY+LNz7egH62shBqLHZOGFyhhcOS+6qmblLDp4fC1muEq8PHdkHl6nxQ+trIZoO+thr5VXUKmWinA02rs0nnt5DAhfcSzbKUC8gwLenVy0kD/0xPWLMqQQ5+fYfiFDmKWTQxIqqAE12PuvRPd5WC376n/6NMqWHpj5B/Dh6nhZZOEa7GXVPBH9LkhHs/lYF3cr/X3Fsy6EZPvdOCWDNKzbjxSbVJB5her0G7PddBj+o6XHy4qYZTkQC/9HAUVP1XQ8/CCsGOrlaBcWSGi9QstJK3/y37LLDlUUjlE1egk57ePUMBl87luSRvkHO6at+7yu1dXRTDg9YyAmYWEfuxe4P466/Oh2pGaI0TOCo5enmc6SiDk4rwRvUJUMLbGu1YLmmmhTpucqocb5YCvX8TU2x3VkDlukqXbajWMrP7F4o/HYni32rzwUDojF/9JXbxu6qBQ7L1wWs0CsEkMfNuQiR8nA1vfiV+lhDmdql34ULcQxiWu73F4lRamFzjXObpdAZMvLLf5MUUEr6TbxtowOKOrzd54p9UKGL7cv7lhnQTO9pgxyjlNC7YLf6sQZqGCI1k3Y/JTpRDXY/D2tDwG/2W79EmeoAS4lnjabKoUvm/+e1xoLQbnV2sZfXiOFuaveGPbspYUqvT60ujbMBU3znh/cUHGfjF6z2x7NVSfaO3d20YN2zetqG8dmAcfzfKDeg0qgo27vxQWtVLC3ccv3RLX5UKG2eepN3vo4MmwpztaMePxDH4f8SyfXfdHkfUdrftp7DpOcKlD7pR3U1+nw7um3+5k+mpg8OEG9dc01YHV9UOR7Wew71f7oOX7/ZA0cJAfm9j/phqcLNe03hylhxIv27qacXl8/DlQw+KWN9C00pTa3VJ1LH8NxID2uqsqC/X7TcvStVC1wWmX6oeyEA4pYXHIQC2T930do4hKh5XJ787vqcHEp4LlY2r7aOB+/zGLrvvlcfRzNxctvTZCDbmVYs1bxhaica+h4tYQ9n3Sp0n8w9+R5L2/8h/v/U4ZbD5wWRs1eDl1azTHSwPZt3wXRTYqhvH9xotO3FfCtUjRxlj3IpBMa3z79WYdiJMNHrUYnKfeVCvpuEEDs6u+ajohRw3N69+SNbZg/Pc3cWyNWUUcn8U71dv73dHCi8i+fk9+qOG+L6xXv9Ohfk9rUL+MPHD7cj4JGsSnpZaj43GW008w+UuiVYOZQ/XQxal012ilEt4ED0xvGM30vzxmru9lLRq/rwp2xflbLxmrR+M3K4KD02Oe6FaqYczo8bf3fNbCmS7zXZdNVMOIU/t6Stw07DhV3DifBuVn1StTQeUGGnVbgxqetcp5XsNVC6WdXPY97qOHoH7bl9zczuBoyYsHlZfq+fH2thqtUyd0iL9EB/X/0nRZbl0Enhd2Jw8eo0N8brJy6FmM5huoQ3LYzcozX4fm+4ht30fL9qvn+i2XzxzCp5yuLRJ8J8z4X/J/+vth+O/6+Acraw3QwEO/l3usLuvBKXTUa+uGSujv8NKrHoPveiSXhm1hxvnz8aLQGBU7ryJqXhpODrrg/RlNJhchOa8qgqVXR/ZolqiD4i8+YbZWagg7ankn3UaF3nOSrkX1pBtaWHVq5b3Sgyq4cnnKku1XtLC9p1kdxUUN9NiQ7Z0TrKbWOxWLEzQcvRw/iNXsOlgEWbl3RT3TdfB94qH2x8w1rL9JYWHN5/3PvtTDrmlPI598UsHA/aGtfI//xMHLpOPe6+BY0Ir+Sc5aiE11On98goJrL1vSVrrWTANrfhz7Zuig4Pw38dSTR5Waa2CZ+Ry/2nPEMFk0r/kdKZFnxaRDHTYtlrP8tYgP42/l/F/L2HEyOMT3qPmn3lq4/If2L/NGUhSv+hRx8WrpxvB6bQsKYcueosIPn0kce1rL8e9TPSWgOXajyfEnGqh5cHDEmdk6cC2FygoGF/P2o/9xHpAfl7QwQRz5oEpmPkc3e/nipLuTFlxDwqN+7uuj8ejZfnWQ+eb3mKQdOI7pYdWXV6vf7NRBXedPve4fE7PtdYLxo3jC+ldV1t8fqU3aL98fsV9oWb/QUX6hQXSRno1XrH8NLaLiJMbtKup9vji+Svjvl+TO4cs4Phhvonv8vSgzsxZ7NrR47hnCjd9rcKBni+fR3P8RnXy/D7dH/zXAKGmr554tznPt318PkPbfq4Xn8mrPf34XlEevreLuZV7bmHZhoHRvyrRTCdr37J/EjCOZu/ca8Ji5D4UT++Yz/adwdHRFwqvnPfdK+8dR3100M0P0F4Jxuq8MZvq/J5ADniem0/P+r+24cVPy5H/X0MwMzwfPDz8/Zx8etaO0Xgo1jzjA8+X//oWgP5ov3R++j24h7r9XesHEvAyC+SF9FVP8ngLSu47iGwlIjxpqHo/Z+yKBvmqOXdXi+Vs1uPRVzSutdwno79PT80X8tZy8+N/TMQjspZy/px6s36Z42G14BsgOL3PtT41zCw9KeQDPRb2ZeT7n6DOtT2a52j0HZDcPOTrv/afceNK5e5e9K5n+ogD1Kxe0L5dniJy7D/fcJ/35XV7E5w1H539XUyLQa9MQBSNvIR3JO0fAB8XVHHY+j6jxqFh/iufoqF81d4/fj4v6JeNHcktgx4/5xFJxQAF03DGjLkyn/Qnbn6l4hOm0HdP2Tdsxjk/G45CSu8fyNSVv0V+d4xwWSrh7t9idq4NSTpr0Y2x/2B75UoiCdo4GpxbP0wTy6TDt6cAch3RQ7cu3ynG4w/0/b6vl/u6hr2HP3CX2G6oTfgNaJzDjxXp4QfF7Afz/M+O2DDmV4hoHnRtsfpgWQey5/LuIzmkQFybPDW6dzdFts151iwpKhGGRHp/mHiB0ZF+53HeyEDUc3FpqF757kmtiXlnQ9EnG4dJ6d1l93QbnubUXnJ+ZxbWn1w+aDz5PN6DZR2ZeR1m/EQH2L9yu3oOP/RZ2F3H3FZ+lbE9xvQHGx03mg+/x/2k/QvdJsGJ8WLMN1d9Q40sX+AWypzSB36H495KdZxpFT+Lu4zb33Vpd9xIiqpadqfl7Chv3sgR2h/w+g6OjdfE2eZ6RsgN0/xii308N82zxmprfQy4umtIfppuyS1N2TMdNM+rC+sTjx++ND2jXYnZ4gEjQHs1fTn3/gMRNvA7ScRa386nvfaW0Xg58vFPxQ/soMl8k5zzKTgxs/CN+gPOXKVH3xdr2+Rx9eOnTi9u8SfxD8TMZ8Dp1vHByRPsoHI9SOP782enZ9mSdxfHNeBw1COj8OEz4Yzodd3E7ms6PqwZKTuls3NSycfM66zdplNwese2E873kMKxV/ZxMVj8qyh7T2N+rBXaO5UP7EeaD/BTr6w7XLxpHOiVXHRWXo7j22E+w32B6syYxD7uHJrH+nUrJL41tn2hCbolsOylHtxBV62e3IQ3qd3VrqWtP6Oj9SJmgH1rtRVAK8ZsN0amhfudz2fnIOLr/sdysJ1b57LgkgPi+pvgRO+bjMRGnRzPeJWL1+kRAR39fmOTPty9he/w+CyQPMRXPDew8VJTe9WB8fWflH0LjMgO3vtN8jK/7Buh3YcKemEpirn2Vlduah/6hY+2R6AHbP86T+HmJQYCHsD+N/lRQeDomj9L/G5aeLpCz8XVHIdAvlud62ysTYrYVcPRHFs4BQSk58KNtlz4/4x7NP3BPhz2OEWQ8Hau0zbVqL4Hhqaub2ypIe6+cjL+SkmUCvEXHG1NxiI4rOB/l51VYX3qOPx/3G4DOH1tYuA4I/S6Cm/1DWvncfcz9ziVigdNEf5IfW2fapn+LTGT7lVFyiDVhP2Zm5d85ySHtXwdUbBQVFMn6JeGP10NkX8R+8DqM7KeI6hf7g0bQnl4H0IXzRSIfjAdoe8N6MG6fJD+j8zYs51/hbOP5JcnfjeuX8KdxP5138uO1gYsPmM77zrAZxvfZXHu8jtN0U/i5cWzd5dtK0wHhm0KOfmXhuifZDjkCelHX9g33SjOgrs8x/xHxZB3C/nT9XfSYuzcJvsT+1MJh4vt5c8h6hueN829MR/LD3zV5SbXXsO0JvkPykLPzfUbx0QCuV5jK503l/3Seb0ZdWA84D8X4C8ubzlvxukuvxzguY9xE8+HTybqO8Qi9fuD54PwW07Ec8HenMR3nFzRuw+Pjy9XAyZ/GQ7g9WjffcO0xXsV5OZ1n4Hyazic+tqkkc7gghaYX+5pfHx0nkJfxOppBUEfBuITGTfj7NfT6jS+0fhSwciT5DDy9PCEqKAPa7O/90mr+K+77O3deX7AXqel88JlJPG8Kj5/pPbKPrn0q6KcumFrlZCJHR3m5GPj5t5lZlxkFK0vryQDnU3T9gj9fYb2jHFd1JHE+dau+Xn7wa0A4lfg9HifGLZiO4kEK9G9038vuaz5sM0u+MvMdiS8HrrnIt5VmAJIb0deH1h9fxGxLBYfxu3o4Lkym7C0Nuh9c6XugJ1mfrznNmtz9txQY8LRZ/d2TyXiLXNoxeOAVLPmm3Ha+OcE7sw5eltSbkQ47boa7High8n+itJ4aGpMNf4wduzE/mPghinNZMDj02yer+cQePJw3rt7rXgCe9bImwhWCO1L7XtpbOlEKrSr5eOQ3I/P68aNE5pkngq85fT0n+hN748cDA+fnmE77nal4gX9vHL/j9UMPuO6D/Rv/DtcV+HVcjNtIXOSvq0R+/P0siSBe8fNREq9oPn2dw+r53FVBm/VvBkQ1Jvi/c1Xb0sjRGrhffdCUDTvpfBfHVWK/OG4jeclBPDen38epxG49AtwXVXFVQDvf4hUprsQ/P/9Wtyw7QcPiRtIe5bNq+KNJxgXXx8TOy/3soAaOvC3uZRNC6N8uD1/ctZ6c8wv+emaAkmFWP/4OyhPEY/x7P+upMVbz1fBl3waZ62NSp9uzNj5bncHgsrO/7au+jOhl3NudDlVOKln5kHomH2eR9nw8pafkLAPxu8OXUwro+pOGw238+pNSMH5sZzR+RXqRc+sqtje+nRE+tB/w61K5gvYoruQDzlO8pzS/HrPtFvv/LK49rq/gegvNB+el2K6xPfPzJ9Ie6UMMuO6B7ZNvlwZA9axnAhyG4x0/vzdQuMYAfLzzlKLruPa4HZ8PjWcIjsD3NO7gxx8D0HUdft3HALsrLKtSP+c2u07kcftzfH3KOf1gOs4z6XhHy9uUHr5DRZ/uodGs3Yqo9neofJXGzxoOn+N+sT2i8RKcT9s7P14TfynPh8ZLAMcTTPdPnnTVbkMe4LiB6eXrzx8iwHEG0+9o591s3UgErWsumdw9VMHhEoxT8DjwuojXSUy/3rhGVu2ROWycI/Yf+XTmrJdMno3y5myBPbs1mDaioFAEFx+3eDX2Nqnr+UcFDas4ToLGX4/EW/TckgTko8YPDXck621FH4t2nX6IYG976/U9bVn/KCXrNKqX58BM+L4gaR/ht2LYpAnTwjMg/pKLbvsIQl/v0a7j7/liVm8k3yy7MuGvu30KYVPGBbv8YNL/6tJTFsdbi5EeHAj9sHN0Tp3deSbwJ+sHgnzQwNkL5oP9CdGLKLoG6P0lnMcYx7d4HSPzwnU/jOcwHdf3UpqJq1lXJPTy9cIOf8cQr58vOP54X5G/32jgxsmv0xtgn9+SJnsKyPpsFXjyod8CCcXvGTV/A/87k84kfuA8A/uVcdyO64c0zjGg/ZVhRJ5N9wWuWLKR1B0Rrn/B+skbmJLs49g1lfjlkeONA3oaMqhxPubql2i8RI90XZPeLzUuN7J/S+/rYj6m9mlN1VnRPlQcoPwgVxAnMF6h4w3GN2djzY/2NMgpO5RR6wTJm+k6NLY/Om7x8ZAB4P2lVQu7YzycTulTWA/GePyFehgT/wm+1vdfHb5FKwZFTol3xGeSL2Mc10fZv9u7Yf/YN2LxV9UL3l3O55L6YJ/IrCPDn8lgQesqp+pYkDiG/QbXmzEd2ZtKsM+B5YfyvyxKnxpqvliOmC4Cuo6P26H9SOJvuD3yEyI/7GdNliob5TgQP8HrAbZ7TMf90esEv36CcUEetT+kF8wft6f3E7w/XulgPYzBWTYHmfWcyBf5QxbCo9VVAjrmt/R2oL5eTjLQuA23xzgCx2NML7c7uwKOD17/aTyC/sZDiLiK78ajGtZvcik9qQR1AIyP6f0W7B8oTyX6RvabCU4GX1uf9cTPyvdhr2UL8k2E00XQ7saCEeNuEznj8dVe/PuZw0NJ/oPy0DxA+x0k/20sEnVY306C5teE0Es++L9ulyyDxRcH1HCbQPxn0m3bkBiZDn3v+DUZT+ys0qKxH0Vs/Zisk9mf89rl54gB1V3IvBDeFbHnsqg4cZDEA4wHaXyM29M4m6ZjPtg+6fzBjHcZTOIjOt+6/ca6DTgWw6KJNe7GhEsEfEzthxjfnzEz85IuvijpJQffBT3s4s1IHvhHr4P1Ty6XwcupV73svv4D3yyZzeAVBaqbj5cCXU/Ddkb7K8YPdBzA6/2UWrI63yPfCOjG9yPVgPJJERvX0gW/4++rkPiBx8Hn94wbN6aH9f/zzx6X01n5E389mzG3Y2jMC3bdJPaC4wGSP9F/hTk/hi3snsTGK8IHjx/5Pamj6LuLNi/bkc/i3jyOjuuTfD1rTdQtDSbiNl3HJXmT8boNjkMKav/KAMbjj4H7u3LndfMNO9MA1bkKqHm8YvOsAup38Zy//Uqu2E/4OJXgKIxHp817mepvlgP8cyUGwPvW9HxSm87v+tSKyAf7DcYn/LqLAYzHW4NA3liuxtcpkp8aXwewPt9QeamBW2/pvLlyz6bTUgqyoLzOqirk6Lpz0bYX5+cj+5tC7GvunYbnt/bIB5SPEDuL3Cvdbt82h22fBT2qvRq3sDuZ/62ZDmur63LhiM/CXqExZP4Dx8XPsNuQSe23MPnrtQ3+CZVzoGqB3qxDFNGHfmv3Ht6R6SxOEwnsJSjiwwi73CLwkB6MvlSDxD3pbvvu+/fIoU/AjqqGKFL3OlKxyYZpMiYP6rai/4YxZL34WHn0upq+SpZO4h2tb1x3QHoheQPGs6by5GO3A7fJJRJ42vbE71UekH5N1a0aLHxjPrGDFrboDSUOO+j9TOE5EnyOGI8H189N1a345+VI3o/XI0zHdaUUT8vpSd314H36z4xtjeh9clKHpeX2X/fz5/VzmyqRymDa2Gffdm0j/IfHBLS0cVSCo9lE0ZN/5IvJvezzdpap4ZPjmabz99PjUQjyHnRpBPu0qJ1cgGPLXx+wXgHjVrwUZVxRUnIT1h/xvMrrvEESwOdBML3JkPDgXjfFAj9C+8wyav/FYDKfNpXH0/vA9Lki/nx1gv1enN9hfriOieRJ4ije7+316N0jkZrESfRXAY8d3n3f0pXEb4SXJXBriSZuyHUSV5Cfy4DGvchvtKw+SPvyetFvGihq0/V9/TIJVK91avqgOBIP+34oPPngohwy018rW5WROITjDao3Ef/A8Yl/DpTgLXQugPhHtlvv+5eTJTBz06lbS4PJOlS+LulE8HX1w3WtG5F1aIvcJblvOzk877m+zPMdXV8VCdZlTEfjIfKmcSNeJzCeo9dlGq+iOqQOvhe07ep7VcXKjch7RfSX62N+KMEyalP3zDQyzskVHN7p4tWwzT/5Skt3Md/+/nG+hj9+g2BcOP/hn7sx/FIepvTw/+qT1k/jryEHoseTdQTXl8r7dxdRclODs19+6xM7JQK7RX5L5lN/+sjkKcH5MKbX4ooZjYm+xtUceWtEvBgsW17dfyiEtF94oWtxWgRdpxfqP3xMpX1Hj4gBnf8i/oD2NSQQVKl9oGI74ZM3O7ZCrqWUbZ/Fzo+M5/nXJenKxDfs+P9hrxfV6tdhGI8oODr//CqhI79NY9urqfYE39P1yJg1E8N/S1FDXfWOie9WCdeL8nq3K+6HxMmFe1ZuO+xH1ytM401T9T9T9UL6PAuKp8Sv8HMo/Och8Tr7gp1nEdU+SYATyu15hobLq0e36L78QxKxY3xOsPw7NePIOoz2g1Vw4ETvkzOuyqhxSwV+gvclaFyI8xkaF9LrPs5HaZyA13u8b8DfT8DjkVPyVlP1bQO3PuP/8+vEdP5B8jL+PEj/OH7Q+yK/kkelyfeOpC1TgKb5yYod15G4WF7fj5TBlYCXE2xcxL+Ut4/9zNDlDN7061kk6jdG9kt503o+pBz7YddhMn9UZ1HC6lzp6ZnvZBRdzuIMMk+0jyBi/YDwwfsCaB+a0FF8Y98P50z8F+UxGSzOKKL0nga4nojp+PwhX2/CvAfbPa73YvqEkkCPw49UUHPD1Fe2HoUC/eM6erleRxVTdpVMfRcN0+k6Lam74zyfzg/5+x4aSt/0fhrZt6T3CUz9jo/XcTvMT0ONv0hwvpLGc/T5beN4jx4P+d3o+sftRWoyfxSnlBQ+NgjG9+/yE8qj/H1mC1QQ/7fB8oS1jJqn0O8vNHjQrUqBGvxjuixo8rcY5l7z27o8ifSP8IRcoCcUbwth2ff3p/oAGRfCkyT+0nk2Py8S1kEwfsJ1Wz5fLbc/S+9D4/H8V/3x9UbGQ9uNKTul4yU9LzqO0ziOX680cOde6Hnh8yf4no67pp4Toy/6uUz+Rc4Z8Z/vED7n+O/tDNy5xf/aP/08Cf8y3T++TD2fwZ8XjX9TTPClx/+r/gnff5cvvnAcp9dXmp+ZmfFxCM8l/vs86fM3xM6M90/3Sy76d6ba/Wq8+HfGf0+PX9jPv9u76eccjbenxyfEPfTvaTkYHw+Nm0zJWwXG7d+UHk2NS0XJ+9d6NW5fpu3m3/2MHrfKhLyE7Y3//7/2/yv/E/qFKf+m+/lVf/gXpuo9xsdN+jFun6bmI/w/5vvv9vVf5Ysv2h/oi7bD/zcembK7WMH+Hc5r6fNfuD3+Pd7XQ/U8Uv/jfyeCPI/K/z393oFE/vv7uXHEC57rQP09FfDHf40/BxIFdDsz6qL30Y3y2awzwcdgYr5ais4+j7NZ+LwKyrc1Ajmg97CpBfk4lgPvvYtmuC5BnUvYjN/T+ISj8/WbKNALqkvRz3nj53ayBONE/aQC/T4J/PwfLQc0H4UJ/jLj/GMVAv70c1BYf7SeaDun9WfcLmJN0BO5cZiyb3SFs9/Dpt5boKH2FzenCvIuvtyIvvh6IfkVfd4Bt6PltentvIif73Hw6PahgDxnTT/3iPUQDvY1b65t8TyVmlcU9B2oPE+eC8HXVQhbNrml7ix9/iRVEE/w/Gg6mgeZH44ntDzo56bR7wqo8WN7EFPtr7LPNxRQ44xk9UDvi7F8OisE8Q3bH+b/X+2b/3v6nF0ep1dM54+LzqtJvlb+PY3tOijX86hCgf1geZSTBXEBy0sYF/j90n5hoOw8XOBHv1pnjPuRAXqfbWj38xwHvW9E53Hor1bgR+iv2sTvtCbko6bkQfatjccTOn6QfujxoHuFQL/oL11Pw3pQCujY7ozHBXwJ4wLmw/frcI4/36/Jc+R8/BBJ8TPlN5HsuPIFcQjbOU3n2acZXhdVAr9Dl9bEemx63aX7p+NPrM+NKXvbiqD0xrEfcT30VH8SSm+ED5YTjgNDtjtd9HQh+xUTtoTtbPEcnzuicSMdr/B46LiL+80SPEeD4yNN5/Oh44WZWfk5KpmO+y4Gplfc5BjpWqKHJ/MXaT0dhecE0F8RNX4DF1+M6xX3Tz/vqeP2U4zjqljBvPjnmRSUn9HnBEzRifz5filcX/j8hfEB3WlNjF9L2a9BcP4Oj9O4H+k5P6LlgO2PpmM9YD2e3FAnqMVHqWA+/Hnjy8DFF/q5MqQOhQCf/Ts/LB+ZQA54XaXHb/z5dq1gHUGXmtO/8ThAcARf7qbWA9P65v2OweV8OWC9akzkIb/GQXi9Q3ol59dR/LjOnY/n6YOLs8LnQUzFOXQJ45nx+BcJfHxF/IMfr8l6S/sjlq8p/Rnl25muz0dR+vm132O9898zSPrh2xmxB3qcdP7FHw/Js/h6p3EPiVv0/hxuT4+D3mfm/e4/53V0PUA4LpzH89/vSPAflheNF/ly+HW+hClG+WwW4k7+fP4r7jQg+31Lzp/tnOAS9PO8EN+O8RVpct0ylVegi/Znsg4b12+qQE//Lc8j8jf+fHskmMr3jOd1v8oD6fcR6UzgSL1JHGkcL5rGl/9ffkvXFdMouzWlhzzB+P1qH58ovUNwD457NA7l8/mvuAePUyngY7xuoTOxvppej43HdzIe4+dl8wRyp/EqziPRPY1XhfGRdy+Ig0RfxvMnYR6L9cDXj4k8VmAPv5ZH+XxDCB7C8YHGLzx5m8Q9tF7wpTbOR5CfnDWBJ0hd0Gi98B/5H2+enRUCfzCOe2m8Rs4HGV+nY02s63T9l9R1MZ3O7/+1HiewH3wZTNT1aH8ynT/z5/lr+dHz5ccnOg/MEMjBeDyL5OKZ8bqD6ToFb/wMjqX1jNvz6g//oR2frhbYAz0OGicZ31f/9b3xOICvPEEejuMBjWeNxwMcn0lcwXk4XR+j8axx+6e+i2BG6hOYj6n8g89fLeCD7Y6eF23XpnArP39SUv3TdSw6f9X9n/mMAf4HVLLUxQ==
+</DataArray>
+</Points>
+<Cells>
+<DataArray type="Int32" Name="connectivity" format="binary">
+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
+</DataArray>
+<DataArray type="Int32" Name="offsets" format="binary">
+AQAAAAAAAAAsBgAAAAAAACwGAAAAAAAApQIAAAAAAAA=eJwV02tMEFQUB/ADKKQgio8kzB5u9KCHZeDKVtEEsUbNVVLQTNdK8dXQpm3S0BHlRlakjA2djC1d0sBIK5uQFc2WitOgNUcjHzit3GzAdEVb9evD79O95/x3d87NiIgZ3EcBpaygki3spJ1vOMVvjJCaEHEzuRRRxkpep44P+Jzj/MIQSYkRk8lmNkWUsZpN1LOHDrrp5zIJSRETyWY2RSxiDdU08CEddHOGYZJHRUwlhwcpZhFreZMG2jjECc4xyOjREVnkkM8zLGUDW2iilYN0088gickRE7iF+ylmMct4jXfYSRsdHONnLvEvU1IibuUBCillNRt5jx18Qhe9DHCFlGsibiKXx3mBV6ihnl3so4sfuchfjBsTMZ2ZPMoCXmQVG9nGbvZzmF4GGCZpbMQ07uARnuZl1vEWDbRwgCP08TsjjE+Vy13MpZRyqqmjmb108gMX+ZuMNDtAHo/xPCup5G120EYnxznLHySMi5jEjdzLXBZSThXv0sR+DtPLWQaJdLnkMIf5LOFVNtPIx3xLL6cZJmm8OrLJo5BnWU4l77Obz/iOPs5zmcQJEZnMYh7PsZwqttHCl5xggCukZviP5FHIQpaynloa2MMXHOUU57nK2IlqmUUBJbxEBTXU00w7X9PDGa4yZpJZMpN8nmIZ69hMI610cITTDJMy2f5wOw/xBItZwxs00sIBjtHPJWJKRBozyKWAElZRxVZ28Slf0cMFRsi6NuIe5lNGFds5yEl+JX1qxG08TAnrqaOVowyRnCmffMpYSy2t9DBE+nX6UMASNtFEJycZIj0r4m6epII6PqKLc/xD5jRzYR7lbKCevXzPBUZd7x5zWEAFtbTzE3/+fz494k6KKaea7eyjhyHSbvAuillBDc0coo//AIbN2LY=
+</DataArray>
+<DataArray type="UInt8" Name="types" format="binary">
+AQAAAAAAAACLAQAAAAAAAIsBAAAAAAAADgAAAAAAAAA=eJzT0hoFgwQAACPNQM8=
+</DataArray>
+<DataArray type="Int32" Name="faces" format="binary">
+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
+</DataArray>
+<DataArray type="Int32" Name="faceoffsets" format="binary">
+AQAAAAAAAAAsBgAAAAAAACwGAAAAAAAAHwMAAAAAAAA=eJwN1GtMl2UUAPAjlzAgCRUhi8RLoCBZhHmXBMnUvKd4QfOWpmbaRVdzrlTSLbPbyvWhOay0xlpjtkqb6QjU1bRyMttqTosPySS2qIkuYv0+/D68z/P8n/ec857zr4iI3XxHeo+IpdTSQn5CxDo+5zpzEiPe4Wf6J0Vs5muSkiNm8hbNDL4lYiNf0TslYj4f8QeFPe1Rz99MuDViD+fJS43YxDG6KEuL2MlZMtIjFvE+lxl5W0QNZ+jXyx6fcI2xGfb4gczbI5ZwgN8YkhmxhZMk9JYvtbRQ3CdiOYdpJ79vxHMc418mZUW8zLdcp7Cf+vAhbQzLdh91tDIiR414gzP0vSNiFq9ygpuU9pczR0m+M2Iyu6jnJuV3yYWTtDEmN2Ir9Vyl4O6INRwnYYD7eZefyMuTO/v5noSBcmAnTaQOiqhkD6fpYuLgiNUc4hqFQyKWUUszGfdETGMnF8nMj1hMLb+TW+CZt7lA0tCICrbzBX8yepi6cZB2JhZGPM+PJBZ55lkO08644RE7OE92sRx5j1/IujdiNns5Tc8Rfs82mrjBqPsiXuQwVym4X834mH8YURKxniP8xaAHIhbwOk10U1UqJxrJHhmxkINcofhBfcJn/MrAURHVvMlFeo2OmMpezpExxj6HuELuWPHwGke4QeU4fUUrQ8dHrKSODsomRLxCE6kT3c1+WhheFrGWD7hM9kN6mn2cJWWS82ynjjZKytWXE/xHWYV8qKWVIZPNN7tpILFSTanhFGkP6wlqaCRtSsR4tvENPR5xng0cpZvJU8VEAynT9Dk7aCR5esRc9tFAyqNiZjun6KBshvMcp5vpM80VF8iaFTGDLXxJF+Wz9R/Jc9SeAwyYK2Y6mTLPGvmPWaOZovnW6GLFAt+O6irfjdSF5pBmihaZB7qoWew+qpf4b2RAtTU6WbVUj5OzTC/RyfrHIy5RtdyMMnRFxEt0ULVSzPRZ5T4ukrPae2mm5AnxkbomYh7nyF2r72hn65NqwwvrzDKl6/U86Ru8lwZyntKXdFO9MeJTyp/Wy6RviniGS5RvjvgfzpIVxQ==
+</DataArray>
+</Cells>
+</Piece>
+</UnstructuredGrid>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/polyhedrons/hexahedron_and_two_polyhedra.vtu b/src/UnitTests/Meshes/data/polyhedrons/hexahedron_and_two_polyhedra.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..a6e5eb7f24f59717f1cdb7bb1faab4ae2a279789
--- /dev/null
+++ b/src/UnitTests/Meshes/data/polyhedrons/hexahedron_and_two_polyhedra.vtu
@@ -0,0 +1,70 @@
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="18" NumberOfCells="3">
+      <PointData>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="ascii" RangeMin="-0.5" RangeMax="0.5">
+          -0.505 0 0.054 -0.501 0 0.054
+          -0.497 0 0.054 -0.501 0 0.050
+          -0.505 0 0.050 -0.497 0 0.050
+          -0.501 0.00422 0.050 -0.501 0.00422 0.054
+          -0.497 0.00422 0.054 -0.497 0.00422 0.050
+          -0.501 -0.00422 0.050 -0.505 -0.00422 0.050
+          -0.497 -0.00422 0.050 -0.505 -0.00422 0.054
+          -0.497 -0.00422 0.054 -0.5034639835357666 -0.00422 0.050
+          -0.499563992023468 -0.00422 0.050 -0.501 -0.00422 0.054
+          <InformationKey name="L2_NORM_FINITE_RANGE" location="vtkDataArray" length="2">
+            <Value index="0">
+              0.50016638905
+            </Value>
+            <Value index="1">
+              0.50842888496
+            </Value>
+          </InformationKey>
+          <InformationKey name="L2_NORM_RANGE" location="vtkDataArray" length="2">
+            <Value index="0">
+              0.50016638905
+            </Value>
+            <Value index="1">
+              0.50842888496
+            </Value>
+          </InformationKey>
+        </DataArray>
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="0" RangeMax="17">
+          3 1 2 5 6 7
+          8 9 3 1 17 10
+          0 13 11 15 4 5
+          2 14 12 1 17 10
+          16 3
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="8" RangeMax="26">
+          8 17 26
+        </DataArray>
+        <DataArray type="UInt8" Name="types" format="ascii" RangeMin="12" RangeMax="42">
+          12 42 42
+        </DataArray>
+        <DataArray type="Int64" IdType="1" Name="faces" format="ascii" RangeMin="0" RangeMax="17">
+          6 4 3 1 17 10
+          4 1 0 13 17 5
+          17 13 11 15 10 5
+          11 4 3 10 15 4
+          13 0 4 11 4 4
+          0 1 3 6 4 5
+          2 14 12 4 2 1
+          17 14 5 14 17 10
+          16 12 5 10 3 5
+          12 16 4 17 1 3
+          10 4 3 1 2 5
+        </DataArray>
+        <DataArray type="Int64" IdType="1" Name="faceoffsets" format="ascii" RangeMin="-1" RangeMax="66">
+          -1 33 66
+        </DataArray>
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.fpma b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.fpma
new file mode 100644
index 0000000000000000000000000000000000000000..ccd2ad753e5fc43bfb90711d5f3500f75d951a99
--- /dev/null
+++ b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.fpma
@@ -0,0 +1,37 @@
+# 22: number of vertices
+22
+# vertex coordinates (x,y,z)-order
+-1.25 1.1665 1.203 -1.20683 1.16951 1.20537 -1.16843 1.19337 1.17878 -1.21025 1.21901 1.15383 -1.25 1.2128 1.1567 -1.20816 1.25 1.16756 -1.25 1.25 1.18056 -1.14802 1.21553 1.21165 -1.16186 1.25 1.21385 -1.20307 1.17486 1.25 -1.25 1.18056 1.25 -1.15677 1.22115 1.25 -1.18056 1.25 1.25 -1.25 1.25 1.25 -1.09277 1.20806 1.19263 -1.07219 1.22167 1.17994 -1.07215 1.25 1.18679 -1.05697 1.21124 1.19697 -1.04607 1.21508 1.22076 -1.0214 1.25 1.22293 -1.06418 1.22115 1.25 -1.04167 1.25 1.25 
+# 16: number of faces
+16
+# the first number means the number of vertices and the rest of numbers in the same line is vertex indicies attached to the face
+5 0 1 2 3 4 
+4 4 3 5 6 
+5 5 3 2 7 8 
+4 9 1 0 10 
+5 11 7 2 1 9 
+4 8 7 11 12 
+5 13 12 11 9 10 
+5 13 10 0 4 6 
+5 13 6 5 8 12 
+5 8 7 14 15 16 
+5 16 15 17 18 19 
+6 20 18 17 14 7 11 
+3 17 15 14 
+4 21 19 18 20 
+4 21 20 11 12 
+5 12 8 16 19 21 
+# 2: number of cells
+2
+# the first number means the number of faces and the rest of numbers in the same line are face indicies attached to the cell
+9 0 1 2 3 4 5 6 7 8 
+8 9 10 11 12 13 5 14 15 
+# Additional information only, does contain topology information
+# 1: The number of special selections, here there is only one selection named by boudary_face
+1
+# boundary_face" is the name
+boundary_face
+# "3" means a boundary and "5" means 5 faces, and the last line is the face indices. You can see these faces in the figure, surrounded by green edges.
+3
+5
+6 7 8 14 15 
diff --git a/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtk b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtk
new file mode 100644
index 0000000000000000000000000000000000000000..c4f7373ef73aa084eec15d767a6e655c0364fe41
--- /dev/null
+++ b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtk
@@ -0,0 +1,39 @@
+# vtk DataFile Version 5.1
+vtk output
+ASCII
+DATASET UNSTRUCTURED_GRID
+POINTS 22 float
+-1.25 1.1665 1.203 -1.20683 1.16951 1.20537 -1.16843 1.19337 1.17878 
+-1.21025 1.21901 1.15383 -1.25 1.2128 1.1567 -1.20816 1.25 1.16756 
+-1.25 1.25 1.18056 -1.14802 1.21553 1.21165 -1.16186 1.25 1.21385 
+-1.20307 1.17486 1.25 -1.25 1.18056 1.25 -1.15677 1.22115 1.25 
+-1.18056 1.25 1.25 -1.25 1.25 1.25 -1.09277 1.20806 1.19263 
+-1.07219 1.22167 1.17994 -1.07215 1.25 1.18679 -1.05697 1.21124 1.19697 
+-1.04607 1.21508 1.22076 -1.0214 1.25 1.22293 -1.06418 1.22115 1.25 
+-1.04167 1.25 1.25 
+METADATA
+INFORMATION 2
+NAME L2_NORM_RANGE LOCATION vtkDataArray
+DATA 2 2.00425 2.16506 
+NAME L2_NORM_FINITE_RANGE LOCATION vtkDataArray
+DATA 2 2.00425 2.16506 
+
+CELLS 3 97
+OFFSETS vtktypeint64
+0 46 97 
+CONNECTIVITY vtktypeint64
+8 5 0 1 2 3 4 4 4 
+3 5 6 5 5 3 2 7 8 
+4 9 1 0 10 5 11 7 2 
+1 9 4 8 7 11 12 5 13 
+12 11 9 10 5 13 10 0 4 
+6 9 5 13 6 5 8 12 5 
+8 7 14 15 16 5 16 15 17 
+18 19 6 20 18 17 14 7 11 
+3 17 15 14 4 21 19 18 20 
+4 8 7 11 12 4 21 20 11 
+12 5 12 8 16 19 21 
+CELL_TYPES 2
+42
+42
+
diff --git a/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtu b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..cc5a51f66f3cc7f058f93f0acaf056f9ef882fff
--- /dev/null
+++ b/src/UnitTests/Meshes/data/polyhedrons/two_polyhedra.vtu
@@ -0,0 +1,46 @@
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="22" NumberOfCells="2">
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="ascii">
+          -1.25 1.1665 1.203 -1.20683 1.16951 1.20537 -1.16843 1.19337 1.17878 -1.21025 1.21901 1.15383 -1.25 1.2128 1.1567 -1.20816 1.25 1.16756 -1.25 1.25 1.18056 -1.14802 1.21553 1.21165 -1.16186 1.25 1.21385 -1.20307 1.17486 1.25 -1.25 1.18056 1.25 -1.15677 1.22115 1.25 -1.18056 1.25 1.25 -1.25 1.25 1.25 -1.09277 1.20806 1.19263 -1.07219 1.22167 1.17994 -1.07215 1.25 1.18679 -1.05697 1.21124 1.19697 -1.04607 1.21508 1.22076 -1.0214 1.25 1.22293 -1.06418 1.22115 1.25 -1.04167 1.25 1.25
+        </DataArray>
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="ascii">
+          0 0
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii">
+          1 2
+        </DataArray>
+        <DataArray type="UInt8" Name="types" format="ascii">
+          42 42
+        </DataArray>
+        <DataArray type="Int64" Name="faces" format="ascii">
+          8
+          5 0 1 2 3 4
+          4 4 3 5 6
+          5 5 3 2 7 8
+          4 9 1 0 10
+          5 11 7 2 1 9
+          4 8 7 11 12
+          5 13 12 11 9 10
+          5 13 10 0 4 6
+          9
+          5 13 6 5 8 12
+          5 8 7 14 15 16
+          5 16 15 17 18 19
+          6 20 18 17 14 7 11
+          3 17 15 14
+          4 21 19 18 20
+          4 8 7 11 12
+          4 21 20 11 12
+          5 12 8 16 19 21
+        </DataArray>
+        <DataArray type="Int64" Name="faceoffsets" format="ascii">
+          46 97
+        </DataArray>
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vti b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vti
new file mode 100644
index 0000000000000000000000000000000000000000..4304ca1f7a0fc47364e39379af1b4f66ff388a62
--- /dev/null
+++ b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vti
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<VTKFile type="ImageData" version="1.0" byte_order="LittleEndian" header_type="UInt32">
+<ImageData WholeExtent="0 2 0 3 0 0 " Origin="0.000000e+00 0.000000e+00 0 " Spacing="1.000000e+00 1.000000e+00 0 ">
+<Piece Extent="0 2 0 3 0 0 ">
+</Piece>
+</ImageData>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtk b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtk
new file mode 100644
index 0000000000000000000000000000000000000000..410d4c0f7cf35b99d6c0f6480324abe67b0428aa
Binary files /dev/null and b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtk differ
diff --git a/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtu b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtu
new file mode 100644
index 0000000000000000000000000000000000000000..5c5f8564f73f76c9862813bb3c42ba79a210ccb2
--- /dev/null
+++ b/src/UnitTests/Meshes/data/quadrangles/grid_2x3.vtu
@@ -0,0 +1,22 @@
+<VTKFile type="UnstructuredGrid" version="1.0" byte_order="LittleEndian" header_type="UInt64">
+  <UnstructuredGrid>
+    <Piece NumberOfPoints="12" NumberOfCells="6">
+      <Points>
+        <DataArray type="Float64" Name="Points" NumberOfComponents="3" format="binary">
+          IAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/AAAAAAAAAAAAAAAAAADwPwAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAQAAAAAAAAPA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAADwPwAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhAAAAAAAAAAAAAAAAAAADwPwAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAhAAAAAAAAAAAA=
+        </DataArray>
+      </Points>
+      <Cells>
+        <DataArray type="Int64" Name="connectivity" format="binary">
+          wAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAABAAAAAAAAAADAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAAFAAAAAAAAAAQAAAAAAAAAAwAAAAAAAAAEAAAAAAAAAAcAAAAAAAAABgAAAAAAAAAEAAAAAAAAAAUAAAAAAAAACAAAAAAAAAAHAAAAAAAAAAYAAAAAAAAABwAAAAAAAAAKAAAAAAAAAAkAAAAAAAAABwAAAAAAAAAIAAAAAAAAAAsAAAAAAAAACgAAAAAAAAA=
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary">
+          MAAAAAAAAAAEAAAAAAAAAAgAAAAAAAAADAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAGAAAAAAAAAA=
+        </DataArray>
+        <DataArray type="UInt8" Name="types" format="binary">
+          BgAAAAAAAAAJCQkJCQk=
+        </DataArray>
+      </Cells>
+    </Piece>
+  </UnstructuredGrid>
+</VTKFile>
diff --git a/src/UnitTests/Meshes/data/triangles_2x2x2/version_5.1_ascii.vtk b/src/UnitTests/Meshes/data/triangles_2x2x2/version_5.1_ascii.vtk
new file mode 100644
index 0000000000000000000000000000000000000000..02ff76b1fd36712a6ed7dc3f33e5a13c028ab7e6
--- /dev/null
+++ b/src/UnitTests/Meshes/data/triangles_2x2x2/version_5.1_ascii.vtk
@@ -0,0 +1,78 @@
+# vtk DataFile Version 5.1
+vtk output
+ASCII
+DATASET UNSTRUCTURED_GRID
+FIELD FieldData 2
+TIME 1 1 float
+3.1536e+07 
+METADATA
+INFORMATION 0
+
+CYCLE 1 1 int
+366 
+METADATA
+INFORMATION 0
+
+POINTS 9 float
+0 0 0 25 0 0 50 0 0 
+0 25 0 25 25 0 50 25 0 
+0 50 0 25 50 0 50 50 0 
+
+METADATA
+INFORMATION 2
+NAME L2_NORM_RANGE LOCATION vtkDataArray
+DATA 2 0 70.7107 
+NAME L2_NORM_FINITE_RANGE LOCATION vtkDataArray
+DATA 2 0 70.7107 
+
+CELLS 9 24
+OFFSETS vtktypeint64
+0 3 6 9 12 15 18 21 24 
+
+CONNECTIVITY vtktypeint64
+0 1 4 0 4 3 1 2 5 
+1 5 4 3 4 7 3 7 6 
+4 5 8 4 8 7 
+CELL_TYPES 8
+5
+5
+5
+5
+5
+5
+5
+5
+
+CELL_DATA 8
+SCALARS pressure float
+LOOKUP_TABLE default
+6.90056e+06 6.90045e+06 6.90097e+06 6.90073e+06 6.90028e+06 6.90006e+06 6.90056e+06 6.90045e+06 
+METADATA
+INFORMATION 0
+
+FIELD FieldData 5
+c_0 1 8 float
+23.3681 0.93711 2677.75 431.5 0.0582516 0.00303224 23.3681 0.93711 
+METADATA
+INFORMATION 0
+
+c_1 1 8 float
+11653.9 11675.9 8502.15 11245 11676.7 11676.8 11653.9 11675.9 
+METADATA
+INFORMATION 0
+
+x_0 1 8 float
+0.00200117 8.02539e-05 0.239515 0.0369546 4.98867e-06 2.59681e-07 0.00200117 8.02539e-05 
+METADATA
+INFORMATION 0
+
+x_1 1 8 float
+0.997999 0.99992 0.760485 0.963045 0.999995 1 0.997999 0.99992 
+METADATA
+INFORMATION 0
+
+nbOfPhases 1 8 float
+1 1 1 1 1 1 1 1 
+METADATA
+INFORMATION 0
+
diff --git a/src/UnitTests/Meshes/data/triangles_2x2x2/DataFile_version_5.1_exported_from_paraview.vtk b/src/UnitTests/Meshes/data/triangles_2x2x2/version_5.1_binary.vtk
similarity index 100%
rename from src/UnitTests/Meshes/data/triangles_2x2x2/DataFile_version_5.1_exported_from_paraview.vtk
rename to src/UnitTests/Meshes/data/triangles_2x2x2/version_5.1_binary.vtk