diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60fa5d99d55311fd0854a6d5b40265fe493be9b6..3a68013136be86583b84fa315d12e1577cfef772 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,23 +182,6 @@ if( WITH_CUDA STREQUAL "yes" )
         # TODO: this is necessary only due to a bug in cmake
         set( CUDA_ADD_LIBRARY_OPTIONS -shared )
 
-        ####
-        # Check for cuBLAS
-        #
-        if( NOT WITH_CUBLAS STREQUAL "no" )
-            find_path( CUBLAS_INCLUDE_DIR cublas_v2.h
-                       /usr/local/cuda/include
-                       ${CUDA_INCLUDE_DIRS}
-                       DOC "CUBLAS headers." )
-            if( ${CUBLAS_INCLUDE_DIR} STREQUAL "CUBLAS_INCLUDE_DIR-NOTFOUND" )
-                message( "CUBLAS not found." )
-                set( HAVE_CUBLAS "//#define HAVE_CUBLAS 1" )
-            else()
-                message( "CUBLAS found. -- ${CUBLAS_INCLUDE_DIR}" )
-                set( HAVE_CUBLAS "#define HAVE_CUBLAS 1" )
-            endif()
-        endif( NOT WITH_CUBLAS STREQUAL "no" )
-
         ####
         # Check for CUSP
         #
diff --git a/doc/pde-solvers.rst b/doc/pde-solvers.rst
index 6f7eed46d377e19862f297d31ec6d70f3846ed56..d93e49e5a6901c091f1e6672bc91bb2451b75943 100644
--- a/doc/pde-solvers.rst
+++ b/doc/pde-solvers.rst
@@ -1,3 +1,9 @@
 ===========
 PDE Solvers
 ===========
+
+Finite difference method
+
+    Elliptic problems
+
+    Parabolic problems
\ No newline at end of file
diff --git a/examples/heat-equation/HeatEquationBuildConfigTag.h b/examples/heat-equation/HeatEquationBuildConfigTag.h
index 8579b7f473c6ab1a3472aaa8a11913758390a15a..0e0389ca74fa62367ec6d1facd07ac18c528ad9a 100644
--- a/examples/heat-equation/HeatEquationBuildConfigTag.h
+++ b/examples/heat-equation/HeatEquationBuildConfigTag.h
@@ -11,50 +11,57 @@
 #pragma once
 
 #include <TNL/Solvers/BuildConfigTags.h>
+#include <TNL/Meshes/BuildConfigTags.h>
 
 namespace TNL {
-namespace Solvers {
-   
-class HeatEquationBuildConfig
-{
-   public:
 
-      static void print() { std::cerr << "HeatEquationBuildConfig" << std::endl; }
-};
+class HeatEquationBuildConfigTag{};
 
+namespace Solvers {
+   
 /****
  * Turn off support for float and long double.
  */
-template<> struct ConfigTagReal< HeatEquationBuildConfig, float > { enum { enabled = false }; };
-template<> struct ConfigTagReal< HeatEquationBuildConfig, long double > { enum { enabled = false }; };
+template<> struct ConfigTagReal< HeatEquationBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct ConfigTagReal< HeatEquationBuildConfigTag, long double > { enum { enabled = false }; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct ConfigTagIndex< HeatEquationBuildConfig, short int >{ enum { enabled = false }; };
-template<> struct ConfigTagIndex< HeatEquationBuildConfig, long int >{ enum { enabled = false }; };
-
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-template< int Dimension, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< HeatEquationBuildConfig, Meshes::Grid< Dimension, Real, Device, Index > >
-      { enum { enabled = ConfigTagDimension< HeatEquationBuildConfig, Dimension >::enabled  &&
-                         ConfigTagReal< HeatEquationBuildConfig, Real >::enabled &&
-                         ConfigTagDevice< HeatEquationBuildConfig, Device >::enabled &&
-                         ConfigTagIndex< HeatEquationBuildConfig, Index >::enabled }; };
+template<> struct ConfigTagIndex< HeatEquationBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct ConfigTagIndex< HeatEquationBuildConfigTag, long int >{ enum { enabled = false }; };
 
 /****
  * Please, chose your preferred time discretization  here.
  */
-template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; };
-template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, SemiImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
-template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfig, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
+template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; };
+template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
+template<> struct ConfigTagTimeDiscretisation< HeatEquationBuildConfigTag, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
 
 /****
  * Only the Runge-Kutta-Merson solver is enabled by default.
  */
-template<> struct ConfigTagExplicitSolver< HeatEquationBuildConfig, ExplicitEulerSolverTag >{ enum { enabled = false }; };
+template<> struct ConfigTagExplicitSolver< HeatEquationBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = false }; };
 
 } // namespace Solvers
+
+namespace Meshes {
+namespace BuildConfigTags {
+
+template< int Dimensions > struct GridDimensionTag< HeatEquationBuildConfigTag, Dimensions >{ enum { enabled = true }; };
+
+/****
+ * Turn off support for float and long double.
+ */
+template<> struct GridRealTag< HeatEquationBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct GridRealTag< HeatEquationBuildConfigTag, long double > { enum { enabled = false }; };
+
+/****
+ * Turn off support for short int and long int indexing.
+ */
+template<> struct GridIndexTag< HeatEquationBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< HeatEquationBuildConfigTag, long int >{ enum { enabled = false }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
 } // namespace TNL
diff --git a/examples/heat-equation/tnl-heat-equation-eoc.h b/examples/heat-equation/tnl-heat-equation-eoc.h
index f9876fb9adf66479282f1223bd48fb10da759ae7..57ec6536fee8c43add54c4122a1c328ca489b508 100644
--- a/examples/heat-equation/tnl-heat-equation-eoc.h
+++ b/examples/heat-equation/tnl-heat-equation-eoc.h
@@ -24,8 +24,8 @@
 using namespace TNL;
 using namespace TNL::Problems;
 
-//typedef tnlDefaultBuildMeshConfig BuildConfig;
-typedef Solvers::FastBuildConfig BuildConfig;
+//typedef Solvers::DefaultBuildConfigTag BuildConfig;
+typedef Solvers::FastBuildConfigTag BuildConfig;
 
 template< typename MeshConfig >
 class heatEquationEocConfig
diff --git a/examples/heat-equation/tnl-heat-equation.h b/examples/heat-equation/tnl-heat-equation.h
index 1a0041f93e3f6edeb73b8bfe9d632ed9538f9f41..048abb409ac0d4567a22d87817edca057120b328 100644
--- a/examples/heat-equation/tnl-heat-equation.h
+++ b/examples/heat-equation/tnl-heat-equation.h
@@ -26,9 +26,8 @@
 using namespace TNL;
 using namespace TNL::Problems;
 
-//typedef tnlDefaultBuildMeshConfig BuildConfig;
-typedef Solvers::FastBuildConfig BuildConfig;
-//typedef Solvers::HeatEquationBuildConfig BuildConfig;
+//typedef Solvers::DefaultBuildConfigTag BuildConfig;
+typedef Solvers::FastBuildConfigTag BuildConfig;
 
 template< typename MeshConfig >
 class heatEquationConfig
diff --git a/examples/inviscid-flow/eulerBuildConfigTag.h b/examples/inviscid-flow/eulerBuildConfigTag.h
index b219ba4ff58c0c6601f7393e93ee395fa18ce6f8..fec6d0fe721550c828cc475fafcd11d4c3496817 100644
--- a/examples/inviscid-flow/eulerBuildConfigTag.h
+++ b/examples/inviscid-flow/eulerBuildConfigTag.h
@@ -2,6 +2,7 @@
 #define eulerBUILDCONFIGTAG_H_
 
 #include <TNL/Solvers/BuildConfigTags.h>
+#include <TNL/Meshes/BuildConfigTags.h>
 
 namespace TNL {
 
@@ -21,18 +22,6 @@ template<> struct ConfigTagReal< eulerBuildConfigTag, long double > { enum { ena
 template<> struct ConfigTagIndex< eulerBuildConfigTag, short int >{ enum { enabled = false }; };
 template<> struct ConfigTagIndex< eulerBuildConfigTag, long int >{ enum { enabled = false }; };
 
-template< int Dimension > struct ConfigTagDimension< eulerBuildConfigTag, Dimension >{ enum { enabled = ( Dimension == 1 ) }; };
-
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-template< int Dimension, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< eulerBuildConfigTag, Meshes::Grid< Dimension, Real, Device, Index > >
-      { enum { enabled = ConfigTagDimension< eulerBuildConfigTag, Dimension >::enabled  &&
-                         ConfigTagReal< eulerBuildConfigTag, Real >::enabled &&
-                         ConfigTagDevice< eulerBuildConfigTag, Device >::enabled &&
-                         ConfigTagIndex< eulerBuildConfigTag, Index >::enabled }; };
-
 /****
  * Please, chose your preferred time discretisation  here.
  */
@@ -46,6 +35,26 @@ template<> struct ConfigTagTimeDiscretisation< eulerBuildConfigTag, ImplicitTime
 template<> struct ConfigTagExplicitSolver< eulerBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = true }; };
 
 } // namespace Solvers
+
+namespace Meshes {
+namespace BuildConfigTags {
+
+template< int Dimensions > struct GridDimensionTag< eulerBuildConfigTag, Dimensions >{ enum { enabled = ( Dimensions == 1 ) }; };
+
+/****
+ * Turn off support for float and long double.
+ */
+template<> struct GridRealTag< eulerBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct GridRealTag< eulerBuildConfigTag, long double > { enum { enabled = false }; };
+
+/****
+ * Turn off support for short int and long int indexing.
+ */
+template<> struct GridIndexTag< eulerBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< eulerBuildConfigTag, long int >{ enum { enabled = false }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
 } // namespace TNL
 
 #endif /* eulerBUILDCONFIGTAG_H_ */
diff --git a/examples/transport-equation/transportEquationBuildConfigTag.h b/examples/transport-equation/transportEquationBuildConfigTag.h
index 884060fa2d973530f1b5fb926ee280aa11a4b7ed..0121ab2c00582a4b8f47a96d81b30d31b35f51bf 100644
--- a/examples/transport-equation/transportEquationBuildConfigTag.h
+++ b/examples/transport-equation/transportEquationBuildConfigTag.h
@@ -12,6 +12,7 @@
 #pragma once
 
 #include <TNL/Solvers/BuildConfigTags.h>
+#include <TNL/Meshes/BuildConfigTags.h>
 
 namespace TNL {
 
@@ -31,17 +32,6 @@ template<> struct ConfigTagReal< transportEquationBuildConfigTag, long double >
 template<> struct ConfigTagIndex< transportEquationBuildConfigTag, short int >{ enum { enabled = false }; };
 template<> struct ConfigTagIndex< transportEquationBuildConfigTag, long int >{ enum { enabled = false }; };
 
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-
-template< int Dimensions, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< transportEquationBuildConfigTag, Meshes::Grid< Dimensions, Real, Device, Index > >
-      { enum { enabled = ConfigTagDimension< transportEquationBuildConfigTag, Dimensions >::enabled  &&
-                         ConfigTagReal< transportEquationBuildConfigTag, Real >::enabled &&
-                         ConfigTagDevice< transportEquationBuildConfigTag, Device >::enabled &&
-                         ConfigTagIndex< transportEquationBuildConfigTag, Index >::enabled }; };
-
 /****
  * Please, chose your preferred time discretisation  here.
  */
@@ -55,4 +45,24 @@ template<> struct ConfigTagTimeDiscretisation< transportEquationBuildConfigTag,
 template<> struct ConfigTagExplicitSolver< transportEquationBuildConfigTag, Solvers::ExplicitEulerSolverTag >{ enum { enabled = true }; };
 
 } // namespace Solvers
+
+namespace Meshes {
+namespace BuildConfigTags {
+
+template< int Dimensions > struct GridDimensionTag< transportEquationBuildConfigTag, Dimensions >{ enum { enabled = true }; };
+
+/****
+ * Turn off support for float and long double.
+ */
+template<> struct GridRealTag< transportEquationBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct GridRealTag< transportEquationBuildConfigTag, long double > { enum { enabled = false }; };
+
+/****
+ * Turn off support for short int and long int indexing.
+ */
+template<> struct GridIndexTag< transportEquationBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< transportEquationBuildConfigTag, long int >{ enum { enabled = false }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
 } // namespace TNL
diff --git a/src/Python/CMakeLists.txt b/src/Python/CMakeLists.txt
index 6356af0046b95d4f5a61944324cdcf2827408270..598d9faf14446f4073daffccd4a9cc5f15beb7b7 100644
--- a/src/Python/CMakeLists.txt
+++ b/src/Python/CMakeLists.txt
@@ -1,8 +1,36 @@
 find_package( PythonInterp 3 )
+find_package( PythonLibs 3 )
+
+set( PYTHON_SITE_PACKAGES_DIR lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages )
 
 if( PYTHONINTERP_FOUND )
    CONFIGURE_FILE( "__init__.py.in" "${PROJECT_BUILD_PATH}/Python/__init__.py" )
    INSTALL( FILES ${PROJECT_BUILD_PATH}/Python/__init__.py
                   LogParser.py
-            DESTINATION lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages/TNL )
+            DESTINATION ${PYTHON_SITE_PACKAGES_DIR}/TNL )
+endif()
+
+if( PYTHONLIBS_FOUND )
+   # download and build pybind11 at configure time
+   configure_file(pybind11.cmake.in ${CMAKE_BINARY_DIR}/pybind11-download/CMakeLists.txt)
+   execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+      RESULT_VARIABLE result
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pybind11-download )
+   if(result)
+      message(FATAL_ERROR "CMake step for pybind11 failed: ${result}")
+   endif()
+   execute_process(COMMAND ${CMAKE_COMMAND} --build .
+      RESULT_VARIABLE result
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/pybind11-download )
+   if(result)
+      message(FATAL_ERROR "Build step for pybind11 failed: ${result}")
+   endif()
+
+   # add the pybind11 subdirectory to provide the pybind11_add_module macro
+   add_subdirectory(${CMAKE_BINARY_DIR}/pybind11-src ${CMAKE_BINARY_DIR}/pybind11-build)
+
+   # add the subdirectory with our bindings
+   add_subdirectory(pytnl)
+else()
+   message( "The Python.h header file was not found, Python bindings will not be builg." )
 endif()
diff --git a/src/Python/pybind11.cmake.in b/src/Python/pybind11.cmake.in
new file mode 100644
index 0000000000000000000000000000000000000000..18f1aeac607f719a067a8a61c1c3449cfd64687b
--- /dev/null
+++ b/src/Python/pybind11.cmake.in
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.8.2)
+
+project(pybind11-download)
+include(ExternalProject)
+
+ExternalProject_Add(pybind11
+  GIT_REPOSITORY    https://github.com/pybind/pybind11.git
+  GIT_TAG           master
+  SOURCE_DIR        "${CMAKE_BINARY_DIR}/pybind11-src"
+  BINARY_DIR        "${CMAKE_BINARY_DIR}/pybind11-build"
+  CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DPYBIND11_TEST=FALSE
+)
diff --git a/src/Python/pytnl/CMakeLists.txt b/src/Python/pytnl/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..eecb2aeeb6c9abd9acce6650189df3c4129834ee
--- /dev/null
+++ b/src/Python/pytnl/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_subdirectory( tnl )
+
+set( headers
+         exceptions.h
+         RawIterator.h
+         tnl_conversions.h
+         tnl_indexing.h
+         tnl_str_conversion.h
+         tnl_tuple_conversion.h
+         typedefs.h
+)
+
+install( FILES ${headers} DESTINATION "include/pytnl" )
diff --git a/src/Python/pytnl/RawIterator.h b/src/Python/pytnl/RawIterator.h
new file mode 100644
index 0000000000000000000000000000000000000000..6e9aa7b41cfb3f06c4630675062a5b9cbe77c848
--- /dev/null
+++ b/src/Python/pytnl/RawIterator.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <iterator>
+
+template< typename DataType >
+class RawIterator : public std::iterator<std::random_access_iterator_tag,
+                                           DataType,
+                                           ptrdiff_t,
+                                           DataType*,
+                                           DataType&>
+{
+protected:
+    DataType*               m_ptr;
+
+public:
+    RawIterator( DataType* ptr = nullptr ) { m_ptr = ptr; }
+    RawIterator( const RawIterator<DataType> & rawIterator ) = default;
+    ~RawIterator(){}
+
+    RawIterator<DataType>&  operator=( const RawIterator<DataType> & rawIterator ) = default;
+    RawIterator<DataType>&  operator=( DataType* ptr ) { m_ptr = ptr; return (*this); }
+
+    operator                bool() const
+    {
+        if(m_ptr)
+            return true;
+        else
+            return false;
+    }
+
+    bool                    operator==( const RawIterator<DataType> & rawIterator ) const { return ( m_ptr == rawIterator.getConstPtr() ); }
+    bool                    operator!=( const RawIterator<DataType> & rawIterator ) const { return ( m_ptr != rawIterator.getConstPtr() ); }
+
+    RawIterator<DataType>&  operator+=( const ptrdiff_t & movement ){ m_ptr += movement; return (*this); }
+    RawIterator<DataType>&  operator-=( const ptrdiff_t & movement ){ m_ptr -= movement; return (*this); }
+    RawIterator<DataType>&  operator++() { ++m_ptr; return (*this); }
+    RawIterator<DataType>&  operator--() { --m_ptr; return (*this); }
+    RawIterator<DataType>   operator++( int ) { auto temp(*this); ++m_ptr; return temp; }
+    RawIterator<DataType>   operator--( int ) { auto temp(*this); --m_ptr; return temp; }
+    RawIterator<DataType>   operator+( const ptrdiff_t & movement ) { auto oldPtr = m_ptr; m_ptr+=movement; auto temp(*this); m_ptr = oldPtr; return temp; }
+    RawIterator<DataType>   operator-( const ptrdiff_t & movement ) { auto oldPtr = m_ptr; m_ptr-=movement; auto temp(*this); m_ptr = oldPtr; return temp; }
+
+    ptrdiff_t               operator-( const RawIterator<DataType>& rawIterator ) { return std::distance(rawIterator.getPtr(), this->getPtr()); }
+
+    DataType&               operator*() { return *m_ptr; }
+    const DataType&         operator*() const { return *m_ptr; }
+    DataType*               operator->() { return m_ptr; }
+
+    DataType*               getPtr() const { return m_ptr; }
+    const DataType*         getConstPtr() const { return m_ptr; }
+};
diff --git a/src/Python/pytnl/exceptions.h b/src/Python/pytnl/exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..669fb3214c9e6bfad69bd2a80cde79ede532f781
--- /dev/null
+++ b/src/Python/pytnl/exceptions.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <stdexcept>
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include <TNL/Assert.h>
+
+struct NotImplementedError
+   : public std::runtime_error
+{
+   NotImplementedError( const char* msg )
+   : std::runtime_error( msg )
+   {}
+};
+
+static void register_exceptions( py::module & m )
+{
+    py::register_exception_translator(
+        [](std::exception_ptr p) {
+            try {
+                if (p) std::rethrow_exception(p);
+            }
+            // translate exceptions used in the bindings
+            catch (const NotImplementedError & e) {
+                PyErr_SetString(PyExc_NotImplementedError, e.what());
+            }
+            // translate TNL::Assert::AssertionError
+            catch (const TNL::Assert::AssertionError & e) {
+                PyErr_SetString(PyExc_AssertionError, e.what());
+            }
+        }
+    );
+}
diff --git a/src/Python/pytnl/tnl/Array.h b/src/Python/pytnl/tnl/Array.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d74acdccef35773616fb6b7e695caa32c767361
--- /dev/null
+++ b/src/Python/pytnl/tnl/Array.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+namespace py = pybind11;
+
+#include "../tnl_indexing.h"
+
+#include <TNL/Containers/Array.h>
+
+template< typename ArrayType >
+void export_Array(py::module & m, const char* name)
+{
+    auto array = py::class_<ArrayType, TNL::Object>(m, name, py::buffer_protocol())
+        .def(py::init<>())
+        .def(py::init<int>())
+        .def_static("getType",              &ArrayType::getType)
+        .def("getTypeVirtual",              &ArrayType::getTypeVirtual)
+        .def_static("getSerializationType", &ArrayType::getSerializationType)
+        .def("getSerializationTypeVirtual", &ArrayType::getSerializationTypeVirtual)
+        .def("setSize", &ArrayType::setSize)
+        .def("setLike", &ArrayType::template setLike<ArrayType>)
+        .def("swap", &ArrayType::swap)
+        .def("reset", &ArrayType::reset)
+        .def("getSize", &ArrayType::getSize)
+        .def("setElement", &ArrayType::setElement)
+        .def("getElement", &ArrayType::getElement)
+        // operator=
+        .def("assign", []( ArrayType& array, const ArrayType& other ) -> ArrayType& {
+                return array = other;
+            })
+        .def(py::self == py::self)
+        .def(py::self != py::self)
+        .def("setValue", &ArrayType::setValue)
+
+        .def("__str__", []( ArrayType & a ) {
+                std::stringstream ss;
+                ss << a;
+                return ss.str();
+            } )
+
+        // Python buffer protocol: http://pybind11.readthedocs.io/en/master/advanced/pycpp/numpy.html
+        .def_buffer( [](ArrayType & a) -> py::buffer_info {
+            return py::buffer_info(
+                // Pointer to buffer
+                a.getData(),
+                // Size of one scalar
+                sizeof( typename ArrayType::ElementType ),
+                // Python struct-style format descriptor
+                py::format_descriptor< typename ArrayType::ElementType >::format(),
+                // Number of dimensions
+                1,
+                // Buffer dimensions
+                { a.getSize() },
+                // Strides (in bytes) for each index
+                { sizeof( typename ArrayType::ElementType ) }
+            );
+        })
+    ;
+
+    tnl_indexing< ArrayType >( array );
+    tnl_slice_indexing< ArrayType >( array );
+}
diff --git a/src/Python/pytnl/tnl/CMakeLists.txt b/src/Python/pytnl/tnl/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9fa9bef04c181688e90cb8762608d9cf68e72d45
--- /dev/null
+++ b/src/Python/pytnl/tnl/CMakeLists.txt
@@ -0,0 +1,26 @@
+set( sources
+      Grid1D.cpp
+      Grid2D.cpp
+      Grid3D.cpp
+      Mesh.cpp
+      Object.cpp
+      SparseMatrix.cpp
+      String.cpp
+      tnl.cpp
+)
+pybind11_add_module( pytnl ${sources} )
+
+# link against tnl.so
+target_link_libraries( pytnl PRIVATE tnl )
+
+# rename the shared library to tnl.cpython-XXm-x86_64-linux-gnu.so
+set_target_properties( pytnl PROPERTIES LIBRARY_OUTPUT_NAME tnl )
+
+# We have bindings for unsafe objects (e.g. Array::operator[]) where assertion
+# is the only safeguard, so we need to translate the TNL::AssertionError to
+# Python's AssertionError.
+# NDEBUG is defined in the global CMAKE_CXX_FLAGS and cannot be easily removed
+# per-target, so we need to undefine it by passing -U NDEBUG.
+target_compile_options( pytnl PRIVATE -U NDEBUG -D TNL_THROW_ASSERTION_ERROR )
+
+install( TARGETS pytnl DESTINATION ${PYTHON_SITE_PACKAGES_DIR} )
diff --git a/src/Python/pytnl/tnl/EntityTypes.h b/src/Python/pytnl/tnl/EntityTypes.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f10e2827dd2cc24d006c88f509e6b8d5a5cbf90
--- /dev/null
+++ b/src/Python/pytnl/tnl/EntityTypes.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+enum class EntityTypes { Cell, Face, Vertex };
+
+inline void
+export_EntityTypes( py::module & m )
+{
+    // avoid duplicate conversion -> export only once
+    static bool exported = false;
+    if( ! exported ) {
+        // TODO: should be nested types instead
+        py::enum_< EntityTypes >( m, "EntityTypes" )
+            .value("Cell", EntityTypes::Cell)
+            .value("Face", EntityTypes::Face)
+            .value("Vertex", EntityTypes::Vertex)
+        ;
+        exported = true;
+    }
+}
+
+template< typename Mesh >
+typename Mesh::GlobalIndexType
+mesh_getEntitiesCount( const Mesh & self, const EntityTypes & entity )
+{
+    if( entity == EntityTypes::Cell )
+        return self.template getEntitiesCount< typename Mesh::Cell >();
+    else if( entity == EntityTypes::Face )
+        return self.template getEntitiesCount< typename Mesh::Face >();
+    else if( entity == EntityTypes::Vertex )
+        return self.template getEntitiesCount< typename Mesh::Vertex >();
+    else
+        throw py::value_error("The entity parameter must be either Cell, Face or Vertex.");
+}
diff --git a/src/Python/pytnl/tnl/Grid.h b/src/Python/pytnl/tnl/Grid.h
new file mode 100644
index 0000000000000000000000000000000000000000..afc5b39749362a08248befb7716c8f446e888dad
--- /dev/null
+++ b/src/Python/pytnl/tnl/Grid.h
@@ -0,0 +1,98 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include "StaticVector.h"
+#include "Grid_getSpaceStepsProducts.h"
+#include "EntityTypes.h"
+
+#include <type_traits>
+
+template< typename GridEntity, typename PyGrid >
+void export_GridEntity( PyGrid & scope, const char* name )
+{
+    typename GridEntity::CoordinatesType const & (GridEntity::* _getCoordinates1)(void) const = &GridEntity::getCoordinates;
+    typename GridEntity::CoordinatesType       & (GridEntity::* _getCoordinates2)(void) = &GridEntity::getCoordinates;
+
+    py::class_< GridEntity >( scope, name )
+        .def( py::init< typename GridEntity::GridType >(),
+              py::return_value_policy::reference_internal )
+        .def( py::init< typename GridEntity::GridType,
+                        typename GridEntity::CoordinatesType,
+                        typename GridEntity::EntityOrientationType,
+                        typename GridEntity::EntityBasisType >(),
+              py::return_value_policy::reference_internal )
+        .def("getEntityDimension", &GridEntity::getEntityDimension)
+        .def("getMeshDimension", &GridEntity::getMeshDimension)
+        // TODO: constructors
+        .def("getCoordinates", _getCoordinates1, py::return_value_policy::reference_internal)
+        .def("getCoordinates", _getCoordinates2, py::return_value_policy::reference_internal)
+        .def("setCoordinates", &GridEntity::setCoordinates)
+        .def("refresh", &GridEntity::refresh)
+        .def("getIndex", &GridEntity::getIndex)
+        // FIXME: some templates return reference, others value
+//        .def("getOrientation", &GridEntity::getOrientation, py::return_internal_reference<>(), py::return_value_policy<py::copy_const_reference>())
+        .def("setOrientation", &GridEntity::setOrientation)
+        // FIXME: some templates return reference, others value
+//        .def("getBasis", &GridEntity::getBasis, py::return_internal_reference<>(), py::return_value_policy<py::copy_const_reference>())
+        .def("setBasis", &GridEntity::setBasis)
+        // TODO: getNeighbourEntities
+        .def("isBoundaryEntity", &GridEntity::isBoundaryEntity)
+        .def("getCenter", &GridEntity::getCenter)
+        // FIXME: some templates return reference, others value
+//        .def("getMeasure", &GridEntity::getMeasure, py::return_value_policy<py::copy_const_reference>())
+        .def("getMesh", &GridEntity::getMesh, py::return_value_policy::reference_internal)
+    ;
+}
+
+template< typename Grid >
+void export_Grid( py::module & m, const char* name )
+{
+    // function pointers for overloaded methods
+// FIXME: number of parameters depends on the grid dimension
+//    void (Grid::* _setDimensions1)(const IndexType) = &Grid::setDimensions;
+    void (Grid::* _setDimensions2)(const typename Grid::CoordinatesType &) = &Grid::setDimensions;
+
+    export_EntityTypes(m);
+
+    auto grid = py::class_<Grid, TNL::Object>( m, name )
+        .def(py::init<>())
+        .def_static("getMeshDimension", &Grid::getMeshDimension)
+        .def_static("getType",              &Grid::getType)
+        .def("getTypeVirtual",              &Grid::getTypeVirtual)
+        .def_static("getSerializationType", &Grid::getSerializationType)
+        .def("getSerializationTypeVirtual", &Grid::getSerializationTypeVirtual)
+        // FIXME: number of parameters depends on the grid dimension
+//        .def("setDimensions", _setDimensions1)
+        .def("setDimensions", _setDimensions2)
+        .def("getDimensions", &Grid::getDimensions, py::return_value_policy::reference_internal)
+        .def("setDomain", &Grid::setDomain)
+        .def("getOrigin", &Grid::getOrigin, py::return_value_policy::reference_internal)
+        .def("getProportions", &Grid::getProportions, py::return_value_policy::reference_internal)
+        .def("getEntitiesCount", &mesh_getEntitiesCount< Grid >)
+        // TODO: if combined, the return type would depend on the runtime parameter (entity)
+        .def("getEntity_cell", &Grid::template getEntity<typename Grid::Cell>)
+        .def("getEntity_face", &Grid::template getEntity<typename Grid::Face>)
+        .def("getEntity_vertex", &Grid::template getEntity<typename Grid::Vertex>)
+        .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Cell>)
+        .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Face>)
+        .def("getEntityIndex", &Grid::template getEntityIndex<typename Grid::Vertex>)
+        .def("getCellMeasure", &Grid::getCellMeasure, py::return_value_policy::reference_internal)
+        .def("getSpaceSteps", &Grid::getSpaceSteps, py::return_value_policy::reference_internal)
+        .def("getSmallestSpaceStep", &Grid::getSmallestSpaceStep)
+        // TODO: writeProlog()
+    ;
+
+    // complicated methods
+    SpaceStepsProductsGetter< Grid >::export_getSpaceSteps( grid );
+
+    // nested types
+    export_StaticVector< typename Grid::CoordinatesType >( grid, "CoordinatesType" );
+    export_StaticVector< typename Grid::PointType >( grid, "PointType" );
+    export_GridEntity< typename Grid::Cell >( grid, "Cell" );
+    export_GridEntity< typename Grid::Face >( grid, "Face" );
+    // avoid duplicate conversion if the type is the same
+    if( ! std::is_same< typename Grid::Face, typename Grid::Vertex >::value )
+        export_GridEntity< typename Grid::Vertex >( grid, "Vertex" );
+}
diff --git a/src/Python/pytnl/tnl/Grid1D.cpp b/src/Python/pytnl/tnl/Grid1D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d10952b713e89a8deab65c6fe321bfeea5a3b16f
--- /dev/null
+++ b/src/Python/pytnl/tnl/Grid1D.cpp
@@ -0,0 +1,9 @@
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "Grid.h"
+
+void export_Grid1D( py::module & m )
+{
+    export_Grid< Grid1D >( m, "Grid1D" );
+}
diff --git a/src/Python/pytnl/tnl/Grid2D.cpp b/src/Python/pytnl/tnl/Grid2D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69b8683c10453d44ac415da95e83067ba4139376
--- /dev/null
+++ b/src/Python/pytnl/tnl/Grid2D.cpp
@@ -0,0 +1,9 @@
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "Grid.h"
+
+void export_Grid2D( py::module & m )
+{
+    export_Grid< Grid2D >( m, "Grid2D" );
+}
diff --git a/src/Python/pytnl/tnl/Grid3D.cpp b/src/Python/pytnl/tnl/Grid3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15d7dd48071ac310c78d7cf057f5e7d700f72ad2
--- /dev/null
+++ b/src/Python/pytnl/tnl/Grid3D.cpp
@@ -0,0 +1,9 @@
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "Grid.h"
+
+void export_Grid3D( py::module & m )
+{
+    export_Grid< Grid3D >( m, "Grid3D" );
+}
diff --git a/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h b/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h
new file mode 100644
index 0000000000000000000000000000000000000000..f54b9eebc5a6dde5a373a00f57733aa7a15c1885
--- /dev/null
+++ b/src/Python/pytnl/tnl/Grid_getSpaceStepsProducts.h
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include "../typedefs.h"
+
+template< typename Grid >
+struct SpaceStepsProductsGetter
+{};
+
+template<>
+struct SpaceStepsProductsGetter< Grid1D >
+{
+    static inline
+    typename Grid1D::RealType
+    get( const Grid1D & grid, const int & xPow )
+    {
+        if( xPow == -2 ) return grid.template getSpaceStepsProducts< -2 >();
+        if( xPow == -1 ) return grid.template getSpaceStepsProducts< -1 >();
+        if( xPow ==  0 ) return grid.template getSpaceStepsProducts<  0 >();
+        if( xPow ==  1 ) return grid.template getSpaceStepsProducts<  1 >();
+        if( xPow ==  2 ) return grid.template getSpaceStepsProducts<  2 >();
+        const auto hx = grid.template getSpaceStepsProducts< 1 >();
+        return pow( hx, xPow );
+    }
+
+    template< typename PyGrid >
+    static void
+    export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" )
+    {
+        scope.def("getSpaceStepsProducts", get,   py::arg("xPow") );
+    }
+};
+
+template<>
+struct SpaceStepsProductsGetter< Grid2D >
+{
+    static inline
+    typename Grid2D::RealType
+    get( const Grid2D & grid, const int & xPow, const int & yPow = 0 )
+    {
+        if( xPow == 0 && yPow == 0 ) return grid.template getSpaceStepsProducts< 0, 0 >();
+        auto hx = grid.template getSpaceStepsProducts< 1, 0 >();
+        auto hy = grid.template getSpaceStepsProducts< 0, 1 >();
+        if( xPow != 1 ) hx = pow( hx, xPow );
+        if( yPow != 1 ) hy = pow( hy, yPow );
+        return hx * hy;
+    }
+
+    template< typename PyGrid >
+    static void
+    export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" )
+    {
+        scope.def("getSpaceStepsProducts", get,   py::arg("xPow"), py::arg("yPow")=0 );
+    }
+};
+
+template<>
+struct SpaceStepsProductsGetter< Grid3D >
+{
+    static inline
+    typename Grid3D::RealType
+    get( const Grid3D & grid, const int & xPow, const int & yPow = 0, const int & zPow = 0 )
+    {
+        if( xPow == 0 && yPow == 0 && zPow == 0 ) return grid.template getSpaceStepsProducts< 0, 0, 0 >();
+        auto hx = grid.template getSpaceStepsProducts< 1, 0, 0 >();
+        auto hy = grid.template getSpaceStepsProducts< 0, 1, 0 >();
+        auto hz = grid.template getSpaceStepsProducts< 0, 0, 1 >();
+        if( xPow != 1 ) hx = pow( hx, xPow );
+        if( yPow != 1 ) hy = pow( hy, yPow );
+        if( zPow != 1 ) hz = pow( hz, zPow );
+        return hx * hy * hz;
+    }
+
+    template< typename PyGrid >
+    static void
+    export_getSpaceSteps( PyGrid & scope, const char* name = "getSpaceSteps" )
+    {
+        scope.def("getSpaceStepsProducts", get,   py::arg("xPow"), py::arg("yPow")=0, py::arg("zPow")=0 );
+    }
+};
diff --git a/src/Python/pytnl/tnl/Mesh.cpp b/src/Python/pytnl/tnl/Mesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c267aeade67b136d2b425444bc4f010ce3acc12d
--- /dev/null
+++ b/src/Python/pytnl/tnl/Mesh.cpp
@@ -0,0 +1,30 @@
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "Mesh.h"
+#include <TNL/Meshes/Readers/VTKReader.h>
+
+void export_Meshes( py::module & m )
+{
+    export_Mesh< MeshOfEdges >( m, "MeshOfEdges" );
+    export_Mesh< MeshOfTriangles >( m, "MeshOfTriangles" );
+    export_Mesh< MeshOfTetrahedrons >( m, "MeshOfTetrahedrons" );
+
+    using Reader = TNL::Meshes::Readers::VTKReader;
+
+    py::class_< Reader >( m, "VTKReader" )
+        .def(py::init<>())
+        .def("readMesh", &Reader::template readMesh< MeshOfEdges >)
+        .def("readMesh", &Reader::template readMesh< MeshOfTriangles >)
+        .def("readMesh", &Reader::template readMesh< MeshOfTetrahedrons >)
+//        .def("readMesh", []( Reader& reader, const std::string& name, MeshOfEdges & mesh ) {
+//                return reader.readMesh( name.c_str(), mesh );
+//            } )
+//        .def("readMesh", []( Reader& reader, const std::string& name, MeshOfTriangles & mesh ) {
+//                return reader.readMesh( name.c_str(), mesh );
+//            } )
+//        .def("readMesh", []( Reader& reader, const std::string& name, MeshOfTetrahedrons & mesh ) {
+//                return reader.readMesh( name.c_str(), mesh );
+//            } )
+    ;
+}
diff --git a/src/Python/pytnl/tnl/Mesh.h b/src/Python/pytnl/tnl/Mesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..ee17a134804fc2fb71d69f5e81bd2838d57428e2
--- /dev/null
+++ b/src/Python/pytnl/tnl/Mesh.h
@@ -0,0 +1,145 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include "../typedefs.h"
+#include "StaticVector.h"
+#include "EntityTypes.h"
+
+#include <TNL/String.h>
+#include <TNL/Meshes/Geometry/getEntityCenter.h>
+#include <TNL/Meshes/Geometry/getEntityMeasure.h>
+
+#include <type_traits>
+
+template< typename MeshEntity >
+typename MeshEntity::MeshTraitsType::GlobalIndexType
+getIndex( const MeshEntity& entity )
+{
+    return entity.getIndex();
+};
+
+struct _general {};
+struct _special : _general {};
+
+template< typename MeshEntity,
+          int Superdimension,
+          typename Scope,
+          typename = typename std::enable_if< Superdimension <= MeshEntity::MeshTraitsType::meshDimension >::type >
+//                                           && MeshEntity::template SuperentityTraits< Superdimension >::storageEnabled >::type >
+void export_getSuperentityIndex( Scope & m, _special )
+{
+    m.def("getSuperentityIndex", []( const MeshEntity& entity, const typename MeshEntity::LocalIndexType& i ) {
+                                        return entity.template getSuperentityIndex< Superdimension >( i );
+                                    }
+            );
+}
+
+template< typename MeshEntity,
+          int Superdimension,
+          typename Scope >
+void export_getSuperentityIndex( Scope &, _general )
+{
+}
+
+
+template< typename MeshEntity,
+          int Subdimension,
+          typename Scope,
+          typename = typename std::enable_if< Subdimension <= MeshEntity::MeshTraitsType::meshDimension
+                                              && (Subdimension < MeshEntity::getEntityDimension()) >::type >
+void export_getSubentityIndex( Scope & m, const char* name, _special )
+{
+    m.def(name, []( const MeshEntity& entity, const typename MeshEntity::LocalIndexType& i ) {
+                    return entity.template getSubentityIndex< Subdimension >( i );
+                }
+            );
+}
+
+template< typename MeshEntity,
+          int Superdimension,
+          typename Scope >
+void export_getSubentityIndex( Scope &, const char*, _general )
+{
+}
+
+
+template< typename MeshEntity,
+          typename Scope,
+          typename = typename std::enable_if< MeshEntity::getEntityDimension() == 0 >::type >
+void export_getPoint( Scope & scope, _special )
+{
+    scope.def("getPoint", []( const MeshEntity& entity ) {
+                            return entity.getPoint();
+                        }
+            );
+}
+
+template< typename MeshEntity,
+          typename Scope >
+void export_getPoint( Scope &, _general )
+{
+}
+
+
+template< typename MeshEntity, typename Scope >
+void export_MeshEntity( Scope & scope, const char* name )
+{
+    auto entity = py::class_< MeshEntity >( scope, name )
+        .def_static("getEntityDimension", &MeshEntity::getEntityDimension)
+        // FIXME: boost chokes on this
+//        .def("getIndex", &MeshEntity::getIndex, py::return_internal_reference<>())
+        .def("getIndex", getIndex< MeshEntity >)
+        // TODO
+    ;
+
+    export_getSuperentityIndex< MeshEntity, MeshEntity::getEntityDimension() + 1 >( entity, _special() );
+    export_getSubentityIndex< MeshEntity, 0 >( entity, "getSubvertexIndex", _special() );
+    export_getPoint< MeshEntity >( entity, _special() );
+}
+
+template< typename Mesh >
+void export_Mesh( py::module & m, const char* name )
+{
+    // there are two templates - const and non-const - take only the const
+    auto (Mesh::* getEntity_cell)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Cell>;
+    auto (Mesh::* getEntity_face)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Face>;
+    auto (Mesh::* getEntity_vertex)(const typename Mesh::GlobalIndexType&) const = &Mesh::template getEntity<typename Mesh::Vertex>;
+
+    export_EntityTypes(m);
+
+    auto mesh = py::class_< Mesh, TNL::Object >( m, name )
+        .def(py::init<>())
+        .def_static("getMeshDimension", &Mesh::getMeshDimension)
+        .def_static("getType",              &Mesh::getType)
+        .def("getTypeVirtual",              &Mesh::getTypeVirtual)
+        .def_static("getSerializationType", &Mesh::getSerializationType)
+        .def("getSerializationTypeVirtual", &Mesh::getSerializationTypeVirtual)
+        .def("getEntitiesCount", &mesh_getEntitiesCount< Mesh >)
+        // TODO: if combined, the return type would depend on the runtime parameter (entity)
+        .def("getEntity_cell", getEntity_cell, py::return_value_policy::reference_internal)
+        .def("getEntity_face", getEntity_face, py::return_value_policy::reference_internal)
+        .def("getEntity_vertex", getEntity_vertex, py::return_value_policy::reference_internal)
+        .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Cell& cell ){ return getEntityCenter( mesh, cell ); } )
+        .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Face& face ){ return getEntityCenter( mesh, face ); } )
+        .def("getEntityCenter", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){ return getEntityCenter( mesh, vertex ); } )
+        .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Cell& cell ){ return getEntityMeasure( mesh, cell ); } )
+        .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Face& face ){ return getEntityMeasure( mesh, face ); } )
+        .def("getEntityMeasure", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){ return getEntityMeasure( mesh, vertex ); } )
+        .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Cell& cell ){
+                                       return mesh.template isBoundaryEntity< Mesh::Cell::getEntityDimension() >( cell.getIndex() ); } )
+        .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Face& face ){
+                                       return mesh.template isBoundaryEntity< Mesh::Face::getEntityDimension() >( face.getIndex() ); } )
+        .def("isBoundaryEntity", []( const Mesh& mesh, const typename Mesh::Vertex& vertex ){
+                                        return mesh.template isBoundaryEntity< Mesh::Vertex::getEntityDimension() >( vertex.getIndex() ); } )
+        // TODO: more?
+    ;
+
+    // nested types
+    export_MeshEntity< typename Mesh::Cell >( mesh, "Cell" );
+    export_MeshEntity< typename Mesh::Face >( mesh, "Face" );
+    // avoid duplicate conversion if the type is the same
+    if( ! std::is_same< typename Mesh::Face, typename Mesh::Vertex >::value )
+        export_MeshEntity< typename Mesh::Vertex >( mesh, "Vertex" );
+}
diff --git a/src/Python/pytnl/tnl/Object.cpp b/src/Python/pytnl/tnl/Object.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd592a2c6ac8eb0e3cd24ce09c5e27110e92f8a2
--- /dev/null
+++ b/src/Python/pytnl/tnl/Object.cpp
@@ -0,0 +1,22 @@
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include <TNL/Object.h>
+
+void export_Object( py::module & m )
+{
+    py::class_< TNL::Object >( m, "Object" )
+        // TODO: make it abstract class in Python
+        .def("save", (bool (TNL::Object::*)(const TNL::String &) const) &TNL::Object::save)
+        .def("load", (bool (TNL::Object::*)(const TNL::String &)) &TNL::Object::load)
+        .def("boundLoad", (bool (TNL::Object::*)(const TNL::String &)) &TNL::Object::boundLoad)
+        // FIXME: why does it not work?
+//        .def("save", py::overload_cast<TNL::File>(&TNL::Object::save, py::const_))
+//        .def("load", py::overload_cast<TNL::File>(&TNL::Object::load))
+        .def("save", (bool (TNL::Object::*)(TNL::File &) const) &TNL::Object::save)
+        .def("load", (bool (TNL::Object::*)(TNL::File &)) &TNL::Object::load)
+    ;
+}
diff --git a/src/Python/pytnl/tnl/SparseMatrix.cpp b/src/Python/pytnl/tnl/SparseMatrix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e6584998313fa9e3c1314c6f67b99267815cf0a8
--- /dev/null
+++ b/src/Python/pytnl/tnl/SparseMatrix.cpp
@@ -0,0 +1,29 @@
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "SparseMatrix.h"
+
+#include <TNL/Matrices/CSR.h>
+#include <TNL/Matrices/Ellpack.h>
+#include <TNL/Matrices/SlicedEllpack.h>
+
+using CSR_host = TNL::Matrices::CSR< double, TNL::Devices::Host, int >;
+using CSR_cuda = TNL::Matrices::CSR< double, TNL::Devices::Cuda, int >;
+using E_host = TNL::Matrices::Ellpack< double, TNL::Devices::Host, int >;
+using E_cuda = TNL::Matrices::Ellpack< double, TNL::Devices::Cuda, int >;
+using SE_host = TNL::Matrices::SlicedEllpack< double, TNL::Devices::Host, int >;
+using SE_cuda = TNL::Matrices::SlicedEllpack< double, TNL::Devices::Cuda, int >;
+
+void export_SparseMatrices( py::module & m )
+{
+    export_Matrix< CSR_host >( m, "CSR" );
+    export_Matrix< E_host   >( m, "Ellpack" );
+    export_Matrix< SE_host  >( m, "SlicedEllpack" );
+
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< CSR_host, E_host >);
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< E_host, CSR_host >);
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< CSR_host, SE_host >);
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< SE_host, CSR_host >);
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< E_host, SE_host >);
+    m.def("copySparseMatrix", &TNL::Matrices::copySparseMatrix< SE_host, E_host >);
+}
diff --git a/src/Python/pytnl/tnl/SparseMatrix.h b/src/Python/pytnl/tnl/SparseMatrix.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d278ae8a17fc204f51b39652cc5dfe735c28dca
--- /dev/null
+++ b/src/Python/pytnl/tnl/SparseMatrix.h
@@ -0,0 +1,113 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include <TNL/String.h>
+#include <TNL/Containers/Vector.h>
+#include <TNL/Matrices/CSR.h>
+
+template< typename Matrix >
+struct SpecificExports
+{
+    template< typename Scope >
+    static void exec( Scope & s ) {}
+};
+
+template< typename Real, typename Device, typename Index >
+struct SpecificExports< TNL::Matrices::CSR< Real, Device, Index > >
+{
+    template< typename Scope >
+    static void exec( Scope & s )
+    {
+        using Matrix = TNL::Matrices::CSR< Real, Device, Index >;
+
+        s.def("getRowPointers",   py::overload_cast<>(&Matrix::getRowPointers),   py::return_value_policy::reference_internal);
+        s.def("getColumnIndexes", py::overload_cast<>(&Matrix::getColumnIndexes), py::return_value_policy::reference_internal);
+        s.def("getValues",        py::overload_cast<>(&Matrix::getValues),        py::return_value_policy::reference_internal);
+    }
+};
+
+template< typename MatrixRow >
+void export_MatrixRow( py::module & m, const char* name )
+{
+    // guard against duplicate to-Python converters for the same type
+    static bool defined = false;
+    if( ! defined ) {
+        py::class_< MatrixRow >( m, name )
+            .def("setElement", &MatrixRow::setElement)
+            .def("getElementColumn", &MatrixRow::getElementColumn, py::return_value_policy::reference_internal)
+            .def("getElementValue", &MatrixRow::getElementValue, py::return_value_policy::reference_internal)
+//            .def(py::self_ns::str(py::self_ns::self))
+        ;
+        defined = true;
+    }
+}
+
+template< typename Matrix >
+void export_Matrix( py::module & m, const char* name )
+{
+    typename Matrix::MatrixRow (Matrix::* _getRow)(typename Matrix::IndexType) = &Matrix::getRow;
+
+    using VectorType = TNL::Containers::Vector< typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >;
+
+    auto matrix = py::class_< Matrix, TNL::Object >( m, name )
+        .def(py::init<>())
+        // overloads (defined in Object)
+        .def_static("getType",              &Matrix::getType)
+        .def("getTypeVirtual",              &Matrix::getTypeVirtual)
+        .def_static("getSerializationType", &Matrix::getSerializationType)
+        .def("getSerializationTypeVirtual", &Matrix::getSerializationTypeVirtual)
+        .def("print", &Matrix::print)
+        .def("__str__", []( Matrix & m ) {
+                std::stringstream ss;
+                ss << m;
+                return ss.str();
+            } )
+
+        // Matrix
+        .def("setDimensions",           &Matrix::setDimensions)
+        .def("setCompressedRowLengths", &Matrix::setCompressedRowLengths)
+        .def("getRowLength",            &Matrix::getRowLength)
+        .def("getCompressedRowLengths", &Matrix::getCompressedRowLengths)
+        // TODO: export for more types
+        .def("setLike",                 &Matrix::template setLike< typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >)
+        .def("getNumberOfMatrixElements", &Matrix::getNumberOfMatrixElements)
+        .def("getNumberOfNonzeroMatrixElements", &Matrix::getNumberOfNonzeroMatrixElements)
+        .def("reset",                   &Matrix::reset)
+        .def("getRows",                 &Matrix::getRows)
+        .def("getColumns",              &Matrix::getColumns)
+        .def("setElement",              &Matrix::setElement)
+        .def("addElement",              &Matrix::addElement)
+        // setRow and addRow operate on pointers
+        //.def("setRow",                  &Matrix::setRow)
+        //.def("addRow",                  &Matrix::addRow)
+        .def("getElement",              &Matrix::getElement)
+        // TODO: operator== and operator!= are general and very slow
+        
+        // Sparse
+        .def("getMaxRowLength",     &Matrix::getMaxRowLength)
+        .def("getPaddingIndex",     &Matrix::getPaddingIndex)
+        // TODO: this one is empty in the C++ code
+//        .def("printStructure",      &Matrix::printStructure)
+
+        // specific to each format, but with common interface
+        .def("getRow",              _getRow)
+        // TODO: export for more types
+        .def("rowVectorProduct",    &Matrix::template rowVectorProduct< VectorType >)
+        .def("vectorProduct",       &Matrix::template vectorProduct< VectorType, VectorType >)
+        // TODO: these two don't work
+        //.def("addMatrix",           &Matrix::addMatrix)
+        //.def("getTransposition",    &Matrix::getTransposition)
+        .def("performSORIteration", &Matrix::template performSORIteration< VectorType >)
+//        .def("assign",              &Matrix::operator=)
+        .def("assign", []( Matrix& matrix, const Matrix& other ) -> Matrix& {
+                return matrix = other;
+            })
+    ;
+
+    // export format-specific methods
+    SpecificExports< Matrix >::exec( matrix );
+
+    export_MatrixRow< typename Matrix::MatrixRow >( m, "MatrixRow" );
+}
diff --git a/src/Python/pytnl/tnl/StaticVector.h b/src/Python/pytnl/tnl/StaticVector.h
new file mode 100644
index 0000000000000000000000000000000000000000..53197af56195fa0c22dceba6e05bcc7e3b6b9319
--- /dev/null
+++ b/src/Python/pytnl/tnl/StaticVector.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+namespace py = pybind11;
+
+#include "../tnl_indexing.h"
+
+// needed for discovery of operator<< for tnlStaticArray
+#include <TNL/Containers/StaticArray.h>
+
+template< typename VectorType, typename Scope >
+void export_StaticVector( Scope & scope, const char* name )
+{
+    using RealType = typename VectorType::RealType;
+
+    auto vector = py::class_<VectorType>(scope, name)
+        .def(py::init< typename VectorType::RealType >())
+        .def(py::init< VectorType >())
+        .def_static("getType", &VectorType::getType)
+        .def("getSize", &VectorType::getSize)
+        .def("assign", &VectorType::operator=)
+        .def(py::self == py::self)
+        .def(py::self != py::self)
+        .def("setValue", &VectorType::setValue)
+        // TODO: pybind11
+        // explicit namespace resolution is necessary, see http://stackoverflow.com/a/3084341/4180822
+//        .def(py::self_ns::str(py::self))
+        .def(py::self += py::self)
+        .def(py::self -= py::self)
+        .def(py::self *= typename VectorType::RealType())
+        .def(py::self + py::self)
+        .def(py::self - py::self)
+        .def(py::self * typename VectorType::RealType())
+        .def(py::self * py::self)
+        .def(py::self < py::self)
+        .def(py::self > py::self)
+        .def(py::self <= py::self)
+        .def(py::self >= py::self)
+    ;
+
+    tnl_indexing< VectorType >( vector );
+}
diff --git a/src/Python/pytnl/tnl/String.cpp b/src/Python/pytnl/tnl/String.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..309a6fe25fdafae45c672cd321ad851a55f57056
--- /dev/null
+++ b/src/Python/pytnl/tnl/String.cpp
@@ -0,0 +1,41 @@
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+namespace py = pybind11;
+
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include <TNL/String.h>
+#include <TNL/File.h>
+
+void export_String( py::module & m )
+{
+    // function pointers for overloaded methods
+//    const char* (TNL::String::* _String_getString)() const = &TNL::String::getString;
+    bool (TNL::String::* _String_save)(TNL::File &) const = &TNL::String::save;
+    bool (TNL::String::* _String_load)(TNL::File &)       = &TNL::String::load;
+
+    py::class_<TNL::String>(m, "String")
+        .def(py::init<const char*>())
+        .def(py::init<const char*, int>())
+        .def(py::init<const char*, int, int>())
+        .def(py::init<int>())
+        .def(py::init<double>())
+        .def_static("getType", &TNL::String::getType)
+        // __str__ (uses operator<<)
+        // explicit namespace resolution is necessary, see http://stackoverflow.com/a/3084341/4180822
+//        .def(py::self_ns::str(py::self_ns::self))
+        // TODO: operator[]
+//        .def(vector_indexing_suite<TNL::String>())
+        .def(py::self + py::self)
+        .def(py::self += py::self)
+        .def(py::self == py::self)
+        .def(py::self != py::self)
+        .def("getLength", &TNL::String::getLength)
+        .def("__len__", &TNL::String::getLength)
+        // FIXME
+//        .def("replace", &TNL::String::replace)
+        .def("save", _String_save)
+        .def("load", _String_load)
+    ;
+}
diff --git a/src/Python/pytnl/tnl/Vector.h b/src/Python/pytnl/tnl/Vector.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f4232e1bc48954750bacf7c47f4da5b23301dee
--- /dev/null
+++ b/src/Python/pytnl/tnl/Vector.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+#include <pybind11/operators.h>
+namespace py = pybind11;
+
+#include <TNL/Containers/Vector.h>
+
+template< typename ArrayType, typename VectorType >
+void export_Vector(py::module & m, const char* name)
+{
+    // function pointers for overloaded methods
+    void (VectorType::* _addElement1)(const typename VectorType::IndexType,
+                                      const typename VectorType::RealType &)
+        = &VectorType::addElement;
+    void (VectorType::* _addElement2)(const typename VectorType::IndexType,
+                                      const typename VectorType::RealType &,
+                                      const typename VectorType::RealType &)
+        = &VectorType::addElement;
+
+    py::class_<VectorType, ArrayType>(m, name)
+        .def(py::init<>())
+        .def(py::init<int>())
+        .def_static("getType",              &VectorType::getType)
+        .def("getTypeVirtual",              &VectorType::getTypeVirtual)
+        .def_static("getSerializationType", &VectorType::getSerializationType)
+        .def("getSerializationTypeVirtual", &VectorType::getSerializationTypeVirtual)
+        .def("addElement", _addElement1)
+        .def("addElement", _addElement2)
+        .def(py::self == py::self)
+        .def(py::self != py::self)
+        .def(py::self += py::self)
+        .def(py::self -= py::self)
+        .def(py::self *= typename VectorType::RealType())
+        .def(py::self /= typename VectorType::RealType())
+        .def("max", &VectorType::max)
+        .def("min", &VectorType::min)
+        .def("absMax", &VectorType::absMax)
+        .def("absMin", &VectorType::absMin)
+        .def("lpNorm", &VectorType::template lpNorm<double, double>)
+        .def("sum", &VectorType::template sum<double>)
+        .def("differenceMax", &VectorType::template differenceMax<VectorType>)
+        .def("differenceMin", &VectorType::template differenceMin<VectorType>)
+        .def("differenceAbsMax", &VectorType::template differenceAbsMax<VectorType>)
+        .def("differenceAbsMin", &VectorType::template differenceAbsMin<VectorType>)
+        .def("differenceLpNorm", &VectorType::template differenceLpNorm<double, VectorType, double>)
+        .def("differenceSum", &VectorType::template differenceSum<double, VectorType>)
+        .def("scalarProduct", &VectorType::template scalarProduct<VectorType>)
+        .def("addVector", &VectorType::template addVector<VectorType>)
+        .def("addVectors", &VectorType::template addVectors<VectorType>)
+    ;
+}
diff --git a/src/Python/pytnl/tnl/tnl.cpp b/src/Python/pytnl/tnl/tnl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0eb7c3e8b0aee48791a546e36291f4790c9ca8a9
--- /dev/null
+++ b/src/Python/pytnl/tnl/tnl.cpp
@@ -0,0 +1,47 @@
+#include "../exceptions.h"
+#include "../typedefs.h"
+
+// conversions have to be registered for each object file
+#include "../tnl_conversions.h"
+
+#include "Array.h"
+#include "Vector.h"
+
+// external functions
+void export_Object( py::module & m );
+void export_String( py::module & m );
+void export_Grid1D( py::module & m );
+void export_Grid2D( py::module & m );
+void export_Grid3D( py::module & m );
+void export_Meshes( py::module & m );
+void export_SparseMatrices( py::module & m );
+
+template< typename T >
+using _array = TNL::Containers::Array< T, TNL::Devices::Host, IndexType >;
+
+template< typename T >
+using _vector = TNL::Containers::Vector< T, TNL::Devices::Host, IndexType >;
+
+// Python module definition
+PYBIND11_MODULE(tnl, m)
+{
+    register_exceptions(m);
+
+    export_Object(m);
+    // TODO: TNL::File
+    export_String(m);
+
+    export_Array< _array<double> >(m, "Array");
+    export_Vector< _array<double>, _vector<double> >(m, "Vector");
+    export_Array< _array<int> >(m, "Array_int");
+    export_Vector< _array<int>, _vector<int> >(m, "Vector_int");
+    export_Array< _array<bool> >(m, "Array_bool");
+
+    export_Grid1D(m);
+    export_Grid2D(m);
+    export_Grid3D(m);
+
+    export_Meshes(m);
+
+    export_SparseMatrices(m);
+}
diff --git a/src/Python/pytnl/tnl_conversions.h b/src/Python/pytnl/tnl_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..602d1cffd1ccd32660b72630c023f2d913f1da19
--- /dev/null
+++ b/src/Python/pytnl/tnl_conversions.h
@@ -0,0 +1,3 @@
+// conversion has to be registered for each object file
+#include "tnl_str_conversion.h"
+#include "tnl_tuple_conversion.h"
diff --git a/src/Python/pytnl/tnl_indexing.h b/src/Python/pytnl/tnl_indexing.h
new file mode 100644
index 0000000000000000000000000000000000000000..29663d66b553d8095ca0a67f980b346fac04e712
--- /dev/null
+++ b/src/Python/pytnl/tnl_indexing.h
@@ -0,0 +1,81 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include "RawIterator.h"
+
+template< typename Array, typename Scope >
+void tnl_indexing( Scope & scope )
+{
+    using Index = typename Array::IndexType;
+    using Element = typename Array::ElementType;
+
+    scope.def("__len__", &Array::getSize);
+
+    scope.def("__iter__",
+        []( Array& array ) {
+            return py::make_iterator(
+                        RawIterator<Element>(array.getData()),
+                        RawIterator<Element>(array.getData() + array.getSize()) );
+        },
+        py::keep_alive<0, 1>()  // keep array alive while iterator is used
+    );
+
+    scope.def("__getitem__",
+        [](Array &a, Index i) {
+            if (i >= a.getSize())
+                throw py::index_error();
+            return a[i];
+        }
+    );
+
+    scope.def("__setitem__",
+        [](Array &a, Index i, const Element& e) {
+            if (i >= a.getSize())
+                throw py::index_error();
+            a[i] = e;
+        }
+    );
+}
+
+template< typename Array, typename Scope >
+void tnl_slice_indexing( Scope & scope )
+{
+    /// Slicing protocol
+    scope.def("__getitem__",
+        [](const Array& a, py::slice slice) -> Array* {
+            size_t start, stop, step, slicelength;
+
+            if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength))
+                throw py::error_already_set();
+
+            Array* seq = new Array();
+            seq->setSize(slicelength);
+
+            for (size_t i = 0; i < slicelength; ++i) {
+                seq->operator[](i) = a[start];
+                start += step;
+            }
+            return seq;
+        },
+        "Retrieve list elements using a slice object"
+    );
+
+    scope.def("__setitem__",
+        [](Array& a, py::slice slice,  const Array& value) {
+            size_t start, stop, step, slicelength;
+            if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength))
+                throw py::error_already_set();
+
+            if (slicelength != value.getSize())
+                throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
+
+            for (size_t i = 0; i < slicelength; ++i) {
+                a[start] = value[i];
+                start += step;
+            }
+        },
+        "Assign list elements using a slice object"
+    );
+}
diff --git a/src/Python/pytnl/tnl_str_conversion.h b/src/Python/pytnl/tnl_str_conversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..b62886e58a201d30b8d52abba5e3306d203bbd31
--- /dev/null
+++ b/src/Python/pytnl/tnl_str_conversion.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+namespace py = pybind11;
+
+#include <TNL/String.h>
+
+namespace pybind11 { namespace detail {
+
+    template <>
+    struct type_caster<TNL::String>
+    {
+        using StdStringCaster = type_caster<std::string>;
+        StdStringCaster _caster;
+
+    public:
+        /**
+         * This macro establishes the name 'TNL::String' in
+         * function signatures and declares a local variable
+         * 'value' of type TNL::String
+         */
+        PYBIND11_TYPE_CASTER(TNL::String, _("TNL::String"));
+
+        /**
+         * Conversion part 1 (Python->C++): convert a PyObject into a TNL::String
+         * instance or return false upon failure. The second argument
+         * indicates whether implicit conversions should be applied.
+         */
+        bool load(handle src, bool implicit)
+        {
+            if( ! _caster.load(src, implicit) )
+                return false;
+            const std::string& str = (std::string&) _caster;
+            value = TNL::String(str.c_str());
+            return true;
+        }
+
+        /**
+         * Conversion part 2 (C++ -> Python): convert an TNL::String instance into
+         * a Python object. The second and third arguments are used to
+         * indicate the return value policy and parent object (for
+         * ``return_value_policy::reference_internal``) and are generally
+         * ignored by implicit casters.
+         */
+        static handle cast(TNL::String src, return_value_policy policy, handle parent)
+        {
+            return StdStringCaster::cast( src.getString(), policy, parent );
+        }
+    };
+
+}} // namespace pybind11::detail
diff --git a/src/Python/pytnl/tnl_tuple_conversion.h b/src/Python/pytnl/tnl_tuple_conversion.h
new file mode 100644
index 0000000000000000000000000000000000000000..f4ca8045ea18bfd7e9d40a75d3201533628e662f
--- /dev/null
+++ b/src/Python/pytnl/tnl_tuple_conversion.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+namespace py = pybind11;
+
+#include <TNL/Containers/StaticArray.h>
+#include <TNL/Containers/StaticVector.h>
+
+namespace pybind11 { namespace detail {
+
+    template< typename ArrayType >
+    struct _tnl_tuple_caster
+    {
+        using Value = typename std::remove_reference< decltype(ArrayType()[0]) >::type;
+        using StdArray = std::array< Value, ArrayType::size >;
+        using StdArrayCaster = type_caster< StdArray >;
+//        StdArrayCaster _caster;
+		using value_conv = make_caster<Value>;
+
+    public:
+//        PYBIND11_TYPE_CASTER(ArrayType, StdArrayCaster::name);
+        PYBIND11_TYPE_CASTER(ArrayType, _("Tuple[") + value_conv::name + _<false>(_(""), _("[") + _<ArrayType::size>() + _("]")) + _("]"));
+
+        /**
+         * Conversion part 1 (Python -> C++): convert a PyObject into an ArrayType
+         * instance or return false upon failure. The second argument indicates
+         * whether implicit conversions should be applied.
+         */
+        bool load(handle src, bool implicit)
+        {
+            // we don't use StdArrayCaster here because we want to convert Python tuples, not lists
+//            if( ! _caster.load(src, implicit) )
+//                return false;
+//            const StdArray& arr = (StdArray&) _caster;
+//            for( int i = 0; i < ArrayType::size; i++ )
+//                value[ i ] = arr[ i ];
+//            return true;
+
+			if (!isinstance<tuple>(src))
+			    return false;
+			auto t = reinterpret_borrow<tuple>(src);
+			if (t.size() != ArrayType::size)
+			    return false;
+			size_t ctr = 0;
+			for (auto it : t) {
+			    value_conv conv;
+			    if (!conv.load(it, implicit))
+			        return false;
+			    value[ctr++] = cast_op<Value &&>(std::move(conv));
+			}
+			return true;
+        }
+
+        /**
+         * Conversion part 2 (C++ -> Python): convert an ArrayType instance into
+         * a Python object. The second and third arguments are used to
+         * indicate the return value policy and parent object (for
+         * ``return_value_policy::reference_internal``) and are generally
+         * ignored by implicit casters.
+         */
+        static handle cast(const ArrayType& src, return_value_policy policy, handle parent)
+        {
+            StdArray arr;
+            for( int i = 0; i < ArrayType::size; i++ )
+                arr[ i ] = src[ i ];
+            return StdArrayCaster::cast( arr, policy, parent );
+        }
+    };
+
+    template< typename T, int Size >
+    struct type_caster< TNL::Containers::StaticArray< Size, T > >
+        : _tnl_tuple_caster< TNL::Containers::StaticArray< Size, T > > {};
+
+    template< typename T, int Size >
+    struct type_caster< TNL::Containers::StaticVector< Size, T > >
+        : _tnl_tuple_caster< TNL::Containers::StaticVector< Size, T > > {};
+
+}} // namespace pybind11::detail
diff --git a/src/Python/pytnl/typedefs.h b/src/Python/pytnl/typedefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..b06693ab66ee0afb901aea469a347231bf68beae
--- /dev/null
+++ b/src/Python/pytnl/typedefs.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+
+using RealType = double;
+using DeviceType = TNL::Devices::Host;
+using IndexType = int;
+
+using Grid1D = TNL::Meshes::Grid<1, RealType, DeviceType, IndexType>;
+using Grid2D = TNL::Meshes::Grid<2, RealType, DeviceType, IndexType>;
+using Grid3D = TNL::Meshes::Grid<3, RealType, DeviceType, IndexType>;
+
+using LocalIndexType = short int;
+using EdgeTopology = TNL::Meshes::Topologies::Edge;
+using TriangleTopology = TNL::Meshes::Topologies::Triangle;
+using TetrahedronTopology = TNL::Meshes::Topologies::Tetrahedron;
+using MeshOfEdges = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig<
+                            EdgeTopology,
+                            EdgeTopology::dimension,
+                            RealType,
+                            IndexType,
+                            LocalIndexType,
+                            IndexType > >;
+using MeshOfTriangles = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig<
+                            TriangleTopology,
+                            TriangleTopology::dimension,
+                            RealType,
+                            IndexType,
+                            LocalIndexType,
+                            IndexType > >;
+using MeshOfTetrahedrons = TNL::Meshes::Mesh< TNL::Meshes::DefaultConfig<
+                            TetrahedronTopology,
+                            TetrahedronTopology::dimension,
+                            RealType,
+                            IndexType,
+                            LocalIndexType,
+                            IndexType > >;
diff --git a/src/TNL/CMakeLists.txt b/src/TNL/CMakeLists.txt
index b2b23f89251dfe02bd21797818d74bdc0c4b1ff9..13113f9c3fa6b04c3e485eb836e149f48a1c91d7 100644
--- a/src/TNL/CMakeLists.txt
+++ b/src/TNL/CMakeLists.txt
@@ -18,7 +18,7 @@ ADD_SUBDIRECTORY( legacy )
 
 SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL )
 
-set( headers 
+set( headers
      Assert.h
      Constants.h
      CudaSharedMemory.h
@@ -42,7 +42,7 @@ set( headers
      Timer.h
      UniquePointer.h )
 
-set( common_SOURCES 
+set( common_SOURCES
      File.cpp
      FileName.cpp
      Object.cpp
@@ -50,7 +50,7 @@ set( common_SOURCES
      SmartPointersRegister.cpp
      String.cpp
      Timer.cpp )
-     
+
 set( tnl_SOURCES ${tnl_config_SOURCES}
                  ${tnl_containers_SOURCES}
                  ${tnl_devices_SOURCES}
@@ -63,8 +63,8 @@ set( tnl_SOURCES ${tnl_config_SOURCES}
                  ${tnl_solvers_SOURCES}
 
                  ${tnl_core_SOURCES}
-                 ${tnl_legacy_SOURCES}                 
-                                                   
+                 ${tnl_legacy_SOURCES}
+
                  ${common_SOURCES} )
 
 set( tnl_CUDA__SOURCES ${tnl_config_CUDA__SOURCES}
@@ -82,52 +82,56 @@ set( tnl_CUDA__SOURCES ${tnl_config_CUDA__SOURCES}
                        ${tnl_core_CUDA__SOURCES}
                        ${tnl_legacy_CUDA__SOURCES}
                        ${common_SOURCES} )
-                 
-                 
+
+
+ADD_LIBRARY( tnl_static STATIC ${tnl_SOURCES} )
+INSTALL( TARGETS tnl_static DESTINATION lib )
+
 if( BUILD_CUDA )
    CUDA_ADD_LIBRARY( tnl SHARED ${tnl_CUDA__SOURCES}
-                                                  OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} )
-    if( HAVE_CUBLAS )
-       CUDA_ADD_CUBLAS_TO_TARGET( tnl )
-    endif( HAVE_CUBLAS )
+                     OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} )
+   # the static library with CUDA support has to be built separately
+   CUDA_ADD_LIBRARY( tnl-cuda_static STATIC ${tnl_CUDA__SOURCES} )
+   INSTALL( TARGETS tnl-cuda_static DESTINATION lib )
 else( BUILD_CUDA )
-   ADD_LIBRARY( tnl SHARED 
-                ${tnl_SOURCES} )
+   ADD_LIBRARY( tnl SHARED ${tnl_SOURCES} )
 #ifMIC
   #TARGET_COMPILE_DEFINITIONS( tnl PUBLIC -DHAVE_MIC )
-endif( BUILD_CUDA )                                    
-               
-SET_TARGET_PROPERTIES( tnl PROPERTIES 
+endif( BUILD_CUDA )
+
+SET_TARGET_PROPERTIES( tnl PROPERTIES
                        VERSION ${tnlVersion} )
-TARGET_LINK_LIBRARIES( tnl 
-                       ${DCMTK_LIBRARIES})
+TARGET_LINK_LIBRARIES( tnl
+                       ${DCMTK_LIBRARIES} )
 
 
 INSTALL( TARGETS tnl DESTINATION lib )
 
 IF( BUILD_MPI )
-   
+
+   ADD_LIBRARY( tnl-mpi_static STATIC ${tnl_SOURCES} )
+   INSTALL( TARGETS tnl-mpi_static DESTINATION lib )
+
    if( BUILD_CUDA )
-      CUDA_ADD_LIBRARY( tnl-mpi-${tnlVersion} SHARED ${tnl_CUDA__SOURCES} 
-                                                         OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} )
-      if( HAVE_CUBLAS )
-         CUDA_ADD_CUBLAS_TO_TARGET( tnl-mpi-${tnlVersion} )
-      endif( HAVE_CUBLAS )
+      CUDA_ADD_LIBRARY( tnl-mpi SHARED ${tnl_CUDA__SOURCES}
+                        OPTIONS ${CUDA_ADD_LIBRARY_OPTIONS} )
+      # the static library with CUDA support has to be built separately
+      CUDA_ADD_LIBRARY( tnl-mpi-cuda_static STATIC ${tnl_CUDA__SOURCES} )
+      INSTALL( TARGETS tnl-mpi-cuda_static DESTINATION lib )
    else( BUILD_CUDA )
-         ADD_LIBRARY( tnl-mpi-${tnlVersion} SHARED
-                      ${tnl_SOURCES} )  
-   endif( BUILD_CUDA )                        
-   
-   SET_TARGET_PROPERTIES( tnl-mpi-${tnlVersion} PROPERTIES
-                          VERSION ${tnlVersion} ) 
-#   SET_TARGET_PROPERTIES( tnl-mpi-${tnlVersion} 
+      ADD_LIBRARY( tnl-mpi SHARED ${tnl_SOURCES} )
+   endif( BUILD_CUDA )
+
+   SET_TARGET_PROPERTIES( tnl-mpi PROPERTIES
+                          VERSION ${tnlVersion} )
+#   SET_TARGET_PROPERTIES( tnl-mpi
 #                          LINK_INTERFACE_LIBRARIES "")
 
-   
-   TARGET_LINK_LIBRARIES( tnl-mpi-${tnlVersion} 
+
+   TARGET_LINK_LIBRARIES( tnl-mpi
                           ${MPI_LIBRARIES} )
-   INSTALL( TARGETS tnl-mpi-${tnlVersion} DESTINATION lib )
-                                                                
-ENDIF()
+   INSTALL( TARGETS tnl-mpi DESTINATION lib )
+
+endif()
 
 INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY} )
diff --git a/src/TNL/Containers/Algorithms/CMakeLists.txt b/src/TNL/Containers/Algorithms/CMakeLists.txt
index 49e5a36567c973cbd8543b31ddccad085558bd3c..a8c9bf7699f129c21c4930df090af5c7d5910325 100644
--- a/src/TNL/Containers/Algorithms/CMakeLists.txt
+++ b/src/TNL/Containers/Algorithms/CMakeLists.txt
@@ -6,7 +6,6 @@ set( headers ArrayOperations.h
              ArrayOperationsMIC_impl.h
              cuda-prefix-sum.h
              cuda-prefix-sum_impl.h
-             CublasWrapper.h
              CudaMultireductionKernel.h
              CudaReductionBuffer.h
              CudaReductionKernel.h
diff --git a/src/TNL/Containers/Algorithms/CublasWrapper.h b/src/TNL/Containers/Algorithms/CublasWrapper.h
deleted file mode 100644
index bb6572c93b6d37a938646d9bd7d9943952b1e768..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/Algorithms/CublasWrapper.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/***************************************************************************
-                          CublasWraper.h  -  description
-                             -------------------
-    begin                : Apr 7, 2015
-    copyright            : (C) 2015 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#if defined HAVE_CUBLAS && defined HAVE_CUDA
-#include <cublas_v2.h>
-#endif
-
-namespace TNL {
-namespace Containers {
-namespace Algorithms {
-
-template< typename Real1,
-          typename Real2,
-          typename Index >
-class CublasWraper
-{
-    public:
-        static bool dot( const Real1* v1, const Real2* v2, const Index size, Real1& result)
-        {
-            return false;
-        }
-};
-
-#if defined HAVE_CUBLAS && defined HAVE_CUDA
-
-template< typename Index >
-class CublasWraper< float, float, Index >
-{
-    public:
-        static bool dot( const float* v1, const float* v2, const Index size, float& result)
-        {
-
-            cublasHandle_t handle;
-            cublasCreate( &handle );
-            cublasSdot( handle, size, v1, 1, v2, 1, &result );
-            cublasDestroy( handle );
-            return false;
-        }
-};
-
-template< typename Index >
-class CublasWraper< double, double, Index >
-{
-    public:
-        static bool dot( const double* v1, const double* v2, const Index size, double& result)
-        {
-            cublasHandle_t handle;
-            cublasCreate( &handle );
-            cublasDdot( handle, size, v1, 1, v2, 1, &result );
-            cublasDestroy( handle );
-            return false;
-        }
-};
-#endif
-
-} // namespace Algorithms
-} // namespace Containers
-} // namespace TNL
-
diff --git a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h
index e5c21b232a6946710e9ab3e69ec1dcbd40687abe..64846317c486f6f852e2abeeef79c184b7fb0b76 100644
--- a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h
+++ b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h
@@ -14,7 +14,6 @@
 #include <TNL/Exceptions/CudaSupportMissing.h>
 #include <TNL/Containers/Algorithms/VectorOperations.h>
 #include <TNL/Containers/Algorithms/cuda-prefix-sum.h>
-#include <TNL/Containers/Algorithms/CublasWrapper.h>
 
 namespace TNL {
 namespace Containers {   
@@ -426,12 +425,6 @@ getScalarProduct( const Vector1& v1,
    TNL_ASSERT_EQ( v1.getSize(), v2.getSize(), "The vector sizes must be the same." );
 
    Real result( 0 );
-/*#if defined HAVE_CUBLAS && defined HAVE_CUDA
-   if( CublasWraper< typename Vector1::RealType,
-                         typename Vector2::RealType,
-                         typename Vector1::IndexType >::dot( v1.getData(), v1.getData(), v1.getSize(), result ) )
-       return result;
-#endif*/
    Algorithms::ParallelReductionScalarProduct< typename Vector1::RealType, typename Vector2::RealType > operation;
    Reduction< Devices::Cuda >::reduce( operation,
                                        v1.getSize(),
diff --git a/src/TNL/Containers/ArrayIO.h b/src/TNL/Containers/ArrayIO.h
index 0c0ea62eead463311bb2843bbbe42de1ba9f2127..0b79cf9d1db0444f81dea124ca61b7d5f1e41f3e 100644
--- a/src/TNL/Containers/ArrayIO.h
+++ b/src/TNL/Containers/ArrayIO.h
@@ -10,7 +10,9 @@
 
 #pragma once
 
-#include <TNL/Containers/DynamicTypeTag.h>
+#include <type_traits>
+
+#include <TNL/Object.h>
 #include <TNL/File.h>
 
 namespace TNL {
@@ -19,7 +21,7 @@ namespace Containers {
 template< typename Element,
           typename Device,
           typename Index,
-          bool DynamicType = DynamicTypeTag< Element >::value >
+          bool Elementwise = std::is_base_of< Object, Element >::value >
 class ArrayIO
 {};
 
diff --git a/src/TNL/Containers/CMakeLists.txt b/src/TNL/Containers/CMakeLists.txt
index 4beb1159a8eed5eefce3cd1dedd7c4d2f37af4e5..83991f2456b97146284701ab82d5a8927b3e9ab5 100644
--- a/src/TNL/Containers/CMakeLists.txt
+++ b/src/TNL/Containers/CMakeLists.txt
@@ -1,24 +1,25 @@
 ADD_SUBDIRECTORY( Algorithms )
+ADD_SUBDIRECTORY( Multimaps )
 
 set( headers Array.h
              Array_impl.h
              ArrayIO.h
-             DynamicTypeTag.h
              IndexedMap.h
              IndexedMap_impl.h
              IndexedSet.h
              IndexedSet_impl.h
+             UnorderedIndexedSet.h
+             UnorderedIndexedSet_impl.h
              List.h
              List_impl.h
              MultiArray.h
              MultiArray1D_impl.h
              MultiArray2D_impl.h
              MultiArray3D_impl.h
-             MultiArray4D_impl.h             
+             MultiArray4D_impl.h
              SharedArray.h
              SharedArray_impl.h
-             ConstSharedArray.h
-             StaticArray.h 
+             StaticArray.h
              StaticArray_impl.h
              StaticArray1D_impl.h
              StaticArray2D_impl.h
@@ -32,23 +33,23 @@ set( headers Array.h
              MultiVector4D_impl.h
              SharedVector.h
              SharedVector_impl.h
-             StaticVector.h 
+             StaticVector.h
              StaticVector_impl.h
              StaticVector1D_impl.h
              StaticVector2D_impl.h
              StaticVector3D_impl.h  )
 
 SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Containers )
-set( common_SOURCES     
+set( common_SOURCES
      ${CURRENT_DIR}/SharedArray_impl.cpp
      ${CURRENT_DIR}/MultiArray_impl.cpp
      ${CURRENT_DIR}/Array_impl.cpp
-     ${CURRENT_DIR}/StaticArray_impl.cpp 
+     ${CURRENT_DIR}/StaticArray_impl.cpp
      ${CURRENT_DIR}/MultiVector_impl.cpp
      ${CURRENT_DIR}/SharedVector_impl.cpp
      ${CURRENT_DIR}/Vector_impl.cpp
      ${CURRENT_DIR}/StaticVector_impl.cpp
-)       
+)
 
 IF( BUILD_CUDA )
    set( tnl_containers_CUDA__SOURCES
@@ -58,12 +59,12 @@ IF( BUILD_CUDA )
         ${CURRENT_DIR}/MultiArray_impl.cu
         ${CURRENT_DIR}/StaticArray_impl.cu
         ${CURRENT_DIR}/Vector_impl.cu
-        ${CURRENT_DIR}/StaticVector_impl.cu 
+        ${CURRENT_DIR}/StaticVector_impl.cu
         PARENT_SCOPE )
-ENDIF()    
+ENDIF()
 
-set( tnl_containers_SOURCES     
+set( tnl_containers_SOURCES
      ${common_SOURCES}
      PARENT_SCOPE )
-                   
+
 INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Containers )
diff --git a/src/TNL/Containers/ConstSharedArray.h b/src/TNL/Containers/ConstSharedArray.h
deleted file mode 100644
index ec719634f604e95ac92f06ca2259f6990972ba2e..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/ConstSharedArray.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/***************************************************************************
-                          tnlConstSharedArray.h  -  description
-                             -------------------
-    begin                : Feb 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once 
-
-#include <TNL/Object.h>
-
-// Forward declarations
-namespace TNL {
-   class File;
-   
-namespace Devices
-{
-   class Host;
-}
-
-namespace Containers {   
-
-
-template< typename Element, typename Device, typename Index >
-class Array;
-
-template< typename Element,
-          typename Device = Devices::Host,
-          typename Index = int >
-class tnlConstSharedArray : public Object
-{
-   public:
-
-   typedef Element ElementType;
-   typedef Device DeviceType;
-   typedef Index IndexType;
-   typedef tnlConstSharedArray< Element, Devices::Host, Index > HostType;
-   typedef tnlConstSharedArray< Element, Devices::Cuda, Index > CudaType;
-
-   tnlConstSharedArray();
-
-   static String getType();
-
-   String getTypeVirtual() const;
-
-   static String getSerializationType();
-
-   virtual String getSerializationTypeVirtual() const;
-
-   void bind( const Element* _data,
-              const Index _size );
-
-   template< typename Array >
-   void bind( const Array& array,
-              IndexType index = 0,
-              IndexType size = 0 );
-
-   void swap( tnlConstSharedArray< Element, Device, Index >& array );
-
-   void reset();
-
-   __cuda_callable__ Index getSize() const;
-
-   Element getElement( Index i ) const;
-
-   __cuda_callable__ const Element& operator[] ( Index i ) const;
-
-   tnlConstSharedArray< Element, Device, Index >& operator = ( const tnlConstSharedArray< Element, Device, Index >& array );
-
-   template< typename Array >
-   tnlConstSharedArray< Element, Device, Index >& operator = ( const Array& array );
-
-   template< typename Array >
-   bool operator == ( const Array& array ) const;
-
-   template< typename Array >
-   bool operator != ( const Array& array ) const;
-
-   __cuda_callable__ const Element* getData() const;
-
-   /****
-    * Returns true if non-zero size is set.
-    */
-   operator bool() const;
-
-   //! This method measures data transfers done by this vector.
-   /*!
-    * Every time one touches this grid touches * size * sizeof( Real ) bytes are added
-    * to transfered bytes in tnlStatistics.
-    */
-   template< typename IndexType2 = Index >
-   void touch( IndexType2 touches = 1 ) const;
-
-   //! Method for saving the object to a file as a binary data.
-   bool save( File& file ) const;
-
-   bool save( const String& fileName ) const;
-
-   protected:
-
-   //!Number of allocated elements
-   Index size;
-
-   //! Pointer to allocated data
-   const Element* data;
-};
-
-template< typename Element, typename Device, typename Index >
-std::ostream& operator << ( std::ostream& str, const tnlConstSharedArray< Element, Device, Index >& v );
-
-} // namespace Containers
-} // namespace TNL
-
-#include <TNL/Containers/ConstSharedArray_impl.h>
-
-
diff --git a/src/TNL/Containers/ConstSharedArray_impl.h b/src/TNL/Containers/ConstSharedArray_impl.h
deleted file mode 100644
index fde53b35807267d85495f34d0d90ca38f69ba358..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/ConstSharedArray_impl.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/***************************************************************************
-                          tnlConstSharedArray_impl.h  -  description
-                             -------------------
-    begin                : Feb 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <iostream>
-#include <TNL/File.h>
-#include <TNL/Containers/Array.h>
-#include <TNL/Containers/Algorithms/ArrayOperations.h>
-#include <TNL/Math.h>
-#include <TNL/param-types.h>
-
-namespace TNL {
-namespace Containers {   
-
-template< typename Element,
-          typename Device,
-          typename Index >
-tnlConstSharedArray< Element, Device, Index > :: tnlConstSharedArray()
-: size( 0 ), data( 0 )
-{
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-String tnlConstSharedArray< Element, Device, Index > :: getType()
-{
-   return String( "tnlConstSharedArray< " ) + ", " +
-                    TNL::getType< Element >() + ", " +
-                     Device::getDeviceType() + ", " +
-                    TNL::getType< Index >() + " >";
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-String tnlConstSharedArray< Element, Device, Index > :: getTypeVirtual() const
-{
-   return this->getType();
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-String tnlConstSharedArray< Element, Device, Index > :: getSerializationType()
-{
-   return Array< Element, Device, Index >::getSerializationType();
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-String tnlConstSharedArray< Element, Device, Index > :: getSerializationTypeVirtual() const
-{
-   return this->getSerializationType();
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-void tnlConstSharedArray< Element, Device, Index > :: bind( const Element* data,
-                                                            const Index size )
-{
-   TNL_ASSERT( size >= 0,
-              std::cerr << "You try to set size of tnlConstSharedArray to negative value."
-                        << "New size: " << size << std::endl );
-   TNL_ASSERT( data != 0,
-              std::cerr << "You try to use null pointer to data for tnlConstSharedArray." );
-
-   this->size = size;
-   this->data = data;
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-   template< typename Array >
-void tnlConstSharedArray< Element, Device, Index > :: bind( const Array& array,
-                                                            IndexType index,
-                                                            IndexType size )
-{
-   // TODO: This does not work for static arrays.
-   //tnlStaticTNL_ASSERT( Array::DeviceType::DeviceType == DeviceType::DeviceType,
-   //                 "Attempt to bind arrays between different devices." );
-   this->data = &( array. getData()[ index ] );
-   if( ! size )
-      this->size = array. getSize();
-   else
-      this->size = size;
- 
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-void tnlConstSharedArray< Element, Device, Index > :: swap( tnlConstSharedArray< Element, Device, Index >& array )
-{
-   swap( this->size, array. size );
-   swap( this->data, array. data );
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-void tnlConstSharedArray< Element, Device, Index > :: reset()
-{
-   this->size = 0;
-   this->data = 0;
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-__cuda_callable__
-Index tnlConstSharedArray< Element, Device, Index > :: getSize() const
-{
-   return this->size;
-}
-
-template< typename Element,
-          typename Device,
-          typename Index >
-Element tnlConstSharedArray< Element, Device, Index > :: getElement( Index i ) const
-{
-   TNL_ASSERT( 0 <= i && i < this->getSize(),
-              std::cerr << "Wrong index for getElement method in tnlConstSharedArray with name "
-                        << " index is " << i
-                        << " and array size is " << this->getSize() );
-   return Algorithms::ArrayOperations< Device >::getMemoryElement( &( this->data[ i ] ) );
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-__cuda_callable__
-const Element& tnlConstSharedArray< Element, Device, Index > :: operator[] ( Index i ) const
-{
-   TNL_ASSERT( 0 <= i && i < this->getSize(),
-              std::cerr << "Wrong index for operator[] in tnlConstSharedArray with name "
-                        << " index is " << i
-                        << " and array size is " << this->getSize() );
-   // TODO: add static assert - this does not make sense for Devices::CudaDevice
-   return Algorithms::ArrayOperations< Device >::getArrayElementReference( this->data, i );
-};
-
-template< typename Element,
-           typename Device,
-           typename Index >
-tnlConstSharedArray< Element, Device, Index >&
-    tnlConstSharedArray< Element, Device, Index > :: operator = ( const tnlConstSharedArray< Element, Device, Index >& array )
-{
-   this->bind( array );
-   return ( *this );
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-   template< typename Array >
-tnlConstSharedArray< Element, Device, Index >& tnlConstSharedArray< Element, Device, Index > :: operator = ( const Array& array )
-{
-   this->bind( array );
-   return ( *this );
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-   template< typename Array >
-bool tnlConstSharedArray< Element, Device, Index > :: operator == ( const Array& array ) const
-{
-   if( array. getSize() != this->getSize() )
-      return false;
-   return Algorithms::ArrayOperations< Device, typename Array :: DeviceType >::
-      template compareMemory< typename Array :: ElementType,
-                              Element,
-                              typename Array :: IndexType >
-                            ( this->getData(),
-                              array. getData(),
-                              array. getSize() );
-}
-
-template< typename Element,
-          typename Device,
-          typename Index >
-   template< typename Array >
-bool tnlConstSharedArray< Element, Device, Index > :: operator != ( const Array& array ) const
-{
-   return ! ( ( *this ) == array );
-}
-
-template< typename Element,
-          typename Device,
-          typename Index >
-const Element* tnlConstSharedArray< Element, Device, Index > :: getData() const
-{
-   return this->data;
-}
-
-template< typename Element,
-          typename Device,
-          typename Index >
-tnlConstSharedArray< Element, Device, Index > :: operator bool() const
-{
-   return data != 0;
-};
-
-
-template< typename Element,
-          typename Device,
-          typename Index >
-   template< typename IndexType2 >
-void tnlConstSharedArray< Element, Device, Index > :: touch( IndexType2 touches ) const
-{
-   //TODO: implement
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-bool tnlConstSharedArray< Element, Device, Index > :: save( File& file ) const
-{
-   TNL_ASSERT( this->size != 0,
-              std::cerr << "You try to save empty array." );
-   if( ! Object :: save( file ) )
-      return false;
-   if( ! file. write( &this->size ) )
-      return false;
-   if( ! file. write< Element, Device, Index >( this->data, this->size ) )
-   {
-      std::cerr << "I was not able to WRITE tnlConstSharedArray "
-                << " with size " << this->getSize() << std::endl;
-      return false;
-   }
-   return true;
-};
-
-template< typename Element,
-          typename Device,
-          typename Index >
-bool tnlConstSharedArray< Element, Device, Index > :: save( const String& fileName ) const
-{
-   return Object :: save( fileName );
-};
-
-template< typename Element, typename Device, typename Index >
-std::ostream& operator << ( std::ostream& str, const tnlConstSharedArray< Element, Device, Index >& v )
-{
-   str << "[ ";
-   if( v.getSize() > 0 )
-   {
-      str << v.getElement( 0 );
-      for( Index i = 1; i < v.getSize(); i++ )
-         str << ", " << v. getElement( i );
-   }
-   str << " ]";
-   return str;
-}
-
-#ifdef TEMPLATE_EXPLICIT_INSTANTIATION
-
-#ifdef INSTANTIATE_FLOAT
-extern template class tnlConstSharedArray< float, Devices::Host, int >;
-#endif
-extern template class tnlConstSharedArray< double, Devices::Host, int >;
-#ifdef INSTANTIATE_LONG_DOUBLE
-extern template class tnlConstSharedArray< long double, Devices::Host, int >;
-#endif
-
-#ifdef INSTANTIATE_LONG_INT
-#ifdef INSTANTIATE_FLOAT
-extern template class tnlConstSharedArray< float, Devices::Host, long int >;
-#endif
-extern template class tnlConstSharedArray< double, Devices::Host, long int >;
-#ifdef INSTANTIATE_LONG_DOUBLE
-extern template class tnlConstSharedArray< long double, Devices::Host, long int >;
-#endif
-#endif
-
-#ifdef HAVE_CUDA
-#ifdef INSTANTIATE_FLOAT
-extern template class tnlConstSharedArray< float, Devices::Cuda, int >;
-#endif
-extern template class tnlConstSharedArray< double, Devices::Cuda, int >;
-#ifdef INSTANTIATE_LONG_DOUBLE
-extern template class tnlConstSharedArray< long double, Devices::Cuda, int >;
-#endif
-
-#ifdef INSTANTIATE_LONG_INT
-#ifdef INSTANTIATE_FLOAT
-extern template class tnlConstSharedArray< float, Devices::Cuda, long int >;
-#endif
-extern template class tnlConstSharedArray< double, Devices::Cuda, long int >;
-#ifdef INSTANTIATE_LONG_DOUBLE
-extern template class tnlConstSharedArray< long double, Devices::Cuda, long int >;
-#endif
-
-#endif
-#endif
-
-#endif
-
-} // namespace Containers
-} // namespace TNL
diff --git a/src/TNL/Containers/DynamicTypeTag.h b/src/TNL/Containers/DynamicTypeTag.h
deleted file mode 100644
index 40b7bbee35f853fbbb13033b270d8e800ad9112f..0000000000000000000000000000000000000000
--- a/src/TNL/Containers/DynamicTypeTag.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/***************************************************************************
-                          DynamicTypeTag.h  -  description
-                             -------------------
-    begin                : Mar 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-namespace TNL {
-namespace Containers {   
-
-template< typename Element >
-struct DynamicTypeTag
-{
-   enum { value = false };
-};
-
-} // namespace Containers
-} // namespace TNL
diff --git a/src/TNL/Containers/IndexedMap_impl.h b/src/TNL/Containers/IndexedMap_impl.h
index 2adb8872cd488d1ea2448024cff3521928b531a4..488b3b93bcc4716bec28375232130f21d62a58a2 100644
--- a/src/TNL/Containers/IndexedMap_impl.h
+++ b/src/TNL/Containers/IndexedMap_impl.h
@@ -57,9 +57,9 @@ template< typename Element,
    template<typename ArrayType>
 void IndexedMap< Element, Index, Key >::toArray( ArrayType& array ) const
 {
-   Assert( array.getSize() == getSize(),
-              std::cerr << "array.getSize() = " << array.getSize()
-                   << " getSize() = " << getSize() );
+   TNL_ASSERT( array.getSize() == getSize(),
+               std::cerr << "array.getSize() = " << array.getSize()
+                         << " getSize() = " << getSize() );
 
    for( STDMapIteratorType iter = map.begin();
         iter != map.end();
diff --git a/src/TNL/Containers/Multimaps/CMakeLists.txt b/src/TNL/Containers/Multimaps/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..921c735f7bb71c2aca64027f0b70aecde34cf7c6
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/CMakeLists.txt
@@ -0,0 +1,11 @@
+SET( headers EllpackIndexMultimap.h
+             EllpackIndexMultimap_impl.h
+             EllpackIndexMultimapValues.h
+             EllpackIndexMultimapValues_impl.h
+             StaticEllpackIndexMultimap.h
+             StaticEllpackIndexMultimap_impl.h
+             StaticEllpackIndexMultimapValues.h
+             StaticEllpackIndexMultimapValues_impl.h
+             MultimapPermutationApplier.h )
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Containers/Multimaps )
diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h
new file mode 100644
index 0000000000000000000000000000000000000000..3cc3b365969fceef76cf23e197d522c12ea9eef2
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h
@@ -0,0 +1,111 @@
+/***************************************************************************
+                          EllpackIndexMultimap.h  -  description
+                             -------------------
+    begin                : Sep 9, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Containers/Vector.h>
+#include <TNL/Containers/Multimaps/EllpackIndexMultimapValues.h>
+
+namespace TNL {
+
+template< typename Device >
+struct EllpackIndexMultimapSliceSizeGetter
+{
+   static constexpr int SliceSize = 1;
+};
+
+template<>
+struct EllpackIndexMultimapSliceSizeGetter< Devices::Cuda >
+{
+   static constexpr int SliceSize = 32;
+};
+
+template< typename Index = int,
+          typename Device = Devices::Host,
+          typename LocalIndex = Index,
+          int SliceSize = EllpackIndexMultimapSliceSizeGetter< Device >::SliceSize >
+class EllpackIndexMultimap
+   : public Object
+{
+   public:
+      using DeviceType                 = Device;
+      using IndexType                  = Index;
+      using LocalIndexType             = LocalIndex;
+      using ValuesAccessorType         = EllpackIndexMultimapValues< IndexType, DeviceType, LocalIndexType, SliceSize >;
+      using ConstValuesAccessorType    = EllpackIndexMultimapValues< const IndexType, DeviceType, LocalIndexType, SliceSize >;
+      using ValuesAllocationVectorType = Containers::Vector< LocalIndexType, DeviceType, IndexType >;
+
+      EllpackIndexMultimap() = default;
+
+      template< typename Device_ >
+      EllpackIndexMultimap( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other );
+
+      template< typename Device_ >
+      EllpackIndexMultimap& operator=( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other );
+
+      static String getType();
+
+      String getTypeVirtual() const;
+
+      void setKeysRange( const IndexType& keysRange );
+
+      __cuda_callable__
+      const IndexType getKeysRange() const;
+
+      void allocate( const LocalIndexType& maxValuesCount );
+
+      void allocate( const ValuesAllocationVectorType& valuesCounts );
+
+      template< typename Device_, int SliceSize_ >
+      void setLike( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize_ >& other );
+
+      __cuda_callable__
+      ValuesAccessorType getValues( const IndexType& inputIndex );
+
+      __cuda_callable__
+      ConstValuesAccessorType getValues( const IndexType& inputIndex ) const;
+
+      bool operator==( const EllpackIndexMultimap& other ) const;
+
+      bool save( File& file ) const;
+
+      bool load( File& file );
+
+      using Object::load;
+
+      using Object::save;
+
+      void print( std::ostream& str ) const;
+
+   protected:
+      Containers::Vector< IndexType, DeviceType, IndexType > values;
+      ValuesAllocationVectorType valuesCounts;
+
+      IndexType keysRange = 0;
+      LocalIndexType maxValuesCount = 0;
+
+      __cuda_callable__
+      IndexType getAllocationKeysRange( IndexType keysRange ) const;
+
+      // friend class is needed for templated assignment operators
+      template< typename Index_, typename Device_, typename LocalIndex_, int SliceSize_ >
+      friend class EllpackIndexMultimap;
+};
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >& multimap );
+
+} // namespace TNL
+
+#include <TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h>
+
diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h
new file mode 100644
index 0000000000000000000000000000000000000000..87364c5f79d6b3ffcbbfe744b72cd53a0ab17dbd
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h
@@ -0,0 +1,118 @@
+/***************************************************************************
+                          EllpackIndexMultimapValues.h  -  description
+                             -------------------
+    begin                : Sep 10, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <type_traits>
+#include <ostream>
+
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+class EllpackIndexMultimap;
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step = 1 >
+class EllpackIndexMultimapValues
+{
+   public:
+      using DeviceType     = Device;
+      using IndexType      = Index;
+      using LocalIndexType = LocalIndex;
+      using NetworkType    = EllpackIndexMultimap< IndexType, DeviceType, LocalIndexType, step >;
+
+      __cuda_callable__
+      EllpackIndexMultimapValues();
+
+      __cuda_callable__
+      EllpackIndexMultimapValues( EllpackIndexMultimapValues&& other );
+
+      __cuda_callable__
+      EllpackIndexMultimapValues& operator=( const EllpackIndexMultimapValues& );
+
+      // converting assignment, needed for 'const int' -> 'int' etc.
+      template< typename Index_, typename LocalIndex_, int step_ >
+      __cuda_callable__
+      EllpackIndexMultimapValues& operator=( const EllpackIndexMultimapValues< Index_, Device, LocalIndex_, step_ >& other );
+
+      __cuda_callable__
+      EllpackIndexMultimapValues& operator=( EllpackIndexMultimapValues&& other );
+
+      __cuda_callable__
+      void bind( const EllpackIndexMultimapValues& other );
+
+      __cuda_callable__
+      void setSize( const LocalIndexType& portsCount );
+
+      __cuda_callable__
+      LocalIndexType getSize() const;
+
+      __cuda_callable__
+      LocalIndexType getAllocatedSize() const;
+
+      __cuda_callable__
+      void setValue( const LocalIndexType& portIndex,
+                     const IndexType& value );
+
+      __cuda_callable__
+      IndexType getValue( const LocalIndexType& portIndex ) const;
+
+      __cuda_callable__
+      IndexType& operator[]( const LocalIndexType& portIndex );
+
+      __cuda_callable__
+      const IndexType& operator[]( const LocalIndexType& portIndex ) const;
+
+      __cuda_callable__
+      bool operator==( const EllpackIndexMultimapValues& other ) const;
+
+      __cuda_callable__
+      bool operator!=( const EllpackIndexMultimapValues& other ) const;
+
+      void print( std::ostream& str ) const;
+
+   protected:
+      using ValuesCountType = typename std::conditional< std::is_const< IndexType >::value,
+                                                         typename std::add_const< LocalIndexType >::type,
+                                                         LocalIndexType >::type;
+
+      __cuda_callable__
+      EllpackIndexMultimapValues( IndexType* values,
+                                  ValuesCountType* valuesCount,
+                                  const LocalIndexType& allocatedSize );
+
+      IndexType* values;
+
+      ValuesCountType* valuesCount;
+
+      // TODO: this is useless for a const-accessor (without setSize etc.)
+      LocalIndexType allocatedSize;
+
+      friend EllpackIndexMultimap< IndexType, DeviceType, LocalIndexType, step >;
+      friend EllpackIndexMultimap< typename std::remove_const< IndexType >::type, DeviceType, LocalIndexType, step >;
+};
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& ports );
+
+} // namespace TNL
+
+#include <TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h>
+
diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..9585741513a212d91d28c027f440752655eac07c
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h
@@ -0,0 +1,290 @@
+/***************************************************************************
+                          EllpackIndexMultimapValues_impl.h  -  description
+                             -------------------
+    begin                : Sep 10, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include "EllpackIndexMultimapValues.h"
+
+#include <TNL/Assert.h>
+
+namespace TNL {
+ 
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+EllpackIndexMultimapValues()
+: values( nullptr ), valuesCount( nullptr ), allocatedSize( 0 )
+{
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+EllpackIndexMultimapValues( EllpackIndexMultimapValues&& other )
+: values( other.values ), valuesCount( other.valuesCount ), allocatedSize( other.allocatedSize )
+{
+   other.values = nullptr;
+   other.valuesCount = nullptr;
+   other.allocatedSize = 0;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+EllpackIndexMultimapValues( IndexType* values,
+                            ValuesCountType* valuesCount,
+                            const LocalIndexType& allocatedSize )
+: values( values ), valuesCount( valuesCount ), allocatedSize( allocatedSize )
+{
+   TNL_ASSERT( *(this->valuesCount) <= allocatedSize, );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >&
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator=( const EllpackIndexMultimapValues& other )
+{
+   TNL_ASSERT( this->getAllocatedSize() >= other.getSize(), );
+   this->setSize( other.getSize() );
+   if( this->values != other.values ) {
+      for( LocalIndexType i = 0; i < this->getSize(); i++ )
+         this->setValue( i, other[ i ] );
+   }
+   return *this;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+   template< typename Index_, typename LocalIndex_, int step_ >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >&
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator=( const EllpackIndexMultimapValues< Index_, Device, LocalIndex_, step_ >& other )
+{
+   TNL_ASSERT( this->getAllocatedSize() >= other.getSize(), );
+   this->setSize( other.getSize() );
+   for( LocalIndexType i = 0; i < this->getSize(); i++ )
+      this->setValue( i, other[ i ] );
+   return *this;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >&
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator=( EllpackIndexMultimapValues&& other )
+{
+   this->values = other.values;
+   this->valuesCount = other.valuesCount;
+   this->allocatedSize = other.allocatedSize;
+   other.values = nullptr;
+   other.valuesCount = nullptr;
+   other.allocatedSize = 0;
+   return *this;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+void
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+bind( const EllpackIndexMultimapValues& other )
+{
+   this->values = other.values;
+   this->valuesCount = other.valuesCount;
+   this->allocatedSize = other.allocatedSize;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+void
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+setSize( const LocalIndexType& size )
+{
+   TNL_ASSERT( this->valuesCount,
+               std::cerr << "Uninitialized 'valuesCount' pointer in EllpackIndexMultimapValues." << std::endl; );
+   TNL_ASSERT( size >= 0 && size <= this->allocatedSize,
+               std::cerr << "size = " << size << ", allocatedSize = " << this->allocatedSize << std::endl; );
+   *valuesCount = size;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+LocalIndex
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+getSize() const
+{
+   if( ! valuesCount )
+      return 0;
+   return *valuesCount;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+LocalIndex
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+getAllocatedSize() const
+{
+   return this->allocatedSize;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+void
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+setValue( const LocalIndexType& portIndex,
+          const IndexType& value )
+{
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   this->values[ portIndex * step ] = value;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+Index
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+getValue( const LocalIndexType& portIndex ) const
+{
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+Index&
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator[]( const LocalIndexType& portIndex )
+{
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+const Index&
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator[]( const LocalIndexType& portIndex ) const
+{
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+bool
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator==( const EllpackIndexMultimapValues& other ) const
+{
+   if( this->getSize() != other.getSize() )
+      return false;
+   for( LocalIndexType i = 0; i < this->getSize(); i++ )
+      if( this->operator[]( i ) != other[ i ] )
+         return false;
+   return true;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+bool
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+operator!=( const EllpackIndexMultimapValues& other ) const
+{
+   return ! ( *this == other );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+void
+EllpackIndexMultimapValues< Index, Device, LocalIndex, step >::
+print( std::ostream& str ) const
+{
+   str << "[ ";
+   if( this->getSize() > 0 )
+   {
+      str << this->getValue( 0 );
+      for( typename std::remove_const< Index >::type i = 1; i < this->getSize(); i++ )
+         str << ", " << this->getValue( i );
+   }
+   str << " ]";
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device, LocalIndex, step >& ports )
+{
+   ports.print( str );
+   return str;
+}
+
+} // namespace TNL
+
diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..5c10152a7dabf7bb3dca6ce11578fdbe8d3509ac
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h
@@ -0,0 +1,319 @@
+/***************************************************************************
+                          EllpackIndexMultimap_impl.h  -  description
+                             -------------------
+    begin                : Sep 9, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once 
+
+#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h>
+
+namespace TNL {
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_ >
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+EllpackIndexMultimap( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other )
+{
+   operator=( other );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_ >
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >&
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+operator=( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize >& other )
+{
+   values = other.values;
+   valuesCounts = other.valuesCounts;
+   keysRange = other.keysRange;
+   maxValuesCount = other.maxValuesCount;
+   return *this;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+String
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getType()
+{
+   return String( "EllpackIndexMultimap< ") +
+          String( TNL::getType< Index >() ) +
+          String( ", " ) +
+          Device :: getDeviceType() +
+          String( ", " ) +
+          String( TNL::getType< LocalIndexType >() ) +
+          String( " >" );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+String
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getTypeVirtual() const
+{
+   return this->getType();
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+setKeysRange( const IndexType& keysRange )
+{
+   TNL_ASSERT( keysRange >= 0, );
+   this->keysRange = keysRange;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+const Index
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getKeysRange() const
+{
+   return this->keysRange;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+allocate( const LocalIndexType& maxValuesCount )
+{
+   TNL_ASSERT( maxValuesCount >= 0, );
+   this->maxValuesCount = maxValuesCount;
+   const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() );
+   this->values.setSize( ldSize * this->maxValuesCount );
+   this->valuesCounts.setSize( this->getKeysRange() );
+   this->valuesCounts.setValue( maxValuesCount );
+
+   // extra cost at initialization, which allows to have much simpler operator==
+   values.setValue( 0 );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+allocate( const ValuesAllocationVectorType& valuesCounts )
+{
+   TNL_ASSERT( valuesCounts.getSize() == this->keysRange,
+               std::cerr << "valuesCounts.getSize() =  " << valuesCounts.getSize()
+                         << "this->keysRange = " << this->keysRange
+                         << std::endl; );
+   this->maxValuesCount = valuesCounts.max();
+ 
+   TNL_ASSERT( this->maxValuesCount >= 0,
+               std::cerr << "this->maxValuesCount = " << this->maxValuesCount << std::endl; );
+   const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() );
+   this->values.setSize( ldSize * this->maxValuesCount );
+   this->valuesCounts.setSize( this->getKeysRange() );
+   this->valuesCounts = valuesCounts;
+
+   // extra cost at initialization, which allows to have much simpler operator==
+   values.setValue( 0 );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_, int SliceSize_ >
+void
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+setLike( const EllpackIndexMultimap< Index, Device_, LocalIndex, SliceSize_ >& other )
+{
+   const IndexType ldSize = getAllocationKeysRange( other.getKeysRange() );
+   values.setSize( ldSize * other.maxValuesCount );
+   valuesCounts.setLike( other.valuesCounts );
+   valuesCounts = other.valuesCounts;
+   keysRange = other.keysRange;
+   maxValuesCount = other.maxValuesCount;
+
+   // extra cost at initialization, which allows to have much simpler operator==
+   values.setValue( 0 );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+typename EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::ValuesAccessorType
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getValues( const IndexType& inputIndex )
+{
+   TNL_ASSERT( inputIndex < this->getKeysRange(),
+               std::cerr << "inputIndex = " << inputIndex << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange()
+                         << std::endl; );
+   TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * this->maxValuesCount == this->values.getSize() && this->getKeysRange() == this->valuesCounts.getSize(),
+               std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange() << std::endl
+                         << "this->maxValuesCount = " << this->maxValuesCount << std::endl
+                         << "this->values.getSize() = " << this->values.getSize() << std::endl
+                         << "this->valuesCounts.getSize() = " << this->valuesCounts.getSize() << std::endl; );
+   const IndexType sliceIdx = inputIndex / SliceSize;
+   const IndexType sliceOffset = sliceIdx * SliceSize * this->maxValuesCount;
+   const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize;
+   return ValuesAccessorType( &this->values[ offset ], &this->valuesCounts[ inputIndex ], this->maxValuesCount );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+typename EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::ConstValuesAccessorType
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getValues( const IndexType& inputIndex ) const
+{
+   TNL_ASSERT( inputIndex < this->getKeysRange(),
+              std::cerr << "inputIndex = " << inputIndex << std::endl
+                        << "this->getKeysRange() = " << this->getKeysRange()
+                        << std::endl; );
+   TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * this->maxValuesCount == this->values.getSize() && this->getKeysRange() == this->valuesCounts.getSize(),
+              std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl
+                        << "this->getKeysRange() = " << this->getKeysRange() << std::endl
+                        << "this->maxValuesCount = " << this->maxValuesCount << std::endl
+                        << "this->values.getSize() = " << this->values.getSize() << std::endl
+                        << "this->valuesCounts.getSize() = " << this->valuesCounts.getSize() << std::endl; );
+   const IndexType sliceIdx = inputIndex / SliceSize;
+   const IndexType sliceOffset = sliceIdx * SliceSize * this->maxValuesCount;
+   const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize;
+   return ConstValuesAccessorType( &this->values[ offset ], &this->valuesCounts[ inputIndex ], this->maxValuesCount );
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+operator==( const EllpackIndexMultimap& other ) const
+{
+//   if( ! ( this->keysRange == other.keysRange &&
+//           this->maxValuesCount == other.maxValuesCount &&
+//           this->valuesCounts == other.valuesCounts ) )
+//      return false;
+//   // compare values for each key separately - the sizes may vary
+//   for( IndexType i = 0; i < this->keysRange; i++ )
+//      if( this->getValues( i ) != other.getValues( i ) )
+//         return false;
+//   return true;
+
+   // we assume that invalid entries in the ellpack format are always 0
+   return this->keysRange == other.keysRange &&
+          this->maxValuesCount == other.maxValuesCount &&
+          this->valuesCounts == other.valuesCounts &&
+          this->values == other.values;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+save( File& file ) const
+{
+   if( ! Object::save( file ) )
+      return false;
+   if( ! file.write( &this->keysRange ) )
+      return false;
+   if( ! file.write( &this->maxValuesCount ) )
+      return false;
+   if( ! this->values.save( file ) )
+      return false;
+   if( ! this->valuesCounts.save( file ) )
+      return false;
+   return true;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+load( File& file )
+{
+   if( ! Object::load( file ) )
+      return false;
+   if( ! file.read( &this->keysRange ) )
+      return false;
+   if( ! file.read( &this->maxValuesCount ) )
+      return false;
+   if( ! this->values.load( file ) )
+      return false;
+   if( ! this->valuesCounts.load( file ) )
+      return false;
+   return true;
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+print( std::ostream& str ) const
+{
+   str << "[ ";
+   if( this->getKeysRange() > 0 )
+   {
+      str << this->getValues( 0 );
+      for( Index i = 1; i < this->getKeysRange(); i++ )
+         str << ",\n  " << this->getValues( i );
+   }
+   str << " ]";
+}
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+Index
+EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >::
+getAllocationKeysRange( IndexType keysRange ) const
+{
+   return SliceSize * roundUpDivision( keysRange, SliceSize );
+}
+
+
+template< typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimap< Index, Device, LocalIndex, SliceSize >& multimap )
+{
+   multimap.print( str );
+   return str;
+}
+
+} // namespace TNL
+
diff --git a/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h b/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h
new file mode 100644
index 0000000000000000000000000000000000000000..b459b660d9303a7d66c81dc3aa17a6df74a0466c
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/MultimapPermutationApplier.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+                          IndexPermutationApplier.h  -  description
+                             -------------------
+    begin                : Mar 10, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/DevicePointer.h>
+#include <TNL/ParallelFor.h>
+
+namespace TNL {
+
+template< typename Multimap,
+          typename PermutationVector >
+void permuteMultimapKeys( Multimap& multimap, const PermutationVector& perm )
+{
+   static_assert( std::is_same< typename Multimap::DeviceType, typename PermutationVector::DeviceType >::value,
+                  "The multimap and permutation vector must be stored on the same device." );
+   using IndexType = typename Multimap::IndexType;
+   using DeviceType = typename Multimap::DeviceType;
+   TNL_ASSERT( multimap.getKeysRange() == perm.getSize(),
+               std::cerr << "multimap keys range is " << multimap.getKeysRange()
+                         << ", permutation size is " << perm.getSize() << std::endl; );
+
+   // create temporary multimap for the permuted data
+   Multimap multimapCopy;
+   multimapCopy.setLike( multimap );
+
+   // kernel to permute the rows of multimap into multimapCopy
+   auto kernel = [] __cuda_callable__
+      ( IndexType i,
+        const Multimap* multimap,
+        Multimap* multimapCopy,
+        const typename PermutationVector::RealType* perm )
+   {
+      const auto srcValues = multimap->getValues( perm[ i ] );
+      auto destValues = multimapCopy->getValues( i );
+      destValues = srcValues;
+   };
+
+   DevicePointer< Multimap > multimapPointer( multimap );
+   DevicePointer< Multimap > multimapCopyPointer( multimapCopy );
+
+   ParallelFor< DeviceType >::exec( (IndexType) 0, multimap.getKeysRange(),
+                                    kernel,
+                                    &multimapPointer.template getData< DeviceType >(),
+                                    &multimapCopyPointer.template modifyData< DeviceType >(),
+                                    perm.getData() );
+
+   // copy the permuted data back into the multimap
+   multimap = multimapCopy;
+}
+
+template< typename Multimap,
+          typename PermutationVector >
+void permuteMultimapValues( Multimap& multimap, const PermutationVector& iperm )
+{
+   static_assert( std::is_same< typename Multimap::DeviceType, typename PermutationVector::DeviceType >::value,
+                  "The multimap and permutation vector must be stored on the same device." );
+   using IndexType = typename Multimap::IndexType;
+   using DeviceType = typename Multimap::DeviceType;
+
+   // kernel to permute the multimap values
+   auto kernel = [] __cuda_callable__
+      ( IndexType i,
+        Multimap* multimap,
+        const typename PermutationVector::RealType* iperm )
+   {
+      auto values = multimap->getValues( i );
+      for( typename Multimap::LocalIndexType v = 0; v < values.getSize(); v++ )
+         values[ v ] = iperm[ values[ v ] ];
+   };
+
+   DevicePointer< Multimap > multimapPointer( multimap );
+   ParallelFor< DeviceType >::exec( (IndexType) 0, multimap.getKeysRange(),
+                                    kernel,
+                                    &multimapPointer.template modifyData< DeviceType >(),
+                                    iperm.getData() );
+}
+
+} // namespace TNL
diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h
new file mode 100644
index 0000000000000000000000000000000000000000..85f013369828b60098efab5e5653797ec823757a
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h
@@ -0,0 +1,108 @@
+/***************************************************************************
+                          StaticEllpackIndexMultimap.h  -  description
+                             -------------------
+    begin                : Sep 9, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Containers/Vector.h>
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h>
+
+namespace TNL {
+
+template< typename Device >
+struct StaticEllpackIndexMultimapSliceSizeGetter
+{
+   static constexpr int SliceSize = 1;
+};
+
+template<>
+struct StaticEllpackIndexMultimapSliceSizeGetter< Devices::Cuda >
+{
+   static constexpr int SliceSize = 32;
+};
+
+template< int ValuesCount,
+          typename Index = int,
+          typename Device = Devices::Host,
+          typename LocalIndex = Index,
+          int SliceSize = StaticEllpackIndexMultimapSliceSizeGetter< Device >::SliceSize >
+class StaticEllpackIndexMultimap
+   : public Object
+{
+   public:
+      using DeviceType                 = Device;
+      using IndexType                  = Index;
+      using LocalIndexType             = LocalIndex;
+      using ValuesAccessorType         = StaticEllpackIndexMultimapValues< ValuesCount, IndexType, DeviceType, LocalIndexType, SliceSize >;
+      using ConstValuesAccessorType    = StaticEllpackIndexMultimapValues< ValuesCount, const IndexType, DeviceType, LocalIndexType, SliceSize >;
+
+      StaticEllpackIndexMultimap() = default;
+
+      template< typename Device_ >
+      StaticEllpackIndexMultimap( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other );
+
+      template< typename Device_ >
+      StaticEllpackIndexMultimap& operator=( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other );
+
+      static String getType();
+
+      String getTypeVirtual() const;
+
+      void setKeysRange( const IndexType& keysRange );
+
+      __cuda_callable__
+      const IndexType getKeysRange() const;
+
+      void allocate();
+
+      template< typename Device_ >
+      void setLike( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other );
+
+      __cuda_callable__
+      ValuesAccessorType getValues( const IndexType& inputIndex );
+
+      __cuda_callable__
+      ConstValuesAccessorType getValues( const IndexType& inputIndex ) const;
+
+      bool operator==( const StaticEllpackIndexMultimap& other ) const;
+
+      bool save( File& file ) const;
+
+      bool load( File& file );
+
+      using Object::load;
+
+      using Object::save;
+
+      void print( std::ostream& str ) const;
+
+   protected:
+      Containers::Vector< IndexType, DeviceType, IndexType > values;
+
+      IndexType keysRange = 0;
+
+      __cuda_callable__
+      IndexType getAllocationKeysRange( IndexType keysRange ) const;
+
+      // friend class is needed for templated assignment operators
+      template< int ValuesCount_, typename Index_, typename Device_, typename LocalIndex_, int SliceSize_ >
+      friend class StaticEllpackIndexMultimap;
+};
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >& multimap );
+
+} // namespace TNL
+
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h>
+
diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b69861c18d63f4fdfa60a0022ee5d145fdd306a
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+                          StaticEllpackIndexMultimapValues.h  -  description
+                             -------------------
+    begin                : Sep 10, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <type_traits>
+#include <ostream>
+
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+class StaticEllpackIndexMultimap;
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+class StaticEllpackIndexMultimapValues
+{
+   public:
+      using DeviceType     = Device;
+      using IndexType      = Index;
+      using LocalIndexType = LocalIndex;
+      using NetworkType    = StaticEllpackIndexMultimap< ValuesCount, IndexType, DeviceType, LocalIndexType, step >;
+
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues();
+
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues( StaticEllpackIndexMultimapValues&& other );
+
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues& operator=( const StaticEllpackIndexMultimapValues& other );
+
+      // converting assignment, needed for 'const int' -> 'int' etc.
+      template< typename Index_, typename LocalIndex_, int step_ >
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues& operator=( const StaticEllpackIndexMultimapValues< ValuesCount, Index_, Device, LocalIndex_, step_ >& other );
+
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues& operator=( StaticEllpackIndexMultimapValues&& other );
+
+      __cuda_callable__
+      void bind( const StaticEllpackIndexMultimapValues& other );
+
+      constexpr LocalIndexType getSize() const;
+
+      constexpr LocalIndexType getAllocatedSize() const;
+
+      __cuda_callable__
+      void setValue( const LocalIndexType& portIndex,
+                     const IndexType& value );
+
+      __cuda_callable__
+      IndexType getValue( const LocalIndexType& portIndex ) const;
+
+      __cuda_callable__
+      IndexType& operator[]( const LocalIndexType& portIndex );
+
+      __cuda_callable__
+      const IndexType& operator[]( const LocalIndexType& portIndex ) const;
+
+      __cuda_callable__
+      bool operator==( const StaticEllpackIndexMultimapValues& other ) const;
+
+      __cuda_callable__
+      bool operator!=( const StaticEllpackIndexMultimapValues& other ) const;
+
+      void print( std::ostream& str ) const;
+
+   protected:
+      __cuda_callable__
+      StaticEllpackIndexMultimapValues( IndexType* values );
+
+      IndexType* values;
+
+      friend StaticEllpackIndexMultimap< ValuesCount, IndexType, DeviceType, LocalIndexType, step >;
+      friend StaticEllpackIndexMultimap< ValuesCount, typename std::remove_const< IndexType >::type, DeviceType, LocalIndexType, step >;
+};
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& ports );
+
+} // namespace TNL
+
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h>
+
diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..32ed4b137b94fae57e858e935dc42dd6f1333c1b
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h
@@ -0,0 +1,282 @@
+/***************************************************************************
+                          StaticEllpackIndexMultimapValues_impl.h  -  description
+                             -------------------
+    begin                : Sep 10, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include "StaticEllpackIndexMultimapValues.h"
+
+#include <TNL/Assert.h>
+
+namespace TNL {
+ 
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+StaticEllpackIndexMultimapValues()
+: values( nullptr )
+{
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+StaticEllpackIndexMultimapValues( StaticEllpackIndexMultimapValues&& other )
+: values( other.values )
+{
+   other.values = nullptr;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+StaticEllpackIndexMultimapValues( IndexType* values )
+: values( values )
+{
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >&
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator=( const StaticEllpackIndexMultimapValues& other )
+{
+   if( this->values != other.values ) {
+      for( LocalIndexType i = 0; i < this->getSize(); i++ )
+         this->setValue( i, other[ i ] );
+   }
+   return *this;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+   template< typename Index_, typename LocalIndex_, int step_ >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >&
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator=( const StaticEllpackIndexMultimapValues< ValuesCount, Index_, Device, LocalIndex_, step_ >& other )
+{
+   for( LocalIndexType i = 0; i < this->getSize(); i++ )
+      this->setValue( i, other[ i ] );
+   return *this;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >&
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator=( StaticEllpackIndexMultimapValues&& other )
+{
+   this->values = other.values;
+   other.values = nullptr;
+   return *this;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+void
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+bind( const StaticEllpackIndexMultimapValues& other )
+{
+   this->values = other.values;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+constexpr LocalIndex
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+getSize() const
+{
+   return ValuesCount;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+constexpr LocalIndex
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+getAllocatedSize() const
+{
+   return ValuesCount;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+void
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+setValue( const LocalIndexType& portIndex,
+          const IndexType& value )
+{
+   TNL_ASSERT( this->values,
+               std::cerr << "This instance is not bound to any multimap." << std::endl; );
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   this->values[ portIndex * step ] = value;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+Index
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+getValue( const LocalIndexType& portIndex ) const
+{
+   TNL_ASSERT( this->values,
+               std::cerr << "This instance is not bound to any multimap." << std::endl; );
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+Index&
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator[]( const LocalIndexType& portIndex )
+{
+   TNL_ASSERT( this->values,
+               std::cerr << "This instance is not bound to any multimap." << std::endl; );
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+const Index&
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator[]( const LocalIndexType& portIndex ) const
+{
+   TNL_ASSERT( this->values,
+               std::cerr << "This instance is not bound to any multimap." << std::endl; );
+   TNL_ASSERT( portIndex < this->getSize(),
+               std::cerr << " portIndex = " << portIndex
+                         << " getSize() = " << this->getSize()
+                         << std::endl );
+   return this->values[ portIndex * step ];
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+bool
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator==( const StaticEllpackIndexMultimapValues& other ) const
+{
+   if( this->values == other.values )
+      return true;
+   if( ! this->values || ! other.values )
+      return false;
+   for( LocalIndexType i = 0; i < this->getSize(); i++ )
+      if( this->operator[]( i ) != other[ i ] )
+         return false;
+   return true;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+__cuda_callable__
+bool
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+operator!=( const StaticEllpackIndexMultimapValues& other ) const
+{
+   return ! ( *this == other );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+void
+StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >::
+print( std::ostream& str ) const
+{
+   str << "[ ";
+   if( this->getSize() > 0 )
+   {
+      str << this->getValue( 0 );
+      for( typename std::remove_const< Index >::type i = 1; i < this->getSize(); i++ )
+         str << ", " << this->getValue( i );
+   }
+   str << " ]";
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int step >
+std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimapValues< ValuesCount, Index, Device, LocalIndex, step >& ports )
+{
+   ports.print( str );
+   return str;
+}
+
+} // namespace TNL
+
diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..a0c61fa08b508f1f5d75e46f77d7f085232fa032
--- /dev/null
+++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h
@@ -0,0 +1,274 @@
+/***************************************************************************
+                          StaticEllpackIndexMultimap_impl.h  -  description
+                             -------------------
+    begin                : Sep 9, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once 
+
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h>
+
+namespace TNL {
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_ >
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+StaticEllpackIndexMultimap( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other )
+{
+   operator=( other );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_ >
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >&
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+operator=( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other )
+{
+   values = other.values;
+   keysRange = other.keysRange;
+   return *this;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+String
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getType()
+{
+   return String( "StaticEllpackIndexMultimap< ") +
+          String( TNL::getType< Index >() ) +
+          String( ", " ) +
+          Device :: getDeviceType() +
+          String( ", " ) +
+          String( TNL::getType< LocalIndexType >() ) +
+          String( " >" );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+String
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getTypeVirtual() const
+{
+   return this->getType();
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+setKeysRange( const IndexType& keysRange )
+{
+   TNL_ASSERT( keysRange >= 0, );
+   this->keysRange = keysRange;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+const Index
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getKeysRange() const
+{
+   return this->keysRange;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+allocate()
+{
+   const IndexType ldSize = getAllocationKeysRange( this->getKeysRange() );
+   values.setSize( ldSize * ValuesCount );
+
+   // extra cost at initialization, which allows to have much simpler operator==
+   values.setValue( 0 );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+   template< typename Device_ >
+void
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+setLike( const StaticEllpackIndexMultimap< ValuesCount, Index, Device_, LocalIndex, SliceSize >& other )
+{
+   const IndexType ldSize = getAllocationKeysRange( other.getKeysRange() );
+   values.setSize( ldSize * ValuesCount );
+
+   // extra cost at initialization, which allows to have much simpler operator==
+   values.setValue( 0 );
+
+   keysRange = other.keysRange;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+typename StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::ValuesAccessorType
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getValues( const IndexType& inputIndex )
+{
+   TNL_ASSERT( inputIndex < this->getKeysRange(),
+               std::cerr << "inputIndex = " << inputIndex << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange() << std::endl; );
+   TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * ValuesCount == this->values.getSize(),
+               std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange() << std::endl
+                         << "this->values.getSize() = " << this->values.getSize() << std::endl; );
+   const IndexType sliceIdx = inputIndex / SliceSize;
+   const IndexType sliceOffset = sliceIdx * SliceSize * ValuesCount;
+   const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize;
+   return ValuesAccessorType( &this->values[ offset ] );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+typename StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::ConstValuesAccessorType
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getValues( const IndexType& inputIndex ) const
+{
+   TNL_ASSERT( inputIndex < this->getKeysRange(),
+               std::cerr << "inputIndex = " << inputIndex << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange() << std::endl; );
+   TNL_ASSERT( getAllocationKeysRange( this->getKeysRange() ) * ValuesCount == this->values.getSize(),
+               std::cerr << "The map has not been reallocated after calling setKeysRange()." << std::endl
+                         << "this->getKeysRange() = " << this->getKeysRange() << std::endl
+                         << "this->values.getSize() = " << this->values.getSize() << std::endl; );
+   const IndexType sliceIdx = inputIndex / SliceSize;
+   const IndexType sliceOffset = sliceIdx * SliceSize * ValuesCount;
+   const IndexType offset = sliceOffset + inputIndex - sliceIdx * SliceSize;
+   return ConstValuesAccessorType( &this->values[ offset ] );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+operator==( const StaticEllpackIndexMultimap& other ) const
+{
+   return ( this->keysRange == other.keysRange && this->values == other.values );
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+save( File& file ) const
+{
+   if( ! Object::save( file ) )
+      return false;
+   if( ! file.write( &this->keysRange ) )
+      return false;
+   if( ! this->values.save( file ) )
+      return false;
+   return true;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+bool
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+load( File& file )
+{
+   if( ! Object::load( file ) )
+      return false;
+   if( ! file.read( &this->keysRange ) )
+      return false;
+   if( ! this->values.load( file ) )
+      return false;
+   return true;
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+void
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+print( std::ostream& str ) const
+{
+   str << "[ ";
+   if( this->getKeysRange() > 0 )
+   {
+      str << this->getValues( 0 );
+      for( Index i = 1; i < this->getKeysRange(); i++ )
+         str << ",\n  " << this->getValues( i );
+   }
+   str << " ]";
+}
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+__cuda_callable__
+Index
+StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >::
+getAllocationKeysRange( IndexType keysRange ) const
+{
+   return SliceSize * roundUpDivision( keysRange, SliceSize );
+}
+
+
+template< int ValuesCount,
+          typename Index,
+          typename Device,
+          typename LocalIndex,
+          int SliceSize >
+std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimap< ValuesCount, Index, Device, LocalIndex, SliceSize >& multimap )
+{
+   multimap.print( str );
+   return str;
+}
+
+} // namespace TNL
+
diff --git a/src/TNL/Containers/UnorderedIndexedSet.h b/src/TNL/Containers/UnorderedIndexedSet.h
new file mode 100644
index 0000000000000000000000000000000000000000..38a1e53937fabb7ca3de9e7e4c9f31a41b5adbe3
--- /dev/null
+++ b/src/TNL/Containers/UnorderedIndexedSet.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+                          UnorderedIndexedSet.h  -  description
+                             -------------------
+    begin                : Dec 12, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <unordered_map>
+#include <ostream>
+
+namespace TNL {
+namespace Containers {
+
+template< class Key,
+          class Index,
+          class Hash = std::hash< Key >,
+          class KeyEqual = std::equal_to< Key >,
+          class Allocator = std::allocator< std::pair<const Key, Index> > >
+class UnorderedIndexedSet
+{
+protected:
+   using map_type = std::unordered_map< Key, Index, Hash, KeyEqual, Allocator >;
+   map_type map;
+
+public:
+   using key_type = Key;
+   using index_type = Index;
+   using value_type = typename map_type::value_type;
+   using size_type = typename map_type::size_type;
+   using hasher = Hash;
+   using key_equal = KeyEqual;
+
+   void clear();
+
+   size_type size() const;
+
+   Index insert( const Key& key );
+
+   std::pair< Index, bool > try_insert( const Key& key );
+
+   bool find( const Key& key, Index& index ) const;
+
+   size_type count( const Key& key ) const;
+
+   size_type erase( const Key& key );
+
+   void print( std::ostream& str ) const;
+};
+
+template< typename Element,
+          typename Index >
+std::ostream& operator <<( std::ostream& str, UnorderedIndexedSet< Element, Index >& set );
+
+} // namespace Containers
+} // namespace TNL
+
+#include <TNL/Containers/UnorderedIndexedSet_impl.h>
diff --git a/src/TNL/Containers/UnorderedIndexedSet_impl.h b/src/TNL/Containers/UnorderedIndexedSet_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..4402ab55cca466c2c31f5c9f4704d94c33873395
--- /dev/null
+++ b/src/TNL/Containers/UnorderedIndexedSet_impl.h
@@ -0,0 +1,130 @@
+/***************************************************************************
+                          UnorderedIndexedSet_impl.h  -  description
+                             -------------------
+    begin                : Feb 15, 2014
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Containers/UnorderedIndexedSet.h>
+
+namespace TNL {
+namespace Containers {
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+void
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::clear()
+{
+   map.clear();
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size() const
+{
+   return map.size();
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+Index
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::insert( const Key& key )
+{
+   auto iter = map.insert( value_type( key, size() ) ).first;
+   return iter->second;
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+std::pair< Index, bool >
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::try_insert( const Key& key )
+{
+   auto pair = map.insert( value_type( key, size() ) );
+   return std::pair< Index, bool >{ pair.first->second, pair.second };
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+bool
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::find( const Key& key, Index& index ) const
+{
+   auto iter = map.find( Key( key ) );
+   if( iter == map.end() )
+      return false;
+   index = iter->second.index;
+   return true;
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::count( const Key& key ) const
+{
+   return map.count( key );
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+typename UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::size_type
+UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::erase( const Key& key )
+{
+   return map.erase( key );
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+void UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >::print( std::ostream& str ) const
+{
+   auto iter = map.begin();
+   str << iter->second.data;
+   iter++;
+   while( iter != map.end() )
+   {
+      str << ", " << iter->second.data;
+      iter++;
+   }
+}
+
+template< class Key,
+          class Index,
+          class Hash,
+          class KeyEqual,
+          class Allocator >
+std::ostream& operator<<( std::ostream& str, UnorderedIndexedSet< Key, Index, Hash, KeyEqual, Allocator >& set )
+{
+   set.print( str );
+   return str;
+}
+
+} // namespace Containers
+} // namespace TNL
diff --git a/src/TNL/Debugging/FPE.h b/src/TNL/Debugging/FPE.h
index 09011e8953205089db602357ad9840965dc95ede..5f6c18d3214ac1da58376a77dc647fc8f234d865 100644
--- a/src/TNL/Debugging/FPE.h
+++ b/src/TNL/Debugging/FPE.h
@@ -1,5 +1,5 @@
 /***************************************************************************
-                          MeshConfigBase.h  -  description
+                          FPE.h  -  description
                              -------------------
     begin                : Nov 6, 2016
     copyright            : (C) 2016 by Tomas Oberhuber et al.
diff --git a/src/TNL/Debugging/MemoryUsage.h b/src/TNL/Debugging/MemoryUsage.h
index 03ea3fe4d3db40f566ce82762521da1596e45dd5..a657976130faef71f4e592e8a10752767cc04363 100644
--- a/src/TNL/Debugging/MemoryUsage.h
+++ b/src/TNL/Debugging/MemoryUsage.h
@@ -1,5 +1,5 @@
 /***************************************************************************
-                          MeshConfigBase.h  -  description
+                          MemoryUsage.h  -  description
                              -------------------
     begin                : Nov 6, 2016
     copyright            : (C) 2016 by Tomas Oberhuber et al.
diff --git a/src/TNL/Debugging/StackBacktrace.h b/src/TNL/Debugging/StackBacktrace.h
index ee419922637899c7187e25d187abc6a427ebff68..99949eabaaa8c516fcf42ee8671971e5e530153f 100644
--- a/src/TNL/Debugging/StackBacktrace.h
+++ b/src/TNL/Debugging/StackBacktrace.h
@@ -1,5 +1,5 @@
 /***************************************************************************
-                          MeshConfigBase.h  -  description
+                          StackBacktrace.h  -  description
                              -------------------
     begin                : Nov 6, 2016
     copyright            : (C) 2016 by Tomas Oberhuber et al.
diff --git a/src/TNL/Experimental/CMakeLists.txt b/src/TNL/Experimental/CMakeLists.txt
index 47fc9efa44f92699b64e247af1778ad83e6cebfa..fea80728f261adbdaa6519a3efea912f253de31e 100644
--- a/src/TNL/Experimental/CMakeLists.txt
+++ b/src/TNL/Experimental/CMakeLists.txt
@@ -1,3 +1,2 @@
 ADD_SUBDIRECTORY( Arithmetics )
-ADD_SUBDIRECTORY( Multimaps )
 ADD_SUBDIRECTORY( Hamilton-Jacobi )
diff --git a/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h b/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h
index 225ce04b9851b93dd00d37644a7c042f563a3b9d..c4055d95df7afe453337e592de0f9ef224226b52 100644
--- a/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h
+++ b/src/TNL/Experimental/Hamilton-Jacobi/Solvers/hamilton-jacobi/tnl-direct-eikonal-solver.h
@@ -24,7 +24,7 @@
 using namespace TNL;
 
 //typedef tnlDefaultBuildMeshConfig BuildConfig;
-typedef Solvers::FastBuildConfig BuildConfig;
+typedef Solvers::FastBuildConfigTag BuildConfig;
 
 template< typename MeshConfig >
 class tnlDirectEikonalSolverConfig
diff --git a/src/TNL/Experimental/Multimaps/CMakeLists.txt b/src/TNL/Experimental/Multimaps/CMakeLists.txt
deleted file mode 100644
index fc23d168ee5c5d8212f0e761834eff6421933215..0000000000000000000000000000000000000000
--- a/src/TNL/Experimental/Multimaps/CMakeLists.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-SET( headers EllpackIndexMultimap.h
-             EllpackIndexMultimap_impl.h
-             EllpackIndexMultimapValues.h
-             EllpackIndexMultimapValues_impl.h )
-
-SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/core/multimaps )
-set( common_SOURCES
-      )       
-
-IF( BUILD_CUDA )
-   set( tnl_core_multimaps_CUDA__SOURCES
-        ${common_SOURCES}      
-        PARENT_SCOPE )
-ENDIF()    
-
-set( tnl_core_multimaps_SOURCES     
-     ${common_SOURCES}
-     PARENT_SCOPE )
-        
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/core/multimaps )
diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h
deleted file mode 100644
index e5879c7937a7c00a611bbe2676cab08c19d73562..0000000000000000000000000000000000000000
--- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/***************************************************************************
-                          EllpackIndexMultimap.h  -  description
-                             -------------------
-    begin                : Sep 9, 2015
-    copyright            : (C) 2015 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once 
-
-#include <TNL/Containers/Vector.h>
-
-namespace TNL {
-
-template< typename Index = int,
-          typename Device = Devices::Host >
-class EllpackIndexMultimapValues;
-
-template< typename Index = int,
-          typename Device = Devices::Host >
-class EllpackIndexMultimapConstValues;
-
-template< typename Index = int,
-          typename Device = Devices::Host >
-class EllpackIndexMultimap
-{
-   public:
- 
-      typedef Device                                                       DeviceType;
-      typedef Index                                                        IndexType;
-      typedef EllpackIndexMultimapValues< IndexType, DeviceType >       ValuesAccessorType;
-      typedef EllpackIndexMultimapConstValues< IndexType, DeviceType >  ConstValuesAccessorType;
-      typedef Containers::Vector< IndexType, DeviceType, IndexType >                ValuesAllocationVectorType;
- 
-      EllpackIndexMultimap();
- 
-      static String getType();
-
-      String getTypeVirtual() const;
- 
-      void setRanges( const IndexType keysRange,
-                      const IndexType valuesRange );
- 
-      const IndexType getKeysRange() const;
- 
-      const IndexType getValuesRange() const;
- 
-      void allocate( const ValuesAllocationVectorType& portsCount );
- 
-      ValuesAccessorType getValues( const IndexType& inputIndex );
- 
-      ConstValuesAccessorType getValues( const IndexType& inputIndex ) const;
- 
-   protected:
- 
-      Containers::Vector< IndexType, DeviceType, IndexType > values;
- 
-      IndexType keysRange, valuesRange, valuesMaxCount;
-};
-
-} // namespace TNL
-
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h>
-
diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h
deleted file mode 100644
index fd297f030899ca4e3389925ed39c4c2dbd33dcae..0000000000000000000000000000000000000000
--- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/***************************************************************************
-                          EllpackIndexMultimapValues.h  -  description
-                             -------------------
-    begin                : Sep 10, 2015
-    copyright            : (C) 2015 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <ostream>
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h>
-
-namespace TNL {
-
-template< typename Index,
-          typename Device >
-class EllpackIndexMultimapValues
-{
-   public:
- 
-      typedef Device                                     DeviceType;
-      typedef Index                                      IndexType;
-      typedef EllpackIndexMultimap< IndexType, DeviceType > NetworkType;
- 
-      EllpackIndexMultimapValues();
- 
-      IndexType getPortsCount() const;
- 
-      void setOutput( const IndexType portIndex,
-                      const IndexType output );
- 
-      IndexType getOutput( const IndexType portIndex ) const;
- 
-      IndexType& operator[]( const IndexType portIndex );
- 
-      const IndexType& operator[]( const IndexType portIndex ) const;
- 
-      void print( std::ostream& str ) const;
- 
-   protected:
- 
-      EllpackIndexMultimapValues( IndexType* ports,
-                              const IndexType input,
-                              const IndexType portsMaxCount );
- 
-      IndexType* ports;
- 
-      IndexType step, portsMaxCount;
- 
-      friend EllpackIndexMultimap< IndexType, DeviceType >;
-};
-
-template< typename Index,
-          typename Device >
-std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device>& ports );
-
-} // namespace TNL
-
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h>
-
diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h
deleted file mode 100644
index 612d0c5d6770e50e8f568f6a7bcb5a0842d4548e..0000000000000000000000000000000000000000
--- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimapValues_impl.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/***************************************************************************
-                          EllpackIndexMultimapValues_impl.h  -  description
-                             -------------------
-    begin                : Sep 10, 2015
-    copyright            : (C) 2015 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include "EllpackIndexMultimapValues.h"
-
-namespace TNL {
- 
-template< typename Index,
-          typename Device >
-EllpackIndexMultimapValues< Index, Device >::
-EllpackIndexMultimapValues()
-{
-}
-
-template< typename Index,
-          typename Device >
-EllpackIndexMultimapValues< Index, Device >::
-EllpackIndexMultimapValues( IndexType* networkPorts,
-                        const IndexType input,
-                        const IndexType portsMaxCount )
-{
-   this->ports = &networkPorts[ input * portsMaxCount ];
-   this->portsMaxCount = portsMaxCount;
-}
-
-template< typename Index,
-          typename Device >
-Index
-EllpackIndexMultimapValues< Index, Device >::
-getPortsCount() const
-{
-   return this->portsMaxCount;
-}
-
-template< typename Index,
-          typename Device >
-void
-EllpackIndexMultimapValues< Index, Device >::
-setOutput( const IndexType portIndex,
-           const IndexType output )
-{
-   this->ports[ portIndex ] = output;
-}
-
-template< typename Index,
-          typename Device >
-Index
-EllpackIndexMultimapValues< Index, Device >::
-getOutput( const IndexType portIndex ) const
-{
-   return this->ports[ portIndex ];
-}
-
-template< typename Index,
-          typename Device >
-Index&
-EllpackIndexMultimapValues< Index, Device >::
-operator[]( const IndexType portIndex )
-{
-   return this->ports[ portIndex ];
-}
-
-template< typename Index,
-          typename Device >
-const Index&
-EllpackIndexMultimapValues< Index, Device >::
-operator[]( const IndexType portIndex ) const
-{
-   return this->ports[ portIndex ];
-}
-
-template< typename Index,
-          typename Device >
-void
-EllpackIndexMultimapValues< Index, Device >::
-print( std::ostream& str ) const
-{
-   if( this->getPortsCount() == 0 )
-   {
-      str << "[]";
-      return;
-   }
-   str << "[ " << this->getOutput( 0 );
-   for( Index i = 1; i < this->getPortsCount(); i++ )
-      str << ", " << this->getOutput( i );
-   str << " ]";
-}
-
-template< typename Index,
-          typename Device >
-std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< Index, Device>& ports )
-{
-   ports.print( str );
-   return str;
-}
-
-} // namespace TNL
-
diff --git a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h b/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h
deleted file mode 100644
index 1b7c41a937f3fd5b9cd92c600364f09d5b4f28e3..0000000000000000000000000000000000000000
--- a/src/TNL/Experimental/Multimaps/EllpackIndexMultimap_impl.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/***************************************************************************
-                          EllpackIndexMultimap_impl.h  -  description
-                             -------------------
-    begin                : Sep 9, 2015
-    copyright            : (C) 2015 by Tomas Oberhuber et al.
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once 
-
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h>
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimapValues.h>
-
-namespace TNL {
-
-template< typename Index,
-          typename Device >
-EllpackIndexMultimap< Index, Device >::
-EllpackIndexMultimap()
-:  keysRange( 0 ), valuesRange( 0 ), valuesMaxCount( 0 )
-{
-}
-
-template< typename Index,
-          typename Device >
-String EllpackIndexMultimap< Index, Device > :: getType()
-{
-   return String( "EllpackIndexMultimap< ") +
-          Device :: getDeviceType() +
-          String( ", " ) +
-          String( TNL::getType< Index >() ) +
-          String( " >" );
-}
-
-template< typename Index,
-          typename Device >
-String EllpackIndexMultimap< Index, Device >::getTypeVirtual() const
-{
-   return this->getType();
-}
-
-template< typename Index,
-          typename Device >
-void
-EllpackIndexMultimap< Index, Device >::
-setRanges( const IndexType inputs,
-               const IndexType outputs )
-{
-   this->keysRange = inputs;
-   this->valuesRange = outputs;
-}
-
-template< typename Index,
-          typename Device >
-const Index
-EllpackIndexMultimap< Index, Device >::
-getKeysRange() const
-{
-   return this->keysRange;
-}
-
-template< typename Index,
-          typename Device >
-const Index
-EllpackIndexMultimap< Index, Device >::
-getValuesRange() const
-{
-   return this->valuesRange;
-}
-
-template< typename Index,
-          typename Device >
-void
-EllpackIndexMultimap< Index, Device >::
-allocate( const ValuesAllocationVectorType& portsCount )
-{
-   TNL_ASSERT( portsCount.getSize() == this->keysRange,
-              std::cerr << "portsCount.getSize() =  " << portsCount.getSize()
-                   << "this->inputs = " << this->keysRange );
-   this->valuesMaxCount = portsCount.max();
- 
-   TNL_ASSERT( this->valuesMaxCount >= 0 && this->valuesMaxCount <= this->valuesRange,
-              std::cerr << "this->portsMaxCount = " << this->valuesMaxCount
-                   << " this->outputs = " << this->valuesRange );
-   this->values.setSize( this->keysRange * this->valuesMaxCount );
-}
-
-template< typename Index,
-          typename Device >
-typename EllpackIndexMultimap< Index, Device >::ValuesAccessorType
-EllpackIndexMultimap< Index, Device >::
-getValues( const IndexType& inputIndex )
-{
-   return ValuesAccessorType( this->values.getData(), inputIndex, this->valuesMaxCount );
-}
-
-template< typename Index,
-          typename Device >
-typename EllpackIndexMultimap< Index, Device >::ConstValuesAccessorType
-EllpackIndexMultimap< Index, Device >::
-getValues( const IndexType& inputIndex ) const
-{
-   return ConstPortsType( this->values.getData(), inputIndex, this->valuesMaxCount );
-}
-
-} // namespace TNL
-
diff --git a/src/TNL/Functions/Analytic/Constant_impl.h b/src/TNL/Functions/Analytic/Constant_impl.h
index bbd46853dc3cbe98448819876ffc8fc17940cc1a..80102ddf3817248fb3702aa902505f260dad8786 100644
--- a/src/TNL/Functions/Analytic/Constant_impl.h
+++ b/src/TNL/Functions/Analytic/Constant_impl.h
@@ -67,6 +67,7 @@ template< int Dimension,
    template< int XDiffOrder,
              int YDiffOrder,
              int ZDiffOrder >
+__cuda_callable__
 Real
 Constant< Dimension, Real >::
 getPartialDerivative( const PointType& v,
diff --git a/src/TNL/Functions/CMakeLists.txt b/src/TNL/Functions/CMakeLists.txt
index 75a34d3181a6aab9db291407cc73f793549e0e3e..92359a15bf92d3255f9f1d97495cd7efc45725d0 100644
--- a/src/TNL/Functions/CMakeLists.txt
+++ b/src/TNL/Functions/CMakeLists.txt
@@ -8,10 +8,8 @@ SET( headers Domain.h
              MeshFunctionEvaluator.h
              MeshFunctionEvaluator_impl.h
              MeshFunctionGnuplotWriter.h
-             MeshFunctionGnuplotWriter_impl.h
              MeshFunctionNormGetter.h
              MeshFunctionVTKWriter.h
-             MeshFunctionVTKWriter_impl.h             
              OperatorFunction.h
              TestFunction.h             
              TestFunction_impl.h
diff --git a/src/TNL/Functions/MeshFunctionGnuplotWriter.h b/src/TNL/Functions/MeshFunctionGnuplotWriter.h
index 2c21a10328d4bd49bb6f3501246ce476cca83bd2..4b9b6d085ff7a69c0139fce319d3e3cb4d540f78 100644
--- a/src/TNL/Functions/MeshFunctionGnuplotWriter.h
+++ b/src/TNL/Functions/MeshFunctionGnuplotWriter.h
@@ -13,175 +13,73 @@
 #include <TNL/Meshes/Grid.h>
 
 namespace TNL {
-namespace Functions {
 
-template< typename, int, typename > class MeshFunction;
+namespace Meshes {
+   template< typename, typename, typename > class MeshEntity;
+}
+
+namespace Functions {
 
 template< typename MeshFunction >
 class MeshFunctionGnuplotWriter
 {
-   public:
-
-      static bool write( const MeshFunction& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 1D grids cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >
-{
-   public:
-      typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 1D grids vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-
-/***
- * 2D grids cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 2D grids faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 2D grids vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-
-/***
- * 3D grids cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 3, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 3D grids faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-};
-
-/***
- * 3D grids vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
+   using MeshType = typename MeshFunction::MeshType;
+   using EntityType = typename MeshType::template EntityType< MeshFunction::getEntitiesDimension() >;
+   using GlobalIndex = typename MeshType::GlobalIndexType;
+
+   template< typename Entity, int dim = Entity::getEntityDimension() >
+   struct center
+   {
+      static auto get( const Entity& entity ) -> decltype(entity.getCenter())
+      {
+         return entity.getCenter();
+      }
+   };
+
+   template< typename Entity >
+   struct center< Entity, 0 >
+   {
+      static auto get( const Entity& entity ) -> decltype(entity.getPoint())
+      {
+         return entity.getPoint();
+      }
+   };
+
+   template< typename MeshConfig, typename Device, typename Topology, int dim >
+   struct center< TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >, dim >
+   {
+      static int get( const TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >& entity )
+      {
+         throw "not implemented";
+      }
+   };
+
+   template< typename MeshConfig, typename Device, typename Topology >
+   struct center< TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >, 0 >
+   {
+      static int get( const TNL::Meshes::MeshEntity< MeshConfig, Device, Topology >& entity )
+      {
+         throw "not implemented";
+      }
+   };
+
+public:
+   static bool write( const MeshFunction& function,
+                      std::ostream& str,
+                      const double& scale = 1.0 )
+   {
+      const MeshType& mesh = function.getMesh();
+      const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      for( GlobalIndex i = 0; i < entitiesCount; i++ ) {
+         const EntityType& entity = mesh.template getEntity< EntityType >( i );
+         typename MeshType::PointType v = center< EntityType >::get( entity );
+         for( int j = 0; j < v.getSize(); j++ )
+            str << v[ j ] << " ";
+         str << scale * function.getData().getElement( i ) << "\n";
+      }
+      return true;
+   }
 };
 
 } // namespace Functions
 } // namespace TNL
-
-#include <TNL/Functions/MeshFunctionGnuplotWriter_impl.h>
diff --git a/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h b/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h
deleted file mode 100644
index 13c8fa1cb0da1c280a7eb605a0f31f0f7c2a13e8..0000000000000000000000000000000000000000
--- a/src/TNL/Functions/MeshFunctionGnuplotWriter_impl.h
+++ /dev/null
@@ -1,363 +0,0 @@
-/***************************************************************************
-                          MeshFunctionGnuplotWriter.h  -  description
-                             -------------------
-    begin                : Jan 28, 2016
-    copyright            : (C) 2016 by oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/Functions/MeshFunctionGnuplotWriter.h>
-
-namespace TNL {
-namespace Functions {
-
-template< typename MeshFunction >
-bool
-MeshFunctionGnuplotWriter< MeshFunction >::
-write( const MeshFunction& function,
-       std::ostream& str,
-       const double& scale )
-{
-   std::cerr << "Gnuplot writer for mesh functions defined on mesh type " << MeshFunction::MeshType::getType() << " is not (yet) implemented." << std::endl;
-   return false;
-}
-
-/****
- * 1D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Cell entity( mesh );
-   for( entity.getCoordinates().x() = 0;
-        entity.getCoordinates().x() < mesh.getDimensions().x();
-        entity.getCoordinates().x() ++ )
-   {
-      entity.refresh();
-      typename MeshType::PointType v = entity.getCenter();
-      str << v.x() << " "
-          << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-   return true;
-}
-
-/****
- * 1D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Vertex entity( mesh );
-   for( entity.getCoordinates().x() = 0;
-        entity.getCoordinates().x() <= mesh.getDimensions().x();
-        entity.getCoordinates().x() ++ )
-   {
-      entity.refresh();
-      typename MeshType::PointType v = entity.getCenter();
-      str << v.x() << " "
-          << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-   return true;
-}
-
-
-/****
- * 2D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Cell entity( mesh );
-   for( entity.getCoordinates().y() = 0;
-        entity.getCoordinates().y() < mesh.getDimensions().y();
-        entity.getCoordinates().y() ++ )
-   {
-      for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() < mesh.getDimensions().x();
-           entity.getCoordinates().x() ++ )
-      {
-         entity.refresh();
-         typename MeshType::PointType v = entity.getCenter();
-         str << v.x() << " " << v.y() << " "
-             << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-      }
-      str << std::endl;
-   }
-   return true;
-}
-
-/****
- * 2D grid, faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typedef typename MeshType::Face EntityType;
-   typedef typename EntityType::EntityOrientationType EntityOrientation;
-   EntityType entity( mesh );
-
-   entity.setOrientation( EntityOrientation( 1.0, 0.0 ) );
-   for( entity.getCoordinates().y() = 0;
-        entity.getCoordinates().y() < mesh.getDimensions().y();
-        entity.getCoordinates().y() ++ )
-   {
-      for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() <= mesh.getDimensions().x();
-           entity.getCoordinates().x() ++ )
-      {
-         entity.refresh();
-         typename MeshType::PointType v = entity.getCenter();
-         str << v.x() << " " << v.y() << " "
-             << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-      }
-      str << std::endl;
-   }
-
-   entity.setOrientation( EntityOrientation( 0.0, 1.0 ) );
-         for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() < mesh.getDimensions().x();
-           entity.getCoordinates().x() ++ )
-
-   {
-            for( entity.getCoordinates().y() = 0;
-        entity.getCoordinates().y() <= mesh.getDimensions().y();
-        entity.getCoordinates().y() ++ )
-
-      {
-         entity.refresh();
-         typename MeshType::PointType v = entity.getCenter();
-         str << v.x() << " " << v.y() << " "
-             << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-      }
-      str << std::endl;
-   }
-   return true;
-}
-
-
-/****
- * 2D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Vertex entity( mesh );
-   for( entity.getCoordinates().y() = 0;
-        entity.getCoordinates().y() <= mesh.getDimensions().y();
-        entity.getCoordinates().y() ++ )
-   {
-      for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() <= mesh.getDimensions().x();
-           entity.getCoordinates().x() ++ )
-      {
-         entity.refresh();
-         typename MeshType::PointType v = entity.getCenter();
-         str << v.x() << " " << v.y() << " "
-             << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-      }
-      str << std::endl;
-   }
-   return true;
-}
-
-
-/****
- * 3D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Cell entity( mesh );
-   for( entity.getCoordinates().z() = 0;
-        entity.getCoordinates().z() < mesh.getDimensions().z();
-        entity.getCoordinates().z() ++ )
-      for( entity.getCoordinates().y() = 0;
-           entity.getCoordinates().y() < mesh.getDimensions().y();
-           entity.getCoordinates().y() ++ )
-      {
-         for( entity.getCoordinates().x() = 0;
-              entity.getCoordinates().x() < mesh.getDimensions().x();
-              entity.getCoordinates().x() ++ )
-         {
-            entity.refresh();
-            typename MeshType::PointType v = entity.getCenter();
-            str << v.x() << " " << v.y() << " " << v.z() << " "
-                << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-         }
-         str << std::endl;
-      }
-   return true;
-}
-
-/****
- * 3D grid, faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typedef typename MeshType::Face EntityType;
-   typedef typename EntityType::EntityOrientationType EntityOrientation;
-   EntityType entity( mesh );
-
-   entity.setOrientation( EntityOrientation( 1.0, 0.0, 0.0 ) );
-   for( entity.getCoordinates().z() = 0;
-        entity.getCoordinates().z() < mesh.getDimensions().z();
-        entity.getCoordinates().z() ++ )
-      for( entity.getCoordinates().y() = 0;
-           entity.getCoordinates().y() < mesh.getDimensions().y();
-           entity.getCoordinates().y() ++ )
-      {
-         for( entity.getCoordinates().x() = 0;
-              entity.getCoordinates().x() <= mesh.getDimensions().x();
-              entity.getCoordinates().x() ++ )
-         {
-            entity.refresh();
-            typename MeshType::PointType v = entity.getCenter();
-            str << v.x() << " " << v.y() << " " << v.z() << " "
-                << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-         }
-         str << std::endl;
-      }
-
-   entity.setOrientation( EntityOrientation( 0.0, 1.0, 0.0 ) );
-   for( entity.getCoordinates().z() = 0;
-        entity.getCoordinates().z() < mesh.getDimensions().z();
-        entity.getCoordinates().z() ++ )
-      for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() < mesh.getDimensions().x();
-           entity.getCoordinates().x() ++ )
-      {
-         for( entity.getCoordinates().y() = 0;
-              entity.getCoordinates().y() <= mesh.getDimensions().y();
-              entity.getCoordinates().y() ++ )
-         {
-            entity.refresh();
-            typename MeshType::PointType v = entity.getCenter();
-            str << v.x() << " " << v.y() << " " << v.z() << " "
-                << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-         }
-         str << std::endl;
-      }
-
-   entity.setOrientation( EntityOrientation( 0.0, 0.0, 1.0 ) );
-   for( entity.getCoordinates().x() = 0;
-        entity.getCoordinates().x() < mesh.getDimensions().x();
-        entity.getCoordinates().x() ++ )
-      for( entity.getCoordinates().y() = 0;
-           entity.getCoordinates().y() <= mesh.getDimensions().y();
-           entity.getCoordinates().y() ++ )
-      {
-         for( entity.getCoordinates().z() = 0;
-              entity.getCoordinates().z() < mesh.getDimensions().z();
-              entity.getCoordinates().z() ++ )
-         {
-            entity.refresh();
-            typename MeshType::PointType v = entity.getCenter();
-            str << v.x() << " " << v.y() << " " << v.z() << " "
-                << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-         }
-         str << std::endl;
-      }
-   return true;
-}
-
-
-/****
- * 3D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionGnuplotWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   const MeshType& mesh = function.getMesh();
-   typename MeshType::Vertex entity( mesh );
-   for( entity.getCoordinates().z() = 0;
-        entity.getCoordinates().z() <= mesh.getDimensions().z();
-        entity.getCoordinates().z() ++ )
-      for( entity.getCoordinates().y() = 0;
-           entity.getCoordinates().y() <= mesh.getDimensions().y();
-           entity.getCoordinates().y() ++ )
-      {
-         for( entity.getCoordinates().x() = 0;
-              entity.getCoordinates().x() <= mesh.getDimensions().x();
-              entity.getCoordinates().x() ++ )
-         {
-            entity.refresh();
-            typename MeshType::PointType v = entity.getCenter();
-            str << v.x() << " " << v.y() << " " << v.z() << " "
-                << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-         }
-         str << std::endl;
-      }
-   return true;
-}
-
-} // namespace Functions
-} // namespace TNL
-
diff --git a/src/TNL/Functions/MeshFunctionVTKWriter.h b/src/TNL/Functions/MeshFunctionVTKWriter.h
index b4d18e4490901c2824ff922fe10f18607198e780..78608de7461dc5510d280d29b9f7c329836e3eb8 100644
--- a/src/TNL/Functions/MeshFunctionVTKWriter.h
+++ b/src/TNL/Functions/MeshFunctionVTKWriter.h
@@ -2,7 +2,7 @@
                           MeshFunctionVTKWriter.h  -  description
                              -------------------
     begin                : Jan 28, 2016
-    copyright            : (C) 2016 by oberhuber
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -10,225 +10,49 @@
 
 #pragma once
 
-#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Writers/VTKWriter.h>
 
 namespace TNL {
 namespace Functions {   
 
-template< typename, int, typename > class MeshFunction;
-
 template< typename MeshFunction >
 class MeshFunctionVTKWriter
 {
-   public:
- 
-      static bool write( const MeshFunction& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunction& function,
-                         std::ostream& str ){}
-};
-
-/***
- * 1D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >
-{
-   public:
-      typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
- 
-/***
- * 1D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 2D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 2D grid, faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 2D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 3D grid, cells
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 3, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 3D grid, faces
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 2, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 3D grid, edges
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 1, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
-};
-
-/***
- * 3D grid, vertices
- */
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-class MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >
-{
-   public:
-      typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
-      typedef Real RealType;
-      typedef Functions::MeshFunction< MeshType, 0, RealType > MeshFunctionType;
-
-      static bool write( const MeshFunctionType& function,
-                         std::ostream& str,
-                         const double& scale );
-      
-      static void writeHeader(const MeshFunctionType& function,
-                         std::ostream& str );
+   using MeshType = typename MeshFunction::MeshType;
+   using MeshWriter = Meshes::Writers::VTKWriter< MeshType >;
+   using EntityType = typename MeshType::template EntityType< MeshFunction::getEntitiesDimension() >;
+   using GlobalIndex = typename MeshType::GlobalIndexType;
+
+public:
+   static bool write( const MeshFunction& function,
+                      std::ostream& str,
+                      const double& scale = 1.0,
+                      const String& functionName = "cellFunctionValues" )
+   {
+      const MeshType& mesh = function.getMesh();
+      MeshWriter::template writeEntities< MeshFunction::getEntitiesDimension() >( mesh, str );
+      appendFunction( function, str, functionName, scale );
+      return true;
+   }
+
+   // VTK supports writing multiple functions into the same file.
+   // You can call this after 'write', which initializes the mesh entities,
+   // with different function name.
+   static void appendFunction( const MeshFunction& function,
+                               std::ostream& str,
+                               const String& functionName,
+                               const double& scale = 1.0 )
+   {
+      const MeshType& mesh = function.getMesh();
+      const GlobalIndex entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
+      str << "SCALARS " << functionName << " " << getType< typename MeshFunction::RealType >() << " 1" << std::endl;
+      str << "LOOKUP_TABLE default" << std::endl;
+      for( GlobalIndex i = 0; i < entitiesCount; i++ ) {
+         str << scale * function.getData().getElement( i ) << "\n";
+      }
+   }
 };
 
 } // namespace Functions
 } // namespace TNL
-
-#include <TNL/Functions/MeshFunctionVTKWriter_impl.h>
diff --git a/src/TNL/Functions/MeshFunctionVTKWriter_impl.h b/src/TNL/Functions/MeshFunctionVTKWriter_impl.h
deleted file mode 100644
index 606eac9ce348e2260109845af0bb05cea064a3e8..0000000000000000000000000000000000000000
--- a/src/TNL/Functions/MeshFunctionVTKWriter_impl.h
+++ /dev/null
@@ -1,841 +0,0 @@
-/***************************************************************************
-                          MeshFunctionVTKWriter_impl.h  -  description
-                             -------------------
-    begin                : Jan 28, 2016
-    copyright            : (C) 2016 by oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/Functions/MeshFunctionVTKWriter.h>
-
-namespace TNL {
-namespace Functions {   
-
-template< typename MeshFunction >
-bool
-MeshFunctionVTKWriter< MeshFunction >::
-write( const MeshFunction& function,
-       std::ostream& str,
-       const double& scale )
-{
-   std::cerr << "VTK writer for mesh functions defined on mesh type " << MeshFunction::MeshType::getType() << " is not (yet) implemented." << std::endl;
-   return false;
-}
-
-/****
- * 1D grid, cells
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 1, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType origin = mesh.getOrigin().x();
-   const RealType spaceStep = mesh.getSpaceSteps().x();
- 
-   str << "POINTS " << mesh.getDimensions().x() + 1 << " float" << std::endl;
-   for (int i = 0; i <= mesh.getDimensions().x(); i++)
-   {
-       str << origin + i * spaceStep << " 0 0" << std::endl;
-   }
- 
-   str << std::endl << "CELLS " << mesh.getDimensions().x() << " " << mesh.getDimensions().x() * 3 << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x(); i++)
-   {
-       str << "2 " << i << " " << i+1 << std::endl;
-   }
- 
-   str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x(); i++)
-   {
-       str << "3 " << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << mesh.getDimensions().x() << std::endl;
-   str << "SCALARS cellFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < mesh.template getEntitiesCount< typename MeshType::Cell >(); i++ )
-   {
-      typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
- 
-   return true;
-}
-
-/****
- * 1D grid, vertices
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType origin = mesh.getOrigin().x();
-   const RealType spaceStep = mesh.getSpaceSteps().x();
- 
-   str << "POINTS " << mesh.getDimensions().x() + 1 << " float" << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x() + 1; i++)
-   {
-       str << origin + i * spaceStep << " 0 0" << std::endl;
-   }
- 
-   str << std::endl << "CELLS " << mesh.getDimensions().x() + 1 << " " << ( mesh.getDimensions().x() + 1 ) * 2 << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x() + 1; i++)
-   {
-       str << "1 " << i << std::endl;
-   }
- 
-   str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() + 1 << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x() + 1; i++)
-   {
-       str << "1 " << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << mesh.getDimensions().x() + 1 << std::endl;
-   str << "SCALARS VerticesFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < mesh.template getEntitiesCount< typename MeshType::Vertex >(); i++ )
-   {
-      typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
- 
-   return true;
-}
-
-/****
- * 2D grid, cells
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 2, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
-   const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Cell >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int j = 0; j < mesh.getDimensions().y() + 1; j++)
-   {
-        for (int i = 0; i < mesh.getDimensions().x() + 1; i++)
-        {
-             str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl;
-        }
-   }
- 
-   str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 5 << std::endl;
-   for (int j = 0; j < mesh.getDimensions().y(); j++)
-   {
-        for (int i = 0; i < mesh.getDimensions().x(); i++)
-        {
-            str << "4 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " << j * ( mesh.getDimensions().x() + 1 )+ i + 1 <<
-                   " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl;
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << mesh.getDimensions().x() * mesh.getDimensions().y() << std::endl;
-   for (int i = 0; i < mesh.getDimensions().x()*mesh.getDimensions().y(); i++)
-   {
-       str << "8 " << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
-   str << "SCALARS cellFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < entitiesCount; i++ )
-   {
-      typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 2D grid, faces
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 1, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   typedef typename MeshType::template EntityType< 0 > Vertex;
-   typedef typename MeshType::template EntityType< 1 > Face;
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
-   const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Face >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int j = 0; j < ( mesh.getDimensions().y() + 1); j++)
-   {
-        for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++)
-        {
-             str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl;
-        }
-   }
- 
-   str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 3 << std::endl;
-   for (int j = 0; j < mesh.getDimensions().y(); j++)
-   {
-        for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++)
-        {
-            str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl;
-        }
-   }
- 
-   for (int j = 0; j < (mesh.getDimensions().y()+1); j++)
-   {
-        for (int i = 0; i < mesh.getDimensions().x(); i++)
-        {
-            str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " " <<j * ( mesh.getDimensions().x() + 1 ) + i + 1<< std::endl;
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << entitiesCount << std::endl;
-   for (int i = 0; i < entitiesCount; i++)
-   {
-       str << "3" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
-   str << "SCALARS FaceslFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < entitiesCount; i++ )
-   {
-      typename MeshType::Face entity = mesh.template getEntity< typename MeshType::Face >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 2D grid, vertices
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   typedef typename MeshType::template EntityType< 0 > Vertex;
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int j = 0; j < ( mesh.getDimensions().y() + 1); j++)
-   {
-        for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++)
-        {
-             str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " 0" << std::endl;
-        }
-   }
- 
-   str << std::endl << "CELLS " << verticesCount << " " << verticesCount * 2 << std::endl;
-   for (int j = 0; j < ( mesh.getDimensions().y() + 1 ); j++)
-   {
-        for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++)
-        {
-            str << "1 " << j * mesh.getDimensions().x() + i  << std::endl;
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << verticesCount << std::endl;
-   for (int i = 0; i < verticesCount; i++)
-   {
-       str << "1" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << verticesCount << std::endl;
-   str << "SCALARS VerticesFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < verticesCount; i++ )
-   {
-      typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 3D grid, cells
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 3, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const RealType originZ = mesh.getOrigin().z();
-   const RealType spaceStepZ = mesh.getSpaceSteps().z();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
-   const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Cell >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int k = 0; k <= mesh.getDimensions().y(); k++)
-   {
-       for (int j = 0; j <= mesh.getDimensions().y(); j++)
-       {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                 str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " <<
-                        originZ + k * spaceStepZ << std::endl;
-            }
-       }
-   }
- 
-   str << std::endl << "CELLS " << entitiesCount << " " <<
-          entitiesCount * 9 << std::endl;
-   for (int k = 0; k < mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j < mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i < mesh.getDimensions().x(); i++)
-            {
-                str << "8 " <<  k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl;
-            }
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << entitiesCount << std::endl;
-   for (int i = 0; i < entitiesCount; i++)
-   {
-       str << "11" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
-   str << "SCALARS cellFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < entitiesCount; i++ )
-   {
-      typename MeshType::Cell entity = mesh.template getEntity< typename MeshType::Cell >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 3D grid, faces
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 2, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const RealType originZ = mesh.getOrigin().z();
-   const RealType spaceStepZ = mesh.getSpaceSteps().z();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
-   const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Face >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int k = 0; k <= mesh.getDimensions().y(); k++)
-   {
-       for (int j = 0; j <= mesh.getDimensions().y(); j++)
-       {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                 str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " <<
-                        originZ + k * spaceStepZ << std::endl;
-            }
-       }
-   }
- 
-   str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 5 << std::endl;
-   for (int k = 0; k < mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j < mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl;
-            }
-        }
-   }
- 
-   for (int k = 0; k < mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j <= mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i < mesh.getDimensions().x(); i++)
-            {
-                str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl;
-            }
-        }
-   }
- 
-   for (int k = 0; k <= mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j < mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i < mesh.getDimensions().x(); i++)
-            {
-                str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1<< std::endl;
-            }
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << entitiesCount << std::endl;
-   for (int i = 0; i < entitiesCount; i++)
-   {
-       str << "8" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
-   str << "SCALARS facesFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < entitiesCount; i++ )
-   {
-      typename MeshType::Face entity = mesh.template getEntity< typename MeshType::Face >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 3D grid, edges
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 1, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const RealType originZ = mesh.getOrigin().z();
-   const RealType spaceStepZ = mesh.getSpaceSteps().z();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
-   const MeshIndex entitiesCount = mesh.template getEntitiesCount< typename MeshType::Edge >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int k = 0; k <= mesh.getDimensions().y(); k++)
-   {
-       for (int j = 0; j <= mesh.getDimensions().y(); j++)
-       {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                 str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " <<
-                        originZ + k * spaceStepZ << std::endl;
-            }
-       }
-   }
- 
-   str << std::endl << "CELLS " << entitiesCount << " " << entitiesCount * 3 << std::endl;
-   for (int k = 0; k <= mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j <= mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i < mesh.getDimensions().x(); i++)
-            {
-                str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << std::endl;
-            }
-        }
-   }
- 
-   for (int k = 0; k <= mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j < mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << std::endl;
-            }
-        }
-   }
- 
-   for (int k = 0; k < mesh.getDimensions().z(); k++)
-   {
-        for (int j = 0; j <= mesh.getDimensions().y(); j++)
-        {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                str << "3 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
-                    << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << std::endl;
-            }
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << entitiesCount << std::endl;
-   for (int i = 0; i < entitiesCount; i++)
-   {
-       str << "3" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << entitiesCount << std::endl;
-   str << "SCALARS edgesFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < entitiesCount; i++ )
-   {
-      typename MeshType::Edge entity = mesh.template getEntity< typename MeshType::Edge >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-/****
- * 3D grid, vertices
- */
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-void
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >::
-writeHeader( const MeshFunctionType& function,
-             std::ostream& str )
-{
-    const MeshType& mesh = function.getMesh();
-    const typename MeshType::PointType& origin = mesh.getOrigin();
-    const typename MeshType::PointType& proportions = mesh.getProportions();
-    str << "# vtk DataFile Version 2.0" << std::endl;
-    str << "TNL DATA" << std::endl;
-    str << "ASCII" << std::endl;
-    str << "DATASET UNSTRUCTURED_GRID" << std::endl;
-}
-
-template< typename MeshReal,
-          typename Device,
-          typename MeshIndex,
-          typename Real >
-bool
-MeshFunctionVTKWriter< MeshFunction< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, 0, Real > >::
-write( const MeshFunctionType& function,
-       std::ostream& str,
-       const double& scale )
-{
-   writeHeader(function, str);
- 
-   const MeshType& mesh = function.getMesh();
-   const RealType originX = mesh.getOrigin().x();
-   const RealType spaceStepX = mesh.getSpaceSteps().x();
-   const RealType originY = mesh.getOrigin().y();
-   const RealType spaceStepY = mesh.getSpaceSteps().y();
-   const RealType originZ = mesh.getOrigin().z();
-   const RealType spaceStepZ = mesh.getSpaceSteps().z();
-   const MeshIndex verticesCount = mesh.template getEntitiesCount< typename MeshType::Vertex >();
- 
-   str << "POINTS " << verticesCount << " float" << std::endl;
-   for (int k = 0; k <= mesh.getDimensions().y(); k++)
-   {
-       for (int j = 0; j <= mesh.getDimensions().y(); j++)
-       {
-            for (int i = 0; i <= mesh.getDimensions().x(); i++)
-            {
-                 str << originX + i * spaceStepX << " " << originY + j * spaceStepY << " " <<
-                        originZ + k * spaceStepZ << std::endl;
-            }
-       }
-   }
- 
-   str << std::endl << "CELLS " << verticesCount << " " << verticesCount * 2 << std::endl;
-   for (int k = 0; k < ( mesh.getDimensions().z() + 1 ); k++)
-   {
-        for (int j = 0; j < ( mesh.getDimensions().y() + 1 ); j++)
-        {
-            for (int i = 0; i < ( mesh.getDimensions().x() + 1 ); i++)
-            {
-                str << "1 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i  << std::endl;
-            }
-        }
-   }
- 
-   str << std::endl << "CELL_TYPES " << verticesCount << std::endl;
-   for (int i = 0; i < verticesCount; i++)
-   {
-       str << "1" << std::endl;
-   }
- 
-   str << std::endl << "CELL_DATA " << verticesCount << std::endl;
-   str << "SCALARS verticesFunctionValues float 1" << std::endl;
-   str << "LOOKUP_TABLE default" << std::endl;
-
-   for( MeshIndex i = 0; i < verticesCount; i++ )
-   {
-      typename MeshType::Vertex entity = mesh.template getEntity< typename MeshType::Vertex >( i );
-      entity.refresh();
-      str << scale * function.getData().getElement( entity.getIndex() ) << std::endl;
-   }
-
-   return true;
-}
-
-} // namespace Functions
-} // namespace TNL
-
diff --git a/src/TNL/Functions/VectorField.h b/src/TNL/Functions/VectorField.h
index 2fe085e750c931d5d81cd1dbdf2c49fd9af38ad9..cbc143251962455b074d426f87928c2a25dd762a 100644
--- a/src/TNL/Functions/VectorField.h
+++ b/src/TNL/Functions/VectorField.h
@@ -87,7 +87,7 @@ class VectorField< Size, MeshFunction< Mesh, MeshEntityDimension, Real > >
       typedef MeshFunction< MeshType, MeshEntityDimension, RealType > FunctionType;
       typedef SharedPointer< FunctionType > FunctionPointer;
       typedef typename MeshType::DeviceType DeviceType;
-      typedef typename MeshType::IndexType IndexType;
+      typedef typename MeshType::GlobalIndexType IndexType;
       typedef VectorField< Size, MeshFunction< Mesh, MeshEntityDimension, RealType > > ThisType;
       typedef Containers::StaticVector< Size, RealType > VectorType;
 
diff --git a/src/TNL/Meshes/BuildConfigTags.h b/src/TNL/Meshes/BuildConfigTags.h
new file mode 100644
index 0000000000000000000000000000000000000000..35aa2b2f89041575587e3f9ac291db02475dd0fa
--- /dev/null
+++ b/src/TNL/Meshes/BuildConfigTags.h
@@ -0,0 +1,142 @@
+/***************************************************************************
+                          BuildConfigTags.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Quadrilateral.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+#include <TNL/Meshes/Topologies/Hexahedron.h>
+#include <TNL/Meshes/Topologies/Simplex.h>
+
+namespace TNL {
+namespace Meshes {
+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 ) }; };
+
+// Grids are enabled for all real types by default.
+template< typename ConfigTag, typename Real > struct GridRealTag { enum { enabled = true }; };
+
+// Grids are enabled on all available devices by default.
+template< typename ConfigTag, typename Device > struct GridDeviceTag { enum { enabled = true }; };
+#ifndef HAVE_CUDA
+template< typename ConfigTag > struct GridDeviceTag< ConfigTag, Devices::Cuda > { enum { enabled = false }; };
+#endif
+
+// Grids are enabled for all index types by default.
+template< typename ConfigTag, typename Index > struct GridIndexTag { enum { 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, int Dimension, typename Real, typename Device, typename Index >
+struct GridTag< ConfigTag, Grid< Dimension, Real, Device, Index > >
+{
+   enum { enabled = GridDimensionTag< ConfigTag, Dimension >::enabled  &&
+                    GridRealTag< ConfigTag, Real >::enabled &&
+                    GridDeviceTag< ConfigTag, Device >::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 }; };
+#ifdef HAVE_CUDA
+template< typename ConfigTag > struct MeshDeviceTag< ConfigTag, Devices::Cuda > { enum { 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::Quadrilateral > { 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 }; };
+// TODO: Simplex has not been tested yet
+//template< typename ConfigTag > struct MeshCellTopologyTag< ConfigTag, Topologies::Simplex > { enum { enabled = true }; };
+
+// All sensible world dimensions are enabled by default.
+template< typename ConfigTag, typename CellTopology, int WorldDimension > struct MeshWorldDimensionTag { enum { enabled = ( WorldDimension >= CellTopology::dimension && WorldDimension <= 3 ) }; };
+
+// Meshes are enabled for all real types by default.
+template< typename ConfigTag, typename Real > struct MeshRealTag { enum { enabled = true }; };
+
+// Meshes are enabled for all global index types by default.
+template< typename ConfigTag, typename GlobalIndex > struct MeshGlobalIndexTag { enum { enabled = true }; };
+
+// Meshes are enabled for all local index types by default.
+template< typename ConfigTag, typename LocalIndex > struct MeshLocalIndexTag { enum { enabled = true }; };
+
+// Meshes are enabled for 'GlobalIndex' and 'void' id types by default.
+template< typename ConfigTag, typename GlobalIndex, typename Id > struct MeshIdTag { enum { enabled = false }; };
+template< typename ConfigTag, typename GlobalIndex > struct MeshIdTag< ConfigTag, GlobalIndex, void > { enum { enabled = true }; };
+template< typename ConfigTag, typename GlobalIndex > struct MeshIdTag< ConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; };
+
+// Config tag specifying the MeshConfig to use.
+template< typename ConfigTag >
+struct MeshConfigTemplateTag
+{
+   template< typename Cell, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id >
+   using MeshConfig = DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >;
+};
+
+// The Mesh is enabled for allowed Device, CellTopology, WorldDimension, Real,
+// GlobalIndex, LocalIndex and Id types as specified above.
+//
+// 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.
+//
+// NOTE: We can't specialize the whole MeshType as it was done for the GridTag,
+//       because we don't know the MeshConfig and the compiler can't deduce it
+//       at the time of template specializations, so something like this does
+//       not work:
+//
+//          struct MeshTag< ConfigTag,
+//                      Mesh< typename MeshConfigTemplateTag< ConfigTag >::
+//                         template MeshConfig< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, Id > > >
+//
+template< typename ConfigTag, typename Device, typename CellTopology, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id >
+struct MeshTag
+{
+   enum { enabled =
+            MeshDeviceTag< ConfigTag, Device >::enabled &&
+            MeshCellTopologyTag< ConfigTag, CellTopology >::enabled &&
+            MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled &&
+            MeshRealTag< ConfigTag, Real >::enabled &&
+            MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled &&
+            MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled &&
+            MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled
+   };
+};
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/CMakeLists.txt b/src/TNL/Meshes/CMakeLists.txt
index d49d84212cdec3709d882af04f78ad7e2d680924..9dd51e9b858050cb095d3a3cb68b672a3ba263ae 100644
--- a/src/TNL/Meshes/CMakeLists.txt
+++ b/src/TNL/Meshes/CMakeLists.txt
@@ -1,17 +1,23 @@
+ADD_SUBDIRECTORY( Geometry )
 ADD_SUBDIRECTORY( GridDetails )
 ADD_SUBDIRECTORY( MeshDetails )
 ADD_SUBDIRECTORY( DistributedMeshes )
+ADD_SUBDIRECTORY( Readers )
 ADD_SUBDIRECTORY( Topologies )
+ADD_SUBDIRECTORY( TypeResolver )
+ADD_SUBDIRECTORY( Writers )
 
-SET( headers Grid.h
-             GridEntity.h
-             GridEntityConfig.h
+SET( headers BuildConfigTags.h
+             DefaultConfig.h
+             DimensionTag.h
              DummyMesh.h
-             MeshDimensionTag.h             
-             Mesh.h
+             GridEntityConfig.h
+             GridEntity.h
+             Grid.h
+             MeshBuilder.h
              MeshEntity.h
+             Mesh.h
              Traverser.h
-             MeshConfigBase.h
     )
 
 SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes )    
diff --git a/src/TNL/Meshes/DefaultConfig.h b/src/TNL/Meshes/DefaultConfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..147a9ab10b911ba0a0bca9ec1dd3b74035508e6e
--- /dev/null
+++ b/src/TNL/Meshes/DefaultConfig.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+                          DefaultConfig.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/String.h>
+#include <TNL/param-types.h>
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
+
+namespace TNL {
+namespace Meshes {
+
+/****
+ * Basic structure for mesh configuration.
+ * Setting Id to GlobalIndex enables storage of entity Id.
+ * It means that each mesh entity stores its index in its
+ * mesh storage layer.
+ */
+template< typename Cell,
+          int WorldDimension = Cell::dimension,
+          typename Real = double,
+          typename GlobalIndex = int,
+          typename LocalIndex = GlobalIndex,
+          typename Id = void >
+struct DefaultConfig
+{
+   using CellTopology = Cell;
+   using RealType = Real;
+   using GlobalIndexType = GlobalIndex;
+   using LocalIndexType = LocalIndex;
+   using IdType = Id;
+
+   static constexpr int worldDimension = WorldDimension;
+   static constexpr int meshDimension = Cell::dimension;
+
+   static String getType()
+   {
+      return String( "Meshes::DefaultConfig< " ) +
+             Cell::getType() + ", " +
+             String( WorldDimension ) + ", " +
+             TNL::getType< Real >() + ", " +
+             TNL::getType< GlobalIndex >() + ", " +
+             TNL::getType< LocalIndex >() + ", " +
+             TNL::getType< Id >() + " >";
+   };
+
+   /****
+    * Storage of mesh entities.
+    */
+   static constexpr bool entityStorage( int dimension )
+   {
+      /****
+       * Vertices and cells must always be stored.
+       */
+      return true;
+      //return ( dimension == 0 || dimension == cellDimension );
+   }
+
+   /****
+    * Storage of subentities of mesh entities.
+    */
+   template< typename EntityTopology >
+   static constexpr bool subentityStorage( EntityTopology, int SubentityDimension )
+   {
+      /****
+       *  Subvertices of all stored entities must always be stored
+       */
+      return entityStorage( EntityTopology::dimension );
+      //return entityStorage( EntityTopology::dimension ) &&
+      //       SubentityDimension == 0;
+   }
+
+   /****
+    * Storage of subentity orientations of mesh entities.
+    * It must be false for vertices and cells.
+    */
+   template< typename EntityTopology >
+   static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimension )
+   {
+      return ( SubentityDimension > 0 );
+   }
+
+   /****
+    * Storage of superentities of mesh entities.
+    */
+   template< typename EntityTopology >
+   static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension )
+   {
+      return entityStorage( EntityTopology::dimension );
+      //return false;
+   }
+
+   /****
+    * Storage of boundary tags of mesh entities. Necessary for the mesh traverser.
+    *
+    * The configuration must satisfy the following necessary conditions in
+    * order to provide boundary tags:
+    *    - faces must be stored
+    *    - faces must store the cell indices in the superentity layer
+    *    - if dim(entity) < dim(face), the entities on which the tags are stored
+    *      must be stored as subentities of faces
+    * TODO: check this in the ConfigValidator
+    */
+   template< typename EntityTopology >
+   static constexpr bool boundaryTagsStorage( EntityTopology )
+   {
+      using FaceTopology = typename Topologies::Subtopology< CellTopology, meshDimension - 1 >::Topology;
+      return entityStorage( meshDimension - 1 ) &&
+             superentityStorage( FaceTopology(), meshDimension ) &&
+             ( EntityTopology::dimension >= meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) );
+      //return false;
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDimensionTag.h b/src/TNL/Meshes/DimensionTag.h
similarity index 61%
rename from src/TNL/Meshes/MeshDimensionTag.h
rename to src/TNL/Meshes/DimensionTag.h
index 10dbcdaf71605a627f29154074dd1e76d0cc0df9..2cf42488ebacaf3abff0a7a12d3595a96b24d1ab 100644
--- a/src/TNL/Meshes/MeshDimensionTag.h
+++ b/src/TNL/Meshes/DimensionTag.h
@@ -1,19 +1,13 @@
 /***************************************************************************
-                          MeshDimensionTag.h  -  description
+                          DimensionTag.h  -  description
                              -------------------
     begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    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/Assert.h>
@@ -30,31 +24,32 @@ namespace Meshes {
  *   expression is a simple identifier.
  *
  * Therefore one cannot specialize the mesh layers just by integers saying the mesh
- * layer dimensions but instead this tag must be used. This makes the code more difficult
+ * layer dimension but instead this tag must be used. This makes the code more difficult
  * to read and we would like to avoid it if it is possible sometime.
- * On the other hand, MeshDimensionTag is also used for method overloading when
+ * On the other hand, DimensionTag is also used for method overloading when
  * asking for different mesh entities. In this case it makes sense and it cannot be
  * replaced.
  */
 
 template< int Dimension >
-class MeshDimensionTag
+class DimensionTag
 {
-   public:
+   static_assert( Dimension >= 0, "The dimension cannot be negative." );
 
-      static const int value = Dimension;
+public:
+   static constexpr int value = Dimension;
 
-      typedef MeshDimensionTag< Dimension - 1 > Decrement;
-
-      static_assert( value >= 0, "The value of the dimensions cannot be negative." );
+   using Decrement = DimensionTag< Dimension - 1 >;
+   using Increment = DimensionTag< Dimension + 1 >;
 };
 
 template<>
-class MeshDimensionTag< 0 >
+class DimensionTag< 0 >
 {
-   public:
- 
-      static const int value = 0;
+public:
+   static const int value = 0;
+
+   using Increment = DimensionTag< 1 >;
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/DummyMesh.h b/src/TNL/Meshes/DummyMesh.h
index ce4cd0bf42f92d8911fa482ca240e5e919ba00e1..4bff7ce1773978c95a9d16fa2edda1d0760ee7bd 100644
--- a/src/TNL/Meshes/DummyMesh.h
+++ b/src/TNL/Meshes/DummyMesh.h
@@ -2,7 +2,7 @@
                           DummyMesh.h  -  description
                              -------------------
     begin                : Apr 17, 2013
-    copyright            : (C) 2013 by Tomas Oberhuber
+    copyright            : (C) 2013 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -10,6 +10,9 @@
 
 #pragma once
 
+#include <TNL/String.h>
+#include <TNL/Devices/Host.h>
+
 namespace TNL {
 namespace Meshes {
 
@@ -18,8 +21,7 @@ template< typename Real = double,
           typename Index = int >
 class DummyMesh
 {
-   public:
-
+public:
    typedef Real RealType;
    typedef Device DeviceType;
    typedef Index IndexType;
diff --git a/src/TNL/Meshes/Geometry/CMakeLists.txt b/src/TNL/Meshes/Geometry/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c743984d782fee8eb9a28960b67682172306f4ff
--- /dev/null
+++ b/src/TNL/Meshes/Geometry/CMakeLists.txt
@@ -0,0 +1,5 @@
+SET( headers getEntityCenter.h
+             getEntityMeasure.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Geometry )
diff --git a/src/TNL/Meshes/Geometry/getEntityCenter.h b/src/TNL/Meshes/Geometry/getEntityCenter.h
new file mode 100644
index 0000000000000000000000000000000000000000..59cd950ca180cdbf8095382536544e9fe0ffde51
--- /dev/null
+++ b/src/TNL/Meshes/Geometry/getEntityCenter.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+                          getEntityCenter.h  -  description
+                             -------------------
+    begin                : Nov 12, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Devices/CudaCallable.h>
+#include <TNL/Meshes/GridEntity.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+
+namespace TNL {
+namespace Meshes {
+
+// compatibility wrapper
+template< typename Grid, int EntityDimension, typename Config >
+__cuda_callable__
+typename Grid::PointType
+getEntityCenter( const Grid & grid, const GridEntity< Grid, EntityDimension, Config > & entity )
+{
+   return entity.getCenter();
+}
+
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshTraits< MeshConfig >::PointType
+getEntityCenter( const Mesh< MeshConfig, Device > & mesh,
+                 const MeshEntity< MeshConfig, Device, Topologies::Vertex > & entity )
+{
+   return entity.getPoint();
+}
+
+/*
+ * Get an arithmetic mean of the entity's subvertices.
+ *
+ * For an simplex entity this corresponds to the centroid of the entity, but
+ * note that other shapes such as general polygons have different formulas for
+ * the centroid: https://en.wikipedia.org/wiki/Centroid#Centroid_of_a_polygon
+ */
+template< typename MeshConfig, typename Device, typename EntityTopology >
+__cuda_callable__
+typename MeshTraits< MeshConfig >::PointType
+getEntityCenter( const Mesh< MeshConfig, Device > & mesh,
+                 const MeshEntity< MeshConfig, Device, EntityTopology > & entity )
+{
+   using EntityType = MeshEntity< MeshConfig, Device, EntityTopology >;
+   constexpr typename MeshConfig::LocalIndexType subvertices = EntityType::template getSubentitiesCount< 0 >();
+   typename MeshTraits< MeshConfig >::PointType c{ 0.0 };
+   for( typename MeshConfig::LocalIndexType i = 0;
+        i < subvertices;
+        i++ )
+   {
+      const auto& v = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( i ) );
+      c += v.getPoint();
+   }
+   return ( 1.0 / subvertices ) * c;
+}
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Geometry/getEntityMeasure.h b/src/TNL/Meshes/Geometry/getEntityMeasure.h
new file mode 100644
index 0000000000000000000000000000000000000000..de61e571a4ae321200753ba086a445fd13f16b71
--- /dev/null
+++ b/src/TNL/Meshes/Geometry/getEntityMeasure.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+                          getEntityMeasure.h  -  description
+                             -------------------
+    begin                : Nov 12, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Devices/CudaCallable.h>
+#include <TNL/Meshes/GridEntity.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Quadrilateral.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Grid, typename Config >
+__cuda_callable__
+typename Grid::RealType
+getEntityMeasure( const Grid & grid, const GridEntity< Grid, 0, Config > & entity )
+{
+    // entity.getMeasure() returns 0.0 !!!
+    return 1.0;
+}
+
+template< typename Grid, int EntityDimension, typename Config >
+__cuda_callable__
+typename Grid::RealType
+getEntityMeasure( const Grid & grid, const GridEntity< Grid, EntityDimension, Config > & entity )
+{
+    return entity.getMeasure();
+}
+
+// Vertex
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshConfig::RealType
+getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
+                  const MeshEntity< MeshConfig, Device, Topologies::Vertex > & entity )
+{
+    return 1.0;
+}
+
+// TODO: move to StaticVector::norm
+template< typename Real >
+__cuda_callable__
+Real
+getVectorLength( const TNL::Containers::StaticVector< 1, Real > & vector )
+{
+    return TNL::abs( vector[ 0 ] );
+}
+
+template< int Size, typename Real >
+__cuda_callable__
+Real
+getVectorLength( const TNL::Containers::StaticVector< Size, Real > & vector )
+{
+    return TNL::sqrt( vector * vector );
+}
+
+// Edge
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshConfig::RealType
+getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
+                  const MeshEntity< MeshConfig, Device, Topologies::Edge > & entity )
+{
+    const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) );
+    const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
+    return getVectorLength( v1.getPoint() - v0.getPoint() );
+}
+
+// Triangle
+template< typename Real >
+__cuda_callable__
+Real
+getTriangleArea( const TNL::Containers::StaticVector< 2, Real > & v1,
+                 const TNL::Containers::StaticVector< 2, Real > & v2 )
+{
+    return 0.5 * TNL::abs( v1.x() * v2.y() - v1.y() * v2.x() );
+}
+
+template< typename Real >
+__cuda_callable__
+Real
+getTriangleArea( const TNL::Containers::StaticVector< 3, Real > & v1,
+                 const TNL::Containers::StaticVector< 3, Real > & v2 )
+{
+    // formula from http://math.stackexchange.com/a/128999
+    Real S = 0.0;
+    Real aux = v1.y() * v2.z() - v1.z() * v2.y();   // first component of the cross product
+    S += aux * aux;
+    aux = v1.z() * v2.x() - v1.x() * v2.z();        // second component of the cross product
+    S += aux * aux;
+    aux = v1.x() * v2.y() - v1.y() * v2.x();        // third component of the cross product
+    S += aux * aux;
+    return 0.5 * ::sqrt( S );
+}
+
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshConfig::RealType
+getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
+                  const MeshEntity< MeshConfig, Device, Topologies::Triangle > & entity )
+{
+    const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) );
+    const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
+    const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) );
+    return getTriangleArea( v2.getPoint() - v0.getPoint(), v1.getPoint() - v0.getPoint() );
+}
+
+// Quadrilateral
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshConfig::RealType
+getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
+                  const MeshEntity< MeshConfig, Device, Topologies::Quadrilateral > & entity )
+{
+    // measure = 0.5 * |AC x BD|, where AC and BD are the diagonals
+    // Hence, we can use the same formula as for the triangle area.
+    const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) );
+    const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
+    const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) );
+    const auto& v3 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 3 ) );
+    return getTriangleArea( v2.getPoint() - v0.getPoint(), v3.getPoint() - v1.getPoint() );
+}
+
+template< typename Real >
+__cuda_callable__
+Real
+getTetrahedronVolume( const TNL::Containers::StaticVector< 3, Real > & v1,
+                      const TNL::Containers::StaticVector< 3, Real > & v2,
+                      const TNL::Containers::StaticVector< 3, Real > & v3 )
+{
+    // V = (1/6) * det(v1, v2, v3)
+    const Real det = v1.x() * v2.y() * v3.z() +
+                     v1.y() * v2.z() * v3.x() +
+                     v1.z() * v2.x() * v3.y() -
+                   ( v1.z() * v2.y() * v3.x() +
+                     v1.y() * v2.x() * v3.z() +
+                     v1.x() * v2.z() * v3.y() );
+    return ( 1.0 / 6.0 ) * TNL::abs( det );
+}
+
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshConfig::RealType
+getEntityMeasure( const Mesh< MeshConfig, Device > & mesh,
+                  const MeshEntity< MeshConfig, Device, Topologies::Tetrahedron > & entity )
+{
+    const auto& v0 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 0 ) );
+    const auto& v1 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 1 ) );
+    const auto& v2 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 2 ) );
+    const auto& v3 = mesh.template getEntity< 0 >( entity.template getSubentityIndex< 0 >( 3 ) );
+    return getTetrahedronVolume( v3.getPoint() - v0.getPoint(), v2.getPoint() - v0.getPoint(), v1.getPoint() - v0.getPoint() );
+}
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/GridDetails/Grid1D.h b/src/TNL/Meshes/GridDetails/Grid1D.h
index 673eabefed5902c29787bda0ba7157a2fa552540..e2c456c83bd966beb1aef2f34ba81edb34a25828 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D.h
@@ -144,14 +144,6 @@ class Grid< 1, Real, Device, Index > : public Object
 
    bool load( const String& fileName );
 
-   bool writeMesh( const String& fileName,
-                   const String& format ) const;
-
-   template< typename MeshFunction >
-   bool write( const MeshFunction& function,
-               const String& fileName,
-               const String& format ) const;
-
    void writeProlog( Logger& logger ) const;
 
    protected:
diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
index 214dfa588f292df2d9993cba29c6c572951b74ff..47bc02fff4f64e5db49bfb0eef539808cb982e7f 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
@@ -411,61 +411,8 @@ bool Grid< 1, Real, Device, Index >::load( const String& fileName )
 }
 
 template< typename Real,
-           typename Device,
-           typename Index >
-bool Grid< 1, Real, Device, Index >::writeMesh( const String& fileName,
-                                                   const String& format ) const
-{
-   /*****
-    * TODO: implement this
-    */
-   return true;
-}
-
-template< typename Real,
-           typename Device,
-           typename Index >
-   template< typename MeshFunction >
-bool Grid< 1, Real, Device, Index >::write( const MeshFunction& function,
-                                                 const String& fileName,
-                                                 const String& format ) const
-{
-   if( this->template getEntitiesCount< Cell >() != function. getSize() )
-   {
-      std::cerr << "The size ( " << function. getSize()
-           << " ) of the mesh function does not agree with the DOFs ( "
-           << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl;
-      return false;
-   }
-   std::fstream file;
-   file. open( fileName. getString(), std::ios::out );
-   if( ! file )
-   {
-      std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
-      return false;
-   }
-   file << std::setprecision( 12 );
-   const RealType hx = getSpaceSteps(). x();
-   if( format == "gnuplot" )
-   {
-      typename ThisType::template EntityType< getMeshDimension() > entity( *this );
-      for( entity.getCoordinates().x() = 0;
-           entity.getCoordinates().x() < getDimensions(). x();
-           entity.getCoordinates().x() ++ )
-      {
-         PointType v = entity.getCenter();
-         GnuplotWriter::write( file,  v );
-         GnuplotWriter::write( file,  function[ this->getEntityIndex( entity ) ] );
-         file << std::endl;
-      }
-   }
-   file. close();
-   return true;
-}
-
-template< typename Real,
-           typename Device,
-           typename Index >
+          typename Device,
+          typename Index >
 void
 Grid< 1, Real, Device, Index >::
 writeProlog( Logger& logger ) const
diff --git a/src/TNL/Meshes/GridDetails/Grid2D.h b/src/TNL/Meshes/GridDetails/Grid2D.h
index 4c25ede692369051483c9e94e65d195b23470022..cc860f4f393bbe81001d511013aedf135d194e5f 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D.h
@@ -151,14 +151,6 @@ class Grid< 2, Real, Device, Index > : public Object
 
    bool load( const String& fileName );
 
-   bool writeMesh( const String& fileName,
-                   const String& format ) const;
-
-   template< typename MeshFunction >
-   bool write( const MeshFunction& function,
-               const String& fileName,
-               const String& format ) const;
-
    void writeProlog( Logger& logger ) const;
 
    protected:
diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
index 91ccf4e1306a6d35b47b6c919833c6eaa6e455f8..4ef0717f37158c5fa1e6703849b431ea9bc9ad9e 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
@@ -492,174 +492,6 @@ bool Grid< 2, Real, Device, Index > :: load( const String& fileName )
 template< typename Real,
           typename Device,
           typename Index >
-bool Grid< 2, Real, Device, Index > :: writeMesh( const String& fileName,
-                                                     const String& format ) const
-{
-   std::fstream file;
-   file. open( fileName. getString(), std::ios::out );
-   if( ! file )
-   {
-      std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
-      return false;
-   }
-   if( format == "asymptote" )
-   {
-      file << "size( "
-           << this->getProportions(). x() << "cm , "
-           << this->getProportions(). y() << "cm );"
-           << std::endl << std::endl;
-      Vertex vertex( *this );
-      CoordinatesType& vertexCoordinates = vertex.getCoordinates();
-      PointType v;
-      for( Index j = 0; j < this->dimensions. y(); j ++ )
-      {
-         file << "draw( ";
-         vertexCoordinates.x() = 0;
-         vertexCoordinates.y() = j;
-         v = vertex.getCenter();
-         file << "( " << v. x() << ", " << v. y() << " )";
-         for( Index i = 0; i < this->dimensions. x(); i ++ )
-         {
-            vertexCoordinates.x() = i + 1;
-            vertexCoordinates.y() = j;
-            v = vertex.getCenter();
-            file << "--( " << v. x() << ", " << v. y() << " )";
-         }
-         file << " );" << std::endl;
-      }
-      file << std::endl;
-      for( Index i = 0; i < this->dimensions. x(); i ++ )
-      {
-         file << "draw( ";
-         vertexCoordinates.x() = i;
-         vertexCoordinates.y() = 0;
-         v = vertex.getCenter();
-         file << "( " << v. x() << ", " << v. y() << " )";
-         for( Index j = 0; j < this->dimensions. y(); j ++ )
-         {
-            vertexCoordinates.x() = i;
-            vertexCoordinates.y() = j + 1;
-            v = vertex.getCenter();
-            file << "--( " << v. x() << ", " << v. y() << " )";
-         }
-         file << " );" << std::endl;
-      }
-      file << std::endl;
-
-      Cell cell( *this );
-      CoordinatesType& cellCoordinates = cell.getCoordinates();
-      const RealType cellMeasure = this->getSpaceSteps().x() * this->getSpaceSteps().y();
-      for( Index i = 0; i < this->dimensions. x(); i ++ )
-         for( Index j = 0; j < this->dimensions. y(); j ++ )
-         {
-            cellCoordinates.x() = i;
-            cellCoordinates.y() = j;
-            v = vertex.getCenter();
-            file << "label( scale(0.33) * Label( \"$" << std::setprecision( 3 ) << cellMeasure << std::setprecision( 8 )
-                 << "$\" ), ( " << v. x() << ", " << v. y() << " ), S );" << std::endl;
-         }
-
-      for( Index i = 0; i < this->dimensions. x(); i ++ )
-         for( Index j = 0; j < this->dimensions. y(); j ++ )
-         {
-            PointType v1, v2, c;
-
-            /****
-             * East edge normal
-             */
-            /*v1 = this->getPoint( CoordinatesType( i + 1, j ), v1 );
-            v2 = this->getPoint( CoordinatesType( i + 1, j + 1 ), v2 );
-            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
-            this->getEdgeNormal< 1, 0 >( CoordinatesType( i, j ), v );
-            v *= 0.5;
-            file << "draw( ( " << c. x() << ", " << c. y() << " )--( "
-                 << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl;
-            */
-            /****
-             * West edge normal
-             */
-            /*this->getPoint< -1, -1 >( CoordinatesType( i, j ), v1 );
-            this->getPoint< -1, 1 >( CoordinatesType( i, j ), v2 );
-            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
-            this->getEdgeNormal< -1, 0 >( CoordinatesType( i, j ), v );
-            v *= 0.5;
-            file << "draw( ( " << c. x() << ", " << c. y() << " )--( "
-                 << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl;
-            */
-            /****
-             * North edge normal
-             */
-            /*this->getPoint< 1, 1 >( CoordinatesType( i, j ), v1 );
-            this->getPoint< -1, 1 >( CoordinatesType( i, j ), v2 );
-            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
-            this->getEdgeNormal< 0, 1 >( CoordinatesType( i, j ), v );
-            v *= 0.5;
-            file << "draw( ( " << c. x() << ", " << c. y() << " )--( "
-                 << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl;
-            */
-            /****
-             * South edge normal
-             */
-            /*this->getPoint< 1, -1 >( CoordinatesType( i, j ), v1 );
-            this->getPoint< -1, -1 >( CoordinatesType( i, j ), v2 );
-            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
-            this->getEdgeNormal< 0, -1 >( CoordinatesType( i, j ), v );
-            v *= 0.5;
-            file << "draw( ( " << c. x() << ", " << c. y() << " )--( "
-                 << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl;
-            */
-         }
-      return true;
-   }
-   return false;
-}
-
-template< typename Real,
-           typename Device,
-           typename Index >
-   template< typename MeshFunction >
-bool Grid< 2, Real, Device, Index > :: write( const MeshFunction& function,
-                                                 const String& fileName,
-                                                 const String& format ) const
-{
-   if( this->template getEntitiesCount< Cell >() != function. getSize() )
-   {
-      std::cerr << "The size ( " << function. getSize()
-           << " ) of a mesh function does not agree with the DOFs ( "
-           << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl;
-      return false;
-   }
-   std::fstream file;
-   file. open( fileName. getString(), std::ios::out );
-   if( ! file )
-   {
-      std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
-      return false;
-   }
-   file << std::setprecision( 12 );
-   if( format == "gnuplot" )
-   {
-      Cell cell( *this );
-      CoordinatesType& cellCoordinates = cell.getCoordinates();
-      for( cellCoordinates.y() = 0; cellCoordinates.y() < getDimensions(). y(); cellCoordinates.y() ++ )
-      {
-         for( cellCoordinates.x() = 0; cellCoordinates.x() < getDimensions(). x(); cellCoordinates.x() ++ )
-         {
-            PointType v = cell.getCenter();
-            GnuplotWriter::write( file,  v );
-            GnuplotWriter::write( file,  function[ this->getEntityIndex( cell ) ] );
-            file << std::endl;
-         }
-         file << std::endl;
-      }
-   }
-   file. close();
-   return true;
-}
-
-template< typename Real,
-           typename Device,
-           typename Index >
 void
 Grid< 2, Real, Device, Index >::
 writeProlog( Logger& logger ) const
diff --git a/src/TNL/Meshes/GridDetails/Grid3D.h b/src/TNL/Meshes/GridDetails/Grid3D.h
index 6f6c1e237c673071859b7cf605ff89887c20c56a..7056e33f655197d14c4c5a61f7f79240335c5876 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D.h
@@ -142,14 +142,6 @@ class Grid< 3, Real, Device, Index > : public Object
 
    bool load( const String& fileName );
 
-   bool writeMesh( const String& fileName,
-                   const String& format ) const;
-
-   template< typename MeshFunction >
-   bool write( const MeshFunction& function,
-               const String& fileName,
-               const String& format ) const;
-
    void writeProlog( Logger& logger ) const;
 
    protected:
diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
index fa1c32dd2ba9fab60f1e9fffc9ce1d592885bfb6..e2f4f273088780dfac733d050ed547468a88639d 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
@@ -563,72 +563,9 @@ bool Grid< 3, Real, Device, Index > :: load( const String& fileName )
    return Object :: load( fileName );
 };
 
-template< typename Real,
-           typename Device,
-           typename Index >
-bool Grid< 3, Real, Device, Index >::writeMesh( const String& fileName,
-                                                   const String& format ) const
-{
-   /*****
-    * TODO: implement this
-    */
-   return true;
-}
-
 template< typename Real,
           typename Device,
           typename Index >
-   template< typename MeshFunction >
-bool Grid< 3, Real, Device, Index > :: write( const MeshFunction& function,
-                                                 const String& fileName,
-                                                 const String& format ) const
-{
-   if( this->template getEntitiesCount< Cell >() != function. getSize() )
-   {
-      std::cerr << "The size ( " << function. getSize()
-           << " ) of a mesh function does not agree with the DOFs ( " << this->template getEntitiesCount< Cell >() << " ) of a mesh." << std::endl;
-      return false;
-   }
-   std::fstream file;
-   file. open( fileName. getString(), std::ios::out );
-   if( ! file )
-   {
-      std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
-      return false;
-   }
-   file << std::setprecision( 12 );
-   if( format == "gnuplot" )
-   {
-      Cell cell( *this );
-      for( cell.getCoordinates().z() = 0;
-           cell.getCoordinates().z() < getDimensions().z();
-           cell.getCoordinates().z()++ )
-      {
-         for( cell.getCoordinates().y() = 0;
-              cell.getCoordinates().y() < getDimensions().y();
-              cell.getCoordinates().y()++ )
-         {
-            for( cell.getCoordinates().x() = 0;
-                 cell.getCoordinates().x() < getDimensions().x();
-                 cell.getCoordinates().x()++ )
-            {
-               PointType v = cell.getCenter();
-               GnuplotWriter::write( file, v );
-               GnuplotWriter::write( file, function[ this->template getEntityIndex( cell ) ] );
-               file << std::endl;
-            }
-         }
-         file << std::endl;
-      }
-   }
-
-   file. close();
-   return true;
-}
-
-template< typename Real,
-           typename Device,
-           typename Index >
 void
 Grid< 3, Real, Device, Index >::
 writeProlog( Logger& logger ) const
diff --git a/src/TNL/Meshes/GridDetails/GridEntity_impl.h b/src/TNL/Meshes/GridDetails/GridEntity_impl.h
index 8703c064fd6e2271ea3705ddb4355261edf14cd9..7c3820f6b6bdda78ea29437c7d10ebc41a172afc 100644
--- a/src/TNL/Meshes/GridDetails/GridEntity_impl.h
+++ b/src/TNL/Meshes/GridDetails/GridEntity_impl.h
@@ -675,6 +675,19 @@ getCenter() const
    return GridEntityCenterGetter< ThisType >::getEntityCenter( *this );
 }
 
+template< int Dimension,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename Config >
+__cuda_callable__ inline
+typename Meshes::Grid< Dimension, Real, Device, Index >::PointType
+GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >::
+getPoint() const
+{
+   return getCenter();
+}
+
 template< int Dimension,
           typename Real,
           typename Device,
diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h b/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h
index c8f3a999b90a08e02b9bcb2cfb29b0270476f046..2bef7d8bdffbe4f797367af3ffb49af01fb47970 100644
--- a/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h
+++ b/src/TNL/Meshes/GridDetails/NeighborGridEntitiesStorage.h
@@ -11,7 +11,7 @@
 #pragma once
 
 #include <TNL/Devices/Cuda.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
+#include <TNL/Meshes/DimensionTag.h>
 #include <TNL/Meshes/GridEntityConfig.h>
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter.h>
 
@@ -44,7 +44,7 @@ class NeighborGridEntityLayer< GridEntity, NeighborEntityDimension, GridEntityCo
       {}
  
       __cuda_callable__
-      const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< NeighborEntityDimension>& tag ) const
+      const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< NeighborEntityDimension>& tag ) const
       {
          return this->neighborEntities;
       }
@@ -76,7 +76,7 @@ class NeighborGridEntityLayer< GridEntity, 0, GridEntityConfig, true >
       {}
 
       __cuda_callable__
-      const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< 0 >& tag ) const
+      const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< 0 >& tag ) const
       {
          return this->neighborEntities;
       }
@@ -112,7 +112,7 @@ class NeighborGridEntityLayer< GridEntity, NeighborEntityDimension, GridEntityCo
       {}
 
       __cuda_callable__
-      const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< NeighborEntityDimension >& tag ) const {}
+      const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< NeighborEntityDimension >& tag ) const {}
  
       __cuda_callable__
       void refresh( const typename GridEntity::GridType& grid,
@@ -131,7 +131,7 @@ class NeighborGridEntityLayer< GridEntity, 0, GridEntityConfig, false >
       NeighborGridEntityLayer( const GridEntity& entity ){}
 
       __cuda_callable__
-      const NeighborEntityGetterType& getNeighborEntities( const MeshDimensionTag< 0 >& tag ) const {}
+      const NeighborEntityGetterType& getNeighborEntities( const DimensionTag< 0 >& tag ) const {}
  
       __cuda_callable__
       void refresh( const typename GridEntity::GridType& grid,
@@ -163,7 +163,7 @@ class NeighborGridEntitiesStorage
       const NeighborGridEntityGetter< GridEntity, EntityDimension >&
       getNeighborEntities() const
       {
-         return BaseType::getNeighborEntities( MeshDimensionTag< EntityDimension >() );
+         return BaseType::getNeighborEntities( DimensionTag< EntityDimension >() );
       }
 };
 
diff --git a/src/TNL/Meshes/GridEntity.h b/src/TNL/Meshes/GridEntity.h
index 4db50173285c267e61736a36827073dcb323a002..abad0a57d52695df4c1b34f476e2e99c523bb6ff 100644
--- a/src/TNL/Meshes/GridEntity.h
+++ b/src/TNL/Meshes/GridEntity.h
@@ -362,6 +362,10 @@ class GridEntity< Meshes::Grid< Dimension, Real, Device, Index >, 0, Config >
       __cuda_callable__ inline
       PointType getCenter() const;
 
+      // compatibility with meshes, equivalent to getCenter
+      __cuda_callable__ inline
+      PointType getPoint() const;
+
       __cuda_callable__ inline
       const RealType getMeasure() const;
  
diff --git a/src/TNL/Meshes/Mesh.h b/src/TNL/Meshes/Mesh.h
index 47060304a5072def2801b54990df03a54c368e24..55c5bca319646a16fb927e0e99c8a74a8dd21817 100644
--- a/src/TNL/Meshes/Mesh.h
+++ b/src/TNL/Meshes/Mesh.h
@@ -18,98 +18,181 @@
 
 #include <ostream>
 #include <TNL/Object.h>
+#include <TNL/Logger.h>
+#include <TNL/Containers/Vector.h>
 #include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/MeshDetails/ConfigValidator.h>
 #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
-#include <TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h>
-#include <TNL/Meshes/MeshDetails/config/MeshConfigValidator.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h>
+#include <TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h>
+#include <TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h>
+
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
 
 namespace TNL {
 namespace Meshes {
 
-template< typename MeshConfig > //,
-          //typename Device = Devices::Host >
-class Mesh : public Object/*,
-                public MeshStorageLayers< MeshConfig >*/
+template< typename MeshConfig > class Initializer;
+template< typename Mesh > class EntityStorageRebinder;
+template< typename Mesh, int Dimension > struct IndexPermutationApplier;
+
+
+template< typename MeshConfig, typename Device, typename MeshType >
+class MeshInitializableBase
+{
+   public:
+      using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+
+      // The points and cellSeeds arrays will be reset when not needed to save memory.
+      void init( typename MeshTraitsType::PointArrayType& points,
+                 typename MeshTraitsType::CellSeedArrayType& cellSeeds );
+};
+
+// The mesh cannot be initialized on CUDA GPU, so this specialization is empty.
+template< typename MeshConfig, typename MeshType >
+class MeshInitializableBase< MeshConfig, Devices::Cuda, MeshType >
+{
+};
+
+
+template< typename MeshConfig,
+          typename Device = Devices::Host >
+class Mesh
+   : public Object,
+     public ConfigValidator< MeshConfig >,
+     public MeshInitializableBase< MeshConfig, Device, Mesh< MeshConfig, Device > >,
+     public StorageLayerFamily< MeshConfig, Device >,
+     public BoundaryTags::LayerFamily< MeshConfig, Device, Mesh< MeshConfig, Device > >
 {
+      using StorageBaseType = StorageLayerFamily< MeshConfig, Device >;
+      using BoundaryTagsLayerFamily = BoundaryTags::LayerFamily< MeshConfig, Device, Mesh >;
+
    public:
- 
-      typedef MeshConfig                                        Config;
-      typedef MeshTraits< MeshConfig >                          MeshTraitsType;
-      typedef typename MeshTraitsType::DeviceType               DeviceType;
-      typedef typename MeshTraitsType::GlobalIndexType          GlobalIndexType;
-      typedef typename MeshTraitsType::LocalIndexType           LocalIndexType;
-      typedef typename MeshTraitsType::CellType                 CellType;
-      typedef typename MeshTraitsType::VertexType               VertexType;
-      typedef typename MeshTraitsType::PointType                PointType;
-      static const int dimension = MeshTraitsType::meshDimension;
-      template< int Dimension > using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >;
-      template< int Dimension > using EntityType = typename EntityTraits< Dimension >::EntityType;
+      using Config          = MeshConfig;
+      using MeshTraitsType  = MeshTraits< MeshConfig, Device >;
+      using DeviceType      = typename MeshTraitsType::DeviceType;
+      using GlobalIndexType = typename MeshTraitsType::GlobalIndexType;
+      using LocalIndexType  = typename MeshTraitsType::LocalIndexType;
+      using PointType       = typename MeshTraitsType::PointType;
+      using RealType        = typename PointType::RealType;
+      using GlobalIndexVector = Containers::Vector< GlobalIndexType, DeviceType, GlobalIndexType >;
+
+      // shortcuts, compatibility with grids
+      using HostType = Mesh< MeshConfig, Devices::Host >;
+      using CudaType = Mesh< MeshConfig, Devices::Cuda >;
+
+      template< int Dimension >
+      using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >;
+
+      template< int Dimension >
+      using EntityType = typename EntityTraits< Dimension >::EntityType;
+
+      // constructors
+      Mesh() = default;
+
+      Mesh( const Mesh& mesh );
+
+      template< typename Device_ >
+      Mesh( const Mesh< MeshConfig, Device_ >& mesh );
+
+      Mesh& operator=( const Mesh& mesh );
+
+      template< typename Device_ >
+      Mesh& operator=( const Mesh< MeshConfig, Device_ >& mesh );
+
+
+      static constexpr int getMeshDimension();
+
+      // types of common entities
+      using Cell = EntityType< getMeshDimension() >;
+      using Face = EntityType< getMeshDimension() - 1 >;
+      using Vertex = EntityType< 0 >;
 
       static String getType();
- 
+
       virtual String getTypeVirtual() const;
- 
-      static constexpr int getMeshDimension();
 
-      template< int Dimension >
-      bool entitiesAvalable() const;
- 
-      GlobalIndexType getNumberOfCells() const;
+      static String getSerializationType();
+
+      virtual String getSerializationTypeVirtual() const;
+
 
-      // TODO: rename to getEntitiesCount
       template< int Dimension >
-      GlobalIndexType getNumberOfEntities() const;
+      static constexpr bool entitiesAvailable();
 
-      CellType& getCell( const GlobalIndexType entityIndex );
+      template< int Dimension >
+      __cuda_callable__
+      GlobalIndexType getEntitiesCount() const;
 
-      const CellType& getCell( const GlobalIndexType entityIndex ) const;
+      template< int Dimension >
+      __cuda_callable__
+      EntityType< Dimension >& getEntity( const GlobalIndexType& entityIndex );
 
       template< int Dimension >
-       EntityType< Dimension >& getEntity( const GlobalIndexType entityIndex );
- 
+      __cuda_callable__
+      const EntityType< Dimension >& getEntity( const GlobalIndexType& entityIndex ) const;
+
+
+      // duplicated for compatibility with grids
+      template< typename EntityType >
+      __cuda_callable__
+      GlobalIndexType getEntitiesCount() const;
+
+      template< typename EntityType >
+      __cuda_callable__
+      EntityType& getEntity( const GlobalIndexType& entityIndex );
+
+      template< typename EntityType >
+      __cuda_callable__
+      const EntityType& getEntity( const GlobalIndexType& entityIndex ) const;
+
+
+      /*
+       * The permutations follow the definition used in the Metis library: Let M
+       * be the original mesh and M' the permuted mesh. Then entity with index i
+       * in M' is the entity with index perm[i] in M and entity with index j in
+       * M is the entity with index iperm[j] in M'.
+       */
       template< int Dimension >
-      const EntityType< Dimension >& getEntity( const GlobalIndexType entityIndex ) const;
+      void reorderEntities( const GlobalIndexVector& perm,
+                            const GlobalIndexVector& iperm );
+
 
       bool save( File& file ) const;
 
       bool load( File& file );
- 
+
       using Object::load;
       using Object::save;
- 
+
       void print( std::ostream& str ) const;
 
       bool operator==( const Mesh& mesh ) const;
 
-      // TODO: this is only for mesh intializer - remove it if possible
-      template< typename DimensionTag >
-           typename EntityTraits< DimensionTag::value >::StorageArrayType& entitiesArray();
-
- 
-      template< typename DimensionTag, typename SuperDimensionTag >
-           typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray();
- 
-      template< typename EntityTopology, typename SuperdimensionsTag >
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType&
-      getSuperentityStorageNetwork()
+      bool operator!=( const Mesh& mesh ) const;
+
+      void writeProlog( Logger& logger ) const;
+
+      DistributedMeshes::DistributedMesh< Mesh<MeshConfig,Device> >* GetDistMesh(void) const
       {
-         return entitiesStorage.template getSuperentityStorageNetwork< SuperdimensionsTag >( MeshDimensionTag< EntityTopology::dimensions >() );
-      }
- 
-      bool init( const typename MeshTraitsType::PointArrayType& points,
-                 const typename MeshTraitsType::CellSeedArrayType& cellSeeds );
- 
- 
+            return NULL;
+      };
+
    protected:
- 
-      MeshStorageLayers< MeshConfig > entitiesStorage;
- 
-      MeshConfigValidator< MeshConfig > configValidator;
+      // Methods for the mesh initializer
+      using StorageBaseType::setEntitiesCount;
+      using StorageBaseType::getSubentityStorageNetwork;
+      using StorageBaseType::getSuperentityStorageNetwork;
+
+      friend Initializer< MeshConfig >;
+
+      friend EntityStorageRebinder< Mesh >;
+
+      template< typename Mesh, int Dimension >
+      friend struct IndexPermutationApplier;
 };
 
-template< typename MeshConfig >
-std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh );
+template< typename MeshConfig, typename Device >
+std::ostream& operator<<( std::ostream& str, const Mesh< MeshConfig, Device >& mesh );
 
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Meshes/MeshBuilder.h b/src/TNL/Meshes/MeshBuilder.h
index cfa5058a280edadcfa489b971f9dbbac9e2ada98..f0d9996357d3048126d8ae8f06ca2e820aa32b39 100644
--- a/src/TNL/Meshes/MeshBuilder.h
+++ b/src/TNL/Meshes/MeshBuilder.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <TNL/Containers/Vector.h>
 #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
 
 namespace TNL {
@@ -24,101 +25,96 @@ namespace Meshes {
 template< typename Mesh >
 class MeshBuilder
 {
-	//static constexpr const char *CLASS_NAME = "MeshBuilder";
-
-   public:
-      typedef Mesh                                         MeshType;
-      typedef typename MeshType::MeshTraitsType            MeshTraitsType;
-      typedef typename MeshTraitsType::GlobalIndexType     GlobalIndexType;
-      typedef typename MeshTraitsType::LocalIndexType      LocalIndexType;
-      typedef typename MeshTraitsType::PointType           PointType;
-      typedef typename MeshTraitsType::CellTopology        CellTopology;
-      typedef typename MeshTraitsType::CellSeedType        CellSeedType;
-
-   bool setPointsCount( const GlobalIndexType& points )
+public:
+   using MeshType        = Mesh;
+   using MeshTraitsType  = typename MeshType::MeshTraitsType;
+   using GlobalIndexType = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType  = typename MeshTraitsType::LocalIndexType;
+   using PointType       = typename MeshTraitsType::PointType;
+   using CellTopology    = typename MeshTraitsType::CellTopology;
+   using CellSeedType    = typename MeshTraitsType::CellSeedType;
+
+   void setPointsCount( const GlobalIndexType& points )
    {
-      TNL_ASSERT( 0 <= points, std::cerr << "pointsCount = " << points );
       this->points.setSize( points );
       this->pointsSet.setSize( points );
       pointsSet.setValue( false );
-      return true;
    }
- 
-   bool setCellsCount( const GlobalIndexType& cellsCount )
+
+   void setCellsCount( const GlobalIndexType& cellsCount )
    {
-      TNL_ASSERT( 0 <= cellsCount, std::cerr << "cellsCount = " << cellsCount );
       this->cellSeeds.setSize( cellsCount );
-      return true;
    }
- 
-   GlobalIndexType getPointsCount() const { return this->points.getSize(); }
-	
-   GlobalIndexType getCellsCount() const  { return this->cellSeeds.getSize(); }
 
-   void setPoint( GlobalIndexType index,
-                 const PointType& point )
+   GlobalIndexType getPointsCount() const
+   {
+      return this->points.getSize();
+   }
+
+   GlobalIndexType getCellsCount() const
    {
-	TNL_ASSERT( 0 <= index && index < getPointsCount(), std::cerr << "Index = " << index );
+      return this->cellSeeds.getSize();
+   }
 
-        this->points[ index ] = point;
-        this->pointsSet[ index ] = true;
+   void setPoint( GlobalIndexType index,
+                  const PointType& point )
+   {
+      this->points[ index ] = point;
+      this->pointsSet[ index ] = true;
    }
 
    CellSeedType& getCellSeed( GlobalIndexType index )
    {
-      TNL_ASSERT( 0 <= index && index < getCellsCount(), std::cerr << "Index = " << index );
- 
       return this->cellSeeds[ index ];
    }
 
-   bool build( MeshType& mesh ) const
+   bool build( MeshType& mesh )
    {
       if( ! this->validate() )
          return false;
-      if( ! mesh.init( this->points, this->cellSeeds ) )
-         return false;
+      mesh.init( this->points, this->cellSeeds );
       return true;
    }
 
-   private:
-      typedef typename MeshTraitsType::PointArrayType    PointArrayType;
-      typedef typename MeshTraitsType::CellSeedArrayType CellSeedArrayType;
-
-      bool validate() const
-      {
-         if( !allPointsSet() )
-         {
-            std::cerr << "Mesh builder error: Not all points were set." << std::endl;
-            return false;
-         }
+private:
+   using PointArrayType    = typename MeshTraitsType::PointArrayType;
+   using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType;
+   using BoolVector        = Containers::Vector< bool, Devices::Host, GlobalIndexType >;
 
-         for( GlobalIndexType i = 0; i < getCellsCount(); i++ )
-         {
-            auto cornerIds = this->cellSeeds[ i ].getCornerIds();
-            for( LocalIndexType j = 0; j < cornerIds.getSize(); j++ )
-               if( cornerIds[ j ] < 0 || getPointsCount() <= cornerIds[ j ] )
-               {
-                  std::cerr << "Cell seed " << i << " is referencing unavailable point " << cornerIds[ j ] << std::endl;
-                  return false;
-               }
-         }
-         return true;
+   bool validate() const
+   {
+      if( pointsSet.min() != true ) {
+         std::cerr << "Mesh builder error: Not all points were set." << std::endl;
+         return false;
       }
 
+      BoolVector assignedPoints;
+      assignedPoints.setLike( pointsSet );
+      assignedPoints.setValue( false );
 
-      bool allPointsSet() const
-      {
-         for( GlobalIndexType i = 0; i < this->points.getSize(); i++ )
-            if (! this->pointsSet[ i ] )
+      for( GlobalIndexType i = 0; i < getCellsCount(); i++ ) {
+         const auto cornerIds = this->cellSeeds[ i ].getCornerIds();
+         for( LocalIndexType j = 0; j < cornerIds.getSize(); j++ ) {
+            assignedPoints[ cornerIds[ j ] ] = true;
+            if( cornerIds[ j ] < 0 || getPointsCount() <= cornerIds[ j ] ) {
+               std::cerr << "Cell seed " << i << " is referencing unavailable point " << cornerIds[ j ] << std::endl;
                return false;
-         return true;
+            }
+         }
+      }
+
+      if( assignedPoints.min() != true ) {
+         std::cerr << "Mesh builder error: Some points were not used for cells." << std::endl;
+         return false;
       }
 
-      PointArrayType points;
-      CellSeedArrayType cellSeeds;
-      Containers::Array< bool, Devices::Host, GlobalIndexType > pointsSet;
+      return true;
+   }
+
+   PointArrayType points;
+   CellSeedArrayType cellSeeds;
+   BoolVector pointsSet;
 };
 
 } // namespace Meshes
 } // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshConfigBase.h b/src/TNL/Meshes/MeshConfigBase.h
deleted file mode 100644
index 523afce5b6d84824632eb1b9fd9d01c35ea2ffcb..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshConfigBase.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/***************************************************************************
-                          MeshConfigBase.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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
-
-namespace TNL {
-namespace Meshes {
-
-/****
- * Basic structure for mesh configuration.
- * Setting Id to GlobalIndex enables storage of entity Id.
- * It means that each mesh entity stores its index in its
- * mesh storage layer.
- */
-template< typename Cell,
-          int WorldDimension = Cell::dimensions,
-          typename Real = double,
-          typename GlobalIndex = int,
-          typename LocalIndex = GlobalIndex,
-          typename Id = void >
-struct MeshConfigBase
-{
-   typedef Cell        CellTopology;
-   typedef Real        RealType;
-   typedef GlobalIndex GlobalIndexType;
-   typedef LocalIndex  LocalIndexType;
-   typedef Id          IdType;
-
-   static const int worldDimension = WorldDimension;
-   static const int meshDimension = Cell::dimensions;
-
-   static String getType()
-   {
-      return String( "MeshConfigBase< >");
-   };
- 
-   /****
-    * Storage of mesh entities.
-    */
-	static constexpr bool entityStorage( int dimensions )
-	{
-      /****
-       *  Vertices and cells must always be stored
-       */
-      return true;
-		//return ( dimensions == 0 || dimensions == cellDimension );
-	}
- 
-   /****
-    *  Storage of subentities of mesh entities
-    */
-	template< typename MeshEntity >
-	static constexpr bool subentityStorage( MeshEntity, int SubentityDimension )
-	{
-      /****
-       *  Vertices must always be stored
-       */
-      return true;
-		//return ( SubentityDimension == 0 );
-	}
-
-	/****
-    * Storage of subentity orientations of mesh entities.
-    * It must be false for vertices and cells.
-    */
-	template< typename MeshEntity >
-	static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension )
-	{
-		return ( SubentityDimension > 0 );
-	}
-
-	/****
-    *  Storage of superentities of mesh entities
-    */
-	template< typename MeshEntity >
-	static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension )
-	{
-      return true;
-		//return false;
-	}
- 
-   static_assert( WorldDimension >= Cell::dimensions, "The number of the cell dimensions cannot be larger than the world dimension." );
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/CMakeLists.txt
index 95862f45e781e8be0a3fa163042abf121bcbc9b3..7e6b56e832798053c25c3bac527f2bebba90b586 100644
--- a/src/TNL/Meshes/MeshDetails/CMakeLists.txt
+++ b/src/TNL/Meshes/MeshDetails/CMakeLists.txt
@@ -1,21 +1,18 @@
-ADD_SUBDIRECTORY( config )
 ADD_SUBDIRECTORY( initializer )
-ADD_SUBDIRECTORY( layers )
+ADD_SUBDIRECTORY( EntityLayers )
+ADD_SUBDIRECTORY( MeshLayers )
 ADD_SUBDIRECTORY( traits )
 
-SET( headers MeshEntityId.h
-             MeshEntityIntegrityChecker.h
+SET( headers ConfigValidator.h
+             EntityStorageRebinder.h
+             IndexPermutationApplier.h
+             MeshEntityIndex.h
              MeshEntityOrientation.h
+             MeshEntityReferenceOrientation.h
              MeshEntity_impl.h
              MeshIntegrityChecker.h
              MeshIntegrityCheckerLayer.h
-             MeshReaderNetgen.h
-             MeshWriterNetgen.h
-             MeshWriterVTKLegacy.h
-             Mesh_impl.h )
+             Mesh_impl.h
+             Traverser_impl.h )
 
-SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes/MeshDetails )    
-SET( tnl_mesh_SOURCES ${tnl_mesh_griddetails_SOURCES} 
-     PARENT_SCOPE )
-
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails )
\ No newline at end of file
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails )
diff --git a/src/TNL/Meshes/MeshDetails/ConfigValidator.h b/src/TNL/Meshes/MeshDetails/ConfigValidator.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f27538383a012b2aebc2be2be78bf9817c0c039
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/ConfigValidator.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+                          ConfigValidator.h  -  description
+                             -------------------
+    begin                : Aug 14, 2015
+    copyright            : (C) 2015 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/Topologies/SubentityVertexMap.h>
+#include <TNL/Meshes/DimensionTag.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename EntityTopology,
+          typename DimensionTag >
+class ConfigValidatorSubtopologyLayer
+   : public ConfigValidatorSubtopologyLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement >
+{
+   static_assert( ! MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ) ||
+                    MeshConfig::entityStorage( EntityTopology::dimension ),
+                  "entities of which subentities are stored must be stored" );
+   static_assert( ! MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ) ||
+                    MeshConfig::entityStorage( DimensionTag::value ),
+                  "entities that are stored as subentities must be stored");
+   static_assert( ! MeshConfig::subentityOrientationStorage( EntityTopology(), DimensionTag::value ) ||
+                    MeshConfig::subentityStorage( EntityTopology(), DimensionTag::value ),
+                  "orientation can be stored only for subentities that are stored");
+};
+
+template< typename MeshConfig,
+          typename EntityTopology >
+class ConfigValidatorSubtopologyLayer< MeshConfig, EntityTopology, DimensionTag< 0 > >
+{
+   static_assert( ! MeshConfig::subentityStorage( EntityTopology(), 0 ) ||
+                    MeshConfig::entityStorage( EntityTopology::dimension ),
+                  "entities of which subvertices are stored must be stored" );
+   static_assert( ! MeshConfig::subentityOrientationStorage( EntityTopology(), 0 ),
+                  "storage of vertex orientation does not make sense" );
+};
+
+
+template< typename MeshConfig,
+          typename EntityTopology,
+          typename DimensionTag >
+class ConfigValidatorSupertopologyLayer
+   : public ConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement >
+{
+   static_assert( ! MeshConfig::superentityStorage( EntityTopology(), DimensionTag::value ) ||
+                    MeshConfig::entityStorage( EntityTopology::dimension ),
+                  "entities of which superentities are stored must be stored");
+   static_assert( ! MeshConfig::superentityStorage( EntityTopology(), DimensionTag::value ) ||
+                    MeshConfig::entityStorage( DimensionTag::value ),
+                  "entities that are stored as superentities must be stored");
+};
+
+template< typename MeshConfig,
+          typename EntityTopology >
+class ConfigValidatorSupertopologyLayer< MeshConfig, EntityTopology, DimensionTag< EntityTopology::dimension > >
+{};
+
+
+template< typename MeshConfig, int dimension >
+class ConfigValidatorLayer
+   : public ConfigValidatorLayer< MeshConfig, dimension - 1 >,
+     public ConfigValidatorSubtopologyLayer< MeshConfig,
+                                             typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology,
+                                             DimensionTag< dimension - 1 > >,
+     public ConfigValidatorSupertopologyLayer< MeshConfig,
+                                               typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology,
+                                               DimensionTag< MeshConfig::CellTopology::dimension > >
+{
+   using Topology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, dimension >::Topology;
+
+   static_assert( ! MeshConfig::entityStorage( dimension ) ||
+                    MeshConfig::subentityStorage( Topology(), 0 ),
+                  "subvertices of all stored entities must be stored");
+};
+
+template< typename MeshConfig >
+class ConfigValidatorLayer< MeshConfig, 0 >
+{
+};
+
+template< typename MeshConfig >
+class ConfigValidatorLayerCell
+   : public ConfigValidatorLayer< MeshConfig, MeshConfig::CellTopology::dimension - 1 >,
+     public ConfigValidatorSubtopologyLayer< MeshConfig,
+                                             typename MeshConfig::CellTopology,
+                                             DimensionTag< MeshConfig::CellTopology::dimension - 1 > >
+{
+   using CellTopology = typename MeshConfig::CellTopology;
+   static constexpr int dimension = CellTopology::dimension;
+
+   static_assert( ! MeshConfig::entityStorage( dimension ) ||
+                    MeshConfig::subentityStorage( CellTopology(), 0 ),
+                  "subvertices of all stored entities must be stored" );
+};
+
+template< typename MeshConfig >
+class ConfigValidator
+   : public ConfigValidatorLayerCell< MeshConfig >
+{
+   static constexpr int meshDimension = MeshConfig::CellTopology::dimension;
+
+   static_assert( 1 <= meshDimension, "zero dimensional meshes are not supported" );
+   static_assert( meshDimension <= MeshConfig::worldDimension, "world dimension must not be less than mesh dimension" );
+
+   static_assert( MeshConfig::entityStorage( 0 ), "mesh vertices must be stored" );
+   static_assert( MeshConfig::entityStorage( meshDimension ), "mesh cells must be stored" );
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a53be02ead6d8dea884e6d7ab7f5f926a2617286
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/EntityLayers/CMakeLists.txt
@@ -0,0 +1,5 @@
+SET( headers SubentityAccess.h
+             SuperentityAccess.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/EntityLayers )
diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h b/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h
new file mode 100644
index 0000000000000000000000000000000000000000..4adc400d450d26dff4af235f11334d58249a28c9
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h
@@ -0,0 +1,419 @@
+/***************************************************************************
+                          SubentityAccess.h  -  description
+                             -------------------
+    begin                : Oct 26, 2016
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/File.h>
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h>
+#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag,
+          bool SubentityStorage =
+               WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, DimensionTag >::storageEnabled,
+          bool SubentityOrientationStorage =
+               MeshConfig::subentityOrientationStorage( EntityTopology(), DimensionTag::value ) >
+class SubentityAccessLayer;
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SubentityAccessLayerFamily
+   : public SubentityAccessLayer< MeshConfig,
+                                  Device,
+                                  EntityTopology,
+                                  Meshes::DimensionTag< 0 > >
+{
+   using BaseType = SubentityAccessLayer< MeshConfig,
+                                          Device,
+                                          EntityTopology,
+                                          Meshes::DimensionTag< 0 > >;
+
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+
+   template< int Subdimension >
+   using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >;
+
+public:
+   template< int Subdimension >
+   __cuda_callable__
+   void bindSubentitiesStorageNetwork( const typename SubentityTraits< Subdimension >::SubentityAccessorType& storage )
+   {
+      static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to bind subentities which are not configured for storage." );
+      BaseType::bindSubentitiesStorageNetwork( Meshes::DimensionTag< Subdimension >(),
+                                               storage );
+   }
+
+   template< int Subdimension >
+   static constexpr typename MeshTraitsType::LocalIndexType getSubentitiesCount()
+   {
+      return SubentityTraits< Subdimension >::count;
+   }
+
+   template< int Subdimension >
+   __cuda_callable__
+   void setSubentityIndex( const typename MeshTraitsType::LocalIndexType& localIndex,
+                           const typename MeshTraitsType::GlobalIndexType& globalIndex )
+   {
+      static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to set subentity which is not configured for storage." );
+      BaseType::setSubentityIndex( Meshes::DimensionTag< Subdimension >(),
+                                   localIndex,
+                                   globalIndex );
+   }
+
+   template< int Subdimension >
+   __cuda_callable__
+   typename MeshTraitsType::GlobalIndexType
+   getSubentityIndex( const typename MeshTraitsType::LocalIndexType localIndex ) const
+   {
+      static_assert( SubentityTraits< Subdimension >::storageEnabled, "You try to get subentity which is not configured for storage." );
+      return BaseType::getSubentityIndex( Meshes::DimensionTag< Subdimension >(),
+                                          localIndex );
+   }
+
+   template< int Subdimension >
+   __cuda_callable__
+   typename SubentityTraits< Subdimension >::OrientationArrayType& subentityOrientationsArray()
+   {
+      static_assert( SubentityTraits< Subdimension >::orientationEnabled, "You try to get subentity orientation which is not configured for storage." );
+      return BaseType::subentityOrientationsArray( Meshes::DimensionTag< Subdimension >() );
+   }
+
+   template< int Subdimension >
+   __cuda_callable__
+   typename SubentityTraits< Subdimension >::IdPermutationArrayType getSubentityOrientation( typename MeshTraitsType::LocalIndexType index ) const
+   {
+      static_assert( SubentityTraits< Subdimension >::orientationEnabled, "You try to get subentity orientation which is not configured for storage." );
+      return BaseType::getSubentityOrientation( Meshes::DimensionTag< Subdimension >(), index );
+   }
+
+   __cuda_callable__
+   bool operator==( const SubentityAccessLayerFamily& other ) const
+   {
+      return BaseType::operator==( other );
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+   }
+};
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag >
+class SubentityAccessLayer< MeshConfig,
+                            Device,
+                            EntityTopology,
+                            DimensionTag,
+                            true,
+                            true >
+   : public SubentityAccessLayer< MeshConfig,
+                                  Device,
+                                  EntityTopology,
+                                  typename DimensionTag::Increment >
+{
+   using BaseType = SubentityAccessLayer< MeshConfig,
+                                          Device,
+                                          EntityTopology,
+                                          typename DimensionTag::Increment >;
+
+   using MeshTraitsType         = MeshTraits< MeshConfig, Device >;
+   using SubentityTraitsType    = typename MeshTraitsType::template SubentityTraits< EntityTopology, DimensionTag::value >;
+
+protected:
+   using GlobalIndexType        = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType         = typename MeshTraitsType::LocalIndexType;
+   using SubentityAccessorType  = typename SubentityTraitsType::SubentityAccessorType;
+   using OrientationArrayType   = typename SubentityTraitsType::OrientationArrayType;
+   using IdPermutationArrayType = typename SubentityTraitsType::IdPermutationArrayType;
+
+   SubentityAccessLayer() = default;
+
+   __cuda_callable__
+   explicit SubentityAccessLayer( const SubentityAccessLayer& layer )
+      : BaseType( layer )
+   {
+      this->subentityIndices.bind( layer.subentityIndices );
+   }
+
+   __cuda_callable__
+   SubentityAccessLayer& operator=( const SubentityAccessLayer& layer )
+   {
+      BaseType::operator=( layer );
+      this->subentityIndices.bind( layer.subentityIndices );
+      return *this;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+      str << "\t Subentities with dimension " << DimensionTag::value << " are: " << subentityIndices << "." << std::endl;
+   }
+
+   __cuda_callable__
+   bool operator==( const SubentityAccessLayer& layer ) const
+   {
+      return ( BaseType::operator==( layer ) &&
+               subentityIndices == layer.subentityIndices );
+   }
+
+   /****
+    * Make visible setters and getters of the lower subentities
+    */
+   using BaseType::bindSubentitiesStorageNetwork;
+   using BaseType::getSubentityIndex;
+   using BaseType::setSubentityIndex;
+   using BaseType::getSubentityIndices;
+
+   /****
+    * Define setter/getter for the current level of the subentities
+    */
+   __cuda_callable__
+   void bindSubentitiesStorageNetwork( DimensionTag,
+                                       const SubentityAccessorType& storage )
+   {
+      this->subentityIndices.bind( storage );
+   }
+
+   __cuda_callable__
+   void setSubentityIndex( DimensionTag,
+                           const LocalIndexType localIndex,
+                           const GlobalIndexType globalIndex )
+   {
+      this->subentityIndices[ localIndex ] = globalIndex;
+   }
+
+   __cuda_callable__
+   GlobalIndexType getSubentityIndex( DimensionTag,
+                                      const LocalIndexType localIndex ) const
+   {
+      return this->subentityIndices[ localIndex ];
+   }
+
+   __cuda_callable__
+   const SubentityAccessorType& getSubentityIndices( DimensionTag ) const
+   {
+      return this->subentityIndices;
+   }
+
+   __cuda_callable__
+   SubentityAccessorType& getSubentityIndices( DimensionTag )
+   {
+      return this->subentityIndices;
+   }
+
+   using BaseType::getSubentityOrientation;
+   __cuda_callable__
+   const IdPermutationArrayType& getSubentityOrientation( DimensionTag, LocalIndexType index) const
+   {
+      TNL_ASSERT_GE( index, 0, "index must be non-negative" );
+      TNL_ASSERT_LT( index, SubentityTraitsType::count, "index is out of bounds" );
+      return this->subentityOrientations[ index ].getSubvertexPermutation();
+   }
+
+   using BaseType::subentityOrientationsArray;
+   __cuda_callable__
+	OrientationArrayType& subentityOrientationsArray( DimensionTag ) { return this->subentityOrientations; }
+
+private:
+   SubentityAccessorType subentityIndices;
+
+   OrientationArrayType subentityOrientations;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag >
+class SubentityAccessLayer< MeshConfig,
+                            Device,
+                            EntityTopology,
+                            DimensionTag,
+                            true,
+                            false >
+   : public SubentityAccessLayer< MeshConfig,
+                                  Device,
+                                  EntityTopology,
+                                  typename DimensionTag::Increment >
+{
+   static_assert( DimensionTag::value < EntityTopology::dimension, "" );
+   using BaseType = SubentityAccessLayer< MeshConfig,
+                                          Device,
+                                          EntityTopology,
+                                          typename DimensionTag::Increment >;
+
+   using MeshTraitsType        = MeshTraits< MeshConfig, Device >;
+   using SubentityTraitsType   = typename MeshTraitsType::template SubentityTraits< EntityTopology, DimensionTag::value >;
+
+protected:
+   using GlobalIndexType       = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
+   using SubentityAccessorType = typename SubentityTraitsType::SubentityAccessorType;
+
+   SubentityAccessLayer() = default;
+
+   __cuda_callable__
+   explicit SubentityAccessLayer( const SubentityAccessLayer& layer )
+      : BaseType( layer )
+   {
+      this->subentityIndices.bind( layer.subentityIndices );
+   }
+
+   __cuda_callable__
+   SubentityAccessLayer& operator=( const SubentityAccessLayer& layer )
+   {
+      BaseType::operator=( layer );
+      this->subentityIndices.bind( layer.subentityIndices );
+      return *this;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+      str << "\t Subentities with dimension " << DimensionTag::value << " are: " << subentityIndices << "." << std::endl;
+   }
+
+   __cuda_callable__
+   bool operator==( const SubentityAccessLayer& layer ) const
+   {
+      return ( BaseType::operator==( layer ) &&
+               subentityIndices == layer.subentityIndices );
+   }
+
+   /****
+    * Make visible setters and getters of the lower subentities
+    */
+   using BaseType::bindSubentitiesStorageNetwork;
+   using BaseType::getSubentityIndex;
+   using BaseType::setSubentityIndex;
+   using BaseType::getSubentityIndices;
+
+   /****
+    * Define setter/getter for the current level of the subentities
+    */
+   __cuda_callable__
+   void bindSubentitiesStorageNetwork( DimensionTag,
+                                       const SubentityAccessorType& storage )
+   {
+      this->subentityIndices.bind( storage );
+   }
+
+   __cuda_callable__
+   void setSubentityIndex( DimensionTag,
+                           const LocalIndexType localIndex,
+                           const GlobalIndexType globalIndex )
+   {
+      this->subentityIndices[ localIndex ] = globalIndex;
+   }
+
+   __cuda_callable__
+   GlobalIndexType getSubentityIndex( DimensionTag,
+                                      const LocalIndexType localIndex ) const
+   {
+      return this->subentityIndices[ localIndex ];
+   }
+
+   __cuda_callable__
+   const SubentityAccessorType& getSubentityIndices( DimensionTag ) const
+   {
+      return this->subentityIndices;
+   }
+
+   __cuda_callable__
+   SubentityAccessorType& getSubentityIndices( DimensionTag )
+   {
+      return this->subentityIndices;
+   }
+
+private:
+   SubentityAccessorType subentityIndices;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag,
+          bool SubentityOrientationStorage >
+class SubentityAccessLayer< MeshConfig,
+                            Device,
+                            EntityTopology,
+                            DimensionTag,
+                            false,
+                            SubentityOrientationStorage >
+   : public SubentityAccessLayer< MeshConfig,
+                                  Device,
+                                  EntityTopology,
+                                  typename DimensionTag::Increment >
+{
+};
+
+// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSubentityStorageTrait)
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          bool SubentityOrientationStorage >
+class SubentityAccessLayer< MeshConfig,
+                            Device,
+                            EntityTopology,
+                            Meshes::DimensionTag< EntityTopology::dimension >,
+                            false,
+                            SubentityOrientationStorage >
+{
+   using DimensionTag = Meshes::DimensionTag< EntityTopology::dimension >;
+
+protected:
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType  = typename MeshConfig::LocalIndexType;
+
+   /***
+    * Necessary because of 'using BaseType::...;' in the derived classes
+    */
+   template< typename SubentityAccessorType >
+   __cuda_callable__
+   void bindSubentitiesStorageNetwork( DimensionTag,
+                                       const SubentityAccessorType& storage ) {}
+   __cuda_callable__
+   void getSubentityIndex( DimensionTag,
+                           const LocalIndexType localIndex ) const {}
+   __cuda_callable__
+   void setSubentityIndex( DimensionTag,
+                           const LocalIndexType& localIndex,
+                           const GlobalIndexType& globalIndex ) {}
+   __cuda_callable__
+   void getSubentityIndices() {}
+
+   template< typename LocalIndexType >
+   __cuda_callable__
+   void getSubentityOrientation( DimensionTag, LocalIndexType index) const {}
+   __cuda_callable__
+	void subentityOrientationsArray( DimensionTag ) {}
+
+   __cuda_callable__
+   bool operator==( const SubentityAccessLayer& other ) const
+   {
+      return true;
+   }
+
+   void print( std::ostream& str ) const {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h b/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h
new file mode 100644
index 0000000000000000000000000000000000000000..47457181651a631d6ccce3bcba216c78be18e38d
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h
@@ -0,0 +1,288 @@
+/***************************************************************************
+                          SuperentityAccess.h  -  description
+                             -------------------
+    begin                : Aug 15, 2015
+    copyright            : (C) 2015 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/MeshTraits.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag,
+          bool SuperentityStorage = WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, DimensionTag >::storageEnabled >
+class SuperentityAccessLayer;
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SuperentityAccessLayerFamily
+   : public SuperentityAccessLayer< MeshConfig,
+                                    Device,
+                                    EntityTopology,
+                                    Meshes::DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >
+{
+   using BaseType = SuperentityAccessLayer< MeshConfig,
+                                            Device,
+                                            EntityTopology,
+                                            Meshes::DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >;
+
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+
+   template< int Superdimension >
+   using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >;
+
+public:
+   template< int Superdimension >
+   __cuda_callable__
+   void bindSuperentitiesStorageNetwork( const typename SuperentityTraits< Superdimension >::SuperentityAccessorType& storage )
+   {
+      static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to bind superentities which are not configured for storage." );
+      BaseType::bindSuperentitiesStorageNetwork( Meshes::DimensionTag< Superdimension >(),
+                                                 storage );
+   }
+
+   template< int Superdimension >
+   __cuda_callable__
+   void setNumberOfSuperentities( const typename MeshTraitsType::LocalIndexType size )
+   {
+      static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to set number of superentities which are not configured for storage." );
+      BaseType::setNumberOfSuperentities( Meshes::DimensionTag< Superdimension >(),
+                                          size );
+   }
+
+   template< int Superdimension >
+   __cuda_callable__
+   typename MeshTraitsType::LocalIndexType
+   getSuperentitiesCount() const
+   {
+      static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to get number of superentities which are not configured for storage." );
+      return BaseType::getSuperentitiesCount( Meshes::DimensionTag< Superdimension >() );
+   }
+
+   template< int Superdimension >
+   __cuda_callable__
+   void
+   setSuperentityIndex( const typename MeshTraitsType::LocalIndexType& localIndex,
+                        const typename MeshTraitsType::GlobalIndexType& globalIndex )
+   {
+      static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to set superentities which are not configured for storage." );
+      BaseType::setSuperentityIndex( Meshes::DimensionTag< Superdimension >(),
+                                     localIndex,
+                                     globalIndex );
+   }
+
+   template< int Superdimension >
+   __cuda_callable__
+   typename MeshTraitsType::GlobalIndexType
+   getSuperentityIndex( const typename MeshTraitsType::LocalIndexType localIndex ) const
+   {
+      static_assert( SuperentityTraits< Superdimension >::storageEnabled, "You try to get superentities which are not configured for storage." );
+      return BaseType::getSuperentityIndex( Meshes::DimensionTag< Superdimension >(),
+                                            localIndex );
+   }
+
+   __cuda_callable__
+   bool operator==( const SuperentityAccessLayerFamily& other ) const
+   {
+      return BaseType::operator==( other );
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+   }
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag >
+class SuperentityAccessLayer< MeshConfig,
+                              Device,
+                              EntityTopology,
+                              DimensionTag,
+                              true >
+   : public SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement >
+{
+	using BaseType = SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement >;
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+   using SuperentityTraitsType = typename MeshTraitsType::template SuperentityTraits< EntityTopology, DimensionTag::value >;
+
+public:
+   using GlobalIndexType         = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType          = typename MeshTraitsType::LocalIndexType;
+   using SuperentityAccessorType = typename SuperentityTraitsType::SuperentityAccessorType;
+
+   /****
+     * Make visible setters and getters of the lower superentities
+     */
+   using BaseType::bindSuperentitiesStorageNetwork;
+   using BaseType::setNumberOfSuperentities;
+   using BaseType::getSuperentitiesCount;
+   using BaseType::setSuperentityIndex;
+   using BaseType::getSuperentityIndex;
+   using BaseType::getSuperentityIndices;
+
+   SuperentityAccessLayer() = default;
+
+   __cuda_callable__
+   explicit SuperentityAccessLayer( const SuperentityAccessLayer& layer )
+      : BaseType( layer )
+   {
+      this->superentityIndices.bind( layer.superentityIndices );
+   }
+
+   __cuda_callable__
+   SuperentityAccessLayer& operator=( const SuperentityAccessLayer& layer )
+   {
+      BaseType::operator=( layer );
+      this->superentityIndices.bind( layer.superentityIndices );
+      return *this;
+   }
+
+   /****
+    * Define setter/getter for the current level of the superentities
+    */
+   __cuda_callable__
+   void bindSuperentitiesStorageNetwork( DimensionTag,
+                                         const SuperentityAccessorType& storage )
+   {
+      this->superentityIndices.bind( storage );
+   }
+
+   __cuda_callable__
+   void setNumberOfSuperentities( DimensionTag,
+                                  const LocalIndexType size )
+   {
+      this->superentityIndices.setSize( size );
+   }
+
+   __cuda_callable__
+   LocalIndexType getSuperentitiesCount( DimensionTag ) const
+   {
+      return this->superentityIndices.getSize();
+   }
+
+   __cuda_callable__
+   void setSuperentityIndex( DimensionTag,
+                             const LocalIndexType& localIndex,
+                             const GlobalIndexType& globalIndex )
+   {
+      this->superentityIndices[ localIndex ] = globalIndex;
+   }
+
+   __cuda_callable__
+   GlobalIndexType getSuperentityIndex( DimensionTag,
+                                        const LocalIndexType localIndex ) const
+   {
+      return this->superentityIndices[ localIndex ];
+   }
+
+   __cuda_callable__
+   const SuperentityAccessorType& getSuperentityIndices( DimensionTag ) const
+   {
+      return this->superentityIndices;
+   }
+
+   __cuda_callable__
+   SuperentityAccessorType& getSuperentityIndices( DimensionTag )
+   {
+      return this->superentityIndices;
+   }
+
+   __cuda_callable__
+   bool operator==( const SuperentityAccessLayer& other ) const
+   {
+      return ( BaseType::operator==( other ) && superentityIndices == other.superentityIndices );
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+      str << "\t Superentities with dimension " << DimensionTag::value << " are: " << this->superentityIndices << "." << std::endl;
+   }
+
+private:
+   SuperentityAccessorType superentityIndices;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename DimensionTag >
+class SuperentityAccessLayer< MeshConfig,
+                              Device,
+                              EntityTopology,
+                              DimensionTag,
+                              false >
+   : public SuperentityAccessLayer< MeshConfig, Device, EntityTopology, typename DimensionTag::Decrement >
+{
+};
+
+// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSuperentityStorageTrait)
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SuperentityAccessLayer< MeshConfig,
+                              Device,
+                              EntityTopology,
+                              Meshes::DimensionTag< EntityTopology::dimension >,
+                              false >
+{
+   using DimensionTag = Meshes::DimensionTag< EntityTopology::dimension >;
+
+protected:
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType  = typename MeshConfig::LocalIndexType;
+
+   /***
+    * Necessary because of 'using BaseType::...;' in the derived classes
+    */
+   template< typename SuperentityAccessorType >
+   __cuda_callable__
+   void bindSuperentitiesStorageNetwork( DimensionTag,
+                                         const SuperentityAccessorType& storage ) {}
+   __cuda_callable__
+   void setNumberOfSuperentities( DimensionTag,
+                                  const LocalIndexType size ) {}
+   __cuda_callable__
+   void getSuperentitiesCount( DimensionTag ) const {}
+   __cuda_callable__
+   void getSuperentityIndex( DimensionTag,
+                             const LocalIndexType localIndex ) const {}
+   __cuda_callable__
+   void setSuperentityIndex( DimensionTag,
+                             const LocalIndexType& localIndex,
+                             const GlobalIndexType& globalIndex ) {}
+   __cuda_callable__
+   void getSuperentityIndices() {}
+
+   __cuda_callable__
+   bool operator==( const SuperentityAccessLayer& other ) const
+   {
+      return true;
+   }
+
+   void print( std::ostream& str ) const {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h b/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5c6516cc8936c953a71c265bc024a323a41afb7
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/EntityStorageRebinder.h
@@ -0,0 +1,159 @@
+/***************************************************************************
+                          EntityStorageRebinder.h  -  description
+                             -------------------
+    begin                : Oct 22, 2016
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+/*
+ * Everything in this file is basically just a templatized version of the
+ * following pseudo-code (which does not work because normal variables are not
+ * usable in template arguments):
+ *
+ *   for( int dimension = 0; dimension < MeshTraitsType::meshDimension; dimension++ )
+ *      for( int superdimension = dimension + 1; superdimension <= MeshTraitsType::meshDimension; superdimension++ )
+ *         if( EntityTraits< dimension >::SuperentityTraits< superdimension >::storageEnabled )
+ *            for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< dimension >(); i++ )
+ *            {
+ *               auto& entity = mesh.template getEntity< dimension >( i );
+ *               entity.template bindSuperentitiesStorageNetwork< superdimension >( mesh.template getSuperentityStorageNetwork< superdimension >().getValues( i ) );
+ *            }
+ */
+
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/DevicePointer.h>
+#include <TNL/ParallelFor.h>
+#include <TNL/StaticFor.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Mesh >
+class EntityStorageRebinder
+{
+   using IndexType = typename Mesh::GlobalIndexType;
+   using DeviceType = typename Mesh::DeviceType;
+
+// nvcc does not allow __cuda_callable__ lambdas inside private or protected sections
+#ifdef __NVCC__
+public:
+#endif
+   template< typename DimensionTag,
+             typename SuperdimensionTag,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< DimensionTag::value >::EntityTopology,
+                                                                  SuperdimensionTag::value >::storageEnabled
+             >
+   struct SuperentityWorker
+   {
+      static void bindSuperentities( Mesh& mesh )
+      {
+         const IndexType entitiesCount = mesh.template getEntitiesCount< DimensionTag::value >();
+         auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< DimensionTag::value, SuperdimensionTag::value >();
+         using Multimap = typename std::remove_reference< decltype(superentitiesStorage) >::type;
+         DevicePointer< Mesh > meshPointer( mesh );
+         DevicePointer< Multimap > superentitiesStoragePointer( superentitiesStorage );
+
+         auto kernel = [] __cuda_callable__
+            ( IndexType i,
+              Mesh* mesh,
+              Multimap* superentitiesStorage )
+         {
+            auto& subentity = mesh->template getEntity< DimensionTag::value >( i );
+            subentity.template bindSuperentitiesStorageNetwork< SuperdimensionTag::value >( superentitiesStorage->getValues( i ) );
+         };
+
+         ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount,
+                                          kernel,
+                                          &meshPointer.template modifyData< DeviceType >(),
+                                          &superentitiesStoragePointer.template modifyData< DeviceType >() );
+      }
+   };
+
+   template< typename DimensionTag,
+             typename SuperdimensionTag >
+   struct SuperentityWorker< DimensionTag, SuperdimensionTag, false >
+   {
+      static void bindSuperentities( Mesh& mesh ) {}
+   };
+
+
+   template< typename DimensionTag,
+             typename SuperdimensionTag,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< SuperdimensionTag::value >::EntityTopology,
+                                                                DimensionTag::value >::storageEnabled
+             >
+   struct SubentityWorker
+   {
+      static void bindSubentities( Mesh& mesh )
+      {
+         const IndexType entitiesCount = mesh.template getEntitiesCount< SuperdimensionTag::value >();
+         auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< SuperdimensionTag::value, DimensionTag::value >();
+         using Multimap = typename std::remove_reference< decltype(subentitiesStorage) >::type;
+         DevicePointer< Mesh > meshPointer( mesh );
+         DevicePointer< Multimap > subentitiesStoragePointer( subentitiesStorage );
+
+         auto kernel = [] __cuda_callable__
+            ( IndexType i,
+              Mesh* mesh,
+              Multimap* subentitiesStorage )
+         {
+            auto& superentity = mesh->template getEntity< SuperdimensionTag::value >( i );
+            superentity.template bindSubentitiesStorageNetwork< DimensionTag::value >( subentitiesStorage->getValues( i ) );
+         };
+
+         ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount,
+                                          kernel,
+                                          &meshPointer.template modifyData< DeviceType >(),
+                                          &subentitiesStoragePointer.template modifyData< DeviceType >() );
+      }
+   };
+
+   template< typename DimensionTag,
+             typename SuperdimensionTag >
+   struct SubentityWorker< DimensionTag, SuperdimensionTag, false >
+   {
+      static void bindSubentities( Mesh& mesh ) {}
+   };
+
+
+   template< int Dimension, int Superdimension >
+   struct InnerLoop
+   {
+      static void exec( Mesh& mesh )
+      {
+         using DimensionTag = Meshes::DimensionTag< Dimension >;
+         using SuperdimensionTag = Meshes::DimensionTag< Superdimension >;
+         SuperentityWorker< DimensionTag, SuperdimensionTag >::bindSuperentities( mesh );
+         SubentityWorker< DimensionTag, SuperdimensionTag >::bindSubentities( mesh );
+      }
+   };
+
+   template< int Dimension >
+   struct OuterLoop
+   {
+      template< int Superdimension >
+      using Inner = InnerLoop< Dimension, Superdimension >;
+
+      static void exec( Mesh& mesh )
+      {
+         StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, Inner >::execHost( mesh );
+      }
+   };
+
+public:
+   static void exec( Mesh& mesh )
+   {
+      StaticFor< int, 0, Mesh::getMeshDimension() + 1, OuterLoop >::execHost( mesh );
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h b/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h
new file mode 100644
index 0000000000000000000000000000000000000000..2bf9a007c6e76b532718a11174f8525c9fec0b25
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/IndexPermutationApplier.h
@@ -0,0 +1,184 @@
+/***************************************************************************
+                          IndexPermutationApplier.h  -  description
+                             -------------------
+    begin                : Mar 10, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Containers/Multimaps/MultimapPermutationApplier.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Mesh, int Dimension >
+struct IndexPermutationApplier
+{
+private:
+   using GlobalIndexVector = typename Mesh::GlobalIndexVector;
+
+   template< int Subdimension,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< Dimension >::EntityTopology,
+                                                                Subdimension >::storageEnabled
+             >
+   struct _SubentitiesStorageWorker
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& perm )
+      {
+         auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< Dimension, Subdimension >();
+         permuteMultimapKeys( subentitiesStorage, perm );
+      }
+   };
+
+   template< int Subdimension >
+   struct _SubentitiesStorageWorker< Subdimension, false >
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {}
+   };
+
+
+   template< int Superdimension,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< Dimension >::EntityTopology,
+                                                                  Superdimension >::storageEnabled
+             >
+   struct _SuperentitiesStorageWorker
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& perm )
+      {
+         auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< Dimension, Superdimension >();
+         permuteMultimapKeys( superentitiesStorage, perm );
+      }
+   };
+
+   template< int Superdimension >
+   struct _SuperentitiesStorageWorker< Superdimension, false >
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {}
+   };
+
+
+   template< int Subdimension,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SuperentityTraits< typename Mesh::template EntityType< Subdimension >::EntityTopology,
+                                                                  Dimension >::storageEnabled
+             >
+   struct IndexPermutationApplierSubentitiesWorker
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm )
+      {
+         auto& superentitiesStorage = mesh.template getSuperentityStorageNetwork< Subdimension, Dimension >();
+         permuteMultimapValues( superentitiesStorage, iperm );
+      }
+   };
+
+   template< int Subdimension >
+   struct IndexPermutationApplierSubentitiesWorker< Subdimension, false >
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {}
+   };
+
+
+   template< int Superdimension,
+             bool Enabled =
+                Mesh::MeshTraitsType::template SubentityTraits< typename Mesh::template EntityType< Superdimension >::EntityTopology,
+                                                                Dimension >::storageEnabled
+             >
+   struct IndexPermutationApplierSuperentitiesWorker
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm )
+      {
+         auto& subentitiesStorage = mesh.template getSubentityStorageNetwork< Superdimension, Dimension >();
+         permuteMultimapValues( subentitiesStorage, iperm );
+      }
+   };
+
+   template< int Superdimension >
+   struct IndexPermutationApplierSuperentitiesWorker< Superdimension, false >
+   {
+      static void exec( Mesh& mesh, const GlobalIndexVector& iperm ) {}
+   };
+
+
+   // template aliases needed to hide the 'Enabled' parameter
+   template< int Subdimension >
+   using SubentitiesStorageWorker = _SubentitiesStorageWorker< Subdimension >;
+
+   template< int Superdimension >
+   using SuperentitiesStorageWorker = _SuperentitiesStorageWorker< Superdimension >;
+
+   template< int Subdimension >
+   using SubentitiesWorker = IndexPermutationApplierSubentitiesWorker< Subdimension >;
+
+   template< int Superdimension >
+   using SuperentitiesWorker = IndexPermutationApplierSuperentitiesWorker< Superdimension >;
+
+public:
+   static void exec( Mesh& mesh,
+                     const GlobalIndexVector& perm,
+                     const GlobalIndexVector& iperm )
+   {
+      using IndexType = typename Mesh::GlobalIndexType;
+      using DeviceType = typename Mesh::DeviceType;
+      using StorageArrayType = typename Mesh::template EntityTraits< Dimension >::StorageArrayType;
+
+      const IndexType entitiesCount = mesh.template getEntitiesCount< Dimension >();
+
+      StorageArrayType entities;
+      entities.setSize( entitiesCount );
+
+      // kernel to copy entities to new array, applying the permutation
+      auto kernel1 = [] __cuda_callable__
+         ( IndexType i,
+           const Mesh* mesh,
+           typename StorageArrayType::ElementType* entitiesArray,
+           const IndexType* perm )
+      {
+         entitiesArray[ i ] = mesh->template getEntity< Dimension >( perm[ i ] );
+      };
+
+      // kernel to copy permuted entities back to the mesh
+      auto kernel2 = [] __cuda_callable__
+         ( IndexType i,
+           Mesh* mesh,
+           const typename StorageArrayType::ElementType* entitiesArray )
+      {
+         auto& entity = mesh->template getEntity< Dimension >( i );
+         entity = entitiesArray[ i ];
+         entity.setIndex( i );
+      };
+
+      DevicePointer< Mesh > meshPointer( mesh );
+      ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount,
+                                       kernel1,
+                                       &meshPointer.template getData< DeviceType >(),
+                                       entities.getData(),
+                                       perm.getData() );
+      ParallelFor< DeviceType >::exec( (IndexType) 0, entitiesCount,
+                                       kernel2,
+                                       &meshPointer.template modifyData< DeviceType >(),
+                                       entities.getData() );
+
+      // permute superentities storage
+      StaticFor< int, 0, Dimension, SubentitiesStorageWorker >::execHost( mesh, perm );
+
+      // permute subentities storage
+      StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, SuperentitiesStorageWorker >::execHost( mesh, perm );
+
+      // update superentity indices from the subentities
+      StaticFor< int, 0, Dimension, SubentitiesWorker >::execHost( mesh, iperm );
+
+      // update subentity indices from the superentities
+      StaticFor< int, Dimension + 1, Mesh::getMeshDimension() + 1, SuperentitiesWorker >::execHost( mesh, iperm );
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityId.h b/src/TNL/Meshes/MeshDetails/MeshEntityId.h
deleted file mode 100644
index c514b1b09d86d25998851de8779772d871439766..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/MeshEntityId.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/***************************************************************************
-                          MeshEntityId.h  -  description
-                             -------------------
-    begin                : Feb 28, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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
-
-namespace TNL {
-namespace Meshes {
-
-template< typename IDType,
-          typename GlobalIndexType >
-class MeshEntityId
-{
-   public:
-
-   MeshEntityId()
-      : id( -1 )
-   {}
-
-   const IDType &getId() const
-   {
-      TNL_ASSERT( this->id >= 0, );
-      return this->id;
-   }
-
-   void setId( GlobalIndexType id )
-   {
-      this->id = id;
-   }
-
-   bool operator==( const MeshEntityId< IDType, GlobalIndexType >& id ) const
-   {
-      return ( this->id == id.id );
-   }
-
-   protected:
-   IDType id;
-};
-
-template< typename GlobalIndexType >
-class MeshEntityId< void, GlobalIndexType >
-{
-   public:
-   void setId( GlobalIndexType )
-   {}
-
-   bool operator==( const MeshEntityId< void, GlobalIndexType >& id ) const
-   {
-      return true;
-   }
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h b/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h
new file mode 100644
index 0000000000000000000000000000000000000000..64485dc3c7ecb31ebdeb9891830244776550e315
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshEntityIndex.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+                          MeshEntityIndex.h  -  description
+                             -------------------
+    begin                : Feb 28, 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/Assert.h>
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename IDType >
+class MeshEntityIndex
+{
+public:
+   // FIXME: IDType may be unsigned
+   MeshEntityIndex()
+      : id( -1 )
+   {}
+
+   __cuda_callable__
+   const IDType& getIndex() const
+   {
+      TNL_ASSERT_GE( this->id, 0, "entity index is negative" );
+      return this->id;
+   }
+
+   __cuda_callable__
+   bool operator==( const MeshEntityIndex& id ) const
+   {
+      return ( this->id == id.id );
+   }
+
+protected:
+   __cuda_callable__
+   void setIndex( IDType id )
+   {
+      this->id = id;
+   }
+
+   IDType id;
+};
+
+template<>
+class MeshEntityIndex< void >
+{
+public:
+   __cuda_callable__
+   bool operator==( const MeshEntityIndex& id ) const
+   {
+      return true;
+   }
+
+protected:
+   template< typename Index >
+   __cuda_callable__
+   void setIndex( Index )
+   {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h b/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h
index f497c6306015e97aa60a00728e1153770b94ded1..10132513a0013dbe8e5ababfcde46621aeb715b3 100644
--- a/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h
+++ b/src/TNL/Meshes/MeshDetails/MeshEntityOrientation.h
@@ -25,23 +25,19 @@ template< typename MeshConfig,
           typename EntityTopology>
 class MeshEntityOrientation
 {
-   template< typename, typename> friend class MeshEntityReferenceOrientation;
+   template< typename, typename>
+   friend class MeshEntityReferenceOrientation;
 
    public:
-      typedef typename MeshTraits< MeshConfig >::IdPermutationArrayAccessorType IdPermutationArrayAccessorType;
+      using LocalIndexType = typename MeshTraits< MeshConfig >::LocalIndexType;
+      using IdPermutationArrayType = typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >::IdPermutationArrayType;
 
-      IdPermutationArrayAccessorType getSubvertexPermutation() const
+      const IdPermutationArrayType& getSubvertexPermutation() const
       {
-         IdPermutationArrayAccessorType accessor;
-         accessor.bind( this->subvertexPermutation );
-         return accessor;
-         //return this->subvertexPermutation.subarray( 0, this->subvertexPermutation.getSize() );
+         return subvertexPermutation;
       }
 
    private:
-      typedef typename MeshTraits< MeshConfig >::LocalIndexType        LocalIndexType;
-      typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >::IdPermutationArrayType IdPermutationArrayType;
-
       void setPermutationValue( LocalIndexType index, LocalIndexType value )
       {
          this->subvertexPermutation[ index ] = value;
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h b/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h
index bad26901bc0cdbfb1366ea28eecf34103c82e745..e14e909a52d6824192e66e8d93d469a877ae70ca 100644
--- a/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h
+++ b/src/TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h
@@ -16,6 +16,10 @@
 
 #pragma once
 
+#include <map>
+
+#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h>
+
 namespace TNL {
 namespace Meshes {
 
@@ -26,8 +30,8 @@ class MeshEntityReferenceOrientation
 	typedef typename MeshTraits< MeshConfig >::GlobalIndexType GlobalIndexType;
 
    public:
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >         SeedType;
-      typedef MeshEntityOrientation< MeshConfig, EntityTopology >         EntityOrientation;
+      typedef EntitySeed< MeshConfig, EntityTopology >            SeedType;
+      typedef MeshEntityOrientation< MeshConfig, EntityTopology > EntityOrientation;
 
       MeshEntityReferenceOrientation() = default;
 
@@ -36,7 +40,8 @@ class MeshEntityReferenceOrientation
          auto referenceCornerIds = referenceSeed.getCornerIds();
          for( LocalIndexType i = 0; i < referenceCornerIds.getSize(); i++ )
          {
-            TNL_ASSERT( this->cornerIdsMap.find( referenceCornerIds[i]) == this->cornerIdsMap.end(), );
+            TNL_ASSERT_TRUE( this->cornerIdsMap.find( referenceCornerIds[ i ] ) == this->cornerIdsMap.end(),
+                             "detected duplicate index in the reference seed" );
             this->cornerIdsMap.insert( std::make_pair( referenceCornerIds[i], i ) );
          }
       }
@@ -49,7 +54,8 @@ class MeshEntityReferenceOrientation
          auto cornerIds = seed.getCornerIds();
          for( LocalIndexType i = 0; i < cornerIds.getSize(); i++ )
          {
-            TNL_ASSERT( this->cornerIdsMap.find( cornerIds[ i ] ) != this->cornerIdsMap.end(), );
+            TNL_ASSERT_TRUE( this->cornerIdsMap.find( cornerIds[ i ] ) != this->cornerIdsMap.end(),
+                             "unable to find index for entity orientation" );
             result.setPermutationValue( i, this->cornerIdsMap.find( cornerIds[ i ])->second );
          }
          return result;
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h b/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h
index 9e9ff9b8aac46c8434d00b55c4b9361bcdcecc4d..8a21168de1496d497c248d7cd8fb05c9787066e4 100644
--- a/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h
+++ b/src/TNL/Meshes/MeshDetails/MeshEntity_impl.h
@@ -22,474 +22,323 @@ namespace TNL {
 namespace Meshes {
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-MeshEntity< MeshConfig, EntityTopology >::
-MeshEntity( const SeedType& entitySeed )
+__cuda_callable__
+MeshEntity< MeshConfig, Device, EntityTopology >::
+MeshEntity( const MeshEntity& entity )
+   : SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >( entity ),
+     SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >( entity ),
+     MeshEntityIndex< typename MeshConfig::IdType >( entity )
 {
-   typedef typename SeedType::LocalIndexType LocalIndexType;
-   for( LocalIndexType i = 0; i < entitySeed.getCornerIds().getSize(); i++ )
-      this->template setSubentityIndex< 0 >( i, entitySeed.getCornerIds()[ i ] );
 }
 
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+   template< typename Device_ >
+MeshEntity< MeshConfig, Device, EntityTopology >::
+MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity )
+   // no cross-device copy of subentities and superentities here - Mesh constructor has to rebind pointers
+   : MeshEntityIndex< typename MeshConfig::IdType >( entity )
+{
+   static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" );
+}
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-MeshEntity< MeshConfig, EntityTopology >::
-MeshEntity()
+__cuda_callable__
+MeshEntity< MeshConfig, Device, EntityTopology >& 
+MeshEntity< MeshConfig, Device, EntityTopology >::
+operator=( const MeshEntity& entity )
 {
+   SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator=( entity );
+   SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator=( entity );
+   MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity );
+   return *this;
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-MeshEntity< MeshConfig, EntityTopology >::
-~MeshEntity()
+   template< typename Device_ >
+__cuda_callable__
+MeshEntity< MeshConfig, Device, EntityTopology >& 
+MeshEntity< MeshConfig, Device, EntityTopology >::
+operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity )
 {
-   //cerr << "   Destroying entity with " << EntityTopology::dimensions << " dimensions..." << std::endl;
+   static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" );
+
+   // no cross-device copy of subentities and superentities here - Mesh::operator= has to rebind pointers
+   MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity );
+   return *this;
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
 String
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 getType()
 {
-   return String( "Mesh< ... >" );
+   return String( "MeshEntity< " ) +
+          MeshConfig::getType() + ", " +
+          EntityTopology::getType() + " >";
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
 String
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 getTypeVirtual() const
 {
    return this->getType();
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
 bool
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 save( File& file ) const
 {
-   if( ! MeshSubentityStorageLayers< MeshConfig, EntityTopology >::save( file ) /*||
-       ! MeshSuperentityStorageLayers< MeshConfig, EntityTopology >::save( file )*/ )
-      return false;
+   // no I/O for subentities and superentities - not loaded anyway
    return true;
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
 bool
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 load( File& file )
 {
-   if( ! MeshSubentityStorageLayers< MeshConfig, EntityTopology >::load( file ) /*||
-       ! MeshSuperentityStorageLayers< MeshConfig, EntityTopology >::load( file ) */ )
-      return false;
+   // no I/O for subentities and superentities - Mesh::load has to rebind pointers
    return true;
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
 void
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 print( std::ostream& str ) const
 {
-   str << "\t Mesh entity dimension: " << EntityTopology::dimensions << std::endl;
-   MeshSubentityStorageLayers< MeshConfig, EntityTopology >::print( str );
-   MeshSuperentityAccess< MeshConfig, EntityTopology >::print( str );
+   str << "\t Mesh entity dimension: " << EntityTopology::dimension << std::endl;
+   SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::print( str );
+   SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::print( str );
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
+__cuda_callable__
 bool
-MeshEntity< MeshConfig, EntityTopology >::
+MeshEntity< MeshConfig, Device, EntityTopology >::
 operator==( const MeshEntity& entity ) const
 {
-   return ( MeshSubentityStorageLayers< MeshConfig, EntityTopology >::operator==( entity ) &&
-            MeshSuperentityAccess< MeshConfig, EntityTopology >::operator==( entity ) &&
-            MeshEntityId< typename MeshConfig::IdType,
-                             typename MeshConfig::GlobalIndexType >::operator==( entity ) );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-constexpr int
-MeshEntity< MeshConfig, EntityTopology >::
-getEntityDimension() const
-{
-   return EntityTopology::dimensions;
-}
-
-/****
- * Subentities
- */
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-constexpr bool
-MeshEntity< MeshConfig, EntityTopology >::
-subentitiesAvailable() const
-{
-   return SubentityTraits< Subdimensions >::storageEnabled;
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-constexpr typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
-getNumberOfSubentities() const
-{
-   return SubentityTraits< Subdimensions >::count;
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
-getSubentityIndex( const LocalIndexType localIndex) const
-{
-   static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to get subentity which is not configured for storage." );
-   TNL_ASSERT( 0 <= localIndex &&
-              localIndex < SubentityTraits< Subdimensions >::count,
-              std::cerr << "localIndex = " << localIndex
-                   << " subentitiesCount = "
-                   << SubentityTraits< Subdimensions >::count );
-   typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology >  SubentityBaseType;
-   return SubentityBaseType::getSubentityIndex( MeshDimensionTag< Subdimensions >(),
-                                                localIndex );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
- getSubentitiesIndices()
-{
-   static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to get subentities which are not configured for storage." );
-   typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology >  SubentityBaseType;
-   return SubentityBaseType::getSubentitiesIndices( MeshDimensionTag< Subdimensions >() );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-const typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-getSubentitiesIndices() const
-{
-   static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to set subentities which are not configured for storage." );
-   typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology >  SubentityBaseType;
-   return SubentityBaseType::getSubentitiesIndices( MeshDimensionTag< Subdimensions >() );
+   return ( SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator==( entity ) &&
+            SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology >::operator==( entity ) &&
+            MeshEntityIndex< typename MeshConfig::IdType >::operator==( entity ) );
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-   template< int SuperDimension >
-typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
-getNumberOfSuperentities() const
-{
-   static_assert( SuperentityTraits< SuperDimension >::available, "You try to get number of superentities which are not configured for storage." );
-   typedef MeshSuperentityAccess< MeshConfig, EntityTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getNumberOfSuperentities( MeshDimensionTag< SuperDimension >() );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int SuperDimension >
-typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
-getSuperentityIndex( const LocalIndexType localIndex ) const
-{
-   static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentity which is not configured for storage." );
-   TNL_ASSERT( localIndex < this->getNumberOfSuperentities< SuperDimension >(),
-              std::cerr << " localIndex = " << localIndex
-                   << " this->getNumberOfSuperentities< Dimension >() = " << this->getNumberOfSuperentities< SuperDimension >() << std::endl; );
-   typedef MeshSuperentityAccess< MeshConfig, EntityTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getSuperentityIndex( MeshDimensionTag< SuperDimension >(),
-                                                    localIndex );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int SuperDimension >
-typename MeshEntity< MeshConfig, EntityTopology >::template SuperentityTraits< SuperDimension >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-getSuperentitiesIndices()
+__cuda_callable__
+bool
+MeshEntity< MeshConfig, Device, EntityTopology >::
+operator!=( const MeshEntity& entity ) const
 {
-   static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentities which are not configured for storage." );
-   typedef MeshSuperentityAccess< MeshConfig, EntityTopology >  SuperentityBaseType;
-   //return SuperentityBaseType::getSuperentitiesIndices( MeshDimensionTag< Dimension >() );
+   return ! ( *this == entity );
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-   template< int SuperDimension >
-const typename MeshEntity< MeshConfig, EntityTopology >::template SuperentityTraits< SuperDimension >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-getSuperentitiesIndices() const
+constexpr int
+MeshEntity< MeshConfig, Device, EntityTopology >::
+getEntityDimension()
 {
-   static_assert( SuperentityTraits< SuperDimension >::storageEnabled, "You try to get superentities which are not configured for storage." );
-   typedef MeshSuperentityAccess< MeshConfig, EntityTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getSubentitiesIndices( MeshDimensionTag< SuperDimension >() );
+   return EntityTopology::dimension;
 }
 
+/****
+ * Subentities
+ */
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-constexpr typename MeshEntity< MeshConfig, EntityTopology >::LocalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
-getNumberOfVertices() const
+constexpr typename MeshEntity< MeshConfig, Device, EntityTopology >::LocalIndexType
+MeshEntity< MeshConfig, Device, EntityTopology >::
+getVerticesCount()
 {
    return SubentityTraits< 0 >::count;
 }
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-typename MeshEntity< MeshConfig, EntityTopology >::GlobalIndexType
-MeshEntity< MeshConfig, EntityTopology >::
+typename MeshEntity< MeshConfig, Device, EntityTopology >::GlobalIndexType
+MeshEntity< MeshConfig, Device, EntityTopology >::
 getVertexIndex( const LocalIndexType localIndex ) const
 {
-   return this->getSubentityIndex< 0 >( localIndex  );
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< 0 >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-getVerticesIndices()
-{
-   return this->getSubentitiesIndices< 0 >();
+   return this->template getSubentityIndex< 0 >( localIndex  );
 }
 
-template< typename MeshConfig,
-          typename EntityTopology >
-const typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< 0 >::AccessArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-getVerticesIndices() const
-{
-   return this->getSubentitiesIndices< 0 >();
-}
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Dimension >
-typename MeshEntity< MeshConfig, EntityTopology >::IdPermutationArrayAccessorType
-MeshEntity< MeshConfig, EntityTopology >::
-subentityOrientation( LocalIndexType index ) const
-{
-   static const LocalIndexType subentitiesCount = SubentityTraits< Dimension >::count;
-   TNL_ASSERT( 0 <= index && index < subentitiesCount, );
-
-   return SubentityStorageLayers::subentityOrientation( MeshDimensionTag< Dimension >(), index );
-}
 
 /****
- * Mesh initialization method
+ * Vertex entity specialization
  */
-
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-void
-MeshEntity< MeshConfig, EntityTopology >::
-setSubentityIndex( const LocalIndexType localIndex,
-                   const GlobalIndexType globalIndex )
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+MeshEntity( const MeshEntity& entity )
+   : SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >( entity ),
+     MeshEntityIndex< typename MeshConfig::IdType >( entity )
 {
-   static_assert( SubentityTraits< Subdimensions >::storageEnabled, "You try to set subentity which is not configured for storage." );
-   TNL_ASSERT( 0 <= localIndex &&
-              localIndex < SubentityTraits< Subdimensions >::count,
-              std::cerr << "localIndex = " << localIndex
-                   << " subentitiesCount = "
-                   << SubentityTraits< Subdimensions >::count );
-   typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology >  SubentityBaseType;
-   SubentityBaseType::setSubentityIndex( MeshDimensionTag< Subdimensions >(),
-                                         localIndex,
-                                         globalIndex );
+   setPoint( entity.getPoint() );
 }
 
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::IdArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-subentityIdsArray()
+template< typename MeshConfig, typename Device >
+   template< typename Device_ >
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+MeshEntity( const MeshEntity< MeshConfig, Device_, Topologies::Vertex >& entity )
+   // no cross-device copy of superentities here - Mesh constructor has to rebind pointers
+   : MeshEntityIndex< typename MeshConfig::IdType >( entity )
 {
-   return SubentityStorageLayers::subentityIdsArray( MeshDimensionTag< Subdimensions >() );
+   static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" );
+
+   setPoint( entity.getPoint() );
 }
 
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Superdimensions >
-typename MeshEntity< MeshConfig, EntityTopology >::IdArrayAccessorType&
-MeshEntity< MeshConfig, EntityTopology >::
-superentityIdsArray()
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+MeshEntity< MeshConfig, Device, Topologies::Vertex >& 
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+operator=( const MeshEntity& entity )
 {
-   return SuperentityAccessBase::superentityIdsArray( MeshDimensionTag< Superdimensions >());
+   SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::operator=( entity );
+   MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity );
+   setPoint( entity.getPoint() );
+   return *this;
 }
 
-template< typename MeshConfig,
-          typename EntityTopology >
-   template< int Subdimensions >
-typename MeshEntity< MeshConfig, EntityTopology >::template SubentityTraits< Subdimensions >::OrientationArrayType&
-MeshEntity< MeshConfig, EntityTopology >::
-subentityOrientationsArray()
+template< typename MeshConfig, typename Device >
+   template< typename Device_ >
+__cuda_callable__
+MeshEntity< MeshConfig, Device, Topologies::Vertex >& 
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+operator=( const MeshEntity< MeshConfig, Device_, Topologies::Vertex >& entity )
 {
-   return SubentityStorageLayers::subentityOrientationsArray( MeshDimensionTag< Subdimensions >() );
+   static_assert( ! std::is_same< Device, Device_ >::value, "this should never happen" );
+
+   // no cross-device copy of superentities here - Mesh::operator= has to rebind pointers
+   MeshEntityIndex< typename MeshConfig::IdType >::operator=( entity );
+   setPoint( entity.getPoint() );
+   return *this;
 }
 
-/****
- * Vertex entity specialization
- */
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 String
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 getType()
 {
-   return String( "Mesh< ... >" );
+   return String( "MeshEntity< ... >" );
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 String
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 getTypeVirtual() const
 {
    return this->getType();
 }
 
-template< typename MeshConfig >
-MeshEntity< MeshConfig, MeshVertexTopology >::
-~MeshEntity()
-{
-   //cerr << "   Destroying entity with " << MeshVertexTopology::dimensions << " dimensions..." << std::endl;
-}
-
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 bool
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 save( File& file ) const
 {
-   if( //! MeshSuperentityStorageLayers< MeshConfig, MeshVertexTopology >::save( file ) ||
-       ! point.save( file ) )
+   // no I/O for superentities - not loaded anyway
+   if( ! point.save( file ) )
       return false;
    return true;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 bool
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 load( File& file )
 {
-   if( //! MeshSuperentityStorageLayers< MeshConfig, MeshVertexTopology >::load( file ) ||
-       ! point.load( file ) )
+   // no I/O for superentities - Mesh::load has to rebind pointers
+   if( ! point.load( file ) )
       return false;
    return true;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 void
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 print( std::ostream& str ) const
 {
-   str << "\t Mesh entity dimension: " << MeshVertexTopology::dimensions << std::endl;
-   str << "\t Coordinates = ( " << point << " )";
-   MeshSuperentityAccess< MeshConfig, MeshVertexTopology >::print( str );
+   str << "\t Mesh entity dimension: " << Topologies::Vertex::dimension << std::endl;
+   str << "\t Coordinates = " << point << std::endl;
+   SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::print( str );
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
+__cuda_callable__
 bool
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 operator==( const MeshEntity& entity ) const
 {
-   return ( //MeshSuperentityAccess< MeshConfig, MeshVertexTopology >::operator==( entity ) &&
-            MeshEntityId< typename MeshConfig::IdType,
-                             typename MeshConfig::GlobalIndexType >::operator==( entity ) &&
+   return ( SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::operator==( entity ) &&
+            MeshEntityIndex< typename MeshConfig::IdType >::operator==( entity ) &&
             point == entity.point );
 }
 
-template< typename MeshConfig >
-constexpr int
-MeshEntity< MeshConfig, MeshVertexTopology >::
-getEntityDimension() const
-{
-   return EntityTopology::dimensions;
-}
-
-template< typename MeshConfig >
-   template< int Superdimensions >
-typename MeshEntity< MeshConfig, MeshVertexTopology >::LocalIndexType
-MeshEntity< MeshConfig, MeshVertexTopology >::
-getNumberOfSuperentities() const
-{
-   typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getNumberOfSuperentities( MeshDimensionTag< Superdimensions >() );
-}
-
-template< typename MeshConfig >
-   template< int Superdimensions >
-typename MeshEntity< MeshConfig, MeshVertexTopology >::template SuperentityTraits< Superdimensions >::AccessArrayType&
-MeshEntity< MeshConfig, MeshVertexTopology >::
-getSuperentitiesIndices()
-{
-   typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getSuperentitiesIndices( MeshDimensionTag< Superdimensions >() );
-}
-
-template< typename MeshConfig >
-   template< int Superdimensions >
-const typename MeshEntity< MeshConfig, MeshVertexTopology >::template SuperentityTraits< Superdimensions >::AccessArrayType&
-MeshEntity< MeshConfig, MeshVertexTopology >::
-getSuperentitiesIndeces() const
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+bool
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+operator!=( const MeshEntity& entity ) const
 {
-   typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getSubentitiesIndices( MeshDimensionTag< Superdimensions >() );
+   return ! ( *this == entity );
 }
 
-template< typename MeshConfig >
-   template< int Dimension >
-typename MeshEntity< MeshConfig, MeshVertexTopology >::GlobalIndexType
-MeshEntity< MeshConfig, MeshVertexTopology >::
-getSuperentityIndex( const LocalIndexType localIndex ) const
+template< typename MeshConfig, typename Device >
+constexpr int
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
+getEntityDimension()
 {
-   TNL_ASSERT( localIndex < this->getNumberOfSuperentities< Dimension >(),
-              std::cerr << " localIndex = " << localIndex
-                   << " this->getNumberOfSuperentities< Dimension >() = " << this->getNumberOfSuperentities< Dimension >() << std::endl; );
-   typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology >  SuperentityBaseType;
-   return SuperentityBaseType::getSuperentityIndex( MeshDimensionTag< Dimension >(),
-                                                    localIndex );
+   return EntityTopology::dimension;
 }
 
-template< typename MeshConfig >
-typename MeshEntity< MeshConfig, MeshVertexTopology >::PointType
-MeshEntity< MeshConfig, MeshVertexTopology >::
+template< typename MeshConfig, typename Device >
+__cuda_callable__
+typename MeshEntity< MeshConfig, Device, Topologies::Vertex >::PointType
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 getPoint() const
 {
    return this->point;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
+__cuda_callable__
 void
-MeshEntity< MeshConfig, MeshVertexTopology >::
+MeshEntity< MeshConfig, Device, Topologies::Vertex >::
 setPoint( const PointType& point )
 {
    this->point = point;
 }
 
-template< typename MeshConfig >
-   template< int Superdimensions >
-typename MeshEntity< MeshConfig, MeshVertexTopology >::MeshTraitsType::IdArrayAccessorType&
-MeshEntity< MeshConfig, MeshVertexTopology >::
-superentityIdsArray()
-{
-   return SuperentityAccessBase::superentityIdsArray( MeshDimensionTag< Superdimensions >());
-}
-
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, EntityTopology >& entity )
+std::ostream& operator<<( std::ostream& str, const MeshEntity< MeshConfig, Device, EntityTopology >& entity )
 {
    entity.print( str );
    return str;
@@ -497,4 +346,3 @@ std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, Enti
 
 } // namespace Meshes
 } // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h
index 42ddaa1d2dded36a364bcdafe3ab66828be45c61..13fec6787827ec6177815984096dbfe0ff10e59d 100644
--- a/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h
+++ b/src/TNL/Meshes/MeshDetails/MeshIntegrityChecker.h
@@ -2,7 +2,7 @@
                           MeshIntegrityChecker.h  -  description
                              -------------------
     begin                : Mar 20, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -25,9 +25,9 @@ namespace Meshes {
 template< typename MeshType >
 class MeshIntegrityChecker
 : public MeshIntegrityCheckerLayer< MeshType,
-                                       MeshDimensionTag< MeshType::Config::CellType::dimensions > >
+                                    DimensionTag< MeshType::Config::CellType::dimension > >
 {
-      typedef MeshDimensionTag< MeshType::Config::CellType::dimensions > DimensionTag;
+      typedef Meshes::DimensionTag< MeshType::Config::CellType::dimension > DimensionTag;
       typedef MeshIntegrityCheckerLayer< MeshType, DimensionTag > BaseType;
 
    public:
diff --git a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h b/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h
index 302ed0b05ad395eb1fdf4d1a26228c49f5bdfbad..13e415d4567effbc8c8f5b735c7523045f718cad 100644
--- a/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h
+++ b/src/TNL/Meshes/MeshDetails/MeshIntegrityCheckerLayer.h
@@ -2,7 +2,7 @@
                           MeshIntegrityCheckerLayer.h  -  description
                              -------------------
     begin                : Mar 21, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -17,7 +17,7 @@
 #pragma once
 
 #include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
+#include <TNL/Meshes/DimensionTag.h>
 
 namespace TNL {
 namespace Meshes {
@@ -25,29 +25,29 @@ namespace Meshes {
 template< typename MeshType,
           typename DimensionTag,
           bool EntityStorageTag = MeshEntityTraits< typename MeshType::Config,
-                                                       DimensionTag::value >::storageEnabled >
+                                                    DimensionTag::value >::storageEnabled >
 class MeshIntegrityCheckerLayer;
 
 template< typename MeshType,
           typename DimensionTag >
 class MeshIntegrityCheckerLayer< MeshType,
-                                    DimensionTag,
-                                    true >
+                                 DimensionTag,
+                                 true >
    : public MeshIntegrityCheckerLayer< MeshType,
-                                          typename DimensionTag::Decrement >
+                                       typename DimensionTag::Decrement >
 {
    public:
       typedef MeshIntegrityCheckerLayer< MeshType,
-                                            typename DimensionTag::Decrement >     BaseType;
-      enum { dimensions = DimensionTag::value };
+                                         typename DimensionTag::Decrement >     BaseType;
+      enum { dimension = DimensionTag::value };
 
       static bool checkEntities( const MeshType& mesh )
       {
-         typedef typename MeshType::template EntitiesTraits< dimensions >::ContainerType ContainerType;
+         typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType;
          typedef typename ContainerType::IndexType                                       GlobalIndexType;
-        std::cout << "Checking entities with " << dimensions << " dimensions ..." << std::endl;
+        std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl;
          for( GlobalIndexType entityIdx = 0;
-              entityIdx < mesh.template getNumberOfEntities< dimensions >();
+              entityIdx < mesh.template getEntitiesCount< dimension >();
               entityIdx++ )
          {
            std::cout << "Entity no. " << entityIdx << "               \r" << std::flush;
@@ -61,19 +61,19 @@ class MeshIntegrityCheckerLayer< MeshType,
 
 template< typename MeshType >
 class MeshIntegrityCheckerLayer< MeshType,
-                                    MeshDimensionTag< 0 >,
-                                    true >
+                                 DimensionTag< 0 >,
+                                 true >
 {
    public:
-      enum { dimensions = 0 };
+      enum { dimension = 0 };
 
       static bool checkEntities( const MeshType& mesh )
       {
-         typedef typename MeshType::template EntitiesTraits< dimensions >::ContainerType ContainerType;
+         typedef typename MeshType::template EntitiesTraits< dimension >::ContainerType ContainerType;
          typedef typename ContainerType::IndexType                                       GlobalIndexType;
-        std::cout << "Checking entities with " << dimensions << " dimensions ..." << std::endl;
+        std::cout << "Checking entities with dimension " << dimension << " ..." << std::endl;
          for( GlobalIndexType entityIdx = 0;
-              entityIdx < mesh.template getNumberOfEntities< dimensions >();
+              entityIdx < mesh.template getEntitiesCount< dimension >();
               entityIdx++ )
          {
            std::cout << "Entity no. " << entityIdx << "          \r" << std::flush;
@@ -81,26 +81,23 @@ class MeshIntegrityCheckerLayer< MeshType,
         std::cout << std::endl;
          return true;
       }
-
 };
 
 template< typename MeshType,
           typename DimensionTag >
 class MeshIntegrityCheckerLayer< MeshType,
-                                    DimensionTag,
-                                    false >
+                                 DimensionTag,
+                                 false >
    : public MeshIntegrityCheckerLayer< MeshType,
-                                          typename DimensionTag::Decrement >
+                                       typename DimensionTag::Decrement >
 {
-
 };
 
 template< typename MeshType >
 class MeshIntegrityCheckerLayer< MeshType,
-                                    MeshDimensionTag< 0 >,
-                                    false >
+                                 DimensionTag< 0 >,
+                                 false >
 {
-
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5cf6216c750686a27d87c157fbd85a6239febbad
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/CMakeLists.txt
@@ -0,0 +1,8 @@
+SET( headers ConfigValidator.h
+             Layer.h
+             LayerFamily.h
+             Initializer.h
+             Traits.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/MeshLayers/BoundaryTags )
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h
new file mode 100644
index 0000000000000000000000000000000000000000..aba84ba806b3954aa3812db9f3977db8ce0d251e
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/ConfigValidator.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+                          ConfigValidator.h  -  description
+                             -------------------
+    begin                : Aug 14, 2015
+    copyright            : (C) 2015 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+
+namespace TNL {
+namespace Meshes {
+namespace BoundaryTags {
+
+template< typename MeshConfig,
+          typename EntityTopology,
+          bool BoundaryTagsStorage = MeshConfig::boundaryTagsStorage( EntityTopology() ) >
+class ConfigValidatorBoundaryTagsLayer
+{
+   using FaceTopology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, MeshConfig::meshDimension - 1 >::Topology;
+
+   static_assert( MeshConfig::entityStorage( MeshConfig::meshDimension - 1 ),
+                  "Faces must be stored when any entity has boundary tags." );
+   static_assert( MeshConfig::superentityStorage( FaceTopology(), MeshConfig::meshDimension ),
+                  "Faces must store the cell superentity indices when any entity has boundary tags." );
+   static_assert( EntityTopology::dimension >= MeshConfig::meshDimension - 1 || MeshConfig::subentityStorage( FaceTopology(), EntityTopology::dimension ),
+                  "Faces must store the subentity indices of the entities on which the boundary tags are stored." );
+};
+
+template< typename MeshConfig,
+          typename EntityTopology >
+class ConfigValidatorBoundaryTagsLayer< MeshConfig, EntityTopology, false >
+{
+};
+
+
+template< typename MeshConfig, int dimension = MeshConfig::meshDimension >
+class ConfigValidatorLayer
+   : public ConfigValidatorLayer< MeshConfig, dimension - 1 >,
+     public ConfigValidatorBoundaryTagsLayer< MeshConfig,
+                                              typename MeshTraits< MeshConfig >::template EntityTraits< dimension >::EntityTopology >
+{
+};
+
+template< typename MeshConfig >
+class ConfigValidatorLayer< MeshConfig, 0 >
+{
+};
+
+template< typename MeshConfig >
+class ConfigValidator
+   : public ConfigValidatorLayer< MeshConfig >
+{
+};
+
+} // namespace BoundaryTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..a475ddcb4396bc4fadd5a50388379a0f40f6068b
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Initializer.h
@@ -0,0 +1,168 @@
+/***************************************************************************
+                          Initializer.h  -  description
+                             -------------------
+    begin                : Dec 26, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/StaticFor.h>
+#include <TNL/ParallelFor.h>
+#include <TNL/DevicePointer.h>
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
+
+namespace TNL {
+namespace Meshes {
+namespace BoundaryTags {
+
+template< typename MeshConfig, typename Device, typename Mesh >
+class Initializer
+{
+   using DeviceType      = Device;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType  = typename MeshConfig::LocalIndexType;
+
+protected:
+   // _T is necessary to force *partial* specialization, since explicit specializations
+   // at class scope are forbidden
+   template< typename CurrentDimension = DimensionTag< MeshConfig::meshDimension >, typename _T = void >
+   struct BoundaryTagsNeedInitialization
+   {
+      using EntityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, CurrentDimension::value >::EntityTopology;
+      static constexpr bool value = MeshConfig::boundaryTagsStorage( EntityTopology() ) ||
+                                    BoundaryTagsNeedInitialization< typename CurrentDimension::Decrement >::value;
+   };
+
+   template< typename _T >
+   struct BoundaryTagsNeedInitialization< DimensionTag< 0 >, _T >
+   {
+      using EntityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, 0 >::EntityTopology;
+      static constexpr bool value = MeshConfig::boundaryTagsStorage( EntityTopology() );
+   };
+
+   template< int Dimension >
+   struct SetEntitiesCount
+   {
+      static void exec( Mesh& mesh )
+      {
+         mesh.template boundaryTagsSetEntitiesCount< Dimension >( mesh.template getEntitiesCount< Dimension >() );
+      }
+   };
+
+   template< int Dimension >
+   struct ResetBoundaryTags
+   {
+      static void exec( Mesh& mesh )
+      {
+         mesh.template resetBoundaryTags< Dimension >();
+      }
+   };
+
+   template< int Subdimension >
+   class InitializeSubentities
+   {
+      using SubentityTopology = typename MeshEntityTraits< MeshConfig, DeviceType, Subdimension >::EntityTopology;
+      static constexpr bool enabled = MeshConfig::boundaryTagsStorage( SubentityTopology() );
+
+      // _T is necessary to force *partial* specialization, since explicit specializations
+      // at class scope are forbidden
+      template< bool enabled = true, typename _T = void >
+      struct Worker
+      {
+         __cuda_callable__
+         static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face )
+         {
+            const LocalIndexType subentitiesCount = face.template getSubentitiesCount< Subdimension >();
+            for( LocalIndexType i = 0; i < subentitiesCount; i++ ) {
+               const GlobalIndexType subentityIndex = face.template getSubentityIndex< Subdimension >( i );
+               mesh.template setIsBoundaryEntity< Subdimension >( subentityIndex, true );
+            }
+         }
+      };
+
+      template< typename _T >
+      struct Worker< false, _T >
+      {
+         __cuda_callable__
+         static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face ) {}
+      };
+
+   public:
+      __cuda_callable__
+      static void exec( Mesh& mesh, const GlobalIndexType& faceIndex, const typename Mesh::Face& face )
+      {
+         Worker< enabled >::exec( mesh, faceIndex, face );
+      }
+   };
+
+   template< int Dimension >
+   struct UpdateBoundaryIndices
+   {
+      static void exec( Mesh& mesh )
+      {
+         mesh.template updateBoundaryIndices< Dimension >();
+      }
+   };
+
+// nvcc does not allow __cuda_callable__ lambdas inside private or protected sections
+#ifdef __NVCC__
+public:
+#endif
+   // _T is necessary to force *partial* specialization, since explicit specializations
+   // at class scope are forbidden
+   template< bool AnyBoundaryTags = BoundaryTagsNeedInitialization<>::value, typename _T = void >
+   class Worker
+   {
+   public:
+      static void exec( Mesh& mesh )
+      {
+         StaticFor< int, 0, Mesh::getMeshDimension() + 1, SetEntitiesCount >::execHost( mesh );
+         StaticFor< int, 0, Mesh::getMeshDimension() + 1, ResetBoundaryTags >::execHost( mesh );
+
+         auto kernel = [] __cuda_callable__
+            ( GlobalIndexType faceIndex,
+              Mesh* mesh )
+         {
+            const auto& face = mesh->template getEntity< Mesh::getMeshDimension() - 1 >( faceIndex );
+            if( face.template getSuperentitiesCount< Mesh::getMeshDimension() >() == 1 ) {
+               // initialize the face
+               mesh->template setIsBoundaryEntity< Mesh::getMeshDimension() - 1 >( faceIndex, true );
+               // initialize the cell superentity
+               const GlobalIndexType cellIndex = face.template getSuperentityIndex< Mesh::getMeshDimension() >( 0 );
+               mesh->template setIsBoundaryEntity< Mesh::getMeshDimension() >( cellIndex, true );
+               // initialize all subentities
+               StaticFor< int, 0, Mesh::getMeshDimension() - 1, InitializeSubentities >::exec( *mesh, faceIndex, face );
+            }
+         };
+
+         const GlobalIndexType facesCount = mesh.template getEntitiesCount< Mesh::getMeshDimension() - 1 >();
+         DevicePointer< Mesh > meshPointer( mesh );
+         ParallelFor< DeviceType >::exec( (GlobalIndexType) 0, facesCount,
+                                          kernel,
+                                          &meshPointer.template modifyData< DeviceType >() );
+
+         StaticFor< int, 0, Mesh::getMeshDimension() + 1, UpdateBoundaryIndices >::execHost( mesh );
+      }
+   };
+
+   template< typename _T >
+   struct Worker< false, _T >
+   {
+      static void exec( Mesh& mesh ) {}
+   };
+
+public:
+   void initLayer()
+   {
+      Worker<>::exec( *static_cast<Mesh*>(this) );
+   }
+};
+
+} // namespace BoundaryTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h
new file mode 100644
index 0000000000000000000000000000000000000000..06401f1a351bc087922799f31472337cfac0d988
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h
@@ -0,0 +1,272 @@
+/***************************************************************************
+                          Layer.h  -  description
+                             -------------------
+    begin                : Dec 25, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/File.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+#include <TNL/Containers/Vector.h>
+
+#include "Traits.h"
+
+namespace TNL {
+namespace Meshes {
+namespace BoundaryTags {
+
+// This is the implementation of the boundary tags layer for one specific dimension.
+// It is inherited by the BoundaryTags::LayerFamily.
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag,
+          bool TagStorage = WeakStorageTrait< MeshConfig, Device, DimensionTag >::boundaryTagsEnabled >
+class Layer
+{
+   using MeshTraitsType    = MeshTraits< MeshConfig, Device >;
+
+public:
+   using GlobalIndexType   = typename MeshTraitsType::GlobalIndexType;
+   using BoundaryTagsArray = Containers::Array< bool, Device, GlobalIndexType >;
+   using OrderingArray     = Containers::Array< GlobalIndexType, Device, GlobalIndexType >;
+
+   Layer() = default;
+
+   explicit Layer( const Layer& other )
+   {
+      operator=( other );
+   }
+
+   template< typename Device_ >
+   Layer( const Layer< MeshConfig, Device_, DimensionTag >& other )
+   {
+      operator=( other );
+   }
+
+   Layer& operator=( const Layer& other )
+   {
+      boundaryTags.setLike( other.boundaryTags );
+      boundaryIndices.setLike( other.boundaryIndices );
+      interiorIndices.setLike( other.interiorIndices );
+      boundaryTags = other.boundaryTags;
+      boundaryIndices = other.boundaryIndices;
+      interiorIndices = other.interiorIndices;
+      return *this;
+   }
+
+   template< typename Device_ >
+   Layer& operator=( const Layer< MeshConfig, Device_, DimensionTag >& other )
+   {
+      boundaryTags.setLike( other.boundaryTags );
+      boundaryIndices.setLike( other.boundaryIndices );
+      interiorIndices.setLike( other.interiorIndices );
+      boundaryTags = other.boundaryTags;
+      boundaryIndices = other.boundaryIndices;
+      interiorIndices = other.interiorIndices;
+      return *this;
+   }
+
+
+   void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount )
+   {
+      boundaryTags.setSize( entitiesCount );
+   }
+
+   void resetBoundaryTags( DimensionTag )
+   {
+      boundaryTags.setValue( false );
+   }
+
+   __cuda_callable__
+   void setIsBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex, bool isBoundary )
+   {
+      boundaryTags[ entityIndex ] = isBoundary;
+   }
+
+   __cuda_callable__
+   bool isBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex ) const
+   {
+      return boundaryTags[ entityIndex ];
+   }
+
+   void updateBoundaryIndices( DimensionTag )
+   {
+      // Array does not have sum(), Vector of bools does not fit due to arithmetics
+      Containers::Vector< typename BoundaryTagsArray::ElementType, typename BoundaryTagsArray::DeviceType, typename BoundaryTagsArray::IndexType > _boundaryTagsVector;
+      _boundaryTagsVector.bind( boundaryTags.getData(), boundaryTags.getSize() );
+      const GlobalIndexType boundaryEntities = _boundaryTagsVector.template sum< GlobalIndexType >();
+      boundaryIndices.setSize( boundaryEntities );
+      interiorIndices.setSize( boundaryTags.getSize() - boundaryEntities );
+
+      if( std::is_same< Device, Devices::Host >::value ) {
+         GlobalIndexType b = 0;
+         GlobalIndexType i = 0;
+         while( b + i < boundaryTags.getSize() ) {
+            const GlobalIndexType e = b + i;
+            if( boundaryTags[ e ] )
+               boundaryIndices[ b++ ] = e;
+            else
+               interiorIndices[ i++ ] = e;
+         }
+      }
+      // TODO: parallelize directly on the device
+      else {
+         using BoundaryTagsHostArray = typename BoundaryTagsArray::HostType;
+         using OrderingHostArray     = typename OrderingArray::HostType;
+
+         BoundaryTagsHostArray hostBoundaryTags;
+         OrderingHostArray hostBoundaryIndices;
+         OrderingHostArray hostInteriorIndices;
+
+         hostBoundaryTags.setLike( boundaryTags );
+         hostBoundaryIndices.setLike( boundaryIndices );
+         hostInteriorIndices.setLike( interiorIndices );
+
+         hostBoundaryTags = boundaryTags;
+
+         GlobalIndexType b = 0;
+         GlobalIndexType i = 0;
+         while( b + i < boundaryTags.getSize() ) {
+            const GlobalIndexType e = b + i;
+            if( hostBoundaryTags[ e ] )
+               hostBoundaryIndices[ b++ ] = e;
+            else
+               hostInteriorIndices[ i++ ] = e;
+         }
+
+         boundaryIndices = hostBoundaryIndices;
+         interiorIndices = hostInteriorIndices;
+      }
+   }
+
+   __cuda_callable__
+   GlobalIndexType getBoundaryEntitiesCount( DimensionTag ) const
+   {
+      return boundaryIndices.getSize();
+   }
+
+   __cuda_callable__
+   GlobalIndexType getBoundaryEntityIndex( DimensionTag, const GlobalIndexType& i ) const
+   {
+      return boundaryIndices[ i ];
+   }
+
+   __cuda_callable__
+   GlobalIndexType getInteriorEntitiesCount( DimensionTag ) const
+   {
+      return interiorIndices.getSize();
+   }
+
+   __cuda_callable__
+   GlobalIndexType getInteriorEntityIndex( DimensionTag, const GlobalIndexType& i ) const
+   {
+      return interiorIndices[ i ];
+   }
+
+   bool save( File& file ) const
+   {
+      if( ! boundaryTags.save( file ) )
+      {
+         std::cerr << "Failed to save the boundary tags of the entities with dimension " << DimensionTag::value << "." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      if( ! boundaryTags.load( file ) )
+      {
+         std::cerr << "Failed to load the boundary tags of the entities with dimension " << DimensionTag::value << "." << std::endl;
+         return false;
+      }
+      updateBoundaryIndices( DimensionTag() );
+      return true;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      str << "Boundary tags for entities of dimension " << DimensionTag::value << " are: ";
+      str << boundaryTags << std::endl;
+      str << "Indices of the boundary entities of dimension " << DimensionTag::value << " are: ";
+      str << boundaryIndices << std::endl;
+      str << "Indices of the interior entities of dimension " << DimensionTag::value << " are: ";
+      str << interiorIndices << std::endl;
+   }
+
+   bool operator==( const Layer& layer ) const
+   {
+      TNL_ASSERT( ( boundaryTags == layer.boundaryTags && boundaryIndices == layer.boundaryIndices && interiorIndices == layer.interiorIndices ) ||
+                  ( boundaryTags != layer.boundaryTags && boundaryIndices != layer.boundaryIndices && interiorIndices != layer.interiorIndices ),
+                  std::cerr << "The BoundaryTags layer is in inconsistent state - this is probably a bug in the boundary tags initializer." << std::endl
+                            << "boundaryTags          = " << boundaryTags << std::endl
+                            << "layer.boundaryTags    = " << layer.boundaryTags << std::endl
+                            << "boundaryIndices       = " << boundaryIndices << std::endl
+                            << "layer.boundaryIndices = " << layer.boundaryIndices << std::endl
+                            << "interiorIndices       = " << interiorIndices << std::endl
+                            << "layer.interiorIndices = " << layer.interiorIndices << std::endl; );
+      return boundaryTags == layer.boundaryTags;
+   }
+
+private:
+   BoundaryTagsArray boundaryTags;
+   OrderingArray boundaryIndices;
+   OrderingArray interiorIndices;
+
+   // friend class is needed for templated assignment operators
+   template< typename MeshConfig_, typename Device_, typename DimensionTag_, bool TagStorage_ >
+   friend class Layer;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag >
+class Layer< MeshConfig, Device, DimensionTag, false >
+{
+protected:
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   Layer() = default;
+   explicit Layer( const Layer& other ) {}
+   template< typename Device_ >
+   Layer( const Layer< MeshConfig, Device_, DimensionTag >& other ) {}
+   Layer& operator=( const Layer& other ) { return *this; }
+   template< typename Device_ >
+   Layer& operator=( const Layer< MeshConfig, Device_, DimensionTag >& other ) { return *this; }
+
+   void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount ) {}
+   void resetBoundaryTags( DimensionTag ) {}
+   void setIsBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex, bool isBoundary ) {}
+   void isBoundaryEntity( DimensionTag, const GlobalIndexType& entityIndex ) const {}
+   void updateBoundaryIndices( DimensionTag ) {}
+   void getBoundaryEntitiesCount( DimensionTag ) const {}
+   void getBoundaryEntityIndex( DimensionTag, const GlobalIndexType& i ) const {}
+   void getInteriorEntitiesCount( DimensionTag ) const {}
+   void getInteriorEntityIndex( DimensionTag, const GlobalIndexType& i ) const {}
+
+   bool save( File& file ) const
+   {
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      return true;
+   }
+ 
+   void print( std::ostream& str ) const {}
+
+   bool operator==( const Layer& layer ) const
+   {
+      return true;
+   }
+};
+
+} // namespace BoundaryTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h
new file mode 100644
index 0000000000000000000000000000000000000000..44f6cdc445d00a7f6ae49587500e20b950121873
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/LayerFamily.h
@@ -0,0 +1,240 @@
+/***************************************************************************
+                          LayerFamily.h  -  description
+                             -------------------
+    begin                : Nov 9, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include "ConfigValidator.h"
+#include "Initializer.h"
+#include "Layer.h"
+#include "Traits.h"
+
+namespace TNL {
+namespace Meshes {
+namespace BoundaryTags {
+
+template< typename MeshConfig, typename Device, typename Dimension = DimensionTag< 0 > >
+class LayerInheritor
+   : public Layer< MeshConfig, Device, Dimension >,
+     public LayerInheritor< MeshConfig, Device, typename Dimension::Increment >
+{
+   using LayerType = Layer< MeshConfig, Device, Dimension >;
+   using BaseType = LayerInheritor< MeshConfig, Device, typename Dimension::Increment >;
+protected:
+   using LayerType::setEntitiesCount;
+   using LayerType::resetBoundaryTags;
+   using LayerType::setIsBoundaryEntity;
+   using LayerType::isBoundaryEntity;
+   using LayerType::updateBoundaryIndices;
+   using LayerType::getBoundaryEntitiesCount;
+   using LayerType::getBoundaryEntityIndex;
+   using LayerType::getInteriorEntitiesCount;
+   using LayerType::getInteriorEntityIndex;
+
+   using BaseType::setEntitiesCount;
+   using BaseType::resetBoundaryTags;
+   using BaseType::setIsBoundaryEntity;
+   using BaseType::isBoundaryEntity;
+   using BaseType::updateBoundaryIndices;
+   using BaseType::getBoundaryEntitiesCount;
+   using BaseType::getBoundaryEntityIndex;
+   using BaseType::getInteriorEntitiesCount;
+   using BaseType::getInteriorEntityIndex;
+
+
+   LayerInheritor() = default;
+
+   explicit LayerInheritor( const LayerInheritor& other )
+   {
+      operator=( other );
+   }
+
+   template< typename Device_ >
+   LayerInheritor( const LayerInheritor< MeshConfig, Device_, Dimension >& other )
+   {
+      operator=( other );
+   }
+
+   LayerInheritor& operator=( const LayerInheritor& other )
+   {
+      LayerType::operator=( other );
+      BaseType::operator=( other );
+      return *this;
+   }
+
+   template< typename Device_ >
+   LayerInheritor& operator=( const LayerInheritor< MeshConfig, Device_, Dimension >& other )
+   {
+      LayerType::operator=( other );
+      BaseType::operator=( other );
+      return *this;
+   }
+
+
+   bool save( File& file ) const
+   {
+      return LayerType::save( file ) &&
+             BaseType::save( file );
+   }
+
+   bool load( File& file )
+   {
+      return LayerType::load( file ) &&
+             BaseType::load( file );
+   }
+
+   void print( std::ostream& str ) const
+   {
+      LayerType::print( str );
+      BaseType::print( str );
+   }
+
+   bool operator==( const LayerInheritor& layer ) const
+   {
+      return LayerType::operator==( layer ) &&
+             BaseType::operator==( layer );
+   }
+};
+
+template< typename MeshConfig, typename Device >
+class LayerInheritor< MeshConfig, Device, DimensionTag< MeshConfig::meshDimension + 1 > >
+{
+protected:
+   void setEntitiesCount();
+   void resetBoundaryTags();
+   void setIsBoundaryEntity();
+   void isBoundaryEntity();
+   void updateBoundaryIndices();
+   void getBoundaryEntitiesCount();
+   void getBoundaryEntityIndex();
+   void getInteriorEntitiesCount();
+   void getInteriorEntityIndex();
+
+   LayerInheritor() = default;
+   explicit LayerInheritor( const LayerInheritor& other ) {}
+   template< typename Device_ >
+   LayerInheritor( const LayerInheritor< MeshConfig, Device_, DimensionTag< MeshConfig::meshDimension + 1 > >& other ) {}
+   LayerInheritor& operator=( const LayerInheritor& other ) { return *this; }
+   template< typename Device_ >
+   LayerInheritor& operator=( const LayerInheritor< MeshConfig, Device_, DimensionTag< MeshConfig::meshDimension + 1 > >& other ) { return *this; }
+
+   bool save( File& file ) const
+   {
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      return true;
+   }
+ 
+   void print( std::ostream& str ) const {}
+
+   bool operator==( const LayerInheritor& layer ) const
+   {
+      return true;
+   }
+};
+
+// Note that MeshType is an incomplete type and therefore cannot be used to access
+// MeshType::Config etc. at the time of declaration of this class template.
+template< typename MeshConfig, typename Device, typename MeshType >
+class LayerFamily
+   : public ConfigValidator< MeshConfig >,
+     public Initializer< MeshConfig, Device, MeshType >,
+     public LayerInheritor< MeshConfig, Device >
+{
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+   using GlobalIndexType = typename MeshTraitsType::GlobalIndexType;
+   using BaseType = LayerInheritor< MeshConfig, Device, DimensionTag< 0 > >;
+   template< int Dimension >
+   using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >;
+   template< int Dimension >
+   using WeakTrait = WeakStorageTrait< MeshConfig, Device, DimensionTag< Dimension > >;
+
+   friend Initializer< MeshConfig, Device, MeshType >;
+
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+
+   // getters for boundary tags
+   template< int Dimension >
+   __cuda_callable__
+   bool isBoundaryEntity( const GlobalIndexType& entityIndex ) const
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      return BaseType::isBoundaryEntity( DimensionTag< Dimension >(), entityIndex );
+   }
+
+   template< int Dimension >
+   __cuda_callable__
+   GlobalIndexType getBoundaryEntitiesCount() const
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      return BaseType::getBoundaryEntitiesCount( DimensionTag< Dimension >() );
+   }
+
+   template< int Dimension >
+   __cuda_callable__
+   GlobalIndexType getBoundaryEntityIndex( const GlobalIndexType& i ) const
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      return BaseType::getBoundaryEntityIndex( DimensionTag< Dimension >(), i );
+   }
+
+   template< int Dimension >
+   __cuda_callable__
+   GlobalIndexType getInteriorEntitiesCount() const
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      return BaseType::getInteriorEntitiesCount( DimensionTag< Dimension >() );
+   }
+
+   template< int Dimension >
+   __cuda_callable__
+   GlobalIndexType getInteriorEntityIndex( const GlobalIndexType& i ) const
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      return BaseType::getInteriorEntityIndex( DimensionTag< Dimension >(), i );
+   }
+
+protected:
+   // setters for boundary tags
+   template< int Dimension >
+   void boundaryTagsSetEntitiesCount( const GlobalIndexType& entitiesCount )
+   {
+      BaseType::setEntitiesCount( DimensionTag< Dimension >(), entitiesCount );
+   }
+      
+   template< int Dimension >
+   void resetBoundaryTags()
+   {
+      BaseType::resetBoundaryTags( DimensionTag< Dimension >() );
+   }
+
+   template< int Dimension >
+   void updateBoundaryIndices()
+   {
+      BaseType::updateBoundaryIndices( DimensionTag< Dimension >() );
+   }
+
+   template< int Dimension >
+   __cuda_callable__
+   void setIsBoundaryEntity( const GlobalIndexType& entityIndex, bool isBoundary )
+   {
+      static_assert( WeakTrait< Dimension >::boundaryTagsEnabled, "You try to access boundary tags which are not configured for storage." );
+      BaseType::setIsBoundaryEntity( DimensionTag< Dimension >(), entityIndex, isBoundary );
+   }
+};
+
+} // namespace BoundaryTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d67f0db1d82e29bd893515fab155e9312820fb9
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Traits.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+                          Traits.h  -  description
+                             -------------------
+    begin                : Nov 9, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+
+namespace TNL {
+namespace Meshes {
+namespace BoundaryTags {
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag,
+          bool sensible = (DimensionTag::value <= MeshConfig::meshDimension) >
+struct WeakStorageTrait
+{
+   using EntityTopology = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology;
+   static constexpr bool boundaryTagsEnabled = MeshConfig::boundaryTagsStorage( EntityTopology() );
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag >
+struct WeakStorageTrait< MeshConfig, Device, DimensionTag, false >
+{
+   static constexpr bool boundaryTagsEnabled = false;
+};
+
+} // namespace BoundaryTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a213ba3ae1da52cde09adb2fb5850e78a6ce75d5
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/CMakeLists.txt
@@ -0,0 +1,8 @@
+ADD_SUBDIRECTORY( BoundaryTags )
+
+SET( headers StorageLayer.h
+             SubentityStorageLayer.h
+             SuperentityStorageLayer.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/MeshLayers )
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h
new file mode 100644
index 0000000000000000000000000000000000000000..80bb94da67d4f89b62f2d99794686f4a031a0bb5
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/StorageLayer.h
@@ -0,0 +1,290 @@
+/***************************************************************************
+                          StorageLayer.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/File.h>
+#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h>
+#include <TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h>
+#include <TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag,
+          bool EntityStorage = WeakEntityStorageTrait< MeshConfig, Device, DimensionTag >::storageEnabled >
+class StorageLayer;
+
+
+template< typename MeshConfig, typename Device >
+class StorageLayerFamily
+   : public StorageLayer< MeshConfig, Device, DimensionTag< 0 > >
+{
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+   using BaseType       = StorageLayer< MeshConfig, Device, DimensionTag< 0 > >;
+   template< int Dimension >
+   using EntityTraits = typename MeshTraitsType::template EntityTraits< Dimension >;
+
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+
+protected:
+   template< int Dimension >
+   void setEntitiesCount( const typename MeshTraitsType::GlobalIndexType& entitiesCount )
+   {
+      static_assert( EntityTraits< Dimension >::storageEnabled, "You try to set number of entities which are not configured for storage." );
+      BaseType::setEntitiesCount( DimensionTag< Dimension >(), entitiesCount );
+   }
+
+   template< int Dimension, int Subdimension >
+   typename MeshTraitsType::template SubentityTraits< typename EntityTraits< Dimension >::EntityTopology, Subdimension >::StorageNetworkType&
+   getSubentityStorageNetwork()
+   {
+      static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get subentity storage of entities which are not configured for storage." );
+      static_assert( Dimension > Subdimension, "Invalid combination of Dimension and Subdimension." );
+      using BaseType = SubentityStorageLayerFamily< MeshConfig,
+                                                   Device,
+                                                   typename EntityTraits< Dimension >::EntityTopology >;
+      return BaseType::template getSubentityStorageNetwork< Subdimension >();
+   }
+
+   template< int Dimension, int Superdimension >
+   typename MeshTraitsType::template SuperentityTraits< typename EntityTraits< Dimension >::EntityTopology, Superdimension >::StorageNetworkType&
+   getSuperentityStorageNetwork()
+   {
+      static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get superentity storage of entities which are not configured for storage." );
+      static_assert( Dimension < Superdimension, "Invalid combination of Dimension and Superdimension." );
+      using BaseType = SuperentityStorageLayerFamily< MeshConfig,
+                                                     Device,
+                                                     typename EntityTraits< Dimension >::EntityTopology >;
+      return BaseType::template getSuperentityStorageNetwork< Superdimension >();
+   }
+};
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag >
+class StorageLayer< MeshConfig,
+                    Device,
+                    DimensionTag,
+                    true >
+   : public SubentityStorageLayerFamily< MeshConfig,
+                                         Device,
+                                         typename MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::EntityTopology >,
+     public SuperentityStorageLayerFamily< MeshConfig,
+                                           Device,
+                                           typename MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::EntityTopology >,
+     public StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >
+{
+public:
+   using BaseType = StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >;
+   using MeshTraitsType   = MeshTraits< MeshConfig, Device >;
+   using GlobalIndexType  = typename MeshTraitsType::GlobalIndexType;
+   using EntityTraitsType = typename MeshTraitsType::template EntityTraits< DimensionTag::value >;
+   using StorageArrayType = typename EntityTraitsType::StorageArrayType;
+   using EntityType       = typename EntityTraitsType::EntityType;
+   using EntityTopology   = typename EntityTraitsType::EntityTopology;
+   using SubentityStorageBaseType = SubentityStorageLayerFamily< MeshConfig, Device, EntityTopology >;
+   using SuperentityStorageBaseType = SuperentityStorageLayerFamily< MeshConfig, Device, EntityTopology >;
+
+   StorageLayer() = default;
+
+   explicit StorageLayer( const StorageLayer& other )
+   {
+      operator=( other );
+   }
+
+   template< typename Device_ >
+   StorageLayer( const StorageLayer< MeshConfig, Device_, DimensionTag >& other )
+   {
+      operator=( other );
+   }
+
+   StorageLayer& operator=( const StorageLayer& other )
+   {
+      entities.setLike( other.entities );
+      entities = other.entities;
+      SubentityStorageBaseType::operator=( other );
+      SuperentityStorageBaseType::operator=( other );
+      BaseType::operator=( other );
+      return *this;
+   }
+
+   template< typename Device_ >
+   StorageLayer& operator=( const StorageLayer< MeshConfig, Device_, DimensionTag >& other )
+   {
+      entities.setLike( other.entities );
+      entities = other.entities;
+      SubentityStorageBaseType::operator=( other );
+      SuperentityStorageBaseType::operator=( other );
+      BaseType::operator=( other );
+      return *this;
+   }
+
+   bool save( File& file ) const
+   {
+      if( ! SubentityStorageBaseType::save( file ) ||
+          ! SuperentityStorageBaseType::save( file ) ||
+          ! this->entities.save( file ) ||
+          ! BaseType::save( file ) )
+      {
+         std::cerr << "Saving of the mesh entities with dimension " << DimensionTag::value << " failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      if( ! SubentityStorageBaseType::load( file ) ||
+          ! SuperentityStorageBaseType::load( file ) ||
+          ! this->entities.load( file ) ||
+          ! BaseType::load( file ) )
+      {
+         std::cerr << "Loading of the mesh entities with dimension " << DimensionTag::value << " failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      str << "The entities with dimension " << DimensionTag::value << " are: " << std::endl;
+      for( GlobalIndexType i = 0; i < entities.getSize(); i++ )
+         str << i << " " << entities[ i ] << std::endl;
+      SubentityStorageBaseType::print( str );
+      SuperentityStorageBaseType::print( str );
+      str << std::endl;
+      BaseType::print( str );
+   }
+
+   bool operator==( const StorageLayer& meshLayer ) const
+   {
+      return ( entities == meshLayer.entities &&
+               SubentityStorageBaseType::operator==( meshLayer ) &&
+               SuperentityStorageBaseType::operator==( meshLayer ) &&
+               BaseType::operator==( meshLayer ) );
+   }
+
+
+   using BaseType::getEntitiesCount;
+   __cuda_callable__
+   GlobalIndexType getEntitiesCount( DimensionTag ) const
+   {
+      return this->entities.getSize();
+   }
+
+   using BaseType::getEntity;
+   __cuda_callable__
+   EntityType& getEntity( DimensionTag,
+                          const GlobalIndexType entityIndex )
+   {
+      return this->entities[ entityIndex ];
+   }
+
+   __cuda_callable__
+   const EntityType& getEntity( DimensionTag,
+                                const GlobalIndexType entityIndex ) const
+   {
+      return this->entities[ entityIndex ];
+   }
+
+protected:
+   using BaseType::setEntitiesCount;
+   void setEntitiesCount( DimensionTag, const GlobalIndexType& entitiesCount )
+   {
+      this->entities.setSize( entitiesCount );
+      SubentityStorageBaseType::setEntitiesCount( entitiesCount );
+      SuperentityStorageBaseType::setEntitiesCount( entitiesCount );
+   }
+
+   StorageArrayType entities;
+
+   // friend class is needed for templated assignment operators
+   template< typename MeshConfig_, typename Device_, typename DimensionTag_, bool Storage_ >
+   friend class StorageLayer;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag >
+class StorageLayer< MeshConfig, Device, DimensionTag, false >
+   : public StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >
+{
+   using BaseType = StorageLayer< MeshConfig, Device, typename DimensionTag::Increment >;
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+};
+
+// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakEntityStorageTrait)
+template< typename MeshConfig,
+          typename Device >
+class StorageLayer< MeshConfig, Device, DimensionTag< MeshConfig::meshDimension + 1 >, false >
+{
+protected:
+   using DimensionTag     = Meshes::DimensionTag< MeshConfig::meshDimension >;
+   using GlobalIndexType  = typename MeshConfig::GlobalIndexType;
+
+   StorageLayer() = default;
+
+   explicit StorageLayer( const StorageLayer& other ) {}
+
+   template< typename Device_ >
+   StorageLayer( const StorageLayer< MeshConfig, Device_, DimensionTag >& other ) {}
+
+   StorageLayer& operator=( const StorageLayer& other )
+   {
+      return *this;
+   }
+
+   template< typename Device_ >
+   StorageLayer& operator=( const StorageLayer< MeshConfig, Device_, DimensionTag >& other )
+   {
+      return *this;
+   }
+
+
+   void setEntitiesCount() {}
+   void getEntitiesCount() const {}
+   void getEntity() const {}
+
+   bool save( File& file ) const
+   {
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      return true;
+   }
+
+   void print( std::ostream& str ) const {}
+
+   bool operator==( const StorageLayer& meshLayer ) const
+   {
+      return true;
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h
new file mode 100644
index 0000000000000000000000000000000000000000..c26e525a9c5e532708a3bb430bdeb140b56f0dc4
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/SubentityStorageLayer.h
@@ -0,0 +1,228 @@
+/***************************************************************************
+                          SubentityStorageLayer.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/File.h>
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SubdimensionTag,
+          bool SubentityStorage = WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, SubdimensionTag >::storageEnabled >
+class SubentityStorageLayer;
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SubentityStorageLayerFamily
+   : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< 0 > >
+{
+   using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< 0 > >;
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+
+protected:
+   template< int Subdimension >
+   typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >::StorageNetworkType&
+   getSubentityStorageNetwork()
+   {
+      static_assert( EntityTopology::dimension > Subdimension, "Invalid combination of Dimension and Subdimension." );
+      return BaseType::getSubentityStorageNetwork( DimensionTag< Subdimension >() );
+   }
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SubdimensionTag >
+class SubentityStorageLayer< MeshConfig,
+                             Device,
+                             EntityTopology,
+                             SubdimensionTag,
+                             true >
+   : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >
+{
+   using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >;
+   using MeshTraitsType      = MeshTraits< MeshConfig, Device >;
+   using SubentityTraitsType = typename MeshTraitsType::template SubentityTraits< EntityTopology, SubdimensionTag::value >;
+
+protected:
+   using GlobalIndexType    = typename MeshTraitsType::GlobalIndexType;
+   using StorageNetworkType = typename SubentityTraitsType::StorageNetworkType;
+
+   SubentityStorageLayer() = default;
+
+   explicit SubentityStorageLayer( const SubentityStorageLayer& other )
+   {
+      operator=( other );
+   }
+
+   template< typename Device_ >
+   SubentityStorageLayer( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other )
+   {
+      operator=( other );
+   }
+
+   SubentityStorageLayer& operator=( const SubentityStorageLayer& other )
+   {
+      BaseType::operator=( other );
+      storageNetwork.setLike( other.storageNetwork );
+      storageNetwork = other.storageNetwork;
+      return *this;
+   }
+
+   template< typename Device_ >
+   SubentityStorageLayer& operator=( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other )
+   {
+      BaseType::operator=( other );
+      storageNetwork.setLike( other.storageNetwork );
+      storageNetwork = other.storageNetwork;
+      return *this;
+   }
+
+
+   bool save( File& file ) const
+   {
+      if( ! BaseType::save( file ) ||
+          ! this->storageNetwork.save( file ) )
+      {
+         std::cerr << "Saving of the entity subentities layer with " << SubdimensionTag::value << " dimension failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      if( ! BaseType::load( file ) ||
+          ! this->storageNetwork.load( file ) )
+      {
+         std::cerr << "Loading of the entity subentities layer with " << SubdimensionTag::value << " dimension failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+      str << "Storage network for subentities with dimension " << SubdimensionTag::value << " of entities with dimension " << EntityTopology::dimension << " is: " << std::endl;
+      str << this->storageNetwork << std::endl;
+   }
+
+   bool operator==( const SubentityStorageLayer& layer ) const
+   {
+      return ( BaseType::operator==( layer ) &&
+               storageNetwork == layer.storageNetwork );
+   }
+
+protected:
+   void setEntitiesCount( const GlobalIndexType& entitiesCount )
+   {
+      BaseType::setEntitiesCount( entitiesCount );
+      this->storageNetwork.setKeysRange( entitiesCount );
+      this->storageNetwork.allocate();
+   }
+
+   using BaseType::getSubentityStorageNetwork;
+   StorageNetworkType& getSubentityStorageNetwork( SubdimensionTag )
+   {
+      return this->storageNetwork;
+   }
+
+private:
+   StorageNetworkType storageNetwork;
+
+   // friend class is needed for templated assignment operators
+   template< typename MeshConfig_, typename Device_, typename EntityTopology_, typename SubdimensionTag_, bool Storage_ >
+   friend class SubentityStorageLayer;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SubdimensionTag >
+class SubentityStorageLayer< MeshConfig,
+                             Device,
+                             EntityTopology,
+                             SubdimensionTag,
+                             false >
+   : public SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >
+{
+   using BaseType = SubentityStorageLayer< MeshConfig, Device, EntityTopology, typename SubdimensionTag::Increment >;
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+};
+
+// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSubentityStorageTrait)
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SubentityStorageLayer< MeshConfig,
+                             Device,
+                             EntityTopology,
+                             DimensionTag< EntityTopology::dimension >,
+                             false >
+{
+   using SubdimensionTag = DimensionTag< EntityTopology::dimension >;
+
+protected:
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+
+   SubentityStorageLayer() = default;
+   explicit SubentityStorageLayer( const SubentityStorageLayer& other ) {}
+   template< typename Device_ >
+   SubentityStorageLayer( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) {}
+   template< typename Device_ >
+   SubentityStorageLayer& operator=( const SubentityStorageLayer< MeshConfig, Device_, EntityTopology, SubdimensionTag >& other ) { return *this; }
+
+   void setEntitiesCount( GlobalIndexType entitiesCount ) {}
+
+   void print( std::ostream& str ) const {}
+
+   bool operator==( const SubentityStorageLayer& layer ) const
+   {
+      return true;
+   }
+
+   bool save( File& file ) const
+   {
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      return true;
+   }
+ 
+   void getSubentityStorageNetwork( SubdimensionTag ) {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h
new file mode 100644
index 0000000000000000000000000000000000000000..62d86fe7bff83042f19ab41f68023c91c4cf83ee
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/MeshLayers/SuperentityStorageLayer.h
@@ -0,0 +1,221 @@
+/***************************************************************************
+                          SuperentityStorageLayer.h  -  description
+                             -------------------
+    begin                : Feb 13, 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/File.h>
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+#include <TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SuperdimensionTag,
+          bool SuperentityStorage = WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, SuperdimensionTag >::storageEnabled >
+class SuperentityStorageLayer;
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SuperentityStorageLayerFamily
+   : public SuperentityStorageLayer< MeshConfig,
+                                     Device,
+                                     EntityTopology,
+                                     DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >
+{
+   using BaseType = SuperentityStorageLayer< MeshConfig,
+                                             Device,
+                                             EntityTopology,
+                                             DimensionTag< MeshTraits< MeshConfig, Device >::meshDimension > >;
+   using MeshTraitsType = MeshTraits< MeshConfig, Device >;
+
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+
+protected:
+   template< int Superdimension >
+   typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >::StorageNetworkType&
+   getSuperentityStorageNetwork()
+   {
+      static_assert( EntityTopology::dimension < Superdimension, "Invalid combination of Dimension and Superdimension." );
+      return BaseType::getSuperentityStorageNetwork( DimensionTag< Superdimension >() );
+   }
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SuperdimensionTag >
+class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, SuperdimensionTag, true >
+   : public SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >
+{
+   using BaseType = SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >;
+   using MeshTraitsType        = MeshTraits< MeshConfig, Device >;
+   using SuperentityTraitsType = typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >;
+
+protected:
+   using GlobalIndexType    = typename MeshTraitsType::GlobalIndexType;
+   using StorageNetworkType = typename SuperentityTraitsType::StorageNetworkType;
+ 
+   SuperentityStorageLayer() = default;
+
+   explicit SuperentityStorageLayer( const SuperentityStorageLayer& other )
+   {
+      operator=( other );
+   }
+
+   template< typename Device_ >
+   SuperentityStorageLayer( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other )
+   {
+      operator=( other );
+   }
+
+   SuperentityStorageLayer& operator=( const SuperentityStorageLayer& other )
+   {
+      BaseType::operator=( other );
+      storageNetwork.setLike( other.storageNetwork );
+      storageNetwork = other.storageNetwork;
+      return *this;
+   }
+
+   template< typename Device_ >
+   SuperentityStorageLayer& operator=( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other )
+   {
+      BaseType::operator=( other );
+      storageNetwork.setLike( other.storageNetwork );
+      storageNetwork = other.storageNetwork;
+      return *this;
+   }
+
+
+   bool save( File& file ) const
+   {
+      if( ! BaseType::save( file ) ||
+          ! this->storageNetwork.save( file ) )
+      {
+         std::cerr << "Saving of the entity superentities layer with " << SuperdimensionTag::value << " dimension failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      if( ! BaseType::load( file ) ||
+          ! this->storageNetwork.load( file ) )
+      {
+         std::cerr << "Loading of the entity superentities layer with " << SuperdimensionTag::value << " dimension failed." << std::endl;
+         return false;
+      }
+      return true;
+   }
+
+   void print( std::ostream& str ) const
+   {
+      BaseType::print( str );
+      str << "Storage network for superentities with dimension " << SuperdimensionTag::value << " of entities with dimension " << EntityTopology::dimension << " is: " << std::endl;
+      str << this->storageNetwork << std::endl;
+   }
+
+   bool operator==( const SuperentityStorageLayer& layer ) const
+   {
+      return ( BaseType::operator==( layer ) &&
+               storageNetwork == layer.storageNetwork );
+   }
+
+protected:
+   void setEntitiesCount( const GlobalIndexType& entitiesCount )
+   {
+      BaseType::setEntitiesCount( entitiesCount );
+      this->storageNetwork.setKeysRange( entitiesCount );
+   }
+
+   using BaseType::getSuperentityStorageNetwork;
+   StorageNetworkType& getSuperentityStorageNetwork( SuperdimensionTag )
+   {
+      return this->storageNetwork;
+   }
+
+private:
+   StorageNetworkType storageNetwork;
+
+   // friend class is needed for templated assignment operators
+   template< typename MeshConfig_, typename Device_, typename EntityTopology_, typename SuperdimensionTag_, bool Storage_ >
+   friend class SuperentityStorageLayer;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SuperdimensionTag >
+class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, SuperdimensionTag, false >
+   : public SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >
+{
+   using BaseType = SuperentityStorageLayer< MeshConfig, Device, EntityTopology, typename SuperdimensionTag::Decrement >;
+public:
+   // inherit constructors and assignment operators (including templated versions)
+   using BaseType::BaseType;
+   using BaseType::operator=;
+};
+
+// termination of recursive inheritance (everything is reduced to EntityStorage == false thanks to the WeakSuperentityStorageTrait)
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology >
+class SuperentityStorageLayer< MeshConfig, Device, EntityTopology, DimensionTag< EntityTopology::dimension >, false >
+{
+   using SuperdimensionTag = DimensionTag< EntityTopology::dimension >;
+
+protected:
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+ 
+   SuperentityStorageLayer() = default;
+   explicit SuperentityStorageLayer( const SuperentityStorageLayer& other ) {}
+   template< typename Device_ >
+   SuperentityStorageLayer( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) {}
+   template< typename Device_ >
+   SuperentityStorageLayer& operator=( const SuperentityStorageLayer< MeshConfig, Device_, EntityTopology, SuperdimensionTag >& other ) { return *this; }
+
+   void setEntitiesCount( GlobalIndexType entitiesCount ) {}
+
+   void print( std::ostream& str ) const {}
+
+   bool operator==( const SuperentityStorageLayer& layer ) const
+   {
+      return true;
+   }
+
+   bool save( File& file ) const
+   {
+      return true;
+   }
+
+   bool load( File& file )
+   {
+      return true;
+   }
+ 
+   void getSuperentityStorageNetwork( SuperdimensionTag ) {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h b/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h
deleted file mode 100644
index 82cbc84a24ae2b57bbac34d5b995a6a99befc627..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/MeshWriterNetgen.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/***************************************************************************
-                          MeshWriterNetgen.h  -  description
-                             -------------------
-    begin                : Feb 22, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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 <fstream>
-#include <istream>
-#include <sstream>
-#include <iomanip>
-
-namespace TNL {
-namespace Meshes {
-
-class MeshWriterNetgen
-{
-   public:
-
-   template< typename MeshType >
-   static bool writeMesh( const String& fileName,
-                          MeshType& mesh,
-                          bool verbose )
-   {
-      std::fstream outputFile;
-      outputFile.open( fileName.getString(), std::ios::out );
-      if( ! outputFile )
-      {
-         std::cerr << "I am not able to open the output file " << fileName << "." << std::endl;
-         return false;
-      }
-      outputFile << std::setprecision( 6 );
-      outputFile << fixed;
-
-      const int meshDimension = MeshType::meshDimension;
-      typedef typename MeshType::template EntitiesTraits< 0 >::GlobalIndexType VerticesIndexType;
-      typedef typename MeshType::PointType                                     PointType;
-      const VerticesIndexType numberOfVertices = mesh.getNumberOfVertices();
-      outputFile << numberOfVertices << std::endl;
-      for( VerticesIndexType i = 0; i < numberOfVertices; i++ )
-      {
-         const PointType& point = mesh.getVertex( i ).getPoint();
-         outputFile << " ";
-         for( int d = 0; d < meshDimension; d++ )
-            outputFile << " " << point[ d ];
-         outputFile << std::endl;
-      }
-
-      typedef typename MeshType::template EntitiesTraits< meshDimension >::GlobalIndexType CellIndexType;
-      typedef typename MeshType::template EntitiesTraits< meshDimension >::Type            CellType;
-      typedef typename CellType::LocalIndexType                                             LocalIndexType;
-
-      const CellIndexType numberOfCells = mesh.template getNumberOfEntities< meshDimension >();
-      outputFile << numberOfCells << std::endl;
-      for( CellIndexType cellIdx = 0; cellIdx < numberOfCells; cellIdx++ )
-      {
-         const CellType& cell = mesh.template getEntity< meshDimension >( cellIdx );
-         outputFile << "   1";
-         for( LocalIndexType cellVertexIdx = 0;
-              cellVertexIdx < meshDimension + 1;
-              cellVertexIdx++ )
-            outputFile << " " << cell.getVertexIndex( cellVertexIdx );
-         outputFile << std::endl;
-      }
-
-      return true;
-   }
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h b/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h
deleted file mode 100644
index 930e00e5ba977111f3b9f4adf30a00d7d2a62003..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/***************************************************************************
-                          MeshWriterVTKLegacy.h  -  description
-                             -------------------
-    begin                : Mar 20, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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 <fstream>
-#include <istream>
-#include <sstream>
-#include <iomanip>
-
-#include <TNL/Meshes/Topologies/MeshTriangleTopology.h>
-#include <TNL/Meshes/Topologies/MeshQuadrilateralTopology.h>
-#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h>
-#include <TNL/Meshes/Topologies/MeshHexahedronTopology.h>
-#include <TNL/Meshes/MeshEntity.h>
-
-namespace TNL {
-namespace Meshes {
-
-enum tnlVTKMeshEntities { tnlVTKVertex = 1,
-                          tnlVTKPolyVertex = 2,
-                          tnlVTKLine = 3,
-                          tnlVTKPolyLine = 4,
-                          tnlVTKTriangle = 5,
-                          tnlVTKTriangleStrip = 6,
-                          tnlVTKPolygon = 7,
-                          tnlVTKPixel = 8,
-                          tnlVTKQuad = 9,
-                          tnlVTKTetra = 10,
-                          tnlVTKVoxel = 11,
-                          tnlVTKHexahedron = 12,
-                          tnlVTKWedge = 13,
-                          tnlVTKPyramid = 14 };
-
-template< typename MeshEntity >
-struct MeshEntityVTKType{};
-
-template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshTriangleTopology > >     { enum { VTKType = tnlVTKTriangle }; };
-template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshQuadrilateralTopology > >{ enum { VTKType = tnlVTKQuad }; };
-template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshTetrahedronTopology > >  { enum { VTKType = tnlVTKTetra }; };
-template< typename MeshConfig > struct MeshEntityVTKType< MeshEntity< MeshConfig, MeshHexahedronTopology > >   { enum { VTKType = tnlVTKHexahedron }; };
-
-class MeshWriterVTKLegacy
-{
-   public:
-
-   template< typename MeshType >
-   static bool write( const String& fileName,
-                      MeshType& mesh,
-                      bool verbose )
-   {
-      if( MeshType::dimensions > 3 )
-      {
-         std::cerr << "You try to write mesh with " << MeshType::dimensions
-              << "dimensions but VTK legacy format supports only 1D, 2D and 3D meshes." << std::endl;
-         return false;
-      }
-      std::fstream outputFile;
-      outputFile.open( fileName.getString(), std::ios::out );
-      if( ! outputFile )
-      {
-         std::cerr << "I am not able to open the output file " << fileName << "." << std::endl;
-         return false;
-      }
-      outputFile << std::setprecision( 6 );
-      outputFile << std::fixed;
-
-      return writeMesh( outputFile, mesh, verbose );
-   }
-
-   template< typename MeshType >
-   static bool writeMesh( std::ostream& file,
-                          MeshType& mesh,
-                          bool verbose )
-   {
-      typedef typename MeshType::MeshTraitsType::CellType CellType;
-      file << "# vtk DataFile Version 2.0" << std::endl;
-      file << "TNL Mesh" << std::endl;
-      file << "ASCII" << std::endl;
-      file << "DATASET UNSTRUCTURED_GRID" << std::endl;
-      file << std::endl;
-      file << "POINTS " << mesh.template getNumberOfEntities< 0 >() << " double" << std::endl;
-      for( int i = 0; i < mesh.template getNumberOfEntities< 0 >(); i++ )
-      {
-         mesh.template getEntity< 0 >( i ).getPoint().write( file );
-         for( int j = MeshType::dimensions; j < 3; j++ )
-            file << " 0.0";
-         file << std::endl;
-      }
-      file << std::endl;
-      file << "CELLS " << mesh.getNumberOfCells();
-      long int listSize( 0 );
-      for( int i = 0; i < mesh.getNumberOfCells(); i++ )
-         listSize += mesh.getCell( i ).template getNumberOfSubentities< 0 >() + 1;
-      file << " " << listSize << std::endl;
-      for( int i = 0; i < mesh.getNumberOfCells(); i++ )
-      {
-         int numberOfVertices = mesh.getCell( i ).template getNumberOfSubentities< 0 >();
-         file << numberOfVertices << " ";
-         for( int j = 0; j < numberOfVertices - 1; j++ )
-            file << mesh.getCell( i ).template getSubentityIndex< 0 >( j ) << " ";
-         file << mesh.getCell( i ).template getSubentityIndex< 0 >( numberOfVertices - 1 ) << std::endl;
-      }
-      file << std::endl;
-      file << "CELL_TYPES " <<  mesh.getNumberOfCells() << std::endl;
-      for( int i = 0; i < mesh.getNumberOfCells(); i++ )
-      {
-         file << MeshEntityVTKType< CellType >::VTKType << std::endl;
-      }
-      file << std::endl;
-      return true;
-   }
-
-
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/Mesh_impl.h b/src/TNL/Meshes/MeshDetails/Mesh_impl.h
index eb5f457a6b4449832e750ac96eecba033e173ded..cd704edafc8dd0488ef971586235ed8534ccb0b3 100644
--- a/src/TNL/Meshes/MeshDetails/Mesh_impl.h
+++ b/src/TNL/Meshes/MeshDetails/Mesh_impl.h
@@ -17,101 +17,232 @@
 #pragma once
 
 #include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshDetails/EntityStorageRebinder.h>
+#include <TNL/Meshes/MeshDetails/IndexPermutationApplier.h>
+#include <TNL/Meshes/MeshDetails/initializer/Initializer.h>
 
 namespace TNL {
 namespace Meshes {
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device, typename MeshType >
+void
+MeshInitializableBase< MeshConfig, Device, MeshType >::
+init( typename MeshTraitsType::PointArrayType& points,
+      typename MeshTraitsType::CellSeedArrayType& cellSeeds )
+{
+   Initializer< typename MeshType::Config > initializer;
+   initializer.createMesh( points, cellSeeds, *static_cast<MeshType*>(this) );
+   // init boundary tags
+   static_cast< BoundaryTags::LayerFamily< MeshConfig, Device, MeshType >* >( static_cast< MeshType* >( this ) )->initLayer();
+}
+
+
+template< typename MeshConfig, typename Device >
+Mesh< MeshConfig, Device >::
+Mesh( const Mesh& mesh )
+   : StorageBaseType( mesh ),
+     BoundaryTagsLayerFamily( mesh )
+{
+   // update pointers from entities into the subentity and superentity storage networks
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
+}
+
+template< typename MeshConfig, typename Device >
+   template< typename Device_ >
+Mesh< MeshConfig, Device >::
+Mesh( const Mesh< MeshConfig, Device_ >& mesh )
+   : StorageBaseType( mesh ),
+     BoundaryTagsLayerFamily( mesh )
+{
+   // update pointers from entities into the subentity and superentity storage networks
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
+}
+
+template< typename MeshConfig, typename Device >
+Mesh< MeshConfig, Device >&
+Mesh< MeshConfig, Device >::
+operator=( const Mesh& mesh )
+{
+   StorageBaseType::operator=( mesh );
+   BoundaryTagsLayerFamily::operator=( mesh );
+   // update pointers from entities into the subentity and superentity storage networks
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
+   return *this;
+}
+
+template< typename MeshConfig, typename Device >
+   template< typename Device_ >
+Mesh< MeshConfig, Device >&
+Mesh< MeshConfig, Device >::
+operator=( const Mesh< MeshConfig, Device_ >& mesh )
+{
+   StorageBaseType::operator=( mesh );
+   BoundaryTagsLayerFamily::operator=( mesh );
+   // update pointers from entities into the subentity and superentity storage networks
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
+   return *this;
+}
+
+template< typename MeshConfig, typename Device >
+constexpr int
+Mesh< MeshConfig, Device >::
+getMeshDimension()
+{
+   return MeshTraitsType::meshDimension;
+}
+
+template< typename MeshConfig, typename Device >
 String
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 getType()
 {
    return String( "Meshes::Mesh< ") + MeshConfig::getType() + " >";
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 String
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 getTypeVirtual() const
 {
    return this->getType();
 }
 
-template< typename MeshConfig >
-constexpr int
-Mesh< MeshConfig >::
-getMeshDimension()
+template< typename MeshConfig, typename Device >
+String
+Mesh< MeshConfig, Device >::
+getSerializationType()
+{
+   return Mesh::getType();
+}
+
+template< typename MeshConfig, typename Device >
+String
+Mesh< MeshConfig, Device >::
+getSerializationTypeVirtual() const
 {
-   return dimension;
+   return this->getSerializationType();
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
    template< int Dimension >
-bool
-Mesh< MeshConfig >::
-entitiesAvalable() const
+constexpr bool
+Mesh< MeshConfig, Device >::
+entitiesAvailable()
 {
-   return MeshTraitsType::template EntityTraits< Dimension >::available;
+   return MeshTraitsType::template EntityTraits< Dimension >::storageEnabled;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
    template< int Dimension >
-typename Mesh< MeshConfig >::GlobalIndexType
-Mesh< MeshConfig >::
-getNumberOfEntities() const
+__cuda_callable__
+typename Mesh< MeshConfig, Device >::GlobalIndexType
+Mesh< MeshConfig, Device >::
+getEntitiesCount() const
 {
-   return entitiesStorage.getNumberOfEntities( MeshDimensionTag< Dimension >() );
+   static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get number of entities which are not configured for storage." );
+   return StorageBaseType::getEntitiesCount( DimensionTag< Dimension >() );
 }
 
-template< typename MeshConfig >
-typename Mesh< MeshConfig >::GlobalIndexType
-Mesh< MeshConfig >::
-template getNumberOfCells() const
+template< typename MeshConfig, typename Device >
+   template< int Dimension >
+__cuda_callable__
+typename Mesh< MeshConfig, Device >::template EntityType< Dimension >&
+Mesh< MeshConfig, Device >::
+getEntity( const GlobalIndexType& entityIndex )
 {
-   return entitiesStorage.getNumberOfEntities( MeshDimensionTag< dimensions >() );
+   static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get entity which is not configured for storage." );
+   return StorageBaseType::getEntity( DimensionTag< Dimension >(), entityIndex );
 }
 
-template< typename MeshConfig >
-typename Mesh< MeshConfig >::CellType&
-Mesh< MeshConfig >::
-getCell( const GlobalIndexType cellIndex )
+template< typename MeshConfig, typename Device >
+   template< int Dimension >
+__cuda_callable__
+const typename Mesh< MeshConfig, Device >::template EntityType< Dimension >&
+Mesh< MeshConfig, Device >::
+getEntity( const GlobalIndexType& entityIndex ) const
 {
-   return entitiesStorage.getEntity( MeshDimensionTag< dimensions >(), cellIndex );
+   static_assert( EntityTraits< Dimension >::storageEnabled, "You try to get entity which is not configured for storage." );
+   return StorageBaseType::getEntity( DimensionTag< Dimension >(), entityIndex );
 }
 
-template< typename MeshConfig >
-const typename Mesh< MeshConfig >::CellType&
-Mesh< MeshConfig >::
-getCell( const GlobalIndexType cellIndex ) const
+
+// duplicated for compatibility with grids
+template< typename MeshConfig, typename Device >
+   template< typename Entity >
+__cuda_callable__
+typename Mesh< MeshConfig, Device >::GlobalIndexType
+Mesh< MeshConfig, Device >::
+getEntitiesCount() const
 {
-   return entitiesStorage.getEntity( MeshDimensionTag< dimensions >(), cellIndex );
+   return getEntitiesCount< Entity::getEntityDimension() >();
 }
 
-template< typename MeshConfig >
-   template< int Dimension >
-typename Mesh< MeshConfig >::template EntityType< Dimension >&
-Mesh< MeshConfig >::
-getEntity( const GlobalIndexType entityIndex )
+template< typename MeshConfig, typename Device >
+   template< typename Entity >
+__cuda_callable__
+Entity&
+Mesh< MeshConfig, Device >::
+getEntity( const GlobalIndexType& entityIndex )
 {
-   return entitiesStorage.getEntity( MeshDimensionTag< Dimension >(), entityIndex );
+   return getEntity< Entity::getEntityDimension() >( entityIndex );
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
+   template< typename Entity >
+__cuda_callable__
+const Entity&
+Mesh< MeshConfig, Device >::
+getEntity( const GlobalIndexType& entityIndex ) const
+{
+   return getEntity< Entity::getEntityDimension() >( entityIndex );
+}
+
+
+template< typename MeshConfig, typename Device >
    template< int Dimension >
-const typename Mesh< MeshConfig >::template EntityType< Dimension >&
-Mesh< MeshConfig >::
-getEntity( const GlobalIndexType entityIndex ) const
+void
+Mesh< MeshConfig, Device >::
+reorderEntities( const GlobalIndexVector& perm,
+                 const GlobalIndexVector& iperm )
 {
-   return entitiesStorage.getEntity( MeshDimensionTag< Dimension >(), entityIndex );
+   static_assert( entitiesAvailable< Dimension >(), "Entities which are not stored cannot be reordered." );
+
+   const GlobalIndexType entitiesCount = getEntitiesCount< Dimension >();
+
+   // basic sanity check
+   if( perm.getSize() != entitiesCount || iperm.getSize() != entitiesCount ) {
+      throw std::logic_error( "Wrong size of permutation vectors: "
+                              "perm = " + std::to_string( perm ) + ", "
+                              "iperm = " + std::to_string( iperm ) );
+   }
+   TNL_ASSERT( perm.min() == 0 && perm.max() == entitiesCount - 1,
+               std::cerr << "Given array is not a permutation: min = " << perm.min()
+                         << ", max = " << perm.max()
+                         << ", number of entities = " << entitiesCount
+                         << ", array = " << perm << std::endl; );
+   TNL_ASSERT( iperm.min() == 0 && iperm.max() == entitiesCount - 1,
+               std::cerr << "Given array is not a permutation: min = " << iperm.min()
+                         << ", max = " << iperm.max()
+                         << ", number of entities = " << entitiesCount
+                         << ", array = " << iperm << std::endl; );
+
+   IndexPermutationApplier< Mesh, Dimension >::exec( *this, perm, iperm );
+   // update pointers from entities into the subentity and superentity storage networks
+   // TODO: it would be enough to rebind just the permuted entities
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
+   // update boundary tags
+   static_cast< BoundaryTagsLayerFamily* >( this )->initLayer();
 }
- 
-template< typename MeshConfig >
+
+
+template< typename MeshConfig, typename Device >
 bool
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 save( File& file ) const
 {
    if( ! Object::save( file ) ||
-       ! entitiesStorage.save( file ) )
+       ! StorageBaseType::save( file ) ||
+       ! BoundaryTagsLayerFamily::save( file ) )
    {
       std::cerr << "Mesh saving failed." << std::endl;
       return false;
@@ -119,67 +250,71 @@ save( File& file ) const
    return true;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 bool
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 load( File& file )
 {
    if( ! Object::load( file ) ||
-       ! entitiesStorage.load( file ) )
+       ! StorageBaseType::load( file ) ||
+       ! BoundaryTagsLayerFamily::load( file ) )
    {
       std::cerr << "Mesh loading failed." << std::endl;
       return false;
    }
+   // update pointers from entities into the subentity and superentity storage networks
+   EntityStorageRebinder< Mesh< MeshConfig, Device > >::exec( *this );
    return true;
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 void
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 print( std::ostream& str ) const
 {
-   entitiesStorage.print( str );
+   // FIXME: there is a problem with multimaps and accessors holding pointers into the device memory
+   if( std::is_same< Device, Devices::Cuda >::value ) {
+      str << "Textual representation of meshes stored on the CUDA device is not supported." << std::endl;
+   }
+   else {
+      StorageBaseType::print( str );
+      BoundaryTagsLayerFamily::print( str );
+   }
 }
 
-template< typename MeshConfig >
+template< typename MeshConfig, typename Device >
 bool
-Mesh< MeshConfig >::
+Mesh< MeshConfig, Device >::
 operator==( const Mesh& mesh ) const
 {
-   return entitiesStorage.operator==( mesh.entitiesStorage );
+   return StorageBaseType::operator==( mesh ) &&
+          BoundaryTagsLayerFamily::operator==( mesh );
 }
 
-template< typename MeshConfig >
-   template< typename DimensionTag >
-typename Mesh< MeshConfig >::template EntityTraits< DimensionTag::value >::StorageArrayType&
-Mesh< MeshConfig >::
-entitiesArray()
-{
-   return entitiesStorage.entitiesArray( DimensionTag() );
-}
-
-template< typename MeshConfig >
-   template< typename DimensionTag, typename SuperDimensionTag >
-typename Mesh< MeshConfig >::MeshTraitsType::GlobalIdArrayType&
-Mesh< MeshConfig >::
-superentityIdsArray()
+template< typename MeshConfig, typename Device >
+bool
+Mesh< MeshConfig, Device >::
+operator!=( const Mesh& mesh ) const
 {
-   return entitiesStorage.template superentityIdsArray< SuperDimensionTag >( DimensionTag() );
+   return ! operator==( mesh );
 }
 
-template< typename MeshConfig >
-bool
-Mesh< MeshConfig >::
-init( const typename Mesh< MeshConfig >::MeshTraitsType::PointArrayType& points,
-      const typename Mesh< MeshConfig >::MeshTraitsType::CellSeedArrayType& cellSeeds )
+template< typename MeshConfig, typename Device >
+void
+Mesh< MeshConfig, Device >::
+writeProlog( Logger& logger ) const
 {
-   MeshInitializer< MeshConfig> meshInitializer;
-   return meshInitializer.createMesh( points, cellSeeds, *this );
+   logger.writeParameter( "Dimension:", getMeshDimension() );
+   logger.writeParameter( "Number of cells:", getEntitiesCount< getMeshDimension() >() );
+   if( getMeshDimension() > 1 )
+      logger.writeParameter( "Number of faces:", getEntitiesCount< getMeshDimension() - 1 >() );
+   logger.writeParameter( "Number of vertices:", getEntitiesCount< 0 >() );
+   // TODO: more parameters?
 }
 
 
-template< typename MeshConfig >
-std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh )
+template< typename MeshConfig, typename Device >
+std::ostream& operator<<( std::ostream& str, const Mesh< MeshConfig, Device >& mesh )
 {
    mesh.print( str );
    return str;
@@ -187,4 +322,3 @@ std::ostream& operator <<( std::ostream& str, const Mesh< MeshConfig >& mesh )
 
 } // namespace Meshes
 } // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/Traverser_impl.h b/src/TNL/Meshes/MeshDetails/Traverser_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..12b24868b0f6941b5844dfdeb9de919be5f514a0
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/Traverser_impl.h
@@ -0,0 +1,241 @@
+/***************************************************************************
+                          Traverser_impl.h  -  description
+                             -------------------
+    begin                : Dec 25, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Traverser.h>
+
+#include <TNL/Exceptions/CudaSupportMissing.h>
+
+namespace TNL {
+namespace Meshes {   
+
+template< typename Mesh,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh, MeshEntity, EntitiesDimension >::
+processBoundaryEntities( const MeshPointer& meshPointer,
+                         SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+   auto entitiesCount = meshPointer->template getBoundaryEntitiesCount< EntitiesDimension >();
+#ifdef HAVE_OPENMP
+#pragma omp parallel for if( Devices::Host::isOMPEnabled() )
+#endif
+   for( decltype(entitiesCount) i = 0; i < entitiesCount; i++ ) {
+      const auto entityIndex = meshPointer->template getBoundaryEntityIndex< EntitiesDimension >( i );
+      auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity );
+   }
+}
+
+template< typename Mesh,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh, MeshEntity, EntitiesDimension >::
+processInteriorEntities( const MeshPointer& meshPointer,
+                         SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+   auto entitiesCount = meshPointer->template getInteriorEntitiesCount< EntitiesDimension >();
+#ifdef HAVE_OPENMP
+#pragma omp parallel for if( Devices::Host::isOMPEnabled() )
+#endif
+   for( decltype(entitiesCount) i = 0; i < entitiesCount; i++ ) {
+      const auto entityIndex = meshPointer->template getInteriorEntityIndex< EntitiesDimension >( i );
+      auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity );
+   }
+}
+
+template< typename Mesh,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh, MeshEntity, EntitiesDimension >::
+processAllEntities( const MeshPointer& meshPointer,
+                    SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+   auto entitiesCount = meshPointer->template getEntitiesCount< EntitiesDimension >();
+#ifdef HAVE_OPENMP
+#pragma omp parallel for if( Devices::Host::isOMPEnabled() )
+#endif
+   for( decltype(entitiesCount) entityIndex = 0; entityIndex < entitiesCount; entityIndex++ ) {
+      auto& entity = meshPointer->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *meshPointer, *userDataPointer, entity );
+   }
+}
+
+
+#ifdef HAVE_CUDA
+template< int EntitiesDimension,
+          typename EntitiesProcessor,
+          typename Mesh,
+          typename UserData >
+__global__ void
+MeshTraverserBoundaryEntitiesKernel( const Mesh* mesh,
+                                     UserData* userData,
+                                     typename Mesh::GlobalIndexType entitiesCount )
+{
+   for( typename Mesh::GlobalIndexType i = blockIdx.x * blockDim.x + threadIdx.x;
+        i < entitiesCount;
+        i += blockDim.x * gridDim.x )
+   {
+      const auto entityIndex = mesh->template getBoundaryEntityIndex< EntitiesDimension >( i );
+      auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *mesh, *userData, entity );
+   }
+}
+
+template< int EntitiesDimension,
+          typename EntitiesProcessor,
+          typename Mesh,
+          typename UserData >
+__global__ void
+MeshTraverserInteriorEntitiesKernel( const Mesh* mesh,
+                                     UserData* userData,
+                                     typename Mesh::GlobalIndexType entitiesCount )
+{
+   for( typename Mesh::GlobalIndexType i = blockIdx.x * blockDim.x + threadIdx.x;
+        i < entitiesCount;
+        i += blockDim.x * gridDim.x )
+   {
+      const auto entityIndex = mesh->template getInteriorEntityIndex< EntitiesDimension >( i );
+      auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *mesh, *userData, entity );
+   }
+}
+
+template< int EntitiesDimension,
+          typename EntitiesProcessor,
+          typename Mesh,
+          typename UserData >
+__global__ void
+MeshTraverserAllEntitiesKernel( const Mesh* mesh,
+                                UserData* userData,
+                                typename Mesh::GlobalIndexType entitiesCount )
+{
+   for( typename Mesh::GlobalIndexType entityIndex = blockIdx.x * blockDim.x + threadIdx.x;
+        entityIndex < entitiesCount;
+        entityIndex += blockDim.x * gridDim.x )
+   {
+      auto& entity = mesh->template getEntity< EntitiesDimension >( entityIndex );
+      // TODO: if the Mesh::IdType is void, then we should also pass the entityIndex
+      EntitiesProcessor::processEntity( *mesh, *userData, entity );
+   }
+}
+#endif
+
+template< typename MeshConfig,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >::
+processBoundaryEntities( const MeshPointer& meshPointer,
+                         SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+#ifdef HAVE_CUDA
+   auto entitiesCount = meshPointer->template getBoundaryEntitiesCount< EntitiesDimension >();
+
+   dim3 blockSize( 256 );
+   dim3 gridSize;
+   const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() );
+   gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) );
+
+   Devices::Cuda::synchronizeDevice();
+   MeshTraverserBoundaryEntitiesKernel< EntitiesDimension, EntitiesProcessor >
+      <<< gridSize, blockSize >>>
+      ( &meshPointer.template getData< Devices::Cuda >(),
+        &userDataPointer.template modifyData< Devices::Cuda >(),
+        entitiesCount );
+   cudaDeviceSynchronize();
+   TNL_CHECK_CUDA_DEVICE;
+#else
+   throw Exceptions::CudaSupportMissing();
+#endif
+}
+
+template< typename MeshConfig,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >::
+processInteriorEntities( const MeshPointer& meshPointer,
+                         SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+#ifdef HAVE_CUDA
+   auto entitiesCount = meshPointer->template getInteriorEntitiesCount< EntitiesDimension >();
+
+   dim3 blockSize( 256 );
+   dim3 gridSize;
+   const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() );
+   gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) );
+
+   Devices::Cuda::synchronizeDevice();
+   MeshTraverserInteriorEntitiesKernel< EntitiesDimension, EntitiesProcessor >
+      <<< gridSize, blockSize >>>
+      ( &meshPointer.template getData< Devices::Cuda >(),
+        &userDataPointer.template modifyData< Devices::Cuda >(),
+        entitiesCount );
+   cudaDeviceSynchronize();
+   TNL_CHECK_CUDA_DEVICE;
+#else
+   throw Exceptions::CudaSupportMissing();
+#endif
+}
+
+template< typename MeshConfig,
+          typename MeshEntity,
+          int EntitiesDimension >
+   template< typename UserData,
+             typename EntitiesProcessor >
+void
+Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >::
+processAllEntities( const MeshPointer& meshPointer,
+                    SharedPointer< UserData, DeviceType >& userDataPointer ) const
+{
+#ifdef HAVE_CUDA
+   auto entitiesCount = meshPointer->template getEntitiesCount< EntitiesDimension >();
+
+   dim3 blockSize( 256 );
+   dim3 gridSize;
+   const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() );
+   gridSize.x = min( desGridSize, Devices::Cuda::getNumberOfBlocks( entitiesCount, blockSize.x ) );
+
+   Devices::Cuda::synchronizeDevice();
+   MeshTraverserAllEntitiesKernel< EntitiesDimension, EntitiesProcessor >
+      <<< gridSize, blockSize >>>
+      ( &meshPointer.template getData< Devices::Cuda >(),
+        &userDataPointer.template modifyData< Devices::Cuda >(),
+        entitiesCount );
+   cudaDeviceSynchronize();
+   TNL_CHECK_CUDA_DEVICE;
+#else
+   throw Exceptions::CudaSupportMissing();
+#endif
+}
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt
deleted file mode 100644
index c99141552867ae7b6f139e8ee9f98bb9a3dc3688..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/config/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-SET( headers MeshConfigValidator.h )
-
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/config )
\ No newline at end of file
diff --git a/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h b/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h
deleted file mode 100644
index ba079790e1d18079e881b4b19af4935fa68df1b6..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/config/MeshConfigValidator.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/***************************************************************************
-                          MeshConfigValidator.h  -  description
-                             -------------------
-    begin                : Aug 14, 2015
-    copyright            : (C) 2015 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/Assert.h>
-#include <TNL/Meshes/Topologies/MeshEntityTopology.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename MeshEntity,
-          typename dimensions >
-class MeshConfigValidatorSubtopologyLayer :
-public MeshConfigValidatorSubtopologyLayer< MeshConfig, MeshEntity, typename dimensions::Decrement >
-{
-   static_assert( ! MeshConfig::subentityStorage( MeshEntity(), dimensions::value ) ||
-                    MeshConfig::entityStorage( MeshEntity::dimensions ), "entities of which subentities are stored must be stored" );
-   static_assert( ! MeshConfig::subentityStorage( MeshEntity(), dimensions::value ) ||
-                    MeshConfig::entityStorage( dimensions::value ), "entities that are stored as subentities must be stored");
-   static_assert( ! MeshConfig::subentityOrientationStorage( MeshEntity(), dimensions::value ) ||
-                    MeshConfig::subentityStorage( MeshEntity(), dimensions::value ), "orientation can be stored only for subentities that are stored");
-};
-
-template< typename MeshConfig,
-          typename MeshEntity >
-class MeshConfigValidatorSubtopologyLayer< MeshConfig, MeshEntity, MeshDimensionTag< 0 > >
-{
-   static_assert( ! MeshConfig::subentityStorage( MeshEntity(), 0 ) ||
-                    MeshConfig::entityStorage( 0 ), "entities that are stored as subentities must be stored" );
-   static_assert( ! MeshConfig::subentityOrientationStorage( MeshEntity(), 0 ), "storage of vertex orientation does not make sense" );
-};
-
-
-template< typename MeshConfig,
-          typename MeshEntity,
-          typename dimensions >
-class MeshConfigValidatorSupertopologyLayer :
-public MeshConfigValidatorSupertopologyLayer< MeshConfig, MeshEntity, typename dimensions::Decrement >
-{
-   static_assert( ! MeshConfig::superentityStorage( MeshEntity(), 0 ) ||
-                  MeshConfig::entityStorage( MeshEntity::dimensions ), "entities of which superentities are stored must be stored");
-   static_assert( ! MeshConfig::superentityStorage( MeshEntity(), 0 ) ||
-                  MeshConfig::entityStorage( dimensions::value ), "entities that are stored as superentities must be stored");
-};
-
-template< typename MeshConfig,
-          typename MeshEntity >
-class MeshConfigValidatorSupertopologyLayer< MeshConfig, MeshEntity, MeshDimensionTag< MeshEntity::dimensions > >
-{};
-
-
-template< typename MeshConfig, int dimensions >
-class MeshConfigValidatorLayer :
- public MeshConfigValidatorLayer< MeshConfig, dimensions - 1 >,
- public MeshConfigValidatorSubtopologyLayer< MeshConfig,
-                                                typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology,
-                                                MeshDimensionTag< dimensions - 1 > >,
- public MeshConfigValidatorSupertopologyLayer< MeshConfig,
-                                                  typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology,
-                                                  MeshDimensionTag< MeshConfig::CellTopology::dimensions > >
-{
-	typedef typename MeshSubtopology< typename MeshConfig::CellTopology, dimensions >::Topology Topology;
-
-	static_assert( ! MeshConfig::entityStorage( dimensions ) || MeshConfig::subentityStorage( Topology(), 0 ), "subvertices of all stored entities must be stored");
-};
-
-template< typename MeshConfig >
-class MeshConfigValidatorLayer< MeshConfig, 0 >
-{
-};
-
-template< typename MeshConfig >
-class MeshConfigValidatorLayerCell :
-   public MeshConfigValidatorLayer< MeshConfig, MeshConfig::CellTopology::dimensions - 1 >,
-   public MeshConfigValidatorSubtopologyLayer< MeshConfig,
-                                                  typename MeshConfig::CellTopology,
-                                                  MeshDimensionTag< MeshConfig::CellTopology::dimensions - 1 > >
-{
-	typedef typename MeshConfig::CellTopology    CellTopology;
- 	static const int dimensions =  CellTopology::dimensions;
-
-	static_assert( !MeshConfig::entityStorage( dimensions ) || MeshConfig::subentityStorage( CellTopology(), 0 ), "subvertices of all stored entities must be stored");
-};
-
-template<typename MeshConfig >
-class MeshConfigValidator : public MeshConfigValidatorLayerCell< MeshConfig >
-{
-	static const int meshDimension = MeshConfig::CellTopology::dimensions;
-
-	static_assert(1 <= meshDimension, "zero dimensional meshes are not supported");
-	static_assert( meshDimension <= MeshConfig::worldDimension, "world dimension must not be less than mesh dimension");
-
-	static_assert( MeshConfig::entityStorage( 0 ), "mesh vertices must be stored");
-	static_assert( MeshConfig::entityStorage( meshDimension ), "mesh cells must be stored");
-};
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt
index 9f41f3338965936638f4d57795b20a6b30ce396c..f452c0c02285e94471d7cd8cf91f991b48146132 100644
--- a/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt
+++ b/src/TNL/Meshes/MeshDetails/initializer/CMakeLists.txt
@@ -1,13 +1,8 @@
-SET( headers MeshEntityInitializer.h
-             MeshEntitySeed.h 
-             MeshEntitySeedKey.h
-             MeshInitializer.h
-             MeshSubentitySeedCreator.h
-             MeshSuperentityStorageInitializer.h
- )
+SET( headers EntityInitializer.h
+             EntitySeed.h 
+             Initializer.h
+             SubentitySeedsCreator.h
+             SuperentityStorageInitializer.h
+)
 
-SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Meshes/MeshDetails/initializer )    
-SET( tnl_mesh_initializer_SOURCES
-     PARENT_SCOPE )
-
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/initializer )
\ No newline at end of file
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/initializer )
diff --git a/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..684e60543bc5b8ab8e5702c070c18294706df910
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/initializer/EntityInitializer.h
@@ -0,0 +1,435 @@
+/***************************************************************************
+                          EntityInitializer.h  -  description
+                             -------------------
+    begin                : Feb 23, 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/StaticFor.h>
+
+#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h>
+#include <TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h>
+#include <TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig >
+class Initializer;
+
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag,
+          // storage in the superentity
+          bool SubentityStorage =
+               MeshConfig::subentityStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >::EntityTopology(),
+                                             SubdimensionTag::value ),
+          bool SubentityOrientationStorage =
+               MeshConfig::subentityOrientationStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >::EntityTopology(),
+                                                        SubdimensionTag::value ) &&
+               MeshTraits< MeshConfig >::template EntityTraits< SubdimensionTag::value >::orientationNeeded,
+          // storage in the subentity
+          bool SuperentityStorage =
+               MeshConfig::superentityStorage( typename MeshTraits< MeshConfig >::template EntityTraits< SubdimensionTag::value >::EntityTopology(),
+                                               SuperdimensionTag::value ),
+          // necessary to disambiguate the stop condition for specializations
+          bool valid_dimension = ! std::is_same< SubdimensionTag, SuperdimensionTag >::value >
+class EntityInitializerLayer;
+
+template< typename MeshConfig,
+          typename EntityTopology >
+class EntityInitializer
+   : public EntityInitializerLayer< MeshConfig,
+                                    DimensionTag< EntityTopology::dimension >,
+                                    DimensionTag< MeshTraits< MeshConfig >::meshDimension > >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            DimensionTag< EntityTopology::dimension >,
+                                            DimensionTag< MeshTraits< MeshConfig >::meshDimension > >;
+
+   using MeshTraitsType   = MeshTraits< MeshConfig >;
+   using GlobalIndexType  = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType   = typename MeshTraitsType::LocalIndexType;
+   using EntityTraitsType = typename MeshTraitsType::template EntityTraits< EntityTopology::dimension >;
+   using EntityType       = typename EntityTraitsType::EntityType;
+
+   using SeedType         = EntitySeed< MeshConfig, EntityTopology >;
+   using InitializerType  = Initializer< MeshConfig >;
+
+public:
+   static String getType() { return "EntityInitializer"; };
+
+   static void initEntity( EntityType& entity, const GlobalIndexType& entityIndex, const SeedType& entitySeed, InitializerType& initializer)
+   {
+      initializer.setEntityIndex( entity, entityIndex );
+      // this is necessary if we want to use existing entities instead of intermediate seeds to create subentity seeds
+      for( LocalIndexType i = 0; i < entitySeed.getCornerIds().getSize(); i++ )
+         initializer.template setSubentityIndex< 0 >( entity, entityIndex, i, entitySeed.getCornerIds()[ i ] );
+   }
+};
+
+template< typename MeshConfig >
+class EntityInitializer< MeshConfig, Topologies::Vertex >
+   : public EntityInitializerLayer< MeshConfig,
+                                    DimensionTag< 0 >,
+                                    DimensionTag< MeshTraits< MeshConfig >::meshDimension > >
+{
+public:
+   using VertexType      = typename MeshTraits< MeshConfig >::VertexType;
+   using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using PointType       = typename MeshTraits< MeshConfig >::PointType;
+   using InitializerType = Initializer< MeshConfig >;
+
+   static String getType() { return "EntityInitializer"; };
+
+   static void initEntity( VertexType& entity, const GlobalIndexType& entityIndex, const PointType& point, InitializerType& initializer)
+   {
+      initializer.setEntityIndex( entity, entityIndex );
+      initializer.setVertexPoint( entity, point );
+   }
+};
+
+
+/****
+ *       Mesh entity initializer layer with specializations
+ *
+ *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
+ *      TRUE                    FALSE                    TRUE
+ */
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              true,
+                              false,
+                              true,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            SubdimensionTag,
+                                            typename SuperdimensionTag::Decrement >;
+   using InitializerType            = Initializer< MeshConfig >;
+   using MeshType                   = typename InitializerType::MeshType;
+
+   using GlobalIndexType            = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType             = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using SuperentityTraitsType      = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
+   using SuperentityTopology        = typename SuperentityTraitsType::EntityTopology;
+   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
+   using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
+   {
+      //std::cout << "   Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl;
+      SuperentityInitializerType superentityInitializer;
+
+      for( GlobalIndexType superentityIndex = 0;
+           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
+           superentityIndex++ )
+      {
+         auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex );
+         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) );
+
+         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
+         {
+            const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
+            meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex );
+            superentityInitializer.addSuperentity( subentityIndex, superentityIndex );
+         }
+      }
+
+      superentityInitializer.initSuperentities( meshInitializer );
+
+      BaseType::initSuperentities( meshInitializer, mesh );
+   }
+};
+
+/****
+ *       Mesh entity initializer layer with specializations
+ *
+ *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
+ *      TRUE                    TRUE                    TRUE
+ */
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              true,
+                              true,
+                              true,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            SubdimensionTag,
+                                            typename SuperdimensionTag::Decrement >;
+   using InitializerType            = Initializer< MeshConfig >;
+   using MeshType                   = typename InitializerType::MeshType;
+
+   using GlobalIndexType            = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType             = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using SuperentityTraitsType      = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
+   using SuperentityTopology        = typename SuperentityTraitsType::EntityTopology;
+   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
+   using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
+   {
+      //std::cout << "   Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl;
+      SuperentityInitializerType superentityInitializer;
+
+      for( GlobalIndexType superentityIndex = 0;
+           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
+           superentityIndex++ )
+      {
+         auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex );
+         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) );
+
+         auto& subentityOrientationsArray = InitializerType::template subentityOrientationsArray< SubdimensionTag >( superentity );
+
+         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
+         {
+            const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
+            meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex );
+            superentityInitializer.addSuperentity( subentityIndex, superentityIndex );
+
+            subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< SubdimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] );
+         }
+      }
+
+      superentityInitializer.initSuperentities( meshInitializer );
+
+      BaseType::initSuperentities( meshInitializer, mesh );
+   }
+};
+
+/****
+ *       Mesh entity initializer layer with specializations
+ *
+ *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
+ *      TRUE                    TRUE                    FALSE
+ */
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              true,
+                              true,
+                              false,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            SubdimensionTag,
+                                            typename SuperdimensionTag::Decrement >;
+   using InitializerType           = Initializer< MeshConfig >;
+   using MeshType                  = typename InitializerType::MeshType;
+
+   using GlobalIndexType           = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType            = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using SuperentityTraitsType     = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
+   using SuperentityTopology       = typename SuperentityTraitsType::EntityTopology;
+   using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
+   {
+      //std::cout << "   Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl;
+      for( GlobalIndexType superentityIndex = 0;
+           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
+           superentityIndex++ )
+      {
+         auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex );
+         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) );
+
+         auto& subentityOrientationsArray = InitializerType::template subentityOrientationsArray< SubdimensionTag >( superentity );
+
+         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
+         {
+            const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
+            meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex );
+
+            subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< SubdimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] );
+         }
+      }
+
+      BaseType::initSuperentities( meshInitializer, mesh );
+   }
+};
+
+/****
+ *       Mesh entity initializer layer with specializations
+ *
+ *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
+ *      TRUE                    FALSE                   FALSE
+ */
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              true,
+                              false,
+                              false,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            SubdimensionTag,
+                                            typename SuperdimensionTag::Decrement >;
+   using InitializerType           = Initializer< MeshConfig >;
+   using MeshType                  = typename InitializerType::MeshType;
+
+   using GlobalIndexType           = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType            = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using SuperentityTraitsType     = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
+   using SuperentityTopology       = typename SuperentityTraitsType::EntityTopology;
+   using SubentitySeedsCreatorType = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
+   {
+      //std::cout << "   Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl;
+      for( GlobalIndexType superentityIndex = 0;
+           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
+           superentityIndex++ )
+      {
+         auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex );
+         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) );
+
+         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
+         {
+            const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
+            meshInitializer.template setSubentityIndex< SubdimensionTag::value >( superentity, superentityIndex, i, subentityIndex );
+         }
+      }
+
+      BaseType::initSuperentities( meshInitializer, mesh );
+   }
+};
+
+/****
+ *       Mesh entity initializer layer with specializations
+ *
+ *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
+ *      FALSE                   FALSE                   TRUE
+ */
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              false,
+                              false,
+                              true,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{
+   using BaseType = EntityInitializerLayer< MeshConfig,
+                                            SubdimensionTag,
+                                            typename SuperdimensionTag::Decrement >;
+   using InitializerType            = Initializer< MeshConfig >;
+   using MeshType                   = typename InitializerType::MeshType;
+
+   using GlobalIndexType            = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType             = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using SuperentityTraitsType      = typename MeshTraits< MeshConfig >::template EntityTraits< SuperdimensionTag::value >;
+   using SuperentityTopology        = typename SuperentityTraitsType::EntityTopology;
+   using SubentitySeedsCreatorType  = SubentitySeedsCreator< MeshConfig, SuperdimensionTag, SubdimensionTag >;
+   using SuperentityInitializerType = SuperentityStorageInitializer< MeshConfig, SubdimensionTag, SuperdimensionTag >;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh )
+   {
+      //std::cout << "   Initiating superentities with dimension " << SuperdimensionTag::value << " for subentities with dimension " << SubdimensionTag::value << " ... " << std::endl;
+      SuperentityInitializerType superentityInitializer;
+
+      for( GlobalIndexType superentityIndex = 0;
+           superentityIndex < mesh.template getEntitiesCount< SuperdimensionTag::value >();
+           superentityIndex++ )
+      {
+         auto& superentity = mesh.template getEntity< SuperdimensionTag::value >( superentityIndex );
+         auto subentitySeeds = SubentitySeedsCreatorType::create( meshInitializer.getSubvertices( superentity, superentityIndex ) );
+
+         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
+         {
+            const GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
+            superentityInitializer.addSuperentity( subentityIndex, superentityIndex );
+         }
+      }
+
+      superentityInitializer.initSuperentities( meshInitializer );
+
+      BaseType::initSuperentities( meshInitializer, mesh );
+   }
+};
+
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SuperdimensionTag,
+                              false,
+                              false,
+                              false,
+                              true >
+   : public EntityInitializerLayer< MeshConfig,
+                                    SubdimensionTag,
+                                    typename SuperdimensionTag::Decrement >
+{};
+
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          bool SubentityStorage,
+          bool SubentityOrientationStorage,
+          bool SuperentityStorage >
+class EntityInitializerLayer< MeshConfig,
+                              SubdimensionTag,
+                              SubdimensionTag,
+                              SubentityStorage,
+                              SubentityOrientationStorage,
+                              SuperentityStorage,
+                              false >
+{
+   using InitializerType = Initializer< MeshConfig >;
+   using MeshType        = typename InitializerType::MeshType;
+
+public:
+   static void initSuperentities( InitializerType& meshInitializer, MeshType& mesh ) {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h b/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9d34d070114bf40f71d79df1a0d266f545d7347
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/initializer/EntitySeed.h
@@ -0,0 +1,166 @@
+/***************************************************************************
+                          EntitySeed.h  -  description
+                             -------------------
+    begin                : Aug 18, 2015
+    copyright            : (C) 2015 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/MeshTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename EntitySeed >
+struct EntitySeedHash;
+template< typename EntitySeed >
+struct EntitySeedEq;
+
+template< typename MeshConfig,
+          typename EntityTopology >
+class EntitySeed
+{
+   using MeshConfigTraits = MeshTraits< MeshConfig >;
+   using SubvertexTraits = typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 >;
+
+   public:
+      using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
+      using LocalIndexType  = typename MeshTraits< MeshConfig >::LocalIndexType;
+      using IdArrayType     = Containers::StaticArray< SubvertexTraits::count, GlobalIndexType >;
+      using HashType        = EntitySeedHash< EntitySeed >;
+      using KeyEqual        = EntitySeedEq< EntitySeed >;
+
+      static String getType() { return String( "EntitySeed<>" ); }
+
+      static constexpr LocalIndexType getCornersCount()
+      {
+         return SubvertexTraits::count;
+      }
+
+      void setCornerId( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex )
+      {
+         TNL_ASSERT_GE( cornerIndex, 0, "corner index must be non-negative" );
+         TNL_ASSERT_LT( cornerIndex, getCornersCount(), "corner index is out of bounds" );
+         TNL_ASSERT_GE( pointIndex, 0, "point index must be non-negative" );
+
+         this->cornerIds[ cornerIndex ] = pointIndex;
+      }
+
+      IdArrayType& getCornerIds()
+      {
+         return cornerIds;
+      }
+
+      const IdArrayType& getCornerIds() const
+      {
+         return cornerIds;
+      }
+
+   private:
+      IdArrayType cornerIds;
+};
+
+template< typename MeshConfig >
+class EntitySeed< MeshConfig, Topologies::Vertex >
+{
+   using MeshConfigTraits = MeshTraits< MeshConfig >;
+
+   public:
+      using GlobalIndexType = typename MeshTraits< MeshConfig >::GlobalIndexType;
+      using LocalIndexType  = typename MeshTraits< MeshConfig >::LocalIndexType;
+      using IdArrayType     = Containers::StaticArray< 1, GlobalIndexType >;
+      using HashType        = EntitySeedHash< EntitySeed >;
+      using KeyEqual        = EntitySeedEq< EntitySeed >;
+
+      static String getType() { return String( "EntitySeed<>" ); }
+
+      static constexpr LocalIndexType getCornersCount()
+      {
+         return 1;
+      }
+
+      void setCornerId( const LocalIndexType& cornerIndex, const GlobalIndexType& pointIndex )
+      {
+         TNL_ASSERT_EQ( cornerIndex, 0, "corner index must be 0" );
+         TNL_ASSERT_GE( pointIndex, 0, "point index must be non-negative" );
+
+         this->cornerIds[ cornerIndex ] = pointIndex;
+      }
+
+      IdArrayType& getCornerIds()
+      {
+         return cornerIds;
+      }
+
+      const IdArrayType& getCornerIds() const
+      {
+         return cornerIds;
+      }
+
+   private:
+      IdArrayType cornerIds;
+};
+
+template< typename MeshConfig, typename EntityTopology >
+std::ostream& operator<<( std::ostream& str, const EntitySeed< MeshConfig, EntityTopology >& e )
+{
+   str << e.getCornerIds();
+   return str;
+};
+
+template< typename EntitySeed >
+struct EntitySeedHash
+{
+   std::size_t operator()( const EntitySeed& seed ) const
+   {
+      using LocalIndexType = typename EntitySeed::LocalIndexType;
+      using GlobalIndexType = typename EntitySeed::GlobalIndexType;
+
+      // Note that we must use an associative function to combine the hashes,
+      // because we *want* to ignore the order of the corner IDs.
+      std::size_t hash = 0;
+      for( LocalIndexType i = 0; i < EntitySeed::getCornersCount(); i++ )
+//         hash ^= std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
+         hash += std::hash< GlobalIndexType >{}( seed.getCornerIds()[ i ] );
+      return hash;
+   }
+};
+
+template< typename EntitySeed >
+struct EntitySeedEq
+{
+   bool operator()( const EntitySeed& left, const EntitySeed& right ) const
+   {
+      using IdArrayType = typename EntitySeed::IdArrayType;
+
+      IdArrayType sortedLeft( left.getCornerIds() );
+      IdArrayType sortedRight( right.getCornerIds() );
+      sortedLeft.sort();
+      sortedRight.sort();
+      return sortedLeft == sortedRight;
+   }
+};
+
+template< typename MeshConfig >
+struct EntitySeedEq< EntitySeed< MeshConfig, Topologies::Vertex > >
+{
+   using Seed = EntitySeed< MeshConfig, Topologies::Vertex >;
+
+   bool operator()( const Seed& left, const Seed& right ) const
+   {
+      return left.getCornerIds() == right.getCornerIds();
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/Initializer.h b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe97e530eaa68e711ed7b14d4cdb559145067d0d
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/initializer/Initializer.h
@@ -0,0 +1,470 @@
+/***************************************************************************
+                          Initializer.h  -  description
+                             -------------------
+    begin                : Feb 23, 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/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/initializer/EntityInitializer.h>
+#include <TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h>
+#include <TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h>
+#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h>
+
+/*
+ * How this beast works:
+ *
+ * The algorithm is optimized for memory requirements. Therefore, the mesh is
+ * not allocated at once, but by parts (by dimensions). The flow is roughly the
+ * following:
+ *
+ *  - Allocate cells and set their subvertex indices (but not other subentity
+ *    indices), deallocate cell seeds (the cells will be used later).
+ *  - For all dimensions D from (cell dimension - 1) to 1:
+ *     - Create intermediate entity seeds, count the number of entities with
+ *       current dimension.
+ *     - Allocate entities and set their subvertex indices. Create an indexed
+ *       set of entity seeds and reference orientations (if applicable).
+ *     - For all superdimensions S > D:
+ *        - Iterate over entities with dimension S and initialize their
+ *          subentity indices with dimension D. Inverse mapping (D->S) is
+ *          recorded in the process.
+ *        - For entities with dimension D, initialize their superentity indices
+ *          with dimension S.
+ *     - Deallocate all intermediate data structures.
+ *  - Allocate vertices and set their physical coordinates, deallocate input
+ *    array of points.
+ *  - For all superdimensions S > 0, repeat the same steps as above.
+ *
+ * Optimization notes:
+ *   - Recomputing the seed key involves sorting all subvertex indices, but the
+ *     cost is negligible compared to memory consumption incurred by storing
+ *     both the key and original seed in the indexed set.
+ *   - Since std::set and std::map don't provide a shrink_to_fit method like
+ *     std::vector, these dynamic structures should be kept as local variables
+ *     if possible. This is probably the only way to be sure that the unused
+ *     space is not wasted.
+ */
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename DimensionTag,
+          bool EntityStorage =
+             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::storageEnabled,
+          bool EntityReferenceOrientationStorage =
+             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded >
+class InitializerLayer;
+
+
+template< typename MeshConfig >
+class Initializer
+   : public InitializerLayer< MeshConfig,
+                              typename MeshTraits< MeshConfig >::DimensionTag >
+{
+   protected:
+      // must be declared before its use in expression with decltype()
+      Mesh< MeshConfig >* mesh;
+
+   public:
+      using MeshType          = Mesh< MeshConfig >;
+      using MeshTraitsType    = MeshTraits< MeshConfig >;
+      using DimensionTag      = Meshes::DimensionTag< MeshTraitsType::meshDimension >;
+      using BaseType          = InitializerLayer< MeshConfig, DimensionTag >;
+      using PointArrayType    = typename MeshTraitsType::PointArrayType;
+      using CellSeedArrayType = typename MeshTraitsType::CellSeedArrayType;
+      using GlobalIndexType   = typename MeshTraitsType::GlobalIndexType;
+
+
+      Initializer()
+      : mesh( 0 )
+      {}
+
+      // The points and cellSeeds arrays will be reset when not needed to save memory.
+      void createMesh( PointArrayType& points,
+                       CellSeedArrayType& cellSeeds,
+                       MeshType& mesh )
+      {
+         this->mesh = &mesh;
+         BaseType::initEntities( *this, points, cellSeeds, mesh );
+         // set pointers from entities into the subentity and superentity storage networks
+         EntityStorageRebinder< Mesh< MeshConfig > >::exec( mesh );
+      }
+
+      template< typename Entity, typename GlobalIndex >
+      void setEntityIndex( Entity& entity, const GlobalIndex& index )
+      {
+         entity.setIndex( index );
+      }
+
+      template< int Dimension >
+      void setEntitiesCount( const GlobalIndexType& entitiesCount )
+      {
+         //std::cout << "Setting number of entities with " << Dimension << " dimension to " << entitiesCount << std::endl;
+         mesh->template setEntitiesCount< Dimension >( entitiesCount );
+      }
+
+      template< int Subdimension, typename EntityType, typename LocalIndex, typename GlobalIndex >
+      void
+      setSubentityIndex( const EntityType& entity, const GlobalIndex& entityIndex, const LocalIndex& localIndex, const GlobalIndex& globalIndex )
+      {
+         // The mesh entities are not yet bound to the storage network at this point,
+         // so we operate directly on the storage.
+         mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, Subdimension >().getValues( entityIndex )[ localIndex ] = globalIndex;
+      }
+
+      template< int Subdimension, typename EntityType, typename LocalIndex, typename GlobalIndex >
+      GlobalIndex
+      getSubentityIndex( const EntityType& entity, const GlobalIndex& entityIndex, const LocalIndex& localIndex )
+      {
+         // The mesh entities are not yet bound to the storage network at this point,
+         // so we operate directly on the storage.
+         return mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, Subdimension >().getValues( entityIndex )[ localIndex ];
+      }
+
+      template< typename EntityType, typename GlobalIndex >
+      auto
+      getSubvertices( const EntityType& entity, const GlobalIndex& entityIndex )
+         -> decltype( this->mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, 0 >().getValues( 0 ) )
+      {
+         // The mesh entities are not yet bound to the storage network at this point,
+         // so we operate directly on the storage.
+         return mesh->template getSubentityStorageNetwork< EntityType::EntityTopology::dimension, 0 >().getValues( entityIndex );
+      }
+
+      template< typename EntityTopology, int Superdimension >
+      typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >::StorageNetworkType&
+      meshSuperentityStorageNetwork()
+      {
+         return mesh->template getSuperentityStorageNetwork< EntityTopology::dimension, Superdimension >();
+      }
+
+      static void
+      setVertexPoint( typename MeshType::Vertex& vertex, const typename MeshType::PointType& point )
+      {
+         vertex.setPoint( point );
+      }
+
+
+      template< typename SubDimensionTag, typename MeshEntity >
+      static typename MeshTraitsType::template SubentityTraits< typename MeshEntity::EntityTopology, SubDimensionTag::value >::OrientationArrayType&
+      subentityOrientationsArray( MeshEntity& entity )
+      {
+         return entity.template subentityOrientationsArray< SubDimensionTag::value >();
+      }
+
+      template< typename DimensionTag >
+      const MeshEntityReferenceOrientation< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >&
+      getReferenceOrientation( GlobalIndexType index ) const
+      {
+         return BaseType::getReferenceOrientation( DimensionTag(), index );
+      }
+};
+
+/****
+ * Mesh initializer layer for cells
+ *  - entities storage must turned on (cells must always be stored )
+ *  - entities orientation does not make sense for cells => it is turned off
+ */
+template< typename MeshConfig >
+class InitializerLayer< MeshConfig,
+                        typename MeshTraits< MeshConfig >::DimensionTag,
+                        true,
+                        false >
+   : public InitializerLayer< MeshConfig,
+                              typename MeshTraits< MeshConfig >::DimensionTag::Decrement >
+{
+   using MeshTraitsType        = MeshTraits< MeshConfig >;
+   using DimensionTag          = typename MeshTraitsType::DimensionTag;
+   using BaseType              = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >;
+
+   using MeshType              = Mesh< MeshConfig >;
+   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< DimensionTag::value >;
+   using EntityTopology        = typename EntityTraitsType::EntityTopology;
+   using GlobalIndexType       = typename MeshTraitsType::GlobalIndexType;
+
+   using InitializerType       = Initializer< MeshConfig >;
+   using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >;
+   using CellSeedArrayType     = typename MeshTraitsType::CellSeedArrayType;
+   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
+   using PointArrayType        = typename MeshTraitsType::PointArrayType;
+
+   public:
+
+      void initEntities( InitializerType& initializer, PointArrayType& points, CellSeedArrayType& cellSeeds, MeshType& mesh )
+      {
+         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
+         initializer.template setEntitiesCount< DimensionTag::value >( cellSeeds.getSize() );
+         for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ )
+            EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( i ), i, cellSeeds[ i ], initializer );
+         cellSeeds.reset();
+
+         BaseType::initEntities( initializer, points, mesh );
+      }
+
+      using BaseType::findEntitySeedIndex;
+};
+
+/****
+ * Mesh initializer layer for other mesh entities than cells
+ * - entities storage is turned on
+ * - entities orientation storage is turned off
+ */
+template< typename MeshConfig,
+          typename DimensionTag >
+class InitializerLayer< MeshConfig,
+                        DimensionTag,
+                        true,
+                        false >
+   : public InitializerLayer< MeshConfig,
+                              typename DimensionTag::Decrement >
+{
+   using BaseType              = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >;
+   using MeshType              = Mesh< MeshConfig >;
+   using MeshTraitsType        = MeshTraits< MeshConfig >;
+
+   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< DimensionTag::value >;
+   using EntityTopology        = typename EntityTraitsType::EntityTopology;
+   using GlobalIndexType       = typename MeshTraitsType::GlobalIndexType;
+
+   using InitializerType       = Initializer< MeshConfig >;
+   using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >;
+   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
+   using PointArrayType        = typename MeshTraitsType::PointArrayType;
+   using SeedType              = EntitySeed< MeshConfig, EntityTopology >;
+   using SeedIndexedSet        = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
+   using SeedSet               = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType;
+
+   public:
+
+      GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh )
+      {
+         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
+         SeedSet seedSet;
+
+         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
+         {
+            auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) );
+            for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
+               seedSet.insert( subentitySeeds[ j ] );
+         }
+
+         return seedSet.size();
+      }
+
+      using BaseType::findEntitySeedIndex;
+      GlobalIndexType findEntitySeedIndex( const SeedType& seed )
+      {
+         return this->seedsIndexedSet.insert( seed );
+      }
+
+      void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh )
+      {
+         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
+         const GlobalIndexType numberOfEntities = getEntitiesCount( initializer, mesh );
+         initializer.template setEntitiesCount< DimensionTag::value >( numberOfEntities );
+
+         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
+         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
+         {
+            auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) );
+            for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
+            {
+               auto& seed = subentitySeeds[ j ];
+               const auto pair = this->seedsIndexedSet.try_insert( seed );
+               const GlobalIndexType& entityIndex = pair.first;
+               if( pair.second ) {
+                  // insertion took place, initialize the entity
+                  EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer );
+               }
+            }
+         }
+
+         EntityInitializerType::initSuperentities( initializer, mesh );
+         this->seedsIndexedSet.clear();
+
+         BaseType::initEntities( initializer, points, mesh );
+      }
+
+      using BaseType::getReferenceOrientation;
+      using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType;
+      const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const {}
+
+   private:
+      SeedIndexedSet seedsIndexedSet;
+};
+
+/****
+ * Mesh initializer layer for other mesh entities than cells
+ * - entities storage is turned on
+ * - entities orientation storage is turned on
+ */
+template< typename MeshConfig,
+          typename DimensionTag >
+class InitializerLayer< MeshConfig,
+                        DimensionTag,
+                        true,
+                        true >
+   : public InitializerLayer< MeshConfig,
+                              typename DimensionTag::Decrement >
+{
+   using BaseType                      = InitializerLayer< MeshConfig, typename DimensionTag::Decrement >;
+   using MeshType                      = Mesh< MeshConfig >;
+   using MeshTraitsType                = typename MeshType::MeshTraitsType;
+
+   using EntityTraitsType              = typename MeshType::template EntityTraits< DimensionTag::value >;
+   using EntityTopology                = typename EntityTraitsType::EntityTopology;
+   using GlobalIndexType               = typename MeshTraitsType::GlobalIndexType;
+
+   using InitializerType               = Initializer< MeshConfig >;
+   using EntityInitializerType         = EntityInitializer< MeshConfig, EntityTopology >;
+   using LocalIndexType                = typename MeshTraitsType::LocalIndexType;
+   using PointArrayType                = typename MeshTraitsType::PointArrayType;
+   using SeedType                      = EntitySeed< MeshConfig, EntityTopology >;
+   using SeedIndexedSet                = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedIndexedSetType;
+   using SeedSet                       = typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::SeedSetType;
+   using ReferenceOrientationType      = typename EntityTraitsType::ReferenceOrientationType;
+   using ReferenceOrientationArrayType = typename EntityTraitsType::ReferenceOrientationArrayType;
+
+   public:
+
+      GlobalIndexType getEntitiesCount( InitializerType& initializer, MeshType& mesh )
+      {
+         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
+         SeedSet seedSet;
+
+         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
+         {
+            auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) );
+            for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
+               seedSet.insert( subentitySeeds[ j ] );
+         }
+
+         return seedSet.size();
+      }
+
+      using BaseType::findEntitySeedIndex;
+      GlobalIndexType findEntitySeedIndex( const SeedType& seed )
+      {
+         return this->seedsIndexedSet.insert( seed );
+      }
+
+      void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh )
+      {
+         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
+         const GlobalIndexType numberOfEntities = getEntitiesCount( initializer, mesh );
+         initializer.template setEntitiesCount< DimensionTag::value >( numberOfEntities );
+         this->referenceOrientations.setSize( numberOfEntities );
+
+         using SubentitySeedsCreator = SubentitySeedsCreator< MeshConfig, Meshes::DimensionTag< MeshType::getMeshDimension() >, DimensionTag >;
+         for( GlobalIndexType i = 0; i < mesh.template getEntitiesCount< MeshType::getMeshDimension() >(); i++ )
+         {
+            auto subentitySeeds = SubentitySeedsCreator::create( initializer.getSubvertices( mesh.template getEntity< MeshType::getMeshDimension() >( i ), i ) );
+            for( LocalIndexType j = 0; j < subentitySeeds.getSize(); j++ )
+            {
+               auto& seed = subentitySeeds[ j ];
+               const auto pair = this->seedsIndexedSet.try_insert( seed );
+               const GlobalIndexType& entityIndex = pair.first;
+               if( pair.second ) {
+                  // insertion took place, initialize the entity
+                  EntityInitializerType::initEntity( mesh.template getEntity< DimensionTag::value >( entityIndex ), entityIndex, seed, initializer );
+                  this->referenceOrientations[ entityIndex ] = ReferenceOrientationType( seed );
+               }
+            }
+         }
+
+         EntityInitializerType::initSuperentities( initializer, mesh );
+         this->seedsIndexedSet.clear();
+         this->referenceOrientations.reset();
+
+         BaseType::initEntities( initializer, points, mesh );
+      }
+
+      using BaseType::getReferenceOrientation;
+      const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const
+      {
+         return this->referenceOrientations[ index ];
+      }
+
+   private:
+      SeedIndexedSet seedsIndexedSet;
+      ReferenceOrientationArrayType referenceOrientations;
+};
+
+/****
+ * Mesh initializer layer for entities not being stored
+ */
+template< typename MeshConfig,
+          typename DimensionTag >
+class InitializerLayer< MeshConfig,
+                        DimensionTag,
+                        false,
+                        false >
+   : public InitializerLayer< MeshConfig,
+                              typename DimensionTag::Decrement >
+{};
+
+/****
+ * Mesh initializer layer for vertices
+ * - vertices must always be stored
+ * - their orientation does not make sense
+ */
+template< typename MeshConfig >
+class InitializerLayer< MeshConfig,
+                        DimensionTag< 0 >,
+                        true,
+                        false >
+{
+   using MeshType              = Mesh< MeshConfig >;
+   using MeshTraitsType        = typename MeshType::MeshTraitsType;
+   using DimensionTag          = Meshes::DimensionTag< 0 >;
+
+   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< DimensionTag::value >;
+   using EntityTopology        = typename EntityTraitsType::EntityTopology;
+
+   using InitializerType       = Initializer< MeshConfig >;
+   using GlobalIndexType       = typename MeshTraits< MeshConfig >::GlobalIndexType;
+   using LocalIndexType        = typename MeshTraits< MeshConfig >::LocalIndexType;
+   using PointArrayType        = typename MeshTraits< MeshConfig >::PointArrayType;
+   using EntityInitializerType = EntityInitializer< MeshConfig, EntityTopology >;
+   using SeedType              = EntitySeed< MeshConfig, EntityTopology >;
+
+   public:
+
+      GlobalIndexType findEntitySeedIndex( const SeedType& seed )
+      {
+         return seed.getCornerIds()[ 0 ];
+      }
+
+      void initEntities( InitializerType& initializer, PointArrayType& points, MeshType& mesh )
+      {
+         //std::cout << " Initiating entities with dimension " << DimensionTag::value << " ... " << std::endl;
+         initializer.template setEntitiesCount< 0 >( points.getSize() );
+         for( GlobalIndexType i = 0; i < points.getSize(); i++ )
+            EntityInitializerType::initEntity( mesh.template getEntity< 0 >( i ), i, points[ i ], initializer );
+         points.reset();
+
+         EntityInitializerType::initSuperentities( initializer, mesh );
+      }
+
+      // This method is due to 'using BaseType::findEntityIndex;' in the derived class.
+      void findEntitySeedIndex() {}
+
+      using ReferenceOrientationType = typename EntityTraitsType::ReferenceOrientationType;
+      const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index ) const {}
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h
deleted file mode 100644
index 162ff643063852e9315236fc2ab3ecbe545cd091..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/***************************************************************************
-                          MeshEntityInitializer.h  -  description
-                             -------------------
-    begin                : Feb 23, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/StaticFor.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h>
-
-#include "MeshEntitySeed.h"
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig >
-class MeshInitializer;
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag,
-          bool SubentityStorage = MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled,
-          bool SubentityOrientationStorage = MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::orientationEnabled,
-          bool SuperentityStorage = MeshSuperentityTraits< MeshConfig,
-                                                              typename MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::SubentityTopology,
-                                                              EntityTopology::dimensions >::storageEnabled >
-class MeshEntityInitializerLayer;
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntityInitializer
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           MeshDimensionTag< EntityTopology::dimensions - 1 > >
-{
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                 DimensionTag;
-   private:
-
-      typedef MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           MeshDimensionTag< EntityTopology::dimensions - 1 > > BaseType;
- 
-   typedef
-      MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     MeshDimensionTag< EntityTopology::dimensions - 1 > >   SubentityBaseType;
-   typedef
-      MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename
-                                          MeshTraits< MeshConfig >::DimensionTag > SuperentityBaseType;
-
-   static const int Dimension = DimensionTag::value;
-   typedef MeshTraits< MeshConfig >                                                 MeshTraitsType;
-   typedef typename MeshTraitsType::GlobalIndexType                                 GlobalIndexType;
-   typedef typename MeshTraitsType::LocalIndexType                                  LocalIndexType;
-   typedef typename MeshTraitsType::template EntityTraits< Dimension >             EntityTraitsType;
- 
-   typedef typename EntityTraitsType::EntityType                                    EntityType;
-   typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >   SubvertexTraits;
- 
-   typedef MeshInitializer< MeshConfig >                                            InitializerType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                             SeedType;
-
-   template< typename > class SubentitiesCreator;
-
-   public:
-
-   //using SuperentityBaseType::setNumberOfSuperentities;
-
-   static String getType() { return "MeshEntityInitializer"; };
-
-   MeshEntityInitializer() : entity(0), entityIndex( -1 ) {}
-
-   static void initEntity( EntityType &entity, GlobalIndexType entityIndex, const SeedType &entitySeed, InitializerType &initializer)
-   {
-      entity = EntityType( entitySeed );
-      BaseType::initSubentities( entity, entityIndex, entitySeed, initializer );
-   }
- 
-   template< typename SuperentityDimensionTag >
-   typename MeshSuperentityTraits< MeshConfig, EntityTopology, SuperentityDimensionTag::value >::SharedContainerType& getSuperentityContainer( SuperentityDimensionTag )
-   {
-      return this->entity->template getSuperentitiesIndices< SuperentityDimensionTag::value >();
-   }
-
-   static void setEntityVertex( EntityType& entity,
-                                LocalIndexType localIndex,
-                                GlobalIndexType globalIndex )
-   {
-      entity.setVertexIndex( localIndex, globalIndex );
-   }
-
-   private:
-   EntityType *entity;
-   GlobalIndexType entityIndex;
-
-};
-
-template< typename MeshConfig >
-class MeshEntityInitializer< MeshConfig, MeshVertexTopology >
-{
-   public:
-      typedef typename MeshTraits< MeshConfig >::VertexType VertexType;
-      typedef typename MeshTraits< MeshConfig >::PointType  PointType;
-      typedef MeshInitializer< MeshConfig >                 InitializerType;
-
-      static String getType() { return "MeshEntityInitializer"; };
- 
-      static void setVertexPoint( VertexType& vertex,
-                                  const PointType& point,
-                                  InitializerType& initializer )
-      {
-         initializer.setVertexPoint( vertex, point );
-      }
-};
-
-
-/****
- *       Mesh entity initializer layer with specializations
- *
- *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
- *      TRUE                    FALSE                    TRUE
- */
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     true,
-                                     false,
-                                     true >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{
-   typedef MeshEntityInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >                BaseType;
-
-   static const int Dimension = DimensionTag::value;
-   typedef MeshTraits< MeshConfig >                                                          MeshTraitsType;
-   typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension >   SubentityTraitsType;
-   typedef typename SubentityTraitsType::SubentityContainerType                              SubentityContainerType;
-   typedef typename SubentityTraitsType::AccessArrayType                                     SharedContainerType;
-   typedef typename SharedContainerType::ElementType                                         GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                                                     InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                               EntityInitializerType;
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                    EntityDimensionTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                          EntityType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                                      SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >            SubentitySeedsCreatorType;
-   typedef typename SubentityTraitsType::IdArrayType                                         IdArrayType;
-   typedef typename MeshTraitsType::LocalIndexType                                           LocalIndexType;
-
-   protected:
-   static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                InitializerType& meshInitializer )
-   {
-      //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-      auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed );
-
-      IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity );
-      for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
-      {
-         //cout << "    Adding subentity " << subentityIdsArray[ i ] << std::endl;
-         subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
-         meshInitializer.
-            template getSuperentityInitializer< DimensionTag >().
-               addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex );
-      }
-      BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer );
-   }
-};
-
-/****
- *       Mesh entity initializer layer with specializations
- *
- *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
- *      TRUE                    TRUE                    TRUE
- */
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     true,
-                                     true,
-                                     true >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{
-   typedef MeshEntityInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >                   BaseType;
-
-   typedef MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >                     SubentitiesTraits;
-   typedef typename SubentitiesTraits::SubentityContainerType                                  SubentityContainerType;
-   typedef typename SubentitiesTraits::AccessArrayType                                     SharedContainerType;
-   typedef typename SharedContainerType::ElementType                                           GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                                                          InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                                         EntityInitializerType;
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                                EntityDimensionTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                                                SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                      SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-   typedef typename SubentitiesTraits::OrientationArrayType                                    OrientationArrayType;
-
-   protected:
-   static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                InitializerType& meshInitializer )
-   {
-      //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-      auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed );
-
-      IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity );
-      OrientationArrayType &subentityOrientationsArray = InitializerType::template subentityOrientationsArray< DimensionTag >( entity );
-      for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
-      {
-         //cout << "    Adding subentity " << subentityIdsArray[ i ] << std::endl;
-         GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
-         subentityIdsArray[ i ] = subentityIndex;
-         subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< DimensionTag >( subentityIndex ).createOrientation( subentitySeeds[ i ] );
-         //cout << "    Subentity orientation = " << subentityOrientationsArray[ i ].getSubvertexPermutation() << std::endl;
-         meshInitializer.
-            template getSuperentityInitializer< DimensionTag >().
-               addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex );
-      }
- 
-      BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer );
-   }
-};
-
-/****
- *       Mesh entity initializer layer with specializations
- *
- *  SUBENTITY STORAGE     SUBENTITY ORIENTATION    SUPERENTITY STORAGE
- *      TRUE                    TRUE                    FALSE
- */
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     true,
-                                     true,
-                                     false >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{
-   typedef MeshEntityInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >                   BaseType;
-
-   typedef MeshSubentityTraits< MeshConfig, EntityTopology, DimensionTag::value >                     SubentitiesTraits;
-   typedef typename SubentitiesTraits::SubentityContainerType                                  SubentityContainerType;
-   typedef typename SubentitiesTraits::SharedContainerType                                     SharedContainerType;
-   typedef typename SharedContainerType::ElementType                                           GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                                                          InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                                         EntityInitializerType;
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                                EntityDimensionTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                                                SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                      SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-   typedef typename SubentitiesTraits::OrientationArrayType                                    OrientationArrayType;
-
-   protected:
-   static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                InitializerType& meshInitializer )
-   {
-      //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-      auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed );
-
-      IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity );
-      OrientationArrayType &subentityOrientationsArray = InitializerType::template subentityOrientationsArray< DimensionTag >( entity );
-      for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++ )
-      {
-         //cout << "    Adding subentity " << subentityIdsArray[ i ] << std::endl;
-         subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
-         subentityOrientationsArray[ i ] = meshInitializer.template getReferenceOrientation< DimensionTag >( subentitySeeds[ i ] ).createOrientation( subentitySeeds[ i ] );
-      }
-      BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer );
-   }
-};
-
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     true,
-                                     false,
-                                     false >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{
-   typedef MeshEntityInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >                   BaseType;
-
-   typedef typename MeshSubentityTraits< MeshConfig,
-                                              EntityTopology,
-                                              DimensionTag::value >::SubentityContainerType          SubentityContainerType;
-   typedef typename MeshSubentityTraits< MeshConfig,
-                                              EntityTopology,
-                                              DimensionTag::value >::SharedContainerType             SharedContainerType;
-   typedef typename SharedContainerType::ElementType                                           GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                                                     InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                                    EntityInitializerType;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                               EntityType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                                           SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                 SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-
-   protected:
-   static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                InitializerType& meshInitializer )
-   {
-      //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-      auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed );
-
-		IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity );
-		for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++)
-			subentityIdsArray[ i ] = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
-
-		BaseType::initSubentities(entity, entityIndex, entitySeed, meshInitializer);
-   }
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     false,
-                                     false,
-                                     true >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{
-   typedef MeshEntityInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >                BaseType;
-
-   typedef typename MeshSubentityTraits< MeshConfig,
-                                              EntityTopology,
-                                              DimensionTag::value >::SubentityContainerType        SubentityContainerType;
-   typedef typename MeshSubentityTraits< MeshConfig,
-                                              EntityTopology,
-                                              DimensionTag::value >::SharedContainerType           SharedContainerType;
-   typedef typename SharedContainerType::DataType                                            GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                                                   InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                                  EntityInitializerType;
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                      EntityDimensionTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                           EntityType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                                           SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                 SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-
-
-   protected:
- 
-      static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                   InitializerType& meshInitializer )
-      {
-         //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         auto subentitySeeds = SubentitySeedsCreatorType::create( entitySeed );
-         IdArrayType& subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >( entity );
-         for( LocalIndexType i = 0; i < subentitySeeds.getSize(); i++)
-         {
-            GlobalIndexType subentityIndex = meshInitializer.findEntitySeedIndex( subentitySeeds[ i ] );
-            meshInitializer.
-               template getSuperentityInitializer< DimensionTag >().
-                  addSuperentity( EntityDimensionTag(), subentityIndex, entityIndex );
-         }
-         BaseType::initSubentities( entity, entityIndex, entitySeed, meshInitializer );
-      }
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag,
-                                     false,
-                                     false,
-                                     false >
-   : public MeshEntityInitializerLayer< MeshConfig,
-                                           EntityTopology,
-                                           typename DimensionTag::Decrement >
-{};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     MeshDimensionTag< 0 >,
-                                     true,
-                                     false,
-                                     true >
-{
-   typedef MeshDimensionTag< 0 >                                  DimensionTag;
-   typedef MeshSubentityTraits< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag::value >                 SubentitiesTraits;
-
-   typedef typename SubentitiesTraits::AccessArrayType           SharedContainerType;
-   typedef typename SharedContainerType::ElementType                 GlobalIndexType;
-
-   typedef MeshInitializer< MeshConfig >                           InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >          EntityInitializerType;
-   typedef MeshDimensionTag< EntityTopology::dimensions >              EntityDimensionTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >                                           SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                 SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-
-
-   protected:
- 
-      static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                   InitializerType& meshInitializer )
-      {
-         //cout << "   Initiating subentities with " << DimensionTag::value << " dimensions ... " << std::endl;
-		   const IdArrayType &subentityIdsArray = InitializerType::template subentityIdsArray< DimensionTag >(entity);
-		   for( LocalIndexType i = 0; i < subentityIdsArray.getSize(); i++ )
-			   meshInitializer.template getSuperentityInitializer< DimensionTag >().addSuperentity( EntityDimensionTag(), subentityIdsArray[ i ], entityIndex);
-	}
-
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     MeshDimensionTag< 0 >,
-                                     true,
-                                     false,
-                                     false >
-{
-   typedef MeshInitializer< MeshConfig >         InitializerType;
-   typedef MeshEntityInitializer< MeshConfig,
-                                     EntityTopology >   EntityInitializerType;
-   typedef MeshDimensionTag< 0 >                   DimensionTag;
-   typedef MeshSubentityTraits< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag::value >                 SubentitiesTraits;
-   typedef typename SubentitiesTraits::SharedContainerType           SharedContainerType;
-   typedef typename SharedContainerType::ElementType                 GlobalIndexType;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >                                           SeedType;
-   typedef MeshSubentitySeedsCreator< MeshConfig, EntityTopology, DimensionTag >                 SubentitySeedsCreatorType;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag >::IdArrayType IdArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType                                             LocalIndexType;
-
-
-   protected:
- 
-      static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, const SeedType& entitySeed,
-                                   InitializerType& meshInitializer ) {};
- 
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          bool SuperEntityStorage >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     MeshDimensionTag< 0 >,
-                                     false,
-                                     true,
-                                     SuperEntityStorage > // Forces termination of recursive inheritance (prevents compiler from generating huge error logs)
-{
-   typedef MeshInitializer< MeshConfig >                  InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType;
-   typedef MeshDimensionTag< 0 >                   DimensionTag;
-   typedef MeshSubentityTraits< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag::value >                 SubentitiesTraits;
-   typedef typename SubentitiesTraits::SharedContainerType           SharedContainerType;
-   typedef typename SharedContainerType::ElementType                 GlobalIndexType;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-
-   protected:
-   static void initSubentities( EntityType& entity, GlobalIndexType entityIndex, EntityInitializerType&, InitializerType& ) {}
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          bool SuperEntityStorage >
-class MeshEntityInitializerLayer< MeshConfig,
-                                     EntityTopology,
-                                     MeshDimensionTag< 0 >,
-                                     false,
-                                     false,
-                                     SuperEntityStorage > // Forces termination of recursive inheritance (prevents compiler from generating huge error logs)
-{
-   typedef MeshInitializer< MeshConfig >                  InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology > EntityInitializerType;
-   typedef MeshDimensionTag< 0 >                   DimensionTag;
-   typedef MeshSubentityTraits< MeshConfig,
-                                     EntityTopology,
-                                     DimensionTag::value >                 SubentitiesTraits;
-   typedef typename SubentitiesTraits::SharedContainerType           SharedContainerType;
-   typedef typename SharedContainerType::ElementType                 GlobalIndexType;
-   typedef MeshEntity< MeshConfig, EntityTopology >                                                    EntityType;
-
-   protected:
-   void initSubentities( EntityType& entity, GlobalIndexType entityIndex, EntityInitializerType&,
-                         InitializerType& ) {}
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h
deleted file mode 100644
index a0f7e561bfead6e1602d3ca754ece09475b29faf..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/***************************************************************************
-                          MeshEntitySeed.h  -  description
-                             -------------------
-    begin                : Aug 18, 2015
-    copyright            : (C) 2015 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/MeshTraits.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntitySeed
-{
-   typedef MeshTraits< MeshConfig >      MeshConfigTraits;
-   typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, 0 > SubvertexTraits;
-
-   public:
-      typedef typename MeshTraits< MeshConfig >::GlobalIndexType                                      GlobalIndexType;
-      typedef typename MeshTraits< MeshConfig >::LocalIndexType                                       LocalIndexType;
-      typedef typename MeshTraits< MeshConfig >::IdArrayAccessorType                                  IdArrayAccessorType;
-      typedef typename SubvertexTraits::IdArrayType                                                      IdArrayType;
-
-      static String getType() { return String( "MeshEntitySeed<>" ); }
- 
-      static constexpr LocalIndexType getCornersCount()
-      {
-         return SubvertexTraits::count;
-      }
-
-      void setCornerId( LocalIndexType cornerIndex, GlobalIndexType pointIndex )
-      {
-         TNL_ASSERT( 0 <= cornerIndex && cornerIndex < getCornersCount(), std::cerr << "cornerIndex = " << cornerIndex );
-         TNL_ASSERT( 0 <= pointIndex, std::cerr << "pointIndex = " << pointIndex );
-
-         this->cornerIds[ cornerIndex ] = pointIndex;
-      }
-
-      IdArrayAccessorType getCornerIds()
-      {
-         IdArrayAccessorType accessor;
-         accessor.bind( this->corners.getData(), this->corners.getSize() );
-         return accessor;
-      }
-
- 
-      const IdArrayAccessorType getCornerIds() const
-      {
-         IdArrayAccessorType accessor;
-         accessor.bind( this->cornerIds.getData(), this->cornerIds.getSize() );
-         return accessor;
-      }
-
-   private:
-	
-      IdArrayType cornerIds;
-};
-
-template< typename MeshConfig, typename EntityTopology >
-std::ostream& operator << ( std::ostream& str, const MeshEntitySeed< MeshConfig, EntityTopology >& e )
-{
-   str << e.getCornerIds();
-   return str;
-};
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h b/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h
deleted file mode 100644
index 32ecff1df3b89d6db6c6f96b22aefa3e67f046c2..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/***************************************************************************
-                          MeshEntitySeedKey.h  -  description
-                             -------------------
-    begin                : Feb 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/MeshDimensionTag.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntitySeed;
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          int Dimension >
-class MeshSubentityTraits;
-
-/****
- * Unique identification of a mesh entity by its vertices.
- * Uniqueness is preserved for entities of the same type only.
- */
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshEntitySeedKey
-{
-   typedef
-      MeshEntitySeed< MeshConfig, EntityTopology >                               EntitySeedType;
-
-   typedef typename
-      MeshSubentityTraits< MeshConfig,
-                                EntityTopology,
-                                0 >::StorageArrayType  StorageArrayType;
-
-   public:
-
-   explicit MeshEntitySeedKey( const EntitySeedType& entitySeed )
-   {
-      for( typename StorageArrayType::IndexType i = 0;
-           i < entitySeed.getCornersCount();
-           i++ )
-         this->sortedCorners[ i ] = entitySeed.getCornerIds()[ i ];
-      sortedCorners.sort( );
-   }
-
-   bool operator<( const MeshEntitySeedKey& other ) const
-   {
-      for( typename StorageArrayType::IndexType i = 0;
-           i < StorageArrayType::size;
-           i++)
-      {
-         if( sortedCorners[ i ] < other.sortedCorners[ i ] )
-            return true;
-         else
-            if( sortedCorners[ i ] > other.sortedCorners[ i ] )
-               return false;
-      }
-      return false;
-   }
-
-   private:
-
-   StorageArrayType sortedCorners;
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h
deleted file mode 100644
index e690d35918246db0e51c7206d9a2d90ae2739a6c..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshInitializer.h
+++ /dev/null
@@ -1,629 +0,0 @@
-/***************************************************************************
-                          MeshInitializer.h  -  description
-                             -------------------
-    begin                : Feb 23, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/MeshDimensionTag.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshEntityInitializer.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h>
-#include <TNL/Meshes/MeshDetails/MeshEntityReferenceOrientation.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeedKey.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig >
-class Mesh;
-
-template< typename MeshConfig,
-          typename DimensionTag,
-          bool EntityStorage =
-             MeshEntityTraits< MeshConfig, DimensionTag::value >::storageEnabled,
-          bool EntityReferenceOrientationStorage =
-             MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::orientationNeeded >
-class MeshInitializerLayer;
-
-
-template< typename MeshConfig,
-          typename EntityTopology>
-class MeshEntityInitializer;
-
-template< typename MeshConfig >
-class MeshInitializer
-   : public MeshInitializerLayer< MeshConfig,
-                                     typename MeshTraits< MeshConfig >::DimensionTag >
-{
-   public:
- 
-      typedef Mesh< MeshConfig >                                  MeshType;
-      typedef MeshTraits< MeshConfig >                            MeshTraitsType;
-      static const int Dimension = MeshTraitsType::meshDimension;
-      typedef MeshDimensionTag< Dimension >                      DimensionTag;
-      typedef MeshInitializerLayer< MeshConfig, DimensionTag >   BaseType;
-      typedef typename MeshTraitsType::PointArrayType             PointArrayType;
-      typedef typename MeshTraitsType::CellSeedArrayType          CellSeedArrayType;
-      typedef typename MeshTraitsType::GlobalIndexType            GlobalIndexType;
- 
-      template< typename DimensionTag, typename SuperdimensionsTag > using SuperentityStorageNetwork =
-      typename MeshTraitsType::template SuperentityTraits<
-         typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology,
-         SuperdimensionsTag::value >::StorageNetworkType;
-
-
-      MeshInitializer()
-      : verbose( false ), mesh( 0 )
-      {}
-
-      void setVerbose( bool verbose )
-      {
-         this->verbose = verbose;
-      }
-
-      bool createMesh( const PointArrayType& points,
-                       const CellSeedArrayType& cellSeeds,
-                       MeshType& mesh )
-      {
-        std::cout << "======= Starting mesh initiation ========" << std::endl;
-         this->mesh = &mesh;
-
-        std::cout << "========= Creating entity seeds =============" << std::endl;
-         BaseType::createEntitySeedsFromCellSeeds( cellSeeds );
-
-        std::cout << "========= Creating entity reference orientations =============" << std::endl;
-         BaseType::createEntityReferenceOrientations();
-
-        std::cout << "====== Initiating entities ==============" << std::endl;
-         BaseType::initEntities( *this, points, cellSeeds );
-
-         return true;
-      }
-
-      template<typename SubDimensionTag, typename EntityType >
-      static typename MeshTraitsType::template SubentityTraits< typename EntityType::EntityTopology, SubDimensionTag::value >::IdArrayType&
-      subentityIdsArray( EntityType& entity )
-      {
-         return entity.template subentityIdsArray< SubDimensionTag::value >();
-      }
-
-      template< typename SuperDimensionTag, typename MeshEntity>
-      static typename MeshTraitsType::IdArrayAccessorType&
-      superentityIdsArray( MeshEntity& entity )
-      {
-         return entity.template superentityIdsArray< SuperDimensionTag::value >();
-      }
-
-      template<typename SubDimensionTag, typename MeshEntity >
-      static typename MeshTraitsType::template SubentityTraits< typename MeshEntity::EntityTopology, SubDimensionTag::value >::OrientationArrayType&
-      subentityOrientationsArray( MeshEntity &entity )
-      {
-         return entity.template subentityOrientationsArray< SubDimensionTag::value >();
-      }
-
-      template< typename DimensionTag >
-      typename MeshTraitsType::template EntityTraits< DimensionTag::value >::StorageArrayType&
-      meshEntitiesArray()
-      {
-         return mesh->template entitiesArray< DimensionTag >();
-      }
-
-      template< typename DimensionTag, typename SuperDimensionTag >
-      typename MeshTraitsType::GlobalIdArrayType&
-      meshSuperentityIdsArray()
-      {
-         return mesh->template superentityIdsArray< DimensionTag, SuperDimensionTag >();
-      }
- 
-      template< typename EntityTopology, typename SuperdimensionsTag >
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType&
-      meshSuperentityStorageNetwork()
-      {
-         return mesh->template getSuperentityStorageNetwork< EntityTopology, SuperdimensionsTag >();
-      }
-
-      static void
-      setVertexPoint( typename MeshType::VertexType& vertex, const typename MeshType::PointType& point )
-      {
-         vertex.setPoint( point );
-      }
-
-      template< typename DimensionTag >
-      MeshSuperentityStorageInitializer< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >&
-      getSuperentityInitializer()
-      {
-         return BaseType::getSuperentityInitializer( DimensionTag() );
-      }
-
- 
-      template< typename DimensionTag >
-      const MeshEntityReferenceOrientation< MeshConfig, typename MeshTraitsType::template EntityTraits< DimensionTag::value >::EntityTopology >&
-      getReferenceOrientation( GlobalIndexType index) const
-      {
-         return BaseType::getReferenceOrientation( DimensionTag(), index);
-      }
-
-   protected:
-
-      bool verbose;
-
-      MeshType* mesh;
-};
-
-/****
- * Mesh initializer layer for cells
- *  - entities storage must turned on (cells must always be stored )
- *  - entities orientation does not make sense for cells => it is turned off
- */
-template< typename MeshConfig >
-class MeshInitializerLayer< MeshConfig,
-                               typename MeshTraits< MeshConfig >::DimensionTag,
-                               true,
-                               false >
-   : public MeshInitializerLayer< MeshConfig,
-                                     typename MeshTraits< MeshConfig >::DimensionTag::Decrement >
-{
-   typedef MeshTraits< MeshConfig >                                              MeshTraitsType;
-   static const int Dimension = MeshTraitsType::meshDimension;
-   typedef MeshDimensionTag< Dimension >                                        DimensionTag;
-   typedef MeshInitializerLayer< MeshConfig, typename DimensionTag::Decrement > BaseType;
-
-   typedef Mesh< MeshConfig >                                                    MeshType;
-   typedef typename MeshTraitsType::template EntityTraits< Dimension >          EntityTraitsType;
-   typedef typename EntityTraitsType::EntityTopology                             EntityTopology;
-   typedef typename MeshTraitsType::GlobalIndexType                              GlobalIndexType;
-   typedef typename MeshTraitsType::CellTopology                                 CellTopology;
-   typedef typename EntityTraitsType::StorageArrayType                           StorageArrayType;
-
-   typedef MeshInitializer< MeshConfig >                                         InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                   EntityInitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                   CellInitializerType;
-   typedef Containers::Array< CellInitializerType, Devices::Host, GlobalIndexType >  CellInitializerContainerType;
-   typedef typename MeshTraitsType::CellSeedArrayType                            CellSeedArrayType;
-   typedef typename MeshTraitsType::LocalIndexType                               LocalIndexType;
-   typedef typename MeshTraitsType::PointArrayType                               PointArrayType;
-   typedef MeshEntitySeed< MeshConfig, CellTopology >                            SeedType;
-   typedef  MeshSuperentityStorageInitializer< MeshConfig, EntityTopology >      SuperentityInitializerType;
-
-   public:
-
-      void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds )
-      {
-         BaseType::createEntitySeedsFromCellSeeds( cellSeeds );
-      }
-
-      void initEntities( InitializerType &initializer, const PointArrayType &points, const CellSeedArrayType &cellSeeds)
-      {
-         StorageArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >();
-         //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         entityArray.setSize( cellSeeds.getSize() );
-         for( GlobalIndexType i = 0; i < entityArray.getSize(); i++ )
-         {
-            //cout << "  Initiating entity " << i << std::endl;
-            EntityInitializerType::initEntity( entityArray[i], i, cellSeeds[i], initializer );
-         }
-         /***
-          * There are no superentities in this layer storing mesh cells.
-          */
- 
-         BaseType::initEntities( initializer, points );
-      }
-
-      using BaseType::findEntitySeedIndex;
-      GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const
-      {
-         return this->seedsIndexedSet.find( seed );
-      }
-
-      using BaseType::getSuperentityInitializer;
-      SuperentityInitializerType& getSuperentityInitializer( DimensionTag )
-      {
-         return this->superentityInitializer;
-      }
- 
-      bool checkCells()
-      {
-         typedef typename MeshEntity< MeshConfig, EntityTopology >::template SubentitiesTraits< 0 >::LocalIndexType LocalIndexType;
-         const GlobalIndexType numberOfVertices( this->getMesh().getNumberOfVertices() );
-         for( GlobalIndexType cell = 0;
-              cell < this->getMesh().template getEntitiesCount< typename MeshType::Cell >();
-              cell++ )
-            for( LocalIndexType i = 0;
-                 i < this->getMesh().getCell( cell ).getNumberOfVertices();
-                 i++ )
-            {
-               if( this->getMesh().getCell( cell ).getVerticesIndices()[ i ] == - 1 )
-               {
-                  std::cerr << "The cell number " << cell << " does not have properly set vertex index number " << i << "." << std::endl;
-                  return false;
-               }
-               if( this->getMesh().getCell( cell ).getVerticesIndices()[ i ] >= numberOfVertices )
-               {
-                  std::cerr << "The cell number " << cell << " does not have properly set vertex index number " << i
-                       << ". The index " << this->getMesh().getCell( cell ).getVerticesIndices()[ i ]
-                       << "is higher than the number of all vertices ( " << numberOfVertices
-                       << " )." << std::endl;
-                  return false;
-               }
-            }
-         return true;
-      }
-
-   private:
-      typedef  typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType                     SeedIndexedSet;
-
-      SeedIndexedSet seedsIndexedSet;
-      SuperentityInitializerType superentityInitializer;
-};
-
-/****
- * Mesh initializer layer for other mesh entities than cells
- * - entities storage is turned on
- * - entities orientation storage is turned off
- */
-template< typename MeshConfig,
-          typename DimensionTag >
-class MeshInitializerLayer< MeshConfig,
-                               DimensionTag,
-                               true,
-                               false >
-   : public MeshInitializerLayer< MeshConfig,
-                                     typename DimensionTag::Decrement >
-{
-      typedef MeshTraits< MeshConfig >                                           MeshTraitsType;
-   static const int Dimension = DimensionTag::value;
-   typedef MeshInitializerLayer< MeshConfig, typename DimensionTag::Decrement > BaseType;
-
-   typedef Mesh< MeshConfig >                                                    MeshType;
-   typedef typename MeshTraitsType::template EntityTraits< Dimension >          EntityTraitsType;
-   typedef typename EntityTraitsType::EntityTopology                             EntityTopology;
-   typedef typename MeshTraitsType::GlobalIndexType                              GlobalIndexType;
-   typedef typename MeshTraitsType::CellTopology                                 CellTopology;
-   typedef typename EntityTraitsType::StorageArrayType                           StorageArrayType;
-
-   typedef MeshInitializer< MeshConfig >                                         InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                   EntityInitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                   CellInitializerType;
-   typedef Containers::Array< CellInitializerType, Devices::Host, GlobalIndexType >  CellInitializerContainerType;
-   typedef typename EntityTraitsType::SeedArrayType                              EntitySeedArrayType;
-   typedef typename MeshTraitsType::CellSeedArrayType                            CellSeedArrayType;
-   typedef typename MeshTraitsType::LocalIndexType                               LocalIndexType;
-   typedef typename MeshTraitsType::PointArrayType                               PointArrayType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                          SeedType;
-   typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology >       SuperentityInitializerType;
-
-   typedef typename
-      MeshSubentityTraits< MeshConfig,
-                                typename MeshConfig::CellTopology,
-                                DimensionTag::value >::SubentityContainerType SubentitiesContainerType;
- 
-   public:
-
-      using BaseType::getEntityInitializer;
-      EntityInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index )
-      {
-         //return entityInitializerContainer[ index ];
-      }
-
-      void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds )
-      {
-         typedef MeshSubentitySeedsCreator< MeshConfig, CellTopology, DimensionTag >  SubentitySeedsCreator;
-         //cout << " Creating mesh entities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ )
-         {
-            //cout << "  Creating mesh entities from cell number " << i << " : " << cellSeeds[ i ] << std::endl;
-            typedef typename SubentitySeedsCreator::SubentitySeedArray SubentitySeedArray;
-            SubentitySeedArray subentytiSeeds( SubentitySeedsCreator::create( cellSeeds[ i ] ) );
-            for( LocalIndexType j = 0; j < subentytiSeeds.getSize(); j++ )
-            {
-               //cout << "Creating subentity seed no. " << j << " : " << subentytiSeeds[ j ] << std::endl;
-               //MeshEntitySeed< MeshConfigBase< CellTopology >, EntityTopology >& entitySeed = subentytiSeeds[ j ];
-               this->seedsIndexedSet.insert( subentytiSeeds[ j ] );
-            }
-         }
-         BaseType::createEntitySeedsFromCellSeeds( cellSeeds );
-      }
-
-      using BaseType::findEntitySeedIndex;
-      GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const
-      {
-         // FIXME: index may be uninitialized (when seedsIndexedSet.find returns false)
-         GlobalIndexType index;
-         this->seedsIndexedSet.find( seed, index );
-         return index;
-      }
- 
-      using BaseType::getSuperentityInitializer;
-      SuperentityInitializerType& getSuperentityInitializer( DimensionTag )
-      {
-         return this->superentityInitializer;
-      }
-
-      void initEntities( InitializerType& initializer, const PointArrayType& points )
-      {
-         StorageArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >();
-         //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         entityArray.setSize( this->seedsIndexedSet.getSize() );
-         EntitySeedArrayType seedsArray;
-         seedsArray.setSize( this->seedsIndexedSet.getSize() );
-         this->seedsIndexedSet.toArray( seedsArray );
-         for( GlobalIndexType i = 0; i < this->seedsIndexedSet.getSize(); i++ )
-         {
-            //cout << "  Initiating entity " << i << std::endl;
-            EntityInitializerType::initEntity( entityArray[ i ], i, seedsArray[ i ], initializer );
-         }
-         this->seedsIndexedSet.reset();
-
-         this->superentityInitializer.initSuperentities( initializer );
-
-         BaseType::initEntities(initializer, points);
-      }
-
-      void createEntityReferenceOrientations() const {}
-   private:
- 
-      typedef  typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType                     SeedIndexedSet;
-      SeedIndexedSet seedsIndexedSet;
-      SuperentityInitializerType superentityInitializer;
-};
-
-/****
- * Mesh initializer layer for other mesh entities than cells
- * - entities storage is turned on
- * - entities orientation storage is turned on
- */
-template< typename MeshConfig,
-          typename DimensionTag >
-class MeshInitializerLayer< MeshConfig,
-                            DimensionTag,
-                            true,
-                            true >
-   : public MeshInitializerLayer< MeshConfig,
-                                     typename DimensionTag::Decrement >
-{
-   typedef MeshInitializerLayer< MeshConfig,
-                                    typename DimensionTag::Decrement >       BaseType;
-   typedef Mesh< MeshConfig >                                                 MeshType;
-   typedef typename MeshType::MeshTraitsType                                  MeshTraitsType;
-
-   typedef typename MeshType::template EntityTraits< DimensionTag::value >   EntityTraitsType;
-   typedef typename EntityTraitsType::EntityTopology                          EntityTopology;
-   typedef typename EntityTraitsType::EntityType                              EntityType;
-   typedef typename EntityTraitsType::StorageArrayType                        ContainerType;
-   typedef typename EntityTraitsType::UniqueContainerType                     UniqueContainerType;
-   typedef typename ContainerType::IndexType                                  GlobalIndexType;
-   typedef typename MeshTraitsType::CellTopology                              CellTopology;
-
-   typedef MeshInitializer< MeshConfig >                                      InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, CellTopology >                  CellInitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                EntityInitializerType;
-   typedef Containers::Array< EntityInitializerType, Devices::Host, GlobalIndexType >        EntityInitializerContainerType;
-   typedef typename MeshTraitsType::CellSeedArrayType                         CellSeedArrayType;
-   typedef typename MeshTraitsType::LocalIndexType                            LocalIndexType;
-   typedef typename MeshTraitsType::PointArrayType                            PointArrayType;
-   typedef typename EntityTraitsType::StorageArrayType                        EntityArrayType;
-   typedef typename EntityTraitsType::SeedArrayType                           SeedArrayType;
-   typedef MeshEntitySeed< MeshConfig, EntityTopology >                       SeedType;
-   typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology >    SuperentityInitializerType;
-   typedef typename EntityTraitsType::ReferenceOrientationType                ReferenceOrientationType;
-   typedef typename EntityTraitsType::ReferenceOrientationArrayType           ReferenceOrientationArrayType;
-
-
-   typedef typename
-      MeshSubentityTraits< MeshConfig,
-                                typename MeshConfig::CellTopology,
-                                DimensionTag::value >::SubentityContainerType SubentitiesContainerType;
-
-   public:
- 
-      using BaseType::getEntityInitializer;
-      EntityInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index )
-      {
-         //return entityInitializerContainer[ index ];
-      }
-
-      void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds )
-      {
-         typedef MeshSubentitySeedsCreator< MeshConfig, CellTopology, DimensionTag >  SubentitySeedsCreator;
-         //cout << " Creating mesh entities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         for( GlobalIndexType i = 0; i < cellSeeds.getSize(); i++ )
-         {
-            //cout << "  Creating mesh entities from cell number " << i << " : " << cellSeeds[ i ] << std::endl;
-            typedef typename SubentitySeedsCreator::SubentitySeedArray SubentitySeedArray;
-            SubentitySeedArray subentytiSeeds( SubentitySeedsCreator::create( cellSeeds[ i ] ) );
-            for( LocalIndexType j = 0; j < subentytiSeeds.getSize(); j++ )
-            {
-               //cout << "Creating subentity seed no. " << j << " : " << subentytiSeeds[ j ] << std::endl;
-               //MeshEntitySeed< MeshConfigBase< CellTopology >, EntityTopology >& entitySeed = subentytiSeeds[ j ];
-               this->seedsIndexedSet.insert( subentytiSeeds[ j ] );
-            }
-         }
-         BaseType::createEntitySeedsFromCellSeeds( cellSeeds );
-      }
-
-      using BaseType::findEntitySeedIndex;
-      GlobalIndexType findEntitySeedIndex( const SeedType& seed ) const
-      {
-         GlobalIndexType index;
-         this->seedsIndexedSet.find( seed, index );
-         return index;
-      }
- 
-      using BaseType::getSuperentityInitializer;
-      SuperentityInitializerType& getSuperentityInitializer( DimensionTag )
-      {
-         return this->superentityInitializer;
-      }
-
-      void initEntities( InitializerType& initializer, const PointArrayType& points )
-      {
-         EntityArrayType &entityArray = initializer.template meshEntitiesArray< DimensionTag >();
-         //cout << " Initiating entities with " << DimensionTag::value << " dimensions ... " << std::endl;
-         entityArray.setSize( this->seedsIndexedSet.getSize() );
-         SeedArrayType seedsArray;
-         seedsArray.setSize( this->seedsIndexedSet.getSize() );
-         this->seedsIndexedSet.toArray( seedsArray );
-         for( GlobalIndexType i = 0; i < this->seedsIndexedSet.getSize(); i++ )
-         {
-            //cout << "  Initiating entity " << i << std::endl;
-            EntityInitializerType::initEntity( entityArray[ i ], i, seedsArray[ i ], initializer );
-         }
-         this->seedsIndexedSet.reset();
-
-         this->superentityInitializer.initSuperentities( initializer );
-
-         BaseType::initEntities(initializer, points);
-      }
-
-      using BaseType::getReferenceOrientation;
-      const ReferenceOrientationType& getReferenceOrientation( DimensionTag, GlobalIndexType index) const
-      {
-         return this->referenceOrientations[ index ];
-      }
- 
-      void createEntityReferenceOrientations()
-      {
-         //cout << " Creating entity reference orientations with " << DimensionTag::value << " dimensions ... " << std::endl;
-         SeedArrayType seedsArray;
-         seedsArray.setSize( this->seedsIndexedSet.getSize() );
-         this->seedsIndexedSet.toArray( seedsArray );
-         this->referenceOrientations.setSize( seedsArray.getSize() );
-         for( GlobalIndexType i = 0; i < seedsArray.getSize(); i++ )
-         {
-            //cout << "  Creating reference orientation for entity " << i << std::endl;
-            this->referenceOrientations[ i ] = ReferenceOrientationType( seedsArray[ i ] );
-         }
-         BaseType::createEntityReferenceOrientations();
-		}	
- 
-   private:
- 
-      typedef  typename MeshEntityTraits< MeshConfig, DimensionTag::value >::SeedIndexedSetType                     SeedIndexedSet;
-      SeedIndexedSet seedsIndexedSet;
-      SuperentityInitializerType superentityInitializer;
-      ReferenceOrientationArrayType referenceOrientations;
-};
-
-/****
- * Mesh initializer layer for entities not being stored
- */
-template< typename MeshConfig,
-          typename DimensionTag >
-class MeshInitializerLayer< MeshConfig,
-                               DimensionTag,
-                               false,
-                               false >
-   : public MeshInitializerLayer< MeshConfig,
-                                     typename DimensionTag::Decrement >
-{};
-
-/****
- * Mesh initializer layer for vertices
- * - vertices must always be stored
- * - their orientation does not make sense
- */
-template< typename MeshConfig >
-class MeshInitializerLayer< MeshConfig,
-                               MeshDimensionTag< 0 >,
-                               true,
-                               false >
-{
-   typedef Mesh< MeshConfig >                                                 MeshType;
-   typedef typename MeshType::MeshTraitsType                                  MeshTraitsType;
-   typedef MeshDimensionTag< 0 >                                              DimensionTag;
-
-   typedef typename MeshType::template EntityTraits< DimensionTag::value >   EntityTraitsType;
-   typedef typename EntityTraitsType::EntityTopology                          EntityTopology;
-   typedef typename EntityTraitsType::StorageArrayType                        ContainerType;
-   typedef typename EntityTraitsType::AccessArrayType                         SharedContainerType;
-   typedef typename ContainerType::IndexType                                  GlobalIndexType;
-
-   typedef typename MeshTraitsType::CellTopology                                       CellTopology;
-
-   typedef MeshInitializer< MeshConfig >                                           InitializerType;
-   typedef MeshEntityInitializer< MeshConfig, CellTopology >                       CellInitializerType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >                     VertexInitializerType;
-   typedef Containers::Array< VertexInitializerType, Devices::Host, GlobalIndexType >  VertexInitializerContainerType;
-   typedef typename MeshTraits< MeshConfig >::CellSeedArrayType            CellSeedArrayType;
-   typedef typename MeshTraits< MeshConfig >::LocalIndexType               LocalIndexType;
-   typedef typename MeshTraits< MeshConfig >::PointArrayType               PointArrayType;
-   typedef typename EntityTraitsType::StorageArrayType                            EntityArrayType;
-   typedef MeshEntityInitializer< MeshConfig, EntityTopology >             EntityInitializerType;
-   typedef MeshSuperentityStorageInitializer< MeshConfig, EntityTopology > SuperentityInitializerType;
-
-   public:
-
-      void setMesh( MeshType& mesh )
-      {
-         this->mesh = &mesh;
-      }
-
-      MeshType& getMesh()
-      {
-         TNL_ASSERT( this->mesh, );
-         return *( this->mesh );
-      }
-
-      VertexInitializerType& getEntityInitializer( DimensionTag, GlobalIndexType index )
-      {
-         TNL_ASSERT( index >= 0 && index < vertexInitializerContainer.getSize(),
-                  std::cerr << " index = " << index
-                       << " vertexInitializerContainer.getSize() = " << vertexInitializerContainer.getSize() << std::endl; );
-         return vertexInitializerContainer[ index ];
-      }
- 
-      void createEntitySeedsFromCellSeeds( const CellSeedArrayType& cellSeeds ){};
- 
-      void initEntities( InitializerType& initializer, const PointArrayType& points )
-      {
-         EntityArrayType &vertexArray = initializer.template meshEntitiesArray< DimensionTag >();
-         vertexArray.setSize( points.getSize() );
-         for( GlobalIndexType i = 0; i < vertexArray.getSize(); i++ )
-            EntityInitializerType::setVertexPoint( vertexArray[i], points[i], initializer );
-
-         superentityInitializer.initSuperentities( initializer );
-      }
- 
-      void findEntitySeedIndex() const                               {} // This method is due to 'using BaseType::findEntityIndex;' in the derived class.
-
-      void createEntityInitializers()
-      {
-         vertexInitializerContainer.setSize( this->getMesh().template getNumberOfEntities< DimensionTag::value >() );
-      }
- 
-      SuperentityInitializerType& getSuperentityInitializer( DimensionTag )
-      {
-         return this->superentityInitializer;
-      }
-
-      void createEntityReferenceOrientations() const {}
- 
-      void getReferenceOrientation() const {}
- 
-   private:
- 
-      SuperentityInitializerType superentityInitializer;
-
-      VertexInitializerContainerType vertexInitializerContainer;
-
-      MeshType* mesh;
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h b/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h
deleted file mode 100644
index f7069f4cf5d5e674f61b37d8f604a10dd0c17140..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshSubentitySeedCreator.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/***************************************************************************
-                          MeshSubentitySeedCreator.h  -  description
-                             -------------------
-    begin                : Aug 20, 2015
-    copyright            : (C) 2015 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/StaticFor.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename SubDimensionTag >
-class MeshSubentitySeedsCreator
-{
-	typedef typename MeshTraits< MeshConfig >::LocalIndexType                                                      LocalIndexType;
-	typedef typename MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, SubDimensionTag::value > SubentityTraits;
-	typedef typename SubentityTraits::SubentityTopology                                                               SubentityTopology;
-	typedef typename MeshTraits< MeshConfig >::IdArrayAccessorType                                                 IdArrayAccessorType;
-	typedef typename MeshTraits< MeshConfig >::template SubentityTraits< SubentityTopology, 0 >                    SubentityVertexTraits;
-
-	static const LocalIndexType SUBENTITIES_COUNT = SubentityTraits::count;
-	static const LocalIndexType SUBENTITY_VERTICES_COUNT = SubentityVertexTraits::count;
-
-   public:
-      typedef typename SubentityTraits::SeedArrayType SubentitySeedArray;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >  EntitySeed;
-      //typedef typename MeshEntityTraits< MeshConfig, SubDimensionTag >::SeedIndexedSetType                     SeedIndexedSet;
-
-      //template< typename SeedIndexedSet >
-      static SubentitySeedArray create( const EntitySeed &entitySeed  )
-      {
-         SubentitySeedArray subentitySeeds;
-         StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::exec( subentitySeeds, entitySeed.getCornerIds() );
-         //StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::exec( indexedSet, entitySeed.getCornerIds() );
- 
-         return subentitySeeds;
-      }
-
-   private:
-      typedef MeshEntitySeed< MeshConfig, SubentityTopology > SubentitySeed;
-
-      template< LocalIndexType subentityIndex >
-      class CreateSubentitySeeds
-      {
-         public:
-            static void exec( SubentitySeedArray &subentitySeeds, IdArrayAccessorType vertexIds )
-            //static void exec( SeedIndexedSet& indexedSet, IdArrayAccessorType vertexIds )
-            {
-               //EntitySeed seed;
-               StaticFor< LocalIndexType, 0, SUBENTITY_VERTICES_COUNT, SetSubentitySeedVertex >::exec( subentitySeeds[ subentityIndex ], vertexIds );
-               //indexedSet.insert( seed );
-            }
-
-         private:
-            template< LocalIndexType subentityVertexIndex >
-            class SetSubentitySeedVertex
-            {
-               public:
-                  static void exec( SubentitySeed &subentitySeed, IdArrayAccessorType vertexIds )
-                  {
-                     static const LocalIndexType VERTEX_INDEX = SubentityTraits::template Vertex< subentityIndex, subentityVertexIndex >::index;
-                     subentitySeed.setCornerId( subentityVertexIndex, vertexIds[ VERTEX_INDEX ] );
-                  }
-            };
-      };
-};
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h
deleted file mode 100644
index 587cb03a30c89f22a82a05045ef2dad456b3ab02..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/initializer/MeshSuperentityStorageInitializer.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/***************************************************************************
-                          MeshSuperentityStorageInitializer.h  -  description
-                             -------------------
-    begin                : Feb 27, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/MeshDimensionTag.h>
-#include <algorithm>
-#include <vector>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig >
-class MeshInitializer;
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag,
-          bool SuperentityStorage = MeshSuperentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled >
-class MeshSuperentityStorageInitializerLayer;
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageInitializer :
-   public MeshSuperentityStorageInitializerLayer< MeshConfig, EntityTopology, MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > >
-{};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          DimensionTag,
-                                          true >
-   : public MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                                EntityTopology,
-                                                typename DimensionTag::Decrement >
-{
-   typedef MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                                      EntityTopology,
-                                                      typename DimensionTag::Decrement >      BaseType;
-
-   static const int Dimension = DimensionTag::value;
-   typedef MeshDimensionTag< EntityTopology::dimensions >                                       EntityDimension;
-	
-   typedef MeshTraits< MeshConfig >                                                             MeshTraitsType;
-   typedef typename MeshTraitsType::GlobalIdArrayType                                           GlobalIdArrayType; 
-   typedef typename MeshTraitsType::GlobalIndexType                                             GlobalIndexType;
-   typedef typename MeshTraitsType::LocalIndexType                                              LocalIndexType;
-   typedef MeshInitializer< MeshConfig >                                                        MeshInitializerType;
-   typedef typename MeshTraitsType::template SuperentityTraits< EntityTopology, Dimension >    SuperentityTraitsType;
-   typedef typename SuperentityTraitsType::StorageNetworkType                                   SuperentityStorageNetwork;
-
-   public:
-      using BaseType::addSuperentity;
-	
-      void addSuperentity( DimensionTag, GlobalIndexType entityIndex, GlobalIndexType superentityIndex)
-      {
-         //cout << "Adding superentity with " << DimensionTag::value << " dimensions of enity with " << EntityDimension::value << " ... " << std::endl;
-         indexPairs.push_back( IndexPair{ entityIndex, superentityIndex } );
-      }
-
-      using BaseType::initSuperentities;
-      void initSuperentities( MeshInitializerType& meshInitializer )
-      {
-         throw( 0 ); // TODO: fix this - or it may work with newer version of gcc
-         /*std::sort( indexPairs.begin(),
-                    indexPairs.end(),
-                    []( IndexPair pair0, IndexPair pair1 ){ return ( pair0.entityIndex < pair1.entityIndex ); } );*/
-
-         GlobalIdArrayType &superentityIdsArray = meshInitializer.template meshSuperentityIdsArray< EntityDimension, DimensionTag >();
-         superentityIdsArray.setSize( static_cast< GlobalIndexType >( indexPairs.size() )  );
-         GlobalIndexType currentBegin = 0;
-         GlobalIndexType lastEntityIndex = 0;
-        std::cout << "There are " << superentityIdsArray.getSize() << " superentities with " << DimensionTag::value << " dimensions of enities with " << EntityDimension::value << " ... " << std::endl;
-         for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++)
-         {
-            superentityIdsArray[ i ] = indexPairs[i].superentityIndex;
- 
-            //cout << "Adding superentity " << indexPairs[i].superentityIndex << " to entity " << lastEntityIndex << std::endl;
-            if( indexPairs[ i ].entityIndex != lastEntityIndex )
-            {
-               meshInitializer.template superentityIdsArray< DimensionTag >( meshInitializer.template meshEntitiesArray< EntityDimension >()[ lastEntityIndex ] ).bind( superentityIdsArray, currentBegin, i - currentBegin );
-               currentBegin = i;
-               lastEntityIndex = indexPairs[ i ].entityIndex;
-            }
-         }
-
-         meshInitializer.template superentityIdsArray< DimensionTag >( meshInitializer.template meshEntitiesArray< EntityDimension >()[ lastEntityIndex ] ).bind( superentityIdsArray, currentBegin, superentityIdsArray.getSize() - currentBegin );
-         indexPairs.clear();
- 
-         /****
-          * Network initializer
-          */
-         SuperentityStorageNetwork& superentityStorageNetwork = meshInitializer.template meshSuperentityStorageNetwork< EntityTopology, DimensionTag >();
-         //GlobalIndexType lastEntityIndex( 0 );
-         superentityStorageNetwork.setRanges(
-            meshInitializer.template meshEntitiesArray< EntityDimension >().getSize(),
-            meshInitializer.template meshEntitiesArray< DimensionTag >().getSize() );
-         lastEntityIndex = 0;
-         typename SuperentityStorageNetwork::ValuesAllocationVectorType storageNetworkAllocationVector;
-         storageNetworkAllocationVector.setSize( meshInitializer.template meshEntitiesArray< EntityDimension >().getSize() );
-         storageNetworkAllocationVector.setValue( 0 );
-         for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++)
-         {
-            if( indexPairs[ i ].entityIndex == lastEntityIndex )
-               storageNetworkAllocationVector[ lastEntityIndex ]++;
-            else
-               lastEntityIndex++;
-         }
-         superentityStorageNetwork.allocate( storageNetworkAllocationVector );
-         lastEntityIndex = 0;
-         LocalIndexType superentitiesCount( 0 );
-         typename SuperentityStorageNetwork::ValuesAccessorType superentitiesIndecis =
-            superentityStorageNetwork.getValues( lastEntityIndex );
-         for( GlobalIndexType i = 0; i < superentityIdsArray.getSize(); i++)
-         {
-            if( indexPairs[ i ].entityIndex != lastEntityIndex )
-            {
-               superentitiesIndecis = superentityStorageNetwork.getValues( ++lastEntityIndex );
-               superentitiesCount = 0;
-            }
-            superentitiesIndecis[ superentitiesCount++ ] =  indexPairs[ i ].superentityIndex;
-         }
-         BaseType::initSuperentities( meshInitializer );
-      }
-
-   private:
-      struct IndexPair
-      {
-         GlobalIndexType entityIndex;
-         GlobalIndexType superentityIndex;
-      };
-
-      std::vector< IndexPair > indexPairs;
- 
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          DimensionTag,
-                                          false >
-   : public MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                                EntityTopology,
-                                                typename DimensionTag::Decrement >
-{
-   typedef MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                                EntityTopology,
-                                                typename DimensionTag::Decrement > BaseType;
-   typedef MeshInitializer< MeshConfig >                                      MeshInitializerType;
- 
-   public:
-   void addSuperentity()                           {} // This method is due to 'using BaseType::...;' in the derived classes.
-   using BaseType::initSuperentities;
-   void initSuperentities( MeshInitializerType& ) { std::cerr << "***" << std::endl;}
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          MeshDimensionTag< EntityTopology::dimensions >,
-                                          true >
-{
-   typedef MeshInitializer< MeshConfig >                                      MeshInitializerType;
- 
-   public:
-   void addSuperentity()                           {} // This method is due to 'using BaseType::...;' in the derived classes.
-   void initSuperentities( MeshInitializerType& ) {}
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageInitializerLayer< MeshConfig,
-                                          EntityTopology,
-                                          MeshDimensionTag< EntityTopology::dimensions >,
-                                          false >
-{
-   typedef MeshInitializer< MeshConfig >                                      MeshInitializerType;
-
-   public:
-   void addSuperentity()                           {} // This method is due to 'using BaseType::...;' in the derived classes.
-   void initSuperentities( MeshInitializerType& ) {}
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h b/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d76ae0696f62bf51e3027bb70c699b10d2c6a1d
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/initializer/SubentitySeedsCreator.h
@@ -0,0 +1,109 @@
+/***************************************************************************
+                          SubentitySeedsCreator.h  -  description
+                             -------------------
+    begin                : Aug 20, 2015
+    copyright            : (C) 2015 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/StaticFor.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename EntityDimensionTag,
+          typename SubentityDimensionTag >
+class SubentitySeedsCreator
+{
+   using MeshTraitsType        = MeshTraits< MeshConfig >;
+   using GlobalIndexType       = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
+   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >;
+   using EntityType            = typename EntityTraitsType::EntityType;
+   using EntityTopology        = typename EntityTraitsType::EntityTopology;
+   using SubvertexAccessorType = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >::SubentityAccessorType;
+   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, SubentityDimensionTag::value >;
+   using SubentityType         = typename SubentityTraits::SubentityType;
+   using SubentityTopology     = typename SubentityTraits::SubentityTopology;
+
+   static const LocalIndexType SUBENTITIES_COUNT = EntityType::template getSubentitiesCount< SubentityDimensionTag::value >();
+   static const LocalIndexType SUBENTITY_VERTICES_COUNT = SubentityType::template getSubentitiesCount< 0 >();
+
+public:
+   using SubentitySeedArray = typename SubentityTraits::SeedArrayType;
+
+   static SubentitySeedArray create( const SubvertexAccessorType& subvertices )
+   {
+      SubentitySeedArray subentitySeeds;
+      StaticFor< LocalIndexType, 0, SUBENTITIES_COUNT, CreateSubentitySeeds >::execHost( subentitySeeds, subvertices );
+
+      return subentitySeeds;
+   }
+
+private:
+   using SubentitySeed = EntitySeed< MeshConfig, SubentityTopology >;
+
+   template< LocalIndexType subentityIndex >
+   class CreateSubentitySeeds
+   {
+      public:
+         static void exec( SubentitySeedArray& subentitySeeds, const SubvertexAccessorType& subvertices )
+         {
+            StaticFor< LocalIndexType, 0, SUBENTITY_VERTICES_COUNT, SetSubentitySeedVertex >::execHost( subentitySeeds[ subentityIndex ], subvertices );
+         }
+
+      private:
+         template< LocalIndexType subentityVertexIndex >
+         class SetSubentitySeedVertex
+         {
+            public:
+               static void exec( SubentitySeed& subentitySeed, const SubvertexAccessorType& subvertices )
+               {
+                  static const LocalIndexType VERTEX_INDEX = SubentityTraits::template Vertex< subentityIndex, subentityVertexIndex >::index;
+                  subentitySeed.setCornerId( subentityVertexIndex, subvertices[ VERTEX_INDEX ] );
+               }
+         };
+   };
+};
+
+template< typename MeshConfig,
+          typename EntityDimensionTag >
+class SubentitySeedsCreator< MeshConfig, EntityDimensionTag, DimensionTag< 0 > >
+{
+   using MeshTraitsType        = MeshTraits< MeshConfig >;
+   using GlobalIndexType       = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType        = typename MeshTraitsType::LocalIndexType;
+   using EntityTraitsType      = typename MeshTraitsType::template EntityTraits< EntityDimensionTag::value >;
+   using EntityType            = typename EntityTraitsType::EntityType;
+   using EntityTopology        = typename EntityTraitsType::EntityTopology;
+   using SubvertexAccessorType = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >::SubentityAccessorType;
+   using SubentityTraits       = typename MeshTraitsType::template SubentityTraits< EntityTopology, 0 >;
+
+   static const LocalIndexType SUBENTITIES_COUNT = EntityType::template getSubentitiesCount< 0 >();
+
+public:
+   using SubentitySeedArray = typename SubentityTraits::SeedArrayType;
+
+   static SubentitySeedArray create( const SubvertexAccessorType& subvertices )
+   {
+      SubentitySeedArray seeds;
+      for( LocalIndexType i = 0; i < seeds.getSize(); i++ )
+         seeds[ i ].setCornerId( 0, subvertices[ i ] );
+      return seeds;
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h b/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0327785d64dacc22bfffb380fe3235c5f734051
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/initializer/SuperentityStorageInitializer.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+                          SuperentityStorageInitializer.h  -  description
+                             -------------------
+    begin                : Feb 27, 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 <set>
+#include <unordered_map>
+
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig >
+class Initializer;
+
+template< typename MeshConfig,
+          typename SubdimensionTag,
+          typename SuperdimensionTag >
+class SuperentityStorageInitializer
+{
+   using MeshTraitsType            = MeshTraits< MeshConfig >;
+   using InitializerType           = Initializer< MeshConfig >;
+   using GlobalIndexType           = typename MeshTraitsType::GlobalIndexType;
+   using LocalIndexType            = typename MeshTraitsType::LocalIndexType;
+   using EntityTraitsType          = typename MeshTraitsType::template EntityTraits< SubdimensionTag::value >;
+   using EntityTopology            = typename EntityTraitsType::EntityTopology;
+   using EntityType                = typename EntityTraitsType::EntityType;
+   using SuperentityTraitsType     = typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >;
+   using SuperentityStorageNetwork = typename SuperentityTraitsType::StorageNetworkType;
+
+public:
+   void addSuperentity( GlobalIndexType entityIndex, GlobalIndexType superentityIndex)
+   {
+      //std::cout << "Adding superentity with " << SuperdimensionTag::value << " dimension of entity with " << SubdimensionTag::value << " dimension: entityIndex = " << entityIndex << ", superentityIndex = " << superentityIndex << std::endl;
+      auto& indexSet = this->dynamicStorageNetwork[ entityIndex ];
+      TNL_ASSERT( indexSet.count( superentityIndex ) == 0,
+                  std::cerr << "Superentity " << superentityIndex << " with dimension " << SuperdimensionTag::value
+                            << " of entity " << entityIndex << " with dimension " << SubdimensionTag::value
+                            << " has been already added. This is probably a bug in the mesh initializer." << std::endl; );
+      indexSet.insert( superentityIndex );
+   }
+
+   void initSuperentities( InitializerType& meshInitializer )
+   {
+      TNL_ASSERT_GT( dynamicStorageNetwork.size(), (size_t) 0,
+                     "No superentity indices were collected. This is a bug in the mesh initializer." );
+      TNL_ASSERT_EQ( (size_t) getMaxSuperentityIndex(), dynamicStorageNetwork.size() - 1,
+                     "Superentities for some entities are missing. "
+                     "This is probably a bug in the mesh initializer." );
+
+      SuperentityStorageNetwork& superentityStorageNetwork = meshInitializer.template meshSuperentityStorageNetwork< EntityTopology, SuperdimensionTag::value >();
+      TNL_ASSERT_EQ( (size_t) superentityStorageNetwork.getKeysRange(), dynamicStorageNetwork.size(),
+                     "Sizes of the static and dynamic storage networks don't match. "
+                     "This is probably a bug in the mesh initializer." );
+
+      typename SuperentityStorageNetwork::ValuesAllocationVectorType storageNetworkAllocationVector;
+      storageNetworkAllocationVector.setSize( superentityStorageNetwork.getKeysRange() );
+      for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ )
+         storageNetworkAllocationVector[ it->first ] = it->second.size();
+      superentityStorageNetwork.allocate( storageNetworkAllocationVector );
+
+      for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ ) {
+         auto superentitiesIndices = superentityStorageNetwork.getValues( it->first );
+         LocalIndexType i = 0;
+         for( auto v_it = it->second.cbegin(); v_it != it->second.cend(); v_it++ )
+            superentitiesIndices[ i++ ] = *v_it;
+      }
+
+      dynamicStorageNetwork.clear();
+   }
+
+private:
+   using DynamicIndexSet = std::set< GlobalIndexType >;
+   std::unordered_map< GlobalIndexType, DynamicIndexSet > dynamicStorageNetwork;
+
+   GlobalIndexType getMaxSuperentityIndex()
+   {
+      GlobalIndexType max = 0;
+      for( auto it = dynamicStorageNetwork.cbegin(); it != dynamicStorageNetwork.cend(); it++ ) {
+         if( it->first > max )
+            max = it->first;
+      }
+      return max;
+   }
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt
deleted file mode 100644
index 04987a5db350cd2b9d7b7defd52d863b4df7b118..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-SET( headers MeshStorageLayer.h
-             MeshSubentityStorageLayer.h
-             MeshSuperentityStorageLayer.h )
-
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/layers )
\ No newline at end of file
diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h
deleted file mode 100644
index bd31795a5cb2d774d8a76e87aa6c4c99b96dcab4..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/MeshStorageLayer.h
+++ /dev/null
@@ -1,343 +0,0 @@
-/***************************************************************************
-                          MeshStorageLayer.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/File.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename DimensionTag,
-          bool EntityStorage = MeshEntityTraits< MeshConfig, DimensionTag::value >::storageEnabled >
-class MeshStorageLayer;
-
-
-template< typename MeshConfig >
-class MeshStorageLayers
-   : public MeshStorageLayer< MeshConfig, typename MeshTraits< MeshConfig >::DimensionTag >
-{
-};
-
-
-template< typename MeshConfig,
-          typename DimensionTag >
-class MeshStorageLayer< MeshConfig,
-                           DimensionTag,
-                           true >
-   : public MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement >,
-     public MeshSuperentityStorageLayers< MeshConfig,
-                                             typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology >
-{
-   public:
-
-      static const int Dimension = DimensionTag::value;
-      typedef MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement >   BaseType;
-      typedef MeshSuperentityStorageLayers< MeshConfig,
-                                               typename MeshTraits< MeshConfig >::template EntityTraits< DimensionTag::value >::EntityTopology > SuperentityStorageBaseType;
-      typedef MeshTraits< MeshConfig >                                             MeshTraitsType;
-      typedef typename MeshTraitsType::template EntityTraits< Dimension >         EntityTraitsType;
-
-      typedef typename EntityTraitsType::StorageArrayType                          StorageArrayType;
-      typedef typename EntityTraitsType::AccessArrayType                           AccessArrayType;
-      typedef typename EntityTraitsType::GlobalIndexType                           GlobalIndexType;
-      typedef typename EntityTraitsType::EntityType                                EntityType;
-      typedef typename EntityTraitsType::EntityTopology                            EntityTopology;
-
-
-      using BaseType::getNumberOfEntities;
-      using BaseType::getEntity;
-      using BaseType::getEntities;
-
-      MeshStorageLayer()
-      {
-      }
-
-      GlobalIndexType getNumberOfEntities( DimensionTag ) const
-      {
-         return this->entities.getSize();
-      }
-
-      EntityType& getEntity( DimensionTag,
-                             const GlobalIndexType entityIndex )
-      {
-         return this->entities[ entityIndex ];
-      }
-
-      const EntityType& getEntity( DimensionTag,
-                                   const GlobalIndexType entityIndex ) const
-      {
-         return this->entities[ entityIndex ];
-      }
-
-      AccessArrayType& getEntities( DimensionTag )
-      {
-         return this->sharedEntities;
-      }
-
-      const AccessArrayType& getEntities( DimensionTag ) const
-      {
-         return this->sharedEntities;
-      }
-
-      bool save( File& file ) const
-      {
-         if( ! BaseType::save( file ) ||
-             ! this->entities.save( file ) )
-         {
-            std::cerr << "Saving of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl;
-            return false;
-         }
-         return true;
-      }
-
-      bool load( File& file )
-      {
-         //cout << "Loading mesh layer with dimensions " << DimensionTag::value << std::endl;
-         if( ! BaseType::load( file ) ||
-             ! this->entities.load( file ) )
-         {
-            std::cerr << "Loading of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl;
-            return false;
-         }
-         this->entitiesAccess.bind( this->entities );
-         return true;
-      }
-
-      void print( std::ostream& str ) const
-      {
-         BaseType::print( str );
-         str << "The entities with " << DimensionTag::value << " dimensions are: " << std::endl;
-         for( GlobalIndexType i = 0; i < entities.getSize();i ++ )
-         {
-            str << i << " ";
-            entities[ i ].print( str );
-            str << std::endl;
-         }
-         SuperentityStorageBaseType::print( str );
-      }
-
-      bool operator==( const MeshStorageLayer& meshLayer ) const
-      {
-         return ( BaseType::operator==( meshLayer ) && entities == meshLayer.entities );
-      }
-
-
-   protected:
-      StorageArrayType entities;
-
-      AccessArrayType entitiesAccess;
- 
-   // TODO: this is only for the mesh initializer - fix it
-   public:
-
-      using BaseType::entitiesArray;
- 
-      typename EntityTraitsType::StorageArrayType& entitiesArray( DimensionTag )
-      {
-         return entities;
-      }
- 
-      using BaseType::superentityIdsArray;
-	
-      template< typename SuperDimensionTag >
-      typename MeshTraitsType::GlobalIdArrayType& superentityIdsArray( DimensionTag )
-      {
-         return SuperentityStorageBaseType::superentityIdsArray( SuperDimensionTag() );
-      }
- 
-      using BaseType::getSuperentityStorageNetwork;
-      template< typename SuperdimensionsTag >
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType&
-      getSuperentityStorageNetwork( MeshDimensionTag< EntityTopology::dimensions > )
-      {
-         return SuperentityStorageBaseType::getStorageNetwork( SuperdimensionsTag() );
-      }
-};
-
-template< typename MeshConfig,
-          typename DimensionTag >
-class MeshStorageLayer< MeshConfig, DimensionTag, false >
-   : public MeshStorageLayer< MeshConfig, typename DimensionTag::Decrement  >
-{
-};
-
-template< typename MeshConfig >
-class MeshStorageLayer< MeshConfig, MeshDimensionTag< 0 >, true > :
-   public MeshSuperentityStorageLayers< MeshConfig,
-                                           MeshVertexTopology >
-
-{
-   public:
-
-   typedef MeshDimensionTag< 0 >                        DimensionTag;
- 
-   typedef MeshSuperentityStorageLayers< MeshConfig,
-                                            MeshVertexTopology >     SuperentityStorageBaseType;
-
-   typedef MeshTraits< MeshConfig >                                   MeshTraitsType;
-   typedef typename MeshTraitsType::template EntityTraits< 0 >        EntityTraitsType;
- 
-   typedef typename EntityTraitsType::StorageArrayType                StorageArrayType;
-   typedef typename EntityTraitsType::AccessArrayType                 AccessArrayType;
-   typedef typename EntityTraitsType::GlobalIndexType                 GlobalIndexType;
-   typedef typename EntityTraitsType::EntityType                      VertexType;
-   typedef typename VertexType::PointType                             PointType;
-   typedef MeshVertexTopology                                         EntityTopology;
- 
-   MeshStorageLayer()
-   {
-   }
-
-   GlobalIndexType getNumberOfVertices() const
-   {
-      return this->vertices.getSize();
-   }
-
-   void setVertex( const GlobalIndexType vertexIndex,
-                   const VertexType& vertex ) const
-   {
-      this->vertices.setElement( vertexIndex, vertex );
-   }
-
-   VertexType& getVertex( const GlobalIndexType vertexIndex )
-   {
-      return this->vertices[ vertexIndex ];
-   }
-
-   const VertexType& getVertex( const GlobalIndexType vertexIndex ) const
-   {
-      return this->vertices[ vertexIndex ];
-   }
-
-
-   void setVertex( const GlobalIndexType vertexIndex,
-                   const PointType& point )
-   {
-      this->vertices[ vertexIndex ].setPoint( point );
-   }
-
-   /****
-    * This is only for the completeness and compatibility
-    * with higher dimensions entities storage layers.
-    */
-
-   GlobalIndexType getNumberOfEntities( DimensionTag ) const
-   {
-      return this->vertices.getSize();
-   }
-
-   VertexType& getEntity( DimensionTag,
-                          const GlobalIndexType entityIndex )
-   {
-      return this->vertices[ entityIndex ];
-   }
-
-   const VertexType& getEntity( DimensionTag,
-                                const GlobalIndexType entityIndex ) const
-   {
-      return this->vertices.getElement( entityIndex );
-   }
-
-   AccessArrayType& getEntities( DimensionTag )
-   {
-      return this->sharedVertices;
-   }
-
-   const AccessArrayType& getEntities( DimensionTag ) const
-   {
-      return this->sharedVertices;
-   }
-
-   bool save( File& file ) const
-   {
-      if( ! this->vertices.save( file ) )
-      {
-         std::cerr << "Saving of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      if( ! this->vertices.load( file ) )
-      {
-         std::cerr << "Loading of the mesh entities with " << DimensionTag::value << " dimensions failed." << std::endl;
-         return false;
-      }
-      this->verticesAccess.bind( this->vertices );
-      return true;
-   }
-
-   void print( std::ostream& str ) const
-   {
-      str << "The mesh vertices are: " << std::endl;
-      for( GlobalIndexType i = 0; i < vertices.getSize();i ++ )
-      {
-         str << i << vertices[ i ] << std::endl;
-      }
-      SuperentityStorageBaseType::print( str );
-   }
-
-   bool operator==( const MeshStorageLayer& meshLayer ) const
-   {
-      return ( vertices == meshLayer.vertices );
-   }
-
-   private:
-
-   StorageArrayType vertices;
-
-   AccessArrayType verticesAccess;
- 
-   // TODO: this is only for the mesh initializer - fix it
-   public:
- 
-      typename EntityTraitsType::StorageArrayType& entitiesArray( DimensionTag )
-      {
-         return vertices;
-      }
-
- 
-      template< typename SuperDimensionTag >
-      typename MeshTraitsType::GlobalIdArrayType& superentityIdsArray( DimensionTag )
-      {
-         return SuperentityStorageBaseType::superentityIdsArray( SuperDimensionTag() );
-      }
-
-      template< typename SuperdimensionsTag >
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperdimensionsTag::value >::StorageNetworkType& getSuperentityStorageNetwork( MeshDimensionTag< EntityTopology::dimensions > )
-      {
-         return SuperentityStorageBaseType::getStorageNetwork( SuperdimensionsTag() );
-      }
-
-};
-
-/****
- * Forces termination of recursive inheritance (prevents compiler from generating huge error logs)
- */
-template< typename MeshConfig >
-class MeshStorageLayer< MeshConfig, MeshDimensionTag< 0 >, false >
-{
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h
deleted file mode 100644
index 13d40fd980f9616741eaf14986c6010ab9fb9beb..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h
+++ /dev/null
@@ -1,408 +0,0 @@
-/***************************************************************************
-                          MeshSubentityStorageLayer.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/File.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h>
-#include <TNL/Meshes/MeshDetails/MeshEntityOrientation.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag,
-          bool SubentityStorage =
-            MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::storageEnabled,
-          bool SubentityOrientationStorage =
-            MeshTraits< MeshConfig >::template SubentityTraits< EntityTopology, DimensionTag::value >::orientationEnabled >
-class MeshSubentityStorageLayer;
-
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSubentityStorageLayers
-   : public MeshSubentityStorageLayer< MeshConfig,
-                                          EntityTopology,
-                                          MeshDimensionTag< EntityTopology::dimensions - 1 > >
-{
-};
-
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSubentityStorageLayer< MeshConfig,
-                                    EntityTopology,
-                                    DimensionTag,
-                                    true,
-                                    true >
-   : public MeshSubentityStorageLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >
-{
-   typedef MeshSubentityStorageLayer< MeshConfig,
-                                         EntityTopology,
-                                         typename DimensionTag::Decrement > BaseType;
-
-   protected:
-
-   static const int Dimension = DimensionTag::value;
-   typedef MeshTraits< MeshConfig >                                                      MeshTraitsType;
-   typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension >   SubentityTraitsType;
-   typedef typename MeshTraitsType::GlobalIndexType                                          GlobalIndexType;
-   typedef typename MeshTraitsType::LocalIndexType                                           LocalIndexType;
-   typedef typename SubentityTraitsType::IdArrayType                                         IdArrayType;
-   typedef typename SubentityTraitsType::OrientationArrayType                                OrientationArrayType;
-   typedef typename MeshTraitsType::IdPermutationArrayAccessorType                           IdPermutationArrayAccessorType;
-
-   MeshSubentityStorageLayer()
-   {
-      this->subentitiesIndices.setValue( -1 );
-   }
-
-   ~MeshSubentityStorageLayer()
-   {
-      //cout << "      Destroying " << this->sharedSubentitiesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl;
-   }
-
-   MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer )
-   {
-      BaseType::operator=( layer );
-      this->subentitiesIndices = layer.subentitiesIndices;
-      return *this;
-   }
-
-   bool save( File& file ) const
-   {
-      if( ! BaseType::save( file ) ||
-          ! this->subentitiesIndices.save( file ) )
-      {
-         std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      if( ! BaseType::load( file ) ||
-          ! this->subentitiesIndices.load( file ) )
-      {
-         std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   void print( std::ostream& str ) const
-   {
-      BaseType::print( str );
-      str << std::endl;
-      str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << subentitiesIndices << ".";
-   }
-
-   bool operator==( const MeshSubentityStorageLayer& layer  ) const
-   {
-      return ( BaseType::operator==( layer ) &&
-               subentitiesIndices == layer.subentitiesIndices );
-   }
-
-   /****
-    * Make visible setters and getters of the lower subentities
-    */
-   using BaseType::getSubentityIndex;
-   using BaseType::setSubentityIndex;
-
-   /****
-    * Define setter/getter for the current level of the subentities
-    */
-   void setSubentityIndex( DimensionTag,
-                           const LocalIndexType localIndex,
-                           const GlobalIndexType globalIndex )
-   {
-      this->subentitiesIndices[ localIndex ] = globalIndex;
-   }
-
-   GlobalIndexType getSubentityIndex( DimensionTag,
-                                      const LocalIndexType localIndex ) const
-   {
-      return this->subentitiesIndices[ localIndex ];
-   }
-
-   using BaseType::subentityIdsArray;
-   IdArrayType& subentityIdsArray( DimensionTag ) { return this->subentitiesIndices; }
- 
-   using BaseType::subentityOrientation;
-   IdPermutationArrayAccessorType subentityOrientation( DimensionTag, LocalIndexType index) const
-   {
-      TNL_ASSERT( 0 <= index && index < SubentityTraitsType::count, );
- 
-      return this->subentityOrientations[ index ].getSubvertexPermutation();
-   }
-
-   using BaseType::subentityOrientationsArray;
-	OrientationArrayType& subentityOrientationsArray( DimensionTag ) { return this->subentityOrientations; }
- 
-   private:
-      IdArrayType subentitiesIndices;
-
-      OrientationArrayType subentityOrientations;
-};
-
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSubentityStorageLayer< MeshConfig,
-                                    EntityTopology,
-                                    DimensionTag,
-                                    true,
-                                    false >
-   : public MeshSubentityStorageLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >
-{
-   typedef MeshSubentityStorageLayer< MeshConfig,
-                                         EntityTopology,
-                                         typename DimensionTag::Decrement > BaseType;
-
-   protected:
- 
-   static const int Dimension = DimensionTag::value;
-   typedef MeshTraits< MeshConfig >                                                      MeshTraitsType;
-   typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension >   SubentityTraitsType;
-   typedef typename MeshTraitsType::GlobalIndexType                                          GlobalIndexType;
-   typedef typename MeshTraitsType::LocalIndexType                                           LocalIndexType;
-   typedef typename SubentityTraitsType::IdArrayType                                         IdArrayType;
-   typedef typename SubentityTraitsType::OrientationArrayType                                OrientationArrayType;
-   typedef typename MeshTraitsType::IdPermutationArrayAccessorType                           IdPermutationArrayAccessorType;
-
-   MeshSubentityStorageLayer()
-   {
-      this->subentitiesIndices.setValue( -1 );
-   }
-
-   ~MeshSubentityStorageLayer()
-   {
-      //cout << "      Destroying " << this->sharedSubentitiesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl;
-   }
-
-   MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer )
-   {
-      BaseType::operator=( layer );
-      this->subentitiesIndices = layer.subentitiesIndices;
-      return *this;
-   }
-
-   bool save( File& file ) const
-   {
-      if( ! BaseType::save( file ) ||
-          ! this->subentitiesIndices.save( file ) )
-      {
-         std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      if( ! BaseType::load( file ) ||
-          ! this->subentitiesIndices.load( file ) )
-      {
-         std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   void print( std::ostream& str ) const
-   {
-      BaseType::print( str );
-      str << std::endl;
-      str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << subentitiesIndices << ".";
-   }
-
-   bool operator==( const MeshSubentityStorageLayer& layer  ) const
-   {
-      return ( BaseType::operator==( layer ) &&
-               subentitiesIndices == layer.subentitiesIndices );
-   }
-
-   /****
-    * Make visible setters and getters of the lower subentities
-    */
-   using BaseType::getSubentityIndex;
-   using BaseType::setSubentityIndex;
-
-   /****
-    * Define setter/getter for the current level of the subentities
-    */
-   void setSubentityIndex( DimensionTag,
-                           const LocalIndexType localIndex,
-                           const GlobalIndexType globalIndex )
-   {
-      this->subentitiesIndices[ localIndex ] = globalIndex;
-   }
-
-   GlobalIndexType getSubentityIndex( DimensionTag,
-                                      const LocalIndexType localIndex ) const
-   {
-      return this->subentitiesIndices[ localIndex ];
-   }
-
-   using BaseType::subentityIdsArray;
-   IdArrayType& subentityIdsArray( DimensionTag ) { return this->subentitiesIndices; }
- 
-   using BaseType::subentityOrientationsArray;
-   void subentityOrientationsArray() {}
- 
-   private:
-      IdArrayType subentitiesIndices;
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSubentityStorageLayer< MeshConfig,
-                                    EntityTopology,
-                                    DimensionTag,
-                                    false,
-                                    false >
-   : public MeshSubentityStorageLayer< MeshConfig,
-                                          EntityTopology,
-                                          typename DimensionTag::Decrement >
-{
-};
-
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSubentityStorageLayer< MeshConfig,
-                                    EntityTopology,
-                                    MeshDimensionTag< 0 >,
-                                    true,
-                                    false >
-{
-   typedef MeshDimensionTag< 0 >                           DimensionTag;
-
-   protected:
-   static const int Dimension = 0;
-   typedef MeshTraits< MeshConfig >                                                          MeshTraitsType;
-   typedef typename MeshTraitsType::template SubentityTraits< EntityTopology, Dimension >   SubentityTraitsType;
-   typedef typename MeshTraitsType::GlobalIndexType                                          GlobalIndexType;
-   typedef typename MeshTraitsType::LocalIndexType                                           LocalIndexType;
-   typedef typename SubentityTraitsType::IdArrayType                                         IdArrayType;
-
-   MeshSubentityStorageLayer()
-   {
-      this->verticesIndices.setValue( -1 );
-   }
-
-   ~MeshSubentityStorageLayer()
-   {
-      //cout << "      Destroying " << this->sharedVerticesIndices.getSize() << " subentities with "<< DimensionTag::value << " dimensions." << std::endl;
-   }
-
-
-   MeshSubentityStorageLayer& operator = ( const MeshSubentityStorageLayer& layer )
-   {
-      this->verticesIndices = layer.verticesIndices;
-      return *this;
-   }
-
-   bool save( File& file ) const
-   {
-      if( ! this->verticesIndices.save( file ) )
-      {
-         std::cerr << "Saving of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      if( ! this->verticesIndices.load( file ) )
-      {
-         std::cerr << "Loading of the entity subentities layer with " << DimensionTag::value << " failed." << std::endl;
-         return false;
-      }
-      return true;
-   }
-
-   void print( std::ostream& str ) const
-   {
-      str << "\t Subentities with " << DimensionTag::value << " dimensions are: " << this->verticesIndices << ".";
-   }
-
-   bool operator==( const MeshSubentityStorageLayer& layer  ) const
-   {
-      return ( verticesIndices == layer.verticesIndices );
-   }
-
-   GlobalIndexType getSubentityIndex( DimensionTag,
-                                      const LocalIndexType localIndex ) const
-   {
-      return this->verticesIndices[ localIndex ];
-   }
-   void setSubentityIndex( DimensionTag,
-                           const LocalIndexType localIndex,
-                           const GlobalIndexType globalIndex )
-   {
-      this->verticesIndices[ localIndex ] = globalIndex;
-   }
-
-   IdArrayType& subentityIdsArray( DimensionTag ) { return this->verticesIndices; }
- 
-   protected:
- 
-      /***
-       *  Necessary because of 'using TBase::...;' in the derived classes
-       */
-	   void subentityOrientation()       {}
-	   void subentityOrientationsArray() {}
-
-      IdArrayType verticesIndices;
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSubentityStorageLayer< MeshConfig,
-                                    EntityTopology,
-                                    MeshDimensionTag< 0 >,
-                                    false,
-                                    false >
-{
-   public:
-
-   bool save( File& file ) const
-   {
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      return true;
-   }
-
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h
deleted file mode 100644
index 44476c81cdb57ce40482ba63b5b62206176dfc8f..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/***************************************************************************
-                          MeshSuperentityAccess.h  -  description
-                             -------------------
-    begin                : Aug 15, 2015
-    copyright            : (C) 2015 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/MeshTraits.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename MeshEntity,
-          typename DimensionTag,
-          bool SuperentityStorage =
-             MeshTraits< MeshConfig >::template SuperentityTraits< MeshEntity, DimensionTag::value >::storageEnabled >
-class MeshSuperentityAccessLayer;
-
-
-template< typename MeshConfig,
-          typename MeshEntity >
-class MeshSuperentityAccess :
-   public MeshSuperentityAccessLayer< MeshConfig,
-                                         MeshEntity,
-                                         MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > >
-{
-   public:
-      typedef MeshSuperentityAccessLayer< MeshConfig,
-                                             MeshEntity,
-                                             MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > > BaseType;
- 
-      bool operator == ( const MeshSuperentityAccess< MeshConfig, MeshEntity>& a ) const { return true; } // TODO: fix
- 
-      void print( std::ostream& str ) const
-      {
-         BaseType::print( str );
-      };
-
-};
-
-template< typename MeshConfig,
-          typename MeshEntity,
-          typename Dimension >
-class MeshSuperentityAccessLayer< MeshConfig,
-                                     MeshEntity,
-                                     Dimension,
-                                     true > :
-   public MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement >
-{
-	typedef MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement > BaseType;
-
-   public:
- 
-      typedef MeshTraits< MeshConfig >                                                             MeshTraitsType;
-      typedef typename MeshTraitsType::template SuperentityTraits< MeshEntity, Dimension::value > SuperentityTraitsType;
-      typedef typename MeshTraitsType::IdArrayAccessorType                                         IdArrayAccessorType;
-      typedef typename SuperentityTraitsType::StorageNetworkType                                   StorageNetworkType;
-      typedef typename SuperentityTraitsType::SuperentityAccessorType                              SuperentityAccessorType;
-      //typedef typename StorageNetworkType::PortsType                            SuperentityAccessorType;
-
-	   using BaseType::superentityIds;
-	   IdArrayAccessorType superentityIds( Dimension ) const { return m_superentityIndices; }
-
-	   using BaseType::superentityIdsArray;
-	   IdArrayAccessorType &superentityIdsArray( Dimension ) { return m_superentityIndices; }
- 
-      using BaseType::getSuperentityIndices;
-      const SuperentityAccessorType& getSuperentityIndices( Dimension ) const
-      {
-         std::cerr << "###" << std::endl;
-         return this->superentityIndices;
-      }
- 
-      SuperentityAccessorType& getSuperentityIndices( Dimension )
-      {
-         std::cerr << "######" << std::endl;
-         return this->superentityIndices;
-      }
- 
-      void print( std::ostream& str ) const
-      {
-         str << "Superentities with " << Dimension::value << " dimensions are: " <<
-            this->superentityIndices << std::endl;
-         BaseType::print( str );
-      }
- 
-      //bool operator == ( const MeshSuperentityAccessLayer< MeshConfig, MeshEntity, Dimension, tnlStorageTraits< true > >& l ) { return true; } // TODO: fix
-
-   private:
-	   IdArrayAccessorType m_superentityIndices;
- 
-      SuperentityAccessorType superentityIndices;
- 
-};
-
-template< typename MeshConfig,
-          typename MeshEntity,
-          typename Dimension >
-class MeshSuperentityAccessLayer< MeshConfig,
-                                     MeshEntity,
-                                     Dimension,
-                                     false > :
-   public MeshSuperentityAccessLayer< MeshConfig, MeshEntity, typename Dimension::Decrement >
-{
-};
-
-template< typename MeshConfig,
-          typename MeshEntity >
-class MeshSuperentityAccessLayer< MeshConfig,
-                                     MeshEntity,
-                                     MeshDimensionTag< MeshEntity::dimensions >,
-                                     false >
-{
-   protected:
-	   /***
-       * Necessary because of 'using TBase::...;' in the derived classes
-       */
-	   void superentityIds()      {}
-	   void superentityIdsArray() {}
- 
-      void getSuperentityIndices() {};
- 
-      void print( std::ostream& str ) const {};
-};
-
-template< typename MeshConfig,
-          typename MeshEntity >
-class MeshSuperentityAccessLayer< MeshConfig,
-                                     MeshEntity,
-                                     MeshDimensionTag< MeshEntity::dimensions >,
-                                     true >
-{
-   protected:
-	   /***
-       * Necessary because of 'using TBase::...;' in the derived classes
-       */
-	   void superentityIds()      {}
-	   void superentityIdsArray() {}
- 
-      void getSuperentityIndices() {};
- 
-      void print( std::ostream& str ) const {};
-};
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h
deleted file mode 100644
index ebe8ee41940190935657615eef3b95419def2d41..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/***************************************************************************
-                          MeshSuperentityAccessor.h  -  description
-                             -------------------
-    begin                : Sep 11, 2015
-    copyright            : (C) 2015 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
-
-namespace TNL {
-namespace Meshes {
-
-template< typename IndexMultimapValues >
-class MeshSuperentityAccessor
-{
-   public:
- 
-      typedef typename IndexMultimapValues::IndexType   GlobalIndexType;
-      typedef typename IndexMultimapValues::IndexType   LocalIndexType;
- 
-      // TODO: Add LocalIndexType to EllpackIndexMultimap
- 
-      LocalIndexType getSupernetitiesCount() const
-      {
-         return this->indexes.getPortsCount();
-      };
- 
-      void setSuperentityIndex( const LocalIndexType localIndex,
-                                const GlobalIndexType globalIndex )
-      {
-         indexes.setOutput( localIndex, globalIndex );
-      }
- 
-      GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const
-      {
-         return indexes.getOutput( localIndex );
-      }
- 
-      GlobalIndexType& operator[]( const LocalIndexType localIndex )
-      {
-         return this->indexes[ localIndex ];
-      }
- 
-      const GlobalIndexType& operator[]( const LocalIndexType localIndex ) const
-      {
-         return this->indexes[ localIndex ];
-      }
- 
-      void print( std::ostream& str ) const
-      {
-         str << indexes;
-      }
- 
-   protected:
- 
-      IndexMultimapValues indexes;
- 
-};
-
-template< typename IndexMultimapValues >
-std::ostream& operator << ( std::ostream& str, const MeshSuperentityAccessor< IndexMultimapValues >& superentityAccessor )
-{
-   superentityAccessor.print( str );
-   return str;
-}
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h b/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h
deleted file mode 100644
index d02a1beafb69f6fbf1d86592c0dbc78f9dc4ce07..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h
+++ /dev/null
@@ -1,346 +0,0 @@
-/***************************************************************************
-                          MeshSuperentityStorageLayer.h  -  description
-                             -------------------
-    begin                : Feb 13, 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/File.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
-#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
-
-namespace TNL {
-namespace Meshes {
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag,
-          bool SuperentityStorage =
-             MeshSuperentityTraits< MeshConfig, EntityTopology, DimensionTag::value >::storageEnabled >
-class MeshSuperentityStorageLayer;
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageLayers
-   : public MeshSuperentityStorageLayer< MeshConfig,
-                                            EntityTopology,
-                                            MeshDimensionTag< MeshTraits< MeshConfig >::meshDimension > >
-{
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, DimensionTag, true >
-   : public MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement >
-{
-   typedef
-      MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement >  BaseType;
-
-   static const int Dimension = DimensionTag::value;
-   typedef MeshTraits< MeshConfig >                                                          MeshTraitsType;
-   typedef typename MeshTraitsType::template SuperentityTraits< EntityTopology, Dimension > SuperentityTraitsType;
-
-   protected:
-
-   typedef typename SuperentityTraitsType::StorageArrayType       StorageArrayType;
-   typedef typename SuperentityTraitsType::AccessArrayType        AccessArrayType;
-   typedef typename SuperentityTraitsType::GlobalIndexType        GlobalIndexType;
-   typedef typename SuperentityTraitsType::LocalIndexType         LocalIndexType;
-
-   typedef typename SuperentityTraitsType::StorageNetworkType   StorageNetworkType;
- 
-   /****
-     * Make visible setters and getters of the lower superentities
-     */
-    using BaseType::setNumberOfSuperentities;
-    using BaseType::getNumberOfSuperentities;
-    using BaseType::getSuperentityIndex;
-    using BaseType::setSuperentityIndex;
-    using BaseType::getSuperentitiesIndices;
-
-    MeshSuperentityStorageLayer()
-    {
-    }
-
-    /*~MeshSuperentityStorageLayer()
-    {
-       std::cerr << "      Destroying " << this->superentitiesIndices.getSize() << " superentities with "<< DimensionTag::value << " dimensions." << std::endl;
-       std::cerr << "         this->superentitiesIndices.getName() = " << this->superentitiesIndices.getName() << std::endl;
-       std::cerr << "         this->sharedSuperentitiesIndices.getName() = " << this->sharedSuperentitiesIndices.getName() << std::endl;
-    }*/
-
-    MeshSuperentityStorageLayer& operator = ( const MeshSuperentityStorageLayer& layer )
-    {
-       this->superentitiesIndices.setSize( layer.superentitiesIndices.getSize() );
-       this->superentitiesIndices = layer.superentitiesIndices;
-       this->sharedSuperentitiesIndices.bind( this->superentitiesIndices );
-       return *this;
-    }
-
-    /****
-     * Define setter/getter for the current level of the superentities
-     */
-    bool setNumberOfSuperentities( DimensionTag,
-                                   const LocalIndexType size )
-    {
-       if( ! this->superentitiesIndices.setSize( size ) )
-          return false;
-       this->superentitiesIndices.setValue( -1 );
-       this->sharedSuperentitiesIndices.bind( this->superentitiesIndices );
-       return true;
-    }
-
-    LocalIndexType getNumberOfSuperentities( DimensionTag ) const
-    {
-       return this->superentitiesIndices.getSize();
-    }
-
-    void setSuperentityIndex( DimensionTag,
-                              const LocalIndexType localIndex,
-                              const GlobalIndexType globalIndex )
-    {
-       this->superentitiesIndices[ localIndex ] = globalIndex;
-    }
-
-    GlobalIndexType getSuperentityIndex( DimensionTag,
-                                         const LocalIndexType localIndex ) const
-    {
-       return this->superentitiesIndices[ localIndex ];
-    }
-
-    AccessArrayType& getSuperentitiesIndices( DimensionTag )
-    {
-       return this->sharedSuperentitiesIndices;
-    }
-
-    const AccessArrayType& getSuperentitiesIndices( DimensionTag ) const
-    {
-       return this->sharedSuperentitiesIndices;
-    }
-
-    bool save( File& file ) const
-    {
-       if( ! BaseType::save( file ) ||
-           ! this->superentitiesIndices.save( file ) )
-       {
-          //cerr << "Saving of the entity superentities layer with " << DimensionTag::value << " failed." << std::endl;
-          return false;
-       }
-       return true;
-    }
-
-    bool load( File& file )
-    {
-       if( ! BaseType::load( file ) ||
-           ! this->superentitiesIndices.load( file ) )
-       {
-          //cerr << "Loading of the entity superentities layer with " << DimensionTag::value << " failed." << std::endl;
-          return false;
-       }
-       return true;
-    }
-
-    void print( std::ostream& str ) const
-    {
-       BaseType::print( str );
-       str << std::endl << "\t Superentities with " << DimensionTag::value << " dimensions are: " << this->superentitiesIndices << ".";
-    }
-
-    bool operator==( const MeshSuperentityStorageLayer& layer  ) const
-    {
-       return ( BaseType::operator==( layer ) &&
-                superentitiesIndices == layer.superentitiesIndices );
-    }
-
-    private:
-
-    StorageArrayType superentitiesIndices;
-
-    AccessArrayType sharedSuperentitiesIndices;
- 
-    StorageNetworkType storageNetwork;
- 
-   // TODO: this is only for the mesh initializer - fix it
-   public:
- 
-      using BaseType::superentityIdsArray;
-      typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag )
-      {
-         return this->superentitiesIndices;
-      }
- 
-      using BaseType::getStorageNetwork;
-      StorageNetworkType& getStorageNetwork( DimensionTag )
-      {
-         return this->storageNetwork;
-      }
-};
-
-template< typename MeshConfig,
-          typename EntityTopology,
-          typename DimensionTag >
-class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, DimensionTag, false >
-   : public MeshSuperentityStorageLayer< MeshConfig, EntityTopology, typename DimensionTag::Decrement >
-{
-   public:
-
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageLayer< MeshConfig, EntityTopology, MeshDimensionTag< EntityTopology::dimensions >, false >
-{
-   static const int Dimension = EntityTopology::dimensions;
-   typedef MeshDimensionTag< EntityTopology::dimensions >        DimensionTag;
-
-   typedef MeshSuperentityTraits< MeshConfig, EntityTopology, Dimension >      SuperentityTraits;
-
-   typedef MeshSuperentityStorageLayer< MeshConfig,
-                                           EntityTopology,
-                                           DimensionTag,
-                                           false > ThisType;
-
-   protected:
-
-   typedef typename SuperentityTraits::ContainerType              ContainerType;
-   typedef typename ContainerType::ElementType                 GlobalIndexType;
-   typedef int                                                 LocalIndexType;
-
-   typedef typename SuperentityTraits::StorageNetworkType   StorageNetworkType;
- 
-   /****
-    * These methods are due to 'using BaseType::...;' in the derived classes.
-    */
-   bool setNumberOfSuperentities( DimensionTag,
-                                   const LocalIndexType size );
-   LocalIndexType getNumberOfSuperentities( DimensionTag ) const;
-   GlobalIndexType getSuperentityIndex( DimensionTag,
-                                        const LocalIndexType localIndex ){}
-   void setSuperentityIndex( DimensionTag,
-                             const LocalIndexType localIndex,
-                             const GlobalIndexType globalIndex ) {}
-
-   void print( std::ostream& str ) const{}
-
-   bool operator==( const ThisType& layer  ) const
-   {
-      return true;
-   }
-
-   ContainerType& getSuperentitiesIndices(){}
-
-   const ContainerType& getSuperentitiesIndices() const{}
-
-   bool save( File& file ) const
-   {
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      return true;
-   }
- 
-   typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag )
-   {
-      TNL_ASSERT( false, );
-      //return this->superentitiesIndices;
-   }
-
-   StorageNetworkType& getStorageNetwork( DimensionTag )
-   {
-      TNL_ASSERT( false, );
-     //return this->storageNetwork;
-   }
-
-};
-
-template< typename MeshConfig,
-          typename EntityTopology >
-class MeshSuperentityStorageLayer< MeshConfig,
-                                      EntityTopology,
-                                      MeshDimensionTag< EntityTopology::dimensions >,
-                                      true >
-{
-   static const int Dimension = EntityTopology::dimensions;
-   typedef MeshDimensionTag< Dimension >                          DimensionTag;
-
-   typedef MeshSuperentityTraits< MeshConfig,
-                                     EntityTopology,
-                                     Dimension >               SuperentityTraits;
-   typedef MeshSuperentityStorageLayer< MeshConfig,
-                                           EntityTopology,
-                                           DimensionTag,
-                                           true > ThisType;
-
-   protected:
-
-   typedef typename SuperentityTraits::StorageArrayType              StorageArrayType;
-   typedef typename SuperentityTraits::GlobalIndexType               GlobalIndexType;
-   typedef typename SuperentityTraits::LocalIndexType                LocalIndexType;
-
-   typedef typename SuperentityTraits::StorageNetworkType   StorageNetworkType;
- 
-   /****
-    * These methods are due to 'using BaseType::...;' in the derived classes.
-    */
-   bool setNumberOfSuperentities( DimensionTag,
-                                   const LocalIndexType size );
-   LocalIndexType getNumberOfSuperentities( DimensionTag ) const;
-   GlobalIndexType getSuperentityIndex( DimensionTag,
-                                        const LocalIndexType localIndex ){}
-   void setSuperentityIndex( DimensionTag,
-                             const LocalIndexType localIndex,
-                             const GlobalIndexType globalIndex ) {}
-
-   void print( std::ostream& str ) const{}
-
-   bool operator==( const ThisType& layer  ) const
-   {
-      return true;
-   }
-
-   StorageArrayType& getSuperentitiesIndices(){}
-
-   const StorageArrayType& getSuperentitiesIndices() const{}
-
-   bool save( File& file ) const
-   {
-      return true;
-   }
-
-   bool load( File& file )
-   {
-      return true;
-   }
- 
-   typename MeshTraits< MeshConfig >::GlobalIdArrayType& superentityIdsArray( DimensionTag )
-   {
-      TNL_ASSERT( false, );
-      //return this->superentitiesIndices;
-   }
-
-   StorageNetworkType& getStorageNetwork( DimensionTag )
-   {
-      TNL_ASSERT( false, );
-      //return this->storageNetwork;
-   }
-
- 
-};
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt b/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt
index b82bb335ac96401c3155520b1f6c983249ee9116..90b0fafc1c54ec0891b343dc4ac3e3b178f77d14 100644
--- a/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt
+++ b/src/TNL/Meshes/MeshDetails/traits/CMakeLists.txt
@@ -2,6 +2,7 @@ SET( headers MeshTraits.h
              MeshEntityTraits.h
              MeshSubentityTraits.h
              MeshSuperentityTraits.h
+             WeakStorageTraits.h
                )
 
-INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/traits )
\ No newline at end of file
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/MeshDetails/traits )
diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h
index c8c8be6b9a5c45dea478cacfa349d4525d82aad9..6b21bcde966fc8e16c4e5bfe1894fb66f924d4bf 100644
--- a/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h
+++ b/src/TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h
@@ -2,7 +2,7 @@
                           MeshEntityTraits.h  -  description
                              -------------------
     begin                : Feb 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -16,77 +16,79 @@
 
 #pragma once
 
-#include <TNL/Containers/StaticVector.h>
 #include <TNL/Containers/Array.h>
-#include <TNL/Containers/SharedArray.h>
-//#include <TNL/Containers/ConstSharedArray.h>
-#include <TNL/Containers/IndexedSet.h>
-#include <TNL/Meshes/Topologies/MeshEntityTopology.h>
-#include <TNL/Meshes/MeshConfigBase.h>
+#include <TNL/Containers/UnorderedIndexedSet.h>
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
 #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
+#include <TNL/Meshes/MeshDetails/initializer/EntitySeed.h>
+
+#include <unordered_set>
 
 namespace TNL {
 namespace Meshes {
 
-template< typename MeshConfig, typename EntityTopology > class MeshEntity;
-template< typename MeshConfig, typename EntityTopology > class MeshEntitySeed;
-template< typename MeshConfig, typename EntityTopology > class MeshEntitySeedKey;
+template< typename MeshConfig, typename Device, typename EntityTopology > class MeshEntity;
 template< typename MeshConfig, typename EntityTopology > class MeshEntityReferenceOrientation;
 
 template< typename MeshConfig,
-          typename DimensionTag,
-          typename SuperDimensionTag = MeshDimensionTag< MeshConfig::meshDimension > >
+          typename EntityDimensionTag,
+          typename SuperDimensionTag = DimensionTag< MeshConfig::meshDimension > >
 class MeshEntityOrientationNeeded
 {
-	static_assert( 0 <= DimensionTag::value && DimensionTag::value < MeshConfig::CellTopology::dimensions, "invalid dimensions" );
-	static_assert( DimensionTag::value < SuperDimensionTag::value && SuperDimensionTag::value <= MeshConfig::CellTopology::dimensions, "invalid superentity dimension");
-
-	typedef typename MeshTraits< MeshConfig >::template EntityTraits< SuperDimensionTag::value >::EntityTopology SuperentityTopology;
+   using SuperentityTopology = typename MeshTraits< MeshConfig >::template EntityTraits< SuperDimensionTag::value >::EntityTopology;
 
-	static const bool previousSuperDimensionValue = MeshEntityOrientationNeeded< MeshConfig, DimensionTag, typename SuperDimensionTag::Decrement >::value;
-	static const bool thisSuperDimensionValue = MeshTraits< MeshConfig >::template SubentityTraits< SuperentityTopology, DimensionTag::value >::orientationEnabled;
+   static constexpr bool previousSuperDimensionValue = MeshEntityOrientationNeeded< MeshConfig, EntityDimensionTag, typename SuperDimensionTag::Decrement >::value;
+   static constexpr bool thisSuperDimensionValue = MeshTraits< MeshConfig >::template SubentityTraits< SuperentityTopology, EntityDimensionTag::value >::orientationEnabled;
 
-   public:
-      static const bool value = ( previousSuperDimensionValue || thisSuperDimensionValue );
+public:
+   static constexpr bool value = ( previousSuperDimensionValue || thisSuperDimensionValue );
 };
 
 template< typename MeshConfig, typename DimensionTag >
 class MeshEntityOrientationNeeded< MeshConfig, DimensionTag, DimensionTag >
 {
-	static_assert( 0 <= DimensionTag::value && DimensionTag::value <= MeshConfig::CellTopology::dimensions, "invalid dimensions" );
+public:
+   static constexpr bool value = false;
+};
+
+
+template< typename MeshConfig,
+          typename DimensionTag >
+struct EntityTopologyGetter
+{
+   static_assert( DimensionTag::value <= MeshConfig::meshDimension, "There are no entities with dimension higher than the mesh dimension." );
+   using Topology = typename Topologies::Subtopology< typename MeshConfig::CellTopology, DimensionTag::value >::Topology;
+};
 
-   public:
-      static const bool value = false;
+template< typename MeshConfig >
+struct EntityTopologyGetter< MeshConfig, DimensionTag< MeshConfig::CellTopology::dimension > >
+{
+   using Topology = typename MeshConfig::CellTopology;
 };
 
 
 template< typename MeshConfig,
+          typename Device,
           int Dimension >
 class MeshEntityTraits
 {
-   public:
-
-      static const bool storageEnabled = MeshConfig::entityStorage( Dimension );
-      static const bool orientationNeeded = MeshEntityOrientationNeeded< MeshConfig, MeshDimensionTag< Dimension > >::value;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
 
-      typedef typename MeshConfig::GlobalIndexType                                 GlobalIndexType;
-      typedef typename MeshConfig::LocalIndexType                                  LocalIndexType;
-      typedef typename MeshEntityTopology< MeshConfig, Dimension >::Topology   EntityTopology;
- 
-      typedef MeshEntity< MeshConfig, EntityTopology >                          EntityType;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >                      SeedType;
-      typedef MeshEntityReferenceOrientation< MeshConfig, EntityTopology >      ReferenceOrientationType;
-      typedef MeshEntitySeedKey< MeshConfig, EntityTopology >                   Key;
+public:
+   static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" );
 
+   using EntityTopology                = typename EntityTopologyGetter< MeshConfig, DimensionTag< Dimension > >::Topology;
+   using EntityType                    = MeshEntity< MeshConfig, Device, EntityTopology >;
+   using SeedType                      = EntitySeed< MeshConfig, EntityTopology >;
+   using ReferenceOrientationType      = MeshEntityReferenceOrientation< MeshConfig, EntityTopology >;
 
-      typedef Containers::Array< EntityType, Devices::Host, GlobalIndexType >               StorageArrayType;
-      typedef Containers::SharedArray< EntityType, Devices::Host, GlobalIndexType >         AccessArrayType;
-      typedef Containers::IndexedSet< EntityType, GlobalIndexType, Key >                      UniqueContainerType;
-      typedef Containers::IndexedSet< SeedType, GlobalIndexType, Key >                        SeedIndexedSetType;
-      typedef Containers::Array< SeedType, Devices::Host, GlobalIndexType >                 SeedArrayType;
-      typedef Containers::Array< ReferenceOrientationType, Devices::Host, GlobalIndexType > ReferenceOrientationArrayType;
+   using StorageArrayType              = Containers::Array< EntityType, Device, GlobalIndexType >;
+   using SeedIndexedSetType            = Containers::UnorderedIndexedSet< SeedType, GlobalIndexType, typename SeedType::HashType, typename SeedType::KeyEqual >;
+   using SeedSetType                   = std::unordered_set< typename SeedIndexedSetType::key_type, typename SeedIndexedSetType::hasher, typename SeedIndexedSetType::key_equal >;
+   using ReferenceOrientationArrayType = Containers::Array< ReferenceOrientationType, Device, GlobalIndexType >;
 
-      typedef Containers::tnlConstSharedArray< EntityType, Devices::Host, GlobalIndexType >    SharedArrayType;
+   static constexpr bool storageEnabled = MeshConfig::entityStorage( Dimension );
+   static constexpr bool orientationNeeded = MeshEntityOrientationNeeded< MeshConfig, DimensionTag< Dimension > >::value;
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h
index cbdd144932f6509f14082ea4d7981ba3e3ee47bf..6f44e834e4da3722351abf50f3c73cc73c4434c0 100644
--- a/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h
+++ b/src/TNL/Meshes/MeshDetails/traits/MeshSubentityTraits.h
@@ -2,7 +2,7 @@
                           MeshSubentityTraits.h  -  description
                              -------------------
     begin                : Feb 12, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -17,57 +17,65 @@
 #pragma once
 
 #include <TNL/Containers/StaticArray.h>
-#include <TNL/Containers/SharedArray.h>
 #include <TNL/Meshes/MeshEntity.h>
-#include <TNL/Meshes/MeshConfigBase.h>
-#include <TNL/Meshes/Topologies/MeshEntityTopology.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h>
 
 namespace TNL {
 namespace Meshes {
 
-template< typename MeshConfig, typename EntityTopology > class MeshEntityOrientation;
+template< typename MeshConfig, typename EntityTopology >
+class MeshEntityOrientation;
+template< typename MeshConfig, typename EntityTopology >
+class EntitySeed;
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology,
           int Dimension >
 class MeshSubentityTraits
 {
-   public:
-      static const bool storageEnabled = MeshConfig::subentityStorage( EntityTopology(), Dimension );
-      static const bool orientationEnabled = MeshConfig::subentityOrientationStorage( EntityTopology(), Dimension );
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType  = typename MeshConfig::LocalIndexType;
 
-      typedef typename MeshConfig::GlobalIndexType                                GlobalIndexType;
-      typedef typename MeshConfig::LocalIndexType                                 LocalIndexType;
-      typedef MeshSubtopology< EntityTopology, Dimension >                    Subtopology;
-      typedef typename Subtopology::Topology                                      SubentityTopology;
-      typedef MeshEntity< MeshConfig, SubentityTopology >                      SubentityType;
-      typedef MeshEntitySeed< MeshConfig, SubentityTopology >                  Seed;
-      typedef MeshEntityOrientation< MeshConfig, SubentityTopology >           Orientation;
+public:
+   static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" );
+   static_assert( EntityTopology::dimension > Dimension, "Subentity dimension must be smaller than the entity dimension." );
 
+   static constexpr bool storageEnabled = MeshConfig::subentityStorage( EntityTopology(), Dimension );
+   static constexpr bool orientationEnabled = MeshConfig::subentityOrientationStorage( EntityTopology(), Dimension );
+   static constexpr int count = Topologies::Subtopology< EntityTopology, Dimension >::count;
 
-      static const int count = Subtopology::count;
+   using SubentityTopology = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityTopology;
+   using SubentityType     = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityType;
+   using Seed              = EntitySeed< MeshConfig, SubentityTopology >;
+   using Orientation       = MeshEntityOrientation< MeshConfig, SubentityTopology >;
 
-      typedef Containers::StaticArray< count, GlobalIndexType >              StorageArrayType;
-      typedef Containers::SharedArray< GlobalIndexType,
-                                      Devices::Host,
-                                      LocalIndexType >                      AccessArrayType;
-      typedef Containers::StaticArray< count, GlobalIndexType >              IdArrayType;
-      typedef Containers::StaticArray< count, SubentityType >                SubentityContainerType;
-      typedef Containers::StaticArray< count, Seed >                         SeedArrayType;
-      typedef Containers::StaticArray< count, Orientation >                  OrientationArrayType;
-      typedef Containers::StaticArray< count, LocalIndexType >               IdPermutationArrayType;
+   /****
+    * Type of container for storing of the subentities indices.
+    */
+   // TODO: write general operator= for different SliceSize and remove the '32' here
+   using StorageNetworkType     = StaticEllpackIndexMultimap< count, GlobalIndexType, Device, LocalIndexType, 32 >;
+   using SubentityAccessorType  = typename StorageNetworkType::ValuesAccessorType;
 
-      template< LocalIndexType subentityIndex,
-                LocalIndexType subentityPointIndex >
-      struct Point
-      {
-         enum { index = tnlSubentityPoint< EntityTopology,
-                                            SubentityTopology,
-                                            subentityIndex,
-                                            subentityPointIndex>::index };
-      };
+   // static array used in MeshSubentitySeedCreator
+   using SeedArrayType          = Containers::StaticArray< count, Seed >;
 
-      static_assert( EntityTopology::dimensions > Dimension, "You try to create subentities traits where subentity dimension are not smaller than the entity dimension." );
+   // orientation and its accessor
+   using OrientationArrayType   = Containers::StaticArray< count, Orientation >;
+   using IdPermutationArrayType = Containers::StaticArray< count, LocalIndexType >;
+
+   template< LocalIndexType subentityIndex,
+             LocalIndexType subentityVertexIndex >
+   struct Vertex
+   {
+      static constexpr int index = Topologies::SubentityVertexMap<
+                  EntityTopology,
+                  SubentityTopology,
+                  subentityIndex,
+                  subentityVertexIndex >::index;
+   };
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h
index b4e816399673a2a71ddcc46bac1e273923afdea8..efee12537b1d11bc32e099ea4b8b5930e68a7cb7 100644
--- a/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h
+++ b/src/TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h
@@ -2,7 +2,7 @@
                           MeshSuperentityTraits.h  -  description
                              -------------------
     begin                : Feb 13, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -16,58 +16,37 @@
 
 #pragma once
 
-#include <TNL/Containers/Array.h>
-#include <TNL/Containers/ConstSharedArray.h>
-#include <TNL/Containers/List.h>
 #include <TNL/Meshes/MeshEntity.h>
-#include <TNL/Meshes/MeshConfigBase.h>
-#include <TNL/Meshes/Topologies/MeshEntityTopology.h>
 #include <TNL/Meshes/MeshDetails/traits/MeshEntityTraits.h>
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h>
-#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityAccessor.h>
+#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h>
 
 namespace TNL {
 namespace Meshes {
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology,
           int Dimension >
 class MeshSuperentityTraits
 {
-   public:
- 
-   typedef typename MeshConfig::GlobalIndexType                              GlobalIndexType;
-   typedef typename MeshConfig::LocalIndexType                               LocalIndexType;
+   using GlobalIndexType = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType  = typename MeshConfig::LocalIndexType;
 
+public:
+   static_assert( 0 <= Dimension && Dimension <= MeshConfig::meshDimension, "invalid dimension" );
+   static_assert( EntityTopology::dimension < Dimension, "Superentity dimension must be higher than the entity dimension." );
 
-   static const bool storageEnabled = MeshConfig::template superentityStorage< EntityTopology >( EntityTopology(), Dimension );
-   //typedef tnlStorageTraits< storageEnabled >                               SuperentityStorageTag;
-   typedef MeshEntity< MeshConfig, EntityTopology >                            EntityType;
-   typedef MeshEntityTraits< MeshConfig, Dimension >                     EntityTraits;
-   typedef typename EntityTraits::EntityTopology                             SuperentityTopology;
-   typedef typename EntityTraits::EntityType                                 SuperentityType;
+   static constexpr bool storageEnabled = MeshConfig::template superentityStorage< EntityTopology >( EntityTopology(), Dimension );
 
+   using SuperentityTopology = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityTopology;
+   using SuperentityType     = typename MeshEntityTraits< MeshConfig, Device, Dimension >::EntityType;
 
    /****
-    * Type of container for storing of the superentities indecis.
+    * Type of container for storing of the superentities indices.
     */
-   typedef Containers::Array< GlobalIndexType, Devices::Host, LocalIndexType >             StorageArrayType;
- 
-   typedef EllpackIndexMultimap< GlobalIndexType, Devices::Host >                        StorageNetworkType;
-   typedef MeshSuperentityAccessor< typename StorageNetworkType::ValuesAccessorType > SuperentityAccessorType;
- 
-   /****
-    * Type for passing the superentities indecis by the getSuperentitiesIndices()
-    * method. We introduce it because of the compatibility with the subentities
-    * which are usually stored in static array.
-    */
-   typedef Containers::SharedArray< GlobalIndexType, Devices::Host, LocalIndexType >       AccessArrayType;
-
-   /****
-    * This is used by the mesh initializer.
-    */
-   typedef Containers::List< GlobalIndexType >                                       GrowableContainerType;
-
+   // TODO: write general operator= for different SliceSize and remove the '32' here
+   using StorageNetworkType      = EllpackIndexMultimap< GlobalIndexType, Device, LocalIndexType, 32 >;
+   using SuperentityAccessorType = typename StorageNetworkType::ValuesAccessorType;
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h b/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h
index 4cd115593b534804fd9815f466214388f6556cfa..545edbb23a2a0c8bdbb68f962adbd635ce24cec6 100644
--- a/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h
+++ b/src/TNL/Meshes/MeshDetails/traits/MeshTraits.h
@@ -2,7 +2,7 @@
                           MeshTraits.h  -  description
                              -------------------
     begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -18,57 +18,49 @@
 
 #include <TNL/Containers/StaticVector.h>
 #include <TNL/Containers/Array.h>
-#include <TNL/Containers/SharedArray.h>
-#include <TNL/Containers/ConstSharedArray.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
+#include <TNL/Meshes/DimensionTag.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
 
 namespace TNL {
 namespace Meshes {
 
-struct MeshVertexTopology;
-template< typename MeshConfig, typename EntityTopology > class MeshEntity;
-template< typename MeshConfig, typename EntityTopology > class MeshEntitySeed;
-template< typename MeshConfig, int Dimension > class MeshEntityTraits;
-template< typename MeshConfig, typename MeshEntity, int SubDimension > class MeshSubentityTraits;
-template< typename MeshConfig, typename MeshEntity, int SuperDimension > class MeshSuperentityTraits;
+template< typename MeshConfig, typename Device, typename EntityTopology > class MeshEntity;
+template< typename MeshConfig, typename EntityTopology > class EntitySeed;
+template< typename MeshConfig, typename Device, int Dimension > class MeshEntityTraits;
+template< typename MeshConfig, typename Device, typename MeshEntity, int Subdimension > class MeshSubentityTraits;
+template< typename MeshConfig, typename Device, typename MeshEntity, int Superdimension > class MeshSuperentityTraits;
 
 template< typename MeshConfig,
           typename Device = Devices::Host >
 class MeshTraits
 {
-   public:
- 
-      static const int meshDimension = MeshConfig::CellTopology::dimensions;
-      static const int worldDimension = MeshConfig::worldDimension;
+public:
+   static constexpr int meshDimension  = MeshConfig::CellTopology::dimension;
+   static constexpr int worldDimension = MeshConfig::worldDimension;
 
-      typedef Device                                                               DeviceType;
-      typedef typename MeshConfig::GlobalIndexType                                 GlobalIndexType;
-      typedef typename MeshConfig::LocalIndexType                                  LocalIndexType;
- 
-      typedef typename MeshConfig::CellTopology                                    CellTopology;
-      typedef MeshEntity< MeshConfig, CellTopology >                            CellType;
-      typedef MeshEntity< MeshConfig, MeshVertexTopology >                   VertexType;
-      typedef Containers::StaticVector< worldDimension, typename MeshConfig::RealType >    PointType;
-      typedef MeshEntitySeed< MeshConfig, CellTopology >                        CellSeedType;
- 
-      typedef Containers::Array< PointType, Devices::Host, GlobalIndexType >                  PointArrayType;
-      typedef Containers::Array< CellSeedType, Devices::Host, GlobalIndexType >               CellSeedArrayType;
-      typedef Containers::Array< GlobalIndexType, Devices::Host, GlobalIndexType >            GlobalIdArrayType;
-      typedef Containers::tnlConstSharedArray< GlobalIndexType, Devices::Host, LocalIndexType >  IdArrayAccessorType;
-      typedef Containers::tnlConstSharedArray< LocalIndexType, Devices::Host, LocalIndexType >   IdPermutationArrayAccessorType;
- 
-      template< int Dimension > using EntityTraits =
-         MeshEntityTraits< MeshConfig, Dimension >;
- 
-      template< typename EntityTopology, int SubDimension > using SubentityTraits =
-         MeshSubentityTraits< MeshConfig, EntityTopology, SubDimension >;
- 
-      template< typename EntityTopology, int SuperDimension > using SuperentityTraits =
-         MeshSuperentityTraits< MeshConfig, EntityTopology, SuperDimension >;
- 
- 
-      typedef MeshDimensionTag< meshDimension >                                   DimensionTag;
+   using DeviceType        = Device;
+   using GlobalIndexType   = typename MeshConfig::GlobalIndexType;
+   using LocalIndexType    = typename MeshConfig::LocalIndexType;
 
+   using CellTopology      = typename MeshConfig::CellTopology;
+   using CellType          = MeshEntity< MeshConfig, Device, CellTopology >;
+   using VertexType        = MeshEntity< MeshConfig, Device, Topologies::Vertex >;
+   using PointType         = Containers::StaticVector< worldDimension, typename MeshConfig::RealType >;
+   using CellSeedType      = EntitySeed< MeshConfig, CellTopology >;
+
+   using PointArrayType    = Containers::Array< PointType, DeviceType, GlobalIndexType >;
+   using CellSeedArrayType = Containers::Array< CellSeedType, DeviceType, GlobalIndexType >;
+
+   template< int Dimension >
+   using EntityTraits = MeshEntityTraits< MeshConfig, DeviceType, Dimension >;
+
+   template< typename EntityTopology, int Subdimension >
+   using SubentityTraits = MeshSubentityTraits< MeshConfig, DeviceType, EntityTopology, Subdimension >;
+
+   template< typename EntityTopology, int Superdimension >
+   using SuperentityTraits = MeshSuperentityTraits< MeshConfig, DeviceType, EntityTopology, Superdimension >;
+
+   using DimensionTag = Meshes::DimensionTag< meshDimension >;
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h b/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h
new file mode 100644
index 0000000000000000000000000000000000000000..154681fdd52d29376e26d940a7723e56ba99eddc
--- /dev/null
+++ b/src/TNL/Meshes/MeshDetails/traits/WeakStorageTraits.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+                          MeshSuperentityStorageLayer.h  -  description
+                             -------------------
+    begin                : Feb 13, 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/MeshSubentityTraits.h>
+#include <TNL/Meshes/MeshDetails/traits/MeshSuperentityTraits.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag,
+          bool sensible = (DimensionTag::value <= MeshConfig::meshDimension) >
+struct WeakEntityStorageTrait
+{
+   static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template EntityTraits< DimensionTag::value >::storageEnabled;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename DimensionTag >
+struct WeakEntityStorageTrait< MeshConfig, Device, DimensionTag, false >
+{
+   static constexpr bool storageEnabled = false;
+};
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SubdimensionTag,
+          bool sensible = (SubdimensionTag::value < EntityTopology::dimension) >
+struct WeakSubentityStorageTrait
+{
+   static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template SubentityTraits< EntityTopology, SubdimensionTag::value >::storageEnabled;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SubdimensionTag >
+struct WeakSubentityStorageTrait< MeshConfig, Device, EntityTopology, SubdimensionTag, false >
+{
+   static constexpr bool storageEnabled = false;
+};
+
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SuperdimensionTag,
+          bool sensible = (SuperdimensionTag::value > EntityTopology::dimension) >
+struct WeakSuperentityStorageTrait
+{
+   static constexpr bool storageEnabled = MeshTraits< MeshConfig, Device >::template SuperentityTraits< EntityTopology, SuperdimensionTag::value >::storageEnabled;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename EntityTopology,
+          typename SuperdimensionTag >
+struct WeakSuperentityStorageTrait< MeshConfig, Device, EntityTopology, SuperdimensionTag, false >
+{
+   static constexpr bool storageEnabled = false;
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshEntity.h b/src/TNL/Meshes/MeshEntity.h
index 0aedeb356d1074741efcc6ebaef1bb6a0334b261..7c97686808d3f670f51b0d0fdc9c9f3cd63a0049 100644
--- a/src/TNL/Meshes/MeshEntity.h
+++ b/src/TNL/Meshes/MeshEntity.h
@@ -17,50 +17,60 @@
 #pragma once
 
 #include <TNL/File.h>
-#include <TNL/Containers/DynamicTypeTag.h>
-#include <TNL/Meshes/MeshDetails/MeshEntityId.h>
 #include <TNL/Meshes/MeshDetails/traits/MeshTraits.h>
-#include <TNL/Meshes/MeshDimensionTag.h>
-#include <TNL/Meshes/Topologies/MeshVertexTopology.h>
-#include <TNL/Meshes/MeshDetails/layers/MeshSubentityStorageLayer.h>
-#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityStorageLayer.h>
-#include <TNL/Meshes/MeshDetails/layers/MeshSuperentityAccess.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshEntitySeed.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
+#include <TNL/Meshes/MeshDetails/MeshEntityIndex.h>
+#include <TNL/Meshes/MeshDetails/EntityLayers/SubentityAccess.h>
+#include <TNL/Meshes/MeshDetails/EntityLayers/SuperentityAccess.h>
 
 namespace TNL {
 namespace Meshes {
 
-template< typename MeshConfig >
-class MeshInitializer;
+template< typename MeshConfig, typename Device > class Mesh;
+template< typename MeshConfig > class Initializer;
+template< typename Mesh > class EntityStorageRebinder;
+template< typename Mesh, int Dimension > struct IndexPermutationApplier;
 
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology_ >
 class MeshEntity
-   : public MeshSubentityStorageLayers< MeshConfig, EntityTopology_ >,
-     public MeshSuperentityAccess< MeshConfig, EntityTopology_ >,
-     public MeshEntityId< typename MeshConfig::IdType,
-                             typename MeshConfig::GlobalIndexType >
+   : protected SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >,
+     protected SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >,
+     public MeshEntityIndex< typename MeshConfig::IdType >
 {
+   static_assert( std::is_same< EntityTopology_, typename MeshTraits< MeshConfig, Device >::template EntityTraits< EntityTopology_::dimension >::EntityTopology >::value,
+                  "Specified entity topology is not compatible with the MeshConfig." );
+
    public:
+      using MeshTraitsType  = MeshTraits< MeshConfig, Device >;
+      using DeviceType      = Device;
+      using EntityTopology  = EntityTopology_;
+      using GlobalIndexType = typename MeshTraitsType::GlobalIndexType;
+      using LocalIndexType  = typename MeshTraitsType::LocalIndexType;
+
+      template< int Subdimension >
+      using SubentityTraits = typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimension >;
+
+      template< int Superdimension >
+      using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >;
+
+      // constructors
+      MeshEntity() = default;
+
+      __cuda_callable__
+      MeshEntity( const MeshEntity& entity );
+
+      template< typename Device_ >
+      MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity );
+
+      __cuda_callable__
+      MeshEntity& operator=( const MeshEntity& entity );
+
+      template< typename Device_ >
+      __cuda_callable__
+      MeshEntity& operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity );
 
-      typedef MeshTraits< MeshConfig >                                MeshTraitsType;
-      typedef EntityTopology_                                         EntityTopology;
-      typedef typename MeshTraitsType::GlobalIndexType                GlobalIndexType;
-      typedef typename MeshTraitsType::LocalIndexType                 LocalIndexType;
-      typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >     SeedType;
-
-      template< int Subdimensions > using SubentityTraits =
-      typename MeshTraitsType::template SubentityTraits< EntityTopology, Subdimensions >;
- 
-      template< int SuperDimension > using SuperentityTraits =
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperDimension >;
- 
-      MeshEntity( const SeedType& entitySeed );
-
-      MeshEntity();
- 
-      ~MeshEntity();
 
       static String getType();
 
@@ -72,170 +82,144 @@ class MeshEntity
 
       void print( std::ostream& str ) const;
 
+      __cuda_callable__
       bool operator==( const MeshEntity& entity ) const;
- 
-      constexpr int getEntityDimension() const;
+
+      __cuda_callable__
+      bool operator!=( const MeshEntity& entity ) const;
+
+      static constexpr int getEntityDimension();
 
       /****
        * Subentities
        */
-      template< int Subdimensions >
-      constexpr bool subentitiesAvailable() const;
-
-      template< int Subdimensions >
-      constexpr LocalIndexType getNumberOfSubentities() const;
-
-      template< int Subdimensions >
-      GlobalIndexType getSubentityIndex( const LocalIndexType localIndex) const;
-
-      template< int Subdimensions >
-      typename SubentityTraits< Subdimensions >::AccessArrayType& getSubentitiesIndices();
-
-      template< int Subdimensions >
-      const typename SubentityTraits< Subdimensions >::AccessArrayType& getSubentitiesIndices() const;
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentitiesCount;
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentityIndex;
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSubentityOrientation;
 
       /****
        * Superentities
        */
-      template< int SuperDimension >
-      LocalIndexType getNumberOfSuperentities() const;
-
-      template< int SuperDimension >
-      GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const;
-
-      template< int SuperDimension >
-         typename SuperentityTraits< SuperDimension >::AccessArrayType& getSuperentitiesIndices();
-
-      template< int SuperDimension >
-         const typename SuperentityTraits< SuperDimension >::AccessArrayType& getSuperentitiesIndices() const;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSuperentitiesCount;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::getSuperentityIndex;
 
       /****
        * Vertices
        */
-      constexpr LocalIndexType getNumberOfVertices() const;
+      static constexpr LocalIndexType getVerticesCount();
 
       GlobalIndexType getVertexIndex( const LocalIndexType localIndex ) const;
 
-      typename SubentityTraits< 0 >::AccessArrayType& getVerticesIndices();
-
-      const typename SubentityTraits< 0 >::AccessArrayType& getVerticesIndices() const;
-
-      template< int Dimension >
-      IdPermutationArrayAccessorType subentityOrientation( LocalIndexType index ) const;
- 
    protected:
-
       /****
        * Methods for the mesh initialization
        */
-      typedef MeshSuperentityAccess< MeshConfig, EntityTopology >            SuperentityAccessBase;
-      typedef typename MeshTraitsType::IdArrayAccessorType                   IdArrayAccessorType;
-      typedef MeshSubentityStorageLayers< MeshConfig, EntityTopology >       SubentityStorageLayers;
-
-      template< int Subdimensions >
-      void setSubentityIndex( const LocalIndexType localIndex,
-                              const GlobalIndexType globalIndex );
- 
-      template< int Subdimensions >
-      typename SubentityTraits< Subdimensions >::IdArrayType& subentityIdsArray();
-
-      template< int Superdimensions >
-      IdArrayAccessorType& superentityIdsArray();
-
-      template< int Subdimensions >
-      typename SubentityTraits< Subdimensions >::OrientationArrayType& subentityOrientationsArray();
- 
-   friend MeshInitializer< MeshConfig >;
- 
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::bindSubentitiesStorageNetwork;
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setSubentityIndex;
+      using SubentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::subentityOrientationsArray;
+
+      using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::bindSuperentitiesStorageNetwork;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setNumberOfSuperentities;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, EntityTopology_ >::setSuperentityIndex;
+
+   friend Initializer< MeshConfig >;
+
+   friend EntityStorageRebinder< Mesh< MeshConfig, DeviceType > >;
+
+   template< typename Mesh, int Dimension >
+   friend struct IndexPermutationApplier;
 };
 
 /****
  * Vertex entity specialization
  */
-template< typename MeshConfig >
-class MeshEntity< MeshConfig, MeshVertexTopology >
-   : public MeshSuperentityAccess< MeshConfig, MeshVertexTopology >,
-     public MeshEntityId< typename MeshConfig::IdType,
-                             typename MeshConfig::GlobalIndexType >
+template< typename MeshConfig, typename Device >
+class MeshEntity< MeshConfig, Device, Topologies::Vertex >
+   : protected SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >,
+     public MeshEntityIndex< typename MeshConfig::IdType >
 {
    public:
+      using MeshTraitsType  = MeshTraits< MeshConfig, Device >;
+      using DeviceType      = Device;
+      using EntityTopology  = Topologies::Vertex;
+      using GlobalIndexType = typename MeshTraitsType::GlobalIndexType;
+      using LocalIndexType  = typename MeshTraitsType::LocalIndexType;
+      using PointType       = typename MeshTraitsType::PointType;
+
+      template< int Superdimension >
+      using SuperentityTraits = typename MeshTraitsType::template SuperentityTraits< EntityTopology, Superdimension >;
+
+      // constructors
+      MeshEntity() = default;
+
+      __cuda_callable__
+      MeshEntity( const MeshEntity& entity );
+
+      template< typename Device_ >
+      MeshEntity( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity );
+
+      __cuda_callable__
+      MeshEntity& operator=( const MeshEntity& entity );
+
+      template< typename Device_ >
+      __cuda_callable__
+      MeshEntity& operator=( const MeshEntity< MeshConfig, Device_, EntityTopology >& entity );
 
-      typedef MeshTraits< MeshConfig >                                MeshTraitsType;
-      typedef MeshVertexTopology                                      EntityTopology;
-      typedef typename MeshTraitsType::GlobalIndexType                GlobalIndexType;
-      typedef typename MeshTraitsType::LocalIndexType                 LocalIndexType;
-      typedef typename MeshTraitsType::PointType                      PointType;
-      typedef typename MeshTraitsType::IdPermutationArrayAccessorType IdPermutationArrayAccessorType;
-      typedef MeshEntitySeed< MeshConfig, EntityTopology >     SeedType;
- 
-      template< int SuperDimension > using SuperentityTraits =
-      typename MeshTraitsType::template SuperentityTraits< EntityTopology, SuperDimension >;
 
       static String getType();
 
       String getTypeVirtual() const;
 
-      ~MeshEntity();
-
       bool save( File& file ) const;
 
       bool load( File& file );
 
       void print( std::ostream& str ) const;
 
+      __cuda_callable__
       bool operator==( const MeshEntity& entity ) const;
- 
-      constexpr int getEntityDimension() const;
-
-      template< int Superdimensions > LocalIndexType getNumberOfSuperentities() const;
 
-      template< int Superdimensions >
-         typename SuperentityTraits< Superdimensions >::AccessArrayType& getSuperentitiesIndices();
+      __cuda_callable__
+      bool operator!=( const MeshEntity& entity ) const;
 
-      template< int Superdimensions >
-         const typename SuperentityTraits< Superdimensions >::AccessArrayType& getSuperentitiesIndeces() const;
+      static constexpr int getEntityDimension();
 
-      template< int Dimension >
-      GlobalIndexType getSuperentityIndex( const LocalIndexType localIndex ) const;
+      /****
+       * Superentities
+       */
+      using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::getSuperentitiesCount;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::getSuperentityIndex;
 
       /****
        * Points
        */
+      __cuda_callable__
       PointType getPoint() const;
 
+      __cuda_callable__
       void setPoint( const PointType& point );
 
    protected:
- 
-      typedef typename MeshTraitsType::IdArrayAccessorType                          IdArrayAccessorType;
-      typedef MeshSuperentityAccess< MeshConfig, MeshVertexTopology >     SuperentityAccessBase;
- 
-      template< int Superdimensions >
-      IdArrayAccessorType& superentityIdsArray();
+      using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::bindSuperentitiesStorageNetwork;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::setNumberOfSuperentities;
+      using SuperentityAccessLayerFamily< MeshConfig, Device, Topologies::Vertex >::setSuperentityIndex;
 
       PointType point;
- 
-   friend MeshInitializer< MeshConfig >;
-};
 
-template< typename MeshConfig,
-          typename EntityTopology >
-std::ostream& operator <<( std::ostream& str, const MeshEntity< MeshConfig, EntityTopology >& entity );
-} // namespace Meshes
+   friend Initializer< MeshConfig >;
+
+   friend EntityStorageRebinder< Mesh< MeshConfig, DeviceType > >;
+
+   template< typename Mesh, int Dimension >
+   friend struct IndexPermutationApplier;
+};
 
-/****
- * This tells the compiler that theMeshEntity is a type with a dynamic memory allocation.
- * It is necessary for the loading and the saving of the mesh entities arrays.
- */
-namespace Containers{
 template< typename MeshConfig,
+          typename Device,
           typename EntityTopology >
-struct DynamicTypeTag< Meshes::MeshEntity< MeshConfig, EntityTopology > >
-{
-   enum { value = true };
-};
-}
+std::ostream& operator<<( std::ostream& str, const MeshEntity< MeshConfig, Device, EntityTopology >& entity );
 
+} // namespace Meshes
 } // namespace TNL
 
 #include <TNL/Meshes/MeshDetails/MeshEntity_impl.h>
diff --git a/src/TNL/Meshes/Readers/CMakeLists.txt b/src/TNL/Meshes/Readers/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5d46f5259dc41e2713eeca95adfdf8ec8f6d810d
--- /dev/null
+++ b/src/TNL/Meshes/Readers/CMakeLists.txt
@@ -0,0 +1,7 @@
+SET( headers EntityShape.h
+             NetgenReader.h
+             TNLReader.h
+             VTKReader.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Readers )
diff --git a/src/TNL/Meshes/Readers/EntityShape.h b/src/TNL/Meshes/Readers/EntityShape.h
new file mode 100644
index 0000000000000000000000000000000000000000..c2c39eae53352568bd3f6d5208f5446eb6e85e57
--- /dev/null
+++ b/src/TNL/Meshes/Readers/EntityShape.h
@@ -0,0 +1,133 @@
+/***************************************************************************
+                          EntityShape.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <ostream>
+
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Quadrilateral.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+#include <TNL/Meshes/Topologies/Hexahedron.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Readers {
+
+/*
+ * Enumeration of entity shapes, inspired by the VTK library.
+ */
+enum class EntityShape
+{
+   Vertex = 1,
+   PolyVertex = 2,
+   Line = 3,
+   PolyLine = 4,
+   Triangle = 5,
+   TriangleStrip = 6,
+   Polygon = 7,
+   Pixel = 8,
+   Quad = 9,
+   Tetra = 10,
+   Voxel = 11,
+   Hexahedron = 12,
+   Wedge = 13,
+   Pyramid = 14
+};
+
+inline std::ostream& operator<<( std::ostream& str, EntityShape shape )
+{
+   switch( shape )
+   {
+      case EntityShape::Vertex:
+         str << "Entity::Vertex";
+         break;
+      case EntityShape::PolyVertex:
+         str << "Entity::PolyVertex";
+         break;
+      case EntityShape::Line:
+         str << "Entity::Line";
+         break;
+      case EntityShape::PolyLine:
+         str << "Entity::PolyLine";
+         break;
+      case EntityShape::Triangle:
+         str << "Entity::Triangle";
+         break;
+      case EntityShape::TriangleStrip:
+         str << "Entity::TriangleStrip";
+         break;
+      case EntityShape::Polygon:
+         str << "Entity::Polygon";
+         break;
+      case EntityShape::Pixel:
+         str << "Entity::Pixel";
+         break;
+      case EntityShape::Quad:
+         str << "Entity::Quad";
+         break;
+      case EntityShape::Tetra:
+         str << "Entity::Tetra";
+         break;
+      case EntityShape::Voxel:
+         str << "Entity::Voxel";
+         break;
+      case EntityShape::Hexahedron:
+         str << "Entity::Hexahedron";
+         break;
+      case EntityShape::Wedge:
+         str << "Entity::Wedge";
+         break;
+      case EntityShape::Pyramid:
+         str << "Entity::Pyramid";
+         break;
+      default:
+         str << "<unknown entity>";
+   }
+   return str;
+}
+
+inline int getEntityDimension( EntityShape shape )
+{
+   switch( shape )
+   {
+      case EntityShape::Vertex:         return 0;
+      case EntityShape::PolyVertex:     return 0;
+      case EntityShape::Line:           return 1;
+      case EntityShape::PolyLine:       return 1;
+      case EntityShape::Triangle:       return 2;
+      case EntityShape::TriangleStrip:  return 2;
+      case EntityShape::Polygon:        return 2;
+      case EntityShape::Pixel:          return 2;
+      case EntityShape::Quad:           return 2;
+      case EntityShape::Tetra:          return 3;
+      case EntityShape::Voxel:          return 3;
+      case EntityShape::Hexahedron:     return 3;
+      case EntityShape::Wedge:          return 3;
+      case EntityShape::Pyramid:        return 3;
+   }
+   // this just avoids a compiler warning in GCC and nvcc (clang actually knows if the
+   // switch above covers all cases, and print a warning only when it does not)
+   throw 1;
+}
+
+// static mapping of TNL entity topologies to EntityShape
+template< typename Topology > struct TopologyToEntityShape {};
+template<> struct TopologyToEntityShape< Topologies::Vertex >         { static constexpr EntityShape shape = EntityShape::Vertex; };
+template<> struct TopologyToEntityShape< Topologies::Edge >           { static constexpr EntityShape shape = EntityShape::Line; };
+template<> struct TopologyToEntityShape< Topologies::Triangle >       { static constexpr EntityShape shape = EntityShape::Triangle; };
+template<> struct TopologyToEntityShape< Topologies::Quadrilateral >  { static constexpr EntityShape shape = EntityShape::Quad; };
+template<> struct TopologyToEntityShape< Topologies::Tetrahedron >    { static constexpr EntityShape shape = EntityShape::Tetra; };
+template<> struct TopologyToEntityShape< Topologies::Hexahedron >     { static constexpr EntityShape shape = EntityShape::Hexahedron; };
+
+} // namespace Readers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h b/src/TNL/Meshes/Readers/NetgenReader.h
similarity index 50%
rename from src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h
rename to src/TNL/Meshes/Readers/NetgenReader.h
index d3264a480aefc1bc82a42ae3affb08f95a73e517..a694280ac054735c7b9a87a9453b1bee0f97505f 100644
--- a/src/TNL/Meshes/MeshDetails/MeshReaderNetgen.h
+++ b/src/TNL/Meshes/Readers/NetgenReader.h
@@ -1,8 +1,8 @@
 /***************************************************************************
-                          MeshReaderNetgen.h  -  description
+                          NetgenReader.h  -  description
                              -------------------
     begin                : Feb 19, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -21,20 +21,21 @@
 #include <sstream>
 
 #include <TNL/Meshes/MeshBuilder.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
 
 namespace TNL {
 namespace Meshes {
+namespace Readers {
 
-class MeshReaderNetgen
+class NetgenReader
 {
-   public:
-
-      MeshReaderNetgen()
-      : dimensions( 0 ){}
- 
+public:
    bool detectMesh( const String& fileName )
    {
-      std::fstream inputFile( fileName.getString() );
+      this->reset();
+      this->fileName = fileName;
+
+      std::ifstream inputFile( fileName.getString() );
       if( ! inputFile )
       {
          std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
@@ -69,12 +70,12 @@ class MeshReaderNetgen
       getline( inputFile, line );
       iss.clear();
       iss.str( line );
-      this->dimensions = -1;
+      meshDimension = worldDimension = -1;
       while( iss )
       {
          double aux;
          iss >> aux;
-         this->dimensions++;
+         meshDimension = ++worldDimension;
       }
  
       /****
@@ -113,28 +114,46 @@ class MeshReaderNetgen
       getline( inputFile, line );
       iss.clear();
       iss.str( line );
-      this->verticesInCell = -2;
+      int verticesInCell = -2;
       while( iss )
       {
          int aux;
          iss >> aux;
-         this->verticesInCell++;
+         verticesInCell++;
+      }
+      //cout << "There are " << verticesInCell << " vertices in cell ..." << std::endl;
+      
+      if( meshDimension == 1 && verticesInCell == 2 )
+         cellShape = EntityShape::Line;
+      else if( meshDimension == 2 ) {
+         if( verticesInCell == 3 )
+            cellShape = EntityShape::Triangle;
+         else if( verticesInCell == 4 )
+            cellShape = EntityShape::Quad;
+      }
+      else if( meshDimension == 3 ) {
+         if( verticesInCell == 4 )
+            cellShape = EntityShape::Tetra;
+         else if( verticesInCell == 8 )
+            cellShape = EntityShape::Hexahedron;
+      }
+      if( cellShape == EntityShape::Vertex ) {
+         std::cerr << "Unknown cell topology: mesh dimension is " << meshDimension << ", number of vertices in cells is " << verticesInCell << "." << std::endl;
+         return false;
       }
-      //cout << "There are " << this->verticesInCell << " vertices in cell ..." << std::endl;
+      
       return true;
    }
 
    template< typename MeshType >
-   static bool readMesh( const String& fileName,
-                         MeshType& mesh,
-                         bool verbose )
+   static bool readMesh( const String& fileName, MeshType& mesh )
    {
       typedef typename MeshType::PointType PointType;
       typedef MeshBuilder< MeshType > MeshBuilder;
  
-      const int dimensions = PointType::size;
+      const int dimension = PointType::size;
 
-      std::fstream inputFile( fileName.getString() );
+      std::ifstream inputFile( fileName.getString() );
       if( ! inputFile )
       {
          std::cerr << "I am not able to open the file " << fileName << "." << std::endl;
@@ -157,14 +176,10 @@ class MeshReaderNetgen
          return false;
       getline( inputFile, line );
       iss.str( line );
-      typedef typename MeshType::MeshTraitsType::template EntityTraits< 0 >::GlobalIndexType VertexIndexType;
+      typedef typename MeshType::Config::GlobalIndexType VertexIndexType;
       VertexIndexType pointsCount;
       iss >> pointsCount;
-      if( ! meshBuilder.setPointsCount( pointsCount ) )
-      {
-         std::cerr << "I am not able to allocate enough memory for " << pointsCount << " vertices." << std::endl;
-         return false;
-      }
+      meshBuilder.setPointsCount( pointsCount );
 
       for( VertexIndexType i = 0; i < pointsCount; i++ )
       {
@@ -172,80 +187,117 @@ class MeshReaderNetgen
          iss.clear();
          iss.str( line );
          PointType p;
-         for( int d = 0; d < dimensions; d++ )
+         for( int d = 0; d < dimension; d++ )
             iss >> p[ d ];
          //cout << "Setting point number " << i << " of " << pointsCount << std::endl;
          meshBuilder.setPoint( i, p );
-         if( verbose )
-           std::cout << pointsCount << " vertices expected ... " << i+1 << "/" << pointsCount << "        \r" << std::flush;
          //const PointType& point = mesh.getVertex( i ).getPoint();
       }
-      if( verbose )
-        std::cout << std::endl;
 
       /****
         * Skip white spaces
         */
-       inputFile >> std::ws;
+      inputFile >> std::ws;
 
       /****
        * Read number of cells
        */
-       typedef typename MeshType::MeshTraitsType::template EntityTraits< dimensions >::GlobalIndexType CellIndexType;
-       if( ! inputFile )
-       {
-          std::cerr << "I cannot read the mesh cells." << std::endl;
-          return false;
-       }
-       getline( inputFile, line );
-       iss.clear();
-       iss.str( line );
-       CellIndexType numberOfCells=atoi( line.data() );
-       //iss >> numberOfCells; // TODO: I do not know why this does not work
-       if( ! meshBuilder.setCellsCount( numberOfCells ) )
-       {
-          std::cerr << "I am not able to allocate enough memory for " << numberOfCells << " cells." << std::endl;
-          return false;
-       }
-       for( CellIndexType i = 0; i < numberOfCells; i++ )
-       {
-          getline( inputFile, line );
-          iss.clear();
-          iss.str( line );
-          int subdomainIndex;
-          iss >> subdomainIndex;
-          //cout << "Setting cell number " << i << " of " << numberOfCells << std::endl;
-          typedef typename MeshBuilder::CellSeedType CellSeedType;
-          for( int cellVertex = 0; cellVertex < CellSeedType::getCornersCount(); cellVertex++ )
-          {
-             VertexIndexType vertexIdx;
-             iss >> vertexIdx;
-             meshBuilder.getCellSeed( i ).setCornerId( cellVertex, vertexIdx - 1 );
-          }
-          if( verbose )
-            std::cout << numberOfCells << " cells expected ... " << i+1 << "/" << numberOfCells << "                 \r" << std::flush;
-       }
-       if( verbose )
-         std::cout << std::endl;
-       meshBuilder.build( mesh );
-       return true;
+      typedef typename MeshType::Config::GlobalIndexType CellIndexType;
+      if( ! inputFile )
+      {
+         std::cerr << "I cannot read the mesh cells." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+      iss.clear();
+      iss.str( line );
+      CellIndexType numberOfCells = atoi( line.data() );
+      //iss >> numberOfCells; // TODO: I do not know why this does not work
+      meshBuilder.setCellsCount( numberOfCells );
+      for( CellIndexType i = 0; i < numberOfCells; i++ )
+      {
+         getline( inputFile, line );
+         iss.clear();
+         iss.str( line );
+         int subdomainIndex;
+         iss >> subdomainIndex;
+         //cout << "Setting cell number " << i << " of " << numberOfCells << std::endl;
+         typedef typename MeshBuilder::CellSeedType CellSeedType;
+         for( int cellVertex = 0; cellVertex < CellSeedType::getCornersCount(); cellVertex++ )
+         {
+            VertexIndexType vertexIdx;
+            iss >> vertexIdx;
+            meshBuilder.getCellSeed( i ).setCornerId( cellVertex, vertexIdx - 1 );
+         }
+      }
+      meshBuilder.build( mesh );
+      return true;
    }
 
-   int getDimension() const
+   String
+   getMeshType() const
    {
-      return this->dimensions;
+      return "Meshes::Mesh";
    }
- 
-   int getVerticesInCell() const
+
+   int getMeshDimension() const
    {
-      return this->verticesInCell;
+      return this->meshDimension;
    }
  
-   protected:
+   int
+   getWorldDimension() const
+   {
+      return worldDimension;
+   }
 
-      int dimensions, verticesInCell;
+   EntityShape
+   getCellShape() const
+   {
+      return cellShape;
+   }
+
+   String
+   getRealType() const
+   {
+      // not stored in the Netgen file
+      return "float";
+   }
 
+   String
+   getGlobalIndexType() const
+   {
+      // not stored in the Netgen file
+      return "int";
+   }
+ 
+   String
+   getLocalIndexType() const
+   {
+      // not stored in the Netgen file
+      return "short int";
+   }
+ 
+   String
+   getIdType() const
+   {
+      // not stored in the Netgen file
+      return "int";
+   }
+ 
+protected:
+   String fileName;
+   int meshDimension, worldDimension;
+   EntityShape cellShape = EntityShape::Vertex;
+
+   void reset()
+   {
+      fileName = "";
+      meshDimension = worldDimension = 0;
+      cellShape = EntityShape::Vertex;
+   }
 };
 
+} // namespace Readers
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Meshes/Readers/TNLReader.h b/src/TNL/Meshes/Readers/TNLReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba602b0f97fda13115b171a46d9a3dd4d884c835
--- /dev/null
+++ b/src/TNL/Meshes/Readers/TNLReader.h
@@ -0,0 +1,178 @@
+/***************************************************************************
+                          TNL.h  -  description
+                             -------------------
+    begin                : Nov 20, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/String.h>
+#include <TNL/Object.h>
+#include <TNL/Containers/List.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Readers {
+
+class TNLReader
+{
+public:
+   bool
+   detectMesh( const String& fileName )
+   {
+      this->reset();
+      this->fileName = fileName;
+
+      String objectType;
+      if( ! getObjectType( fileName, objectType ) ) {
+         std::cerr << "Failed to detect the mesh type from the file " << fileName << "." << std::endl;
+         return EXIT_FAILURE;
+      }
+
+      Containers::List< String > parsedMeshType;
+      if( ! parseObjectType( objectType, parsedMeshType ) ) {
+         std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl;
+         return false;
+      }
+
+      meshType = parsedMeshType[ 0 ];
+      if( meshType == "Meshes::Grid" ) {
+         // save parts necessary to determine the mesh type
+         meshDimension = worldDimension = std::atoi( parsedMeshType[ 1 ].getString() );
+         realType = parsedMeshType[ 2 ];
+         globalIndexType = localIndexType = idType = parsedMeshType[ 4 ];
+         // populate entity types (not necessary for GridTypeResolver, but while we're at it...)
+         if( meshDimension == 1 )
+            cellShape = EntityShape::Line;
+         else if( meshDimension == 2 )
+            cellShape = EntityShape::Quad;
+         else if( meshDimension == 3 )
+            cellShape = EntityShape::Hexahedron;
+      }
+      else if( meshType == "Meshes::Mesh" ) {
+         Containers::List< String > parsedMeshConfig;
+         if( ! parseObjectType( parsedMeshType[ 1 ], parsedMeshConfig ) ) {
+            std::cerr << "Unable to parse the mesh config type " << parsedMeshType[ 1 ] << "." << std::endl;
+            return false;
+         }
+         if( parsedMeshConfig.getSize() != 7 ) {
+            std::cerr << "The parsed mesh config type has wrong size (expected 7 elements):" << std::endl
+                      << parsedMeshConfig << std::endl;
+            return false;
+         }
+
+         // save parts necessary to determine the mesh type
+         const String topology = parsedMeshConfig[ 1 ];
+         worldDimension = std::atoi( parsedMeshConfig[ 2 ].getString() );
+         realType = parsedMeshConfig[ 3 ];
+         globalIndexType = parsedMeshConfig[ 4 ];
+         localIndexType = parsedMeshConfig[ 5 ];
+         idType = parsedMeshConfig[ 6 ];
+
+         if( topology == "MeshEdgeTopology" )
+            cellShape = EntityShape::Line;
+         else if( topology == "MeshTriangleTopology" )
+            cellShape = EntityShape::Triangle;
+         else if( topology == "MeshQuadrilateralTopology" )
+            cellShape = EntityShape::Quad;
+         else if( topology == "MeshTetrahedronTopology" )
+            cellShape = EntityShape::Tetra;
+         else if( topology == "MeshHexahedronTopology" )
+            cellShape = EntityShape::Hexahedron;
+         else {
+            std::cerr << "Detected topology '" << topology << "' is not supported." << std::endl;
+            return false;
+         }
+      }
+      else {
+         std::cerr << "The mesh type " << meshType << " is not supported (yet)." << std::endl;
+         return false;
+      }
+
+      return true;
+   }
+
+   template< typename MeshType >
+   static bool
+   readMesh( const String& fileName, MeshType& mesh )
+   {
+      return mesh.load( fileName );
+   }
+
+   String
+   getMeshType() const
+   {
+      return meshType;
+   }
+
+   int
+   getMeshDimension() const
+   {
+      return meshDimension;
+   }
+
+   int
+   getWorldDimension() const
+   {
+      return worldDimension;
+   }
+
+   EntityShape
+   getCellShape() const
+   {
+      return cellShape;
+   }
+ 
+   String
+   getRealType() const
+   {
+      return realType;
+   }
+
+   String
+   getGlobalIndexType() const
+   {
+      return globalIndexType;
+   }
+ 
+   String
+   getLocalIndexType() const
+   {
+      return localIndexType;
+   }
+ 
+   String
+   getIdType() const
+   {
+      return idType;
+   }
+ 
+protected:
+   String fileName;
+   String meshType;
+   int meshDimension = 0;
+   int worldDimension = 0;
+   EntityShape cellShape = EntityShape::Vertex;
+   String realType;
+   String globalIndexType;
+   String localIndexType;
+   String idType;
+
+   void reset()
+   {
+      fileName = "";
+      meshType = "";
+      meshDimension = worldDimension = 0;
+      cellShape = EntityShape::Vertex;
+      realType = localIndexType = globalIndexType = idType = "";
+   }
+};
+
+} // namespace Readers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Readers/VTKReader.h b/src/TNL/Meshes/Readers/VTKReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b52df0bc92401a1187c17feb0636a4cfe305789
--- /dev/null
+++ b/src/TNL/Meshes/Readers/VTKReader.h
@@ -0,0 +1,434 @@
+/***************************************************************************
+                          VTKReader.h  -  description
+                             -------------------
+    begin                : Feb 25, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <fstream>
+#include <sstream>
+#include <map>
+#include <vector>
+
+#include <TNL/Meshes/MeshBuilder.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Readers {
+
+class VTKReader
+{
+public:
+   bool detectMesh( const String& fileName )
+   {
+      this->reset();
+      this->fileName = fileName;
+
+      std::ifstream inputFile( fileName.getString() );
+      if( ! inputFile ) {
+         std::cerr << "Failed to open the file " << fileName << "." << std::endl;
+         return false;
+      }
+
+      if( ! parseHeader( inputFile ) )
+         return false;
+
+      if( dataset != "UNSTRUCTURED_GRID" ) {
+         std::cerr << "VTKReader: the dataset '" << dataset << "' is not supported." << std::endl;
+         return false;
+      }
+
+      // TODO: implement binary parsing
+      if( dataType == "BINARY" ) {
+         std::cerr << "VTKReader: parsing of BINARY data is not implemented yet." << std::endl;
+         return false;
+      }
+
+      std::string line, aux;
+      std::istringstream iss;
+
+      // parse points section
+      if( ! findSection( inputFile, "POINTS" ) ) {
+         std::cerr << "VTKReader: unable to find the POINTS section, the file may be invalid or corrupted." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+      iss.clear();
+      iss.str( line );
+      iss >> aux;
+      long int numberOfVertices;
+      iss >> numberOfVertices;
+      iss >> realType;
+
+      // read points
+      long int verticesRead = 0;
+      worldDimension = 0;
+      while( verticesRead < numberOfVertices ) {
+         if( ! inputFile ) {
+            std::cerr << "VTKReader: unable to read enough vertices, the file may be invalid or corrupted." << std::endl;
+            return false;
+         }
+         getline( inputFile, line );
+
+         // read the coordinates and compute the world dimension
+         iss.clear();
+         iss.str( line );
+         for( int i = 0; i < 3; i++ ) {
+            double aux;
+            iss >> aux;
+            if( ! iss ) {
+               std::cerr << "VTKReader: unable to read " << i << "th component of the vertex number " << verticesRead << "." << std::endl;
+               return false;
+            }
+            if( aux != 0.0 )
+               worldDimension = std::max( worldDimension, i + 1 );
+         }
+
+         verticesRead++;
+      }
+
+      // skip to the CELL_TYPES section
+      if( ! findSection( inputFile, "CELL_TYPES" ) ) {
+         std::cerr << "VTKReader: unable to find the CELL_TYPES section, the file may be invalid or corrupted." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+      iss.clear();
+      iss.str( line );
+      iss >> aux;
+      long int numberOfEntities;
+      iss >> numberOfEntities;
+
+      // read entity types
+      long int entitiesRead = 0;
+      std::map< int, EntityShape > entityTypes;
+      while( entitiesRead < numberOfEntities ) {
+         if( ! inputFile ) {
+            std::cerr << "VTKReader: unable to read enough entity types, the file may be invalid or corrupted." << std::endl;
+            return false;
+         }
+         getline( inputFile, line );
+
+         // get entity type
+         int typeId;
+         iss.clear();
+         iss.str( line );
+         iss >> typeId;
+         const EntityShape type = (EntityShape) typeId;
+         const int dimension = getEntityDimension( type );
+
+         // check entity type
+         if( entityTypes.find( dimension ) == entityTypes.cend() )
+            entityTypes.emplace( std::make_pair( dimension, type ) );
+         else if( entityTypes[ dimension ] != type ) {
+            std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension
+                      << " with type " << entityTypes[ dimension ] << " and " << type << ". "
+                      << "The type of all entities with the same dimension must be the same." << std::endl;
+            this->reset();
+            return false;
+         }
+
+         entitiesRead++;
+      }
+
+      // set meshDimension and cellShape
+      meshDimension = 0;
+      for( auto it : entityTypes )
+         if( it.first > meshDimension ) {
+            meshDimension = it.first;
+            cellShape = it.second;
+         }
+
+      return true;
+   }
+
+   template< typename MeshType >
+   bool readMesh( const String& fileName, MeshType& mesh )
+   {
+      using MeshBuilder = MeshBuilder< MeshType >;
+      using IndexType = typename MeshType::GlobalIndexType;
+      using PointType = typename MeshType::PointType;
+      using CellSeedType = typename MeshBuilder::CellSeedType;
+
+      const EntityShape cellType = TopologyToEntityShape< typename MeshType::template EntityTraits< MeshType::getMeshDimension() >::EntityTopology >::shape;
+      MeshBuilder meshBuilder;
+
+      std::ifstream inputFile( fileName.getString() );
+      if( ! inputFile ) {
+         std::cerr << "Failed to open the file " << fileName << "." << std::endl;
+         return false;
+      }
+
+      if( ! parseHeader( inputFile ) )
+         return false;
+      const auto positionAfterHeading = inputFile.tellg();
+
+      if( dataset != "UNSTRUCTURED_GRID" ) {
+         std::cerr << "VTKReader: the dataset '" << dataset << "' is not supported." << std::endl;
+         return false;
+      }
+
+      // TODO: implement binary parsing
+      if( dataType == "BINARY" ) {
+         std::cerr << "VTKReader: parsing of BINARY data is not implemented yet." << std::endl;
+         return false;
+      }
+
+      std::string line, aux;
+      std::istringstream iss;
+
+      // parse the points section
+      if( ! findSection( inputFile, "POINTS" ) ) {
+         std::cerr << "VTKReader: unable to find the POINTS section, the file may be invalid or corrupted." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+      iss.clear();
+      iss.str( line );
+      iss >> aux;
+      IndexType numberOfVertices;
+      iss >> numberOfVertices;
+
+      // allocate vertices
+      meshBuilder.setPointsCount( numberOfVertices );
+
+      // read points
+      for( IndexType vertexIndex = 0; vertexIndex < numberOfVertices; vertexIndex++ ) {
+         if( ! inputFile ) {
+            std::cerr << "VTKReader: unable to read enough vertices, the file may be invalid or corrupted." << std::endl;
+            return false;
+         }
+         getline( inputFile, line );
+
+         // read the coordinates
+         iss.clear();
+         iss.str( line );
+         PointType p;
+         for( int i = 0; i < p.size; i++ ) {
+            iss >> p[ i ];
+            if( ! iss ) {
+               std::cerr << "VTKReader: unable to read " << i << "th component of the vertex number " << vertexIndex << "." << std::endl;
+               return false;
+            }
+         }
+         meshBuilder.setPoint( vertexIndex, p );
+      }
+
+      // find to the CELL_TYPES section
+      if( ! findSection( inputFile, "CELL_TYPES", positionAfterHeading ) ) {
+         std::cerr << "VTKReader: unable to find the CELL_TYPES section, the file may be invalid or corrupted." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+      iss.clear();
+      iss.str( line );
+      iss >> aux;
+      IndexType numberOfEntities;
+      iss >> numberOfEntities;
+
+      // read entity types, count cells
+      std::vector< EntityShape > entityTypes;
+      entityTypes.resize( numberOfEntities );
+      IndexType numberOfCells = 0;
+      for( IndexType entityIndex = 0; entityIndex < numberOfEntities; entityIndex++ ) {
+         if( ! inputFile ) {
+            std::cerr << "VTKReader: unable to read enough entity types, the file may be invalid or corrupted." << std::endl;
+            return false;
+         }
+         getline( inputFile, line );
+
+         // get entity type
+         int typeId;
+         iss.clear();
+         iss.str( line );
+         iss >> typeId;
+         entityTypes[ entityIndex ] = (EntityShape) typeId;
+         const int dimension = getEntityDimension( entityTypes[ entityIndex ] );
+         if( dimension == MeshType::getMeshDimension() )
+            numberOfCells++;
+      }
+
+      meshBuilder.setCellsCount( numberOfCells );
+
+      // find to the CELLS section
+      if( ! findSection( inputFile, "CELLS", positionAfterHeading ) ) {
+         std::cerr << "VTKReader: unable to find the CELLS section, the file may be invalid or corrupted." << std::endl;
+         return false;
+      }
+      getline( inputFile, line );
+
+      // read cells
+      IndexType cellIndex = 0;
+      for( IndexType entityIndex = 0; entityIndex < numberOfEntities; entityIndex++ ) {
+         if( ! inputFile ) {
+            std::cerr << "VTKReader: unable to read enough entities, the file may be invalid or corrupted." << std::endl;
+            return false;
+         }
+         getline( inputFile, line );
+
+         if( entityTypes[ entityIndex ] == cellType ) {
+            iss.clear();
+            iss.str( line );
+            int vid;
+            iss >> vid;  // ignore number of subvertices
+            CellSeedType& seed = meshBuilder.getCellSeed( cellIndex++ );
+            for( int v = 0; v < CellSeedType::getCornersCount(); v++ ) {
+               iss >> vid;
+               if( ! iss )
+                  return false;
+               seed.setCornerId( v, vid );
+            }
+         }
+      }
+
+      // no cells found
+      if( cellIndex == 0 )
+         return false;
+
+      return meshBuilder.build( mesh );
+   }
+
+   String
+   getMeshType() const
+   {
+      return "Meshes::Mesh";
+   }
+
+   int getMeshDimension() const
+   {
+      return this->meshDimension;
+   }
+
+   int
+   getWorldDimension() const
+   {
+      return worldDimension;
+   }
+
+   EntityShape
+   getCellShape() const
+   {
+      return cellShape;
+   }
+
+   String
+   getRealType() const
+   {
+      return realType.c_str();
+   }
+
+   String
+   getGlobalIndexType() const
+   {
+      // not stored in the VTK file
+      return "int";
+   }
+
+   String
+   getLocalIndexType() const
+   {
+      // not stored in the VTK file
+      return "short int";
+   }
+
+   String
+   getIdType() const
+   {
+      // not stored in the VTK file
+      return "int";
+   }
+
+protected:
+   // output of parseHeader
+   std::string dataType;
+   std::string dataset;
+
+   String fileName;
+   int meshDimension, worldDimension;
+   EntityShape cellShape = EntityShape::Vertex;
+   std::string realType;
+
+   void reset()
+   {
+      fileName = "";
+      meshDimension = worldDimension = 0;
+      cellShape = EntityShape::Vertex;
+      realType = "";
+   }
+
+   bool parseHeader( std::istream& str )
+   {
+      std::string line;
+      std::istringstream iss;
+
+      // check header
+      getline( str, line );
+      if( line != "# vtk DataFile Version 2.0" ) {
+         std::cerr << "VTKReader: unsupported VTK header: '" << line << "'." << std::endl;
+         return false;
+      }
+
+      // skip title
+      if( ! str )
+         return false;
+      getline( str, line );
+
+      // parse data type
+      if( ! str )
+         return false;
+      getline( str, dataType );
+      if( dataType != "ASCII" && dataType != "BINARY" ) {
+         std::cerr << "VTKReader: unknown data type: '" << dataType << "'." << std::endl;
+         return false;
+      }
+
+      // parse dataset
+      if( ! str )
+         return false;
+      getline( str, line );
+      iss.clear();
+      iss.str( line );
+      std::string tmp;
+      iss >> tmp;
+      if( tmp != "DATASET" ) {
+         std::cerr << "VTKReader: wrong dataset specification: '" << line << "'." << std::endl;
+         return false;
+      }
+      iss >> dataset;
+
+      return true;
+   }
+
+   bool findSection( std::istream& str, const std::string& section, std::ios::pos_type begin = -1 )
+   {
+      std::string line, aux;
+      std::istringstream iss;
+
+      if( begin >= 0 )
+         str.seekg( begin );
+
+      while( str ) {
+         std::ios::pos_type currentPosition = str.tellg();
+         getline( str, line );
+         iss.clear();
+         iss.str( line );
+         iss >> aux;
+         if( aux == section ) {
+            str.seekg( currentPosition );
+            return true;
+         }
+      }
+
+      return false;
+   }
+};
+
+} // namespace Readers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Readers/VTKReader_libvtk.h b/src/TNL/Meshes/Readers/VTKReader_libvtk.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8d317eaaa96e340ea63988ac5308ead358ece27
--- /dev/null
+++ b/src/TNL/Meshes/Readers/VTKReader_libvtk.h
@@ -0,0 +1,331 @@
+/***************************************************************************
+                          VTKReader_libvtk.h  -  description
+                             -------------------
+    begin                : Nov 6, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <fstream>
+#include <istream>
+#include <vector>
+#include <map>
+#include <unordered_map>
+#include <type_traits>
+
+#include <TNL/Containers/StaticVector.h>
+#include <TNL/Meshes/MeshBuilder.h>
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
+
+#ifdef HAVE_VTK
+#include <vtkSmartPointer.h>
+#include <vtkCell.h>
+#include <vtkUnstructuredGrid.h>
+#include <vtkUnstructuredGridReader.h>
+#endif
+
+namespace TNL {
+namespace Meshes {
+namespace Readers {
+
+// types used in VTK
+using VTKRealType = double;
+#ifdef HAVE_VTK
+using VTKIndexType = vtkIdType;
+#else
+using VTKIndexType = int;
+#endif
+// wrapper type for physical coordinates to preserve my sanity
+using VTKPointType = Containers::StaticVector< 3, VTKRealType >;
+
+template< typename Index = int >
+class VTKReader_libvtk
+{
+public:
+   using IndexType = Index;
+
+   bool
+   detectMesh( const String& fileName )
+   {
+      resetAll();
+      if( ! loadVTKFile( fileName ) ) {
+         resetAll();
+         return false;
+      }
+      reset();
+      return true;
+   }
+
+   template< typename MeshType >
+   bool
+   readMesh( const String& fileName, MeshType& mesh )
+   {
+      static_assert( std::is_same< IndexType, typename MeshType::GlobalIndexType >::value, "VTKReader_libvtk::IndexType and MeshType::GlobalIndexType must be the same type." );
+
+      resetAll();
+      if( ! loadVTKFile( fileName ) ) {
+         resetAll();
+         return false;
+      }
+
+      // GOTCHA: The unary "+" is a workaround due to odr-use of undefined static data member. See:
+      // https://stackoverflow.com/questions/39646958/constexpr-static-member-before-after-c17
+      // https://stackoverflow.com/questions/272900/undefined-reference-to-static-class-member/272996#272996
+      TNL_ASSERT_EQ( this->worldDimension, + MeshType::Config::worldDimension, "world dimensions do not match" );
+      TNL_ASSERT_EQ( this->meshDimension, + MeshType::Config::meshDimension, "mesh dimensions do not match" );
+      const int subvertices = Topologies::Subtopology< typename MeshType::Config::CellTopology, 0 >::count;
+      TNL_ASSERT_EQ( this->verticesInEntities.at( this->meshDimension ), subvertices, "numbers of cell subvertices do not match" );
+
+      using MeshBuilder = MeshBuilder< MeshType >;
+      using VertexIndexType = typename MeshType::MeshTraitsType::template EntityTraits< 0 >::GlobalIndexType;
+      using CellIndexType = typename MeshType::MeshTraitsType::template EntityTraits< MeshType::Config::meshDimension >::GlobalIndexType;
+
+      const VertexIndexType numberOfPoints = this->pointsData.size();
+      const CellIndexType numberOfCells = this->entityIdMappings.at( this->meshDimension ).size();
+
+      MeshBuilder meshBuilder;
+      meshBuilder.setPointsCount( numberOfPoints );
+      meshBuilder.setCellsCount( numberOfCells );
+
+      for( VertexIndexType i = 0; i < numberOfPoints; i++ ) {
+         typename MeshType::PointType p;
+         for( int j = 0; j < p.size; j++ )
+            p[ j ] = this->pointsData.at( i )[ j ];
+         meshBuilder.setPoint( i, p );
+      }
+
+      const auto& cellIdMap = this->entityIdMappings.at( this->meshDimension );
+      for( CellIndexType i = 0; i < numberOfCells; i++ ) {
+         const VTKIndexType vtkCellIndex = cellIdMap.at( i );
+         const auto& vtkCellSeeds = this->entitySeeds.at( vtkCellIndex );
+         using CellSeedType = typename MeshBuilder::CellSeedType;
+         TNL_ASSERT_EQ( CellSeedType::getCornersCount(), vtkCellSeeds.size(), "wrong number of subvertices" );
+         CellSeedType& seed = meshBuilder.getCellSeed( i );
+         for( int v = 0; v < CellSeedType::getCornersCount(); v++ ) {
+            seed.setCornerId( v, vtkCellSeeds[ v ] );
+         }
+      }
+
+      // drop all data from the VTK file since it's not needed anymore
+      this->resetAll();
+
+      return meshBuilder.build( mesh );
+   }
+
+   String
+   getMeshType() const
+   {
+      // we can read only the UNSTRUCTURED_GRID dataset
+      return "Meshes::Mesh";
+   }
+
+   int
+   getWorldDimension() const
+   {
+      return this->worldDimension;
+   }
+ 
+   int
+   getMeshDimension() const
+   {
+      return this->meshDimension;
+   }
+ 
+   EntityShape
+   getCellShape() const
+   {
+      return this->entityTypes.at( this->meshDimension );
+   }
+ 
+//   int
+//   getVerticesInCell() const
+//   {
+//      return this->verticesInEntities.at( this->getMeshDimension() );
+//   }
+
+//   EntityShape
+//   getEntityType( int entityDimension ) const
+//   {
+//      return this->entityTypes.at( entityDimension );
+//   }
+
+   String
+   getRealType() const
+   {
+      // TODO: how to extract it from the VTK object?
+//      return "float";
+      return "double";
+   }
+
+   String
+   getGlobalIndexType() const
+   {
+      // not stored in the VTK file
+      return "int";
+   }
+ 
+   String
+   getLocalIndexType() const
+   {
+      // not stored in the VTK file
+      return "short int";
+   }
+ 
+   String
+   getIdType() const
+   {
+      // not stored in the VTK file
+      return "int";
+   }
+ 
+protected:
+   int worldDimension = 0;
+   int meshDimension = 0;
+
+   // maps vertex indices to physical coordinates
+   std::unordered_map< VTKIndexType, VTKPointType > pointsData;
+
+   // maps entity dimension to the number of vertices in the entity
+   std::map< int, int > verticesInEntities;
+
+   // type for mapping TNL entity indices to VTK cell indices
+   using TNL2VTKindexmap = std::unordered_map< IndexType, VTKIndexType >;
+   // maps dimension to maps of TNL entity IDs to corresponding VTK cell IDs
+   std::unordered_map< int, TNL2VTKindexmap > entityIdMappings;
+
+   // maps VTK cell indices to entity seeds (set of indices of subvertices)
+   std::unordered_map< VTKIndexType, std::vector< VTKIndexType > > entitySeeds;
+
+   // maps dimension to VTK type of the entity with given dimension
+   std::unordered_map< int, EntityShape > entityTypes;
+
+   void reset()
+   {
+      pointsData.clear();
+      verticesInEntities.clear();
+      entityIdMappings.clear();
+      entitySeeds.clear();
+   }
+
+   void resetAll()
+   {
+      reset();
+      worldDimension = 0;
+      meshDimension = 0;
+      entityTypes.clear();
+   }
+
+   bool loadVTKFile( const String& fileName )
+   {
+#ifdef HAVE_VTK
+      vtkSmartPointer< vtkUnstructuredGridReader > vtkReader
+         = vtkSmartPointer<vtkUnstructuredGridReader>::New();
+      vtkReader->SetFileName( fileName.getString() );
+      vtkReader->Update();
+
+      if( ! vtkReader->IsFileUnstructuredGrid() ) {
+         std::cerr << "The file '" << fileName << "' is not a VTK Legacy file with an UNSTRUCTURED_GRID dataset type." << std::endl;
+         return false;
+      }
+
+      auto& vtkMesh = *vtkReader->GetOutput();
+
+      /* To determine the mesh type, we need:
+       * - world dimension (default 1D, if some 2nd coordinate is non-zero -> 2D, some 3rd coordinate non-zero -> 3D)
+       * - mesh dimension (highest dimension of the entities present in mesh)
+       * - check that it is homogeneous - all entities of the same dimension should have the same number of vertices and type
+       * - types of entities for each dimension
+       *
+       * To initialize the mesh, we need:
+       * - points data (vertex indices and world coordinates)
+       * - cell seeds (indices of vertices composing each cell)
+       */
+      const VTKIndexType numberOfPoints = vtkMesh.GetNumberOfPoints();
+      const VTKIndexType numberOfCells = vtkMesh.GetNumberOfCells();
+
+      if( numberOfPoints == 0 ) {
+         std::cerr << "There are no points data in the file '" << fileName << "'." << std::endl;
+         return false;
+      }
+
+      if( numberOfCells == 0 ) {
+         std::cerr << "There are no cells data in the file '" << fileName << "'." << std::endl;
+         return false;
+      }
+
+      for( VTKIndexType i = 0; i < numberOfPoints; i++ ) {
+         VTKRealType* p = vtkMesh.GetPoint( i );
+
+         // get world dimension
+         for( int j = 0; j < 3; j++ )
+            if( p[ j ] != 0.0 )
+               this->worldDimension = std::max( this->worldDimension, j + 1 );
+
+         // copy points data
+         this->pointsData[ i ] = VTKPointType( p[ 0 ], p[ 1 ], p[ 2 ] );
+      }
+
+      for( VTKIndexType i = 0; i < numberOfCells; i++ ) {
+         vtkCell* cell = vtkMesh.GetCell( i );
+         const int dimension = cell->GetCellDimension();
+         const int points = cell->GetNumberOfPoints();
+         const EntityShape type = (EntityShape) cell->GetCellType();
+
+         // number of vertices in entities
+         if( this->verticesInEntities.find( dimension ) == this->verticesInEntities.cend() )
+            this->verticesInEntities[ dimension ] = points;
+         else if( this->verticesInEntities[ dimension ] != points ) {
+            std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension
+                      << " with " << this->verticesInEntities[ dimension ] << " vertices and with " << points
+                      << " vertices. The number of vertices per entity must be constant." << std::endl;
+            this->reset();
+            return false;
+         }
+
+         // entity types
+         if( this->entityTypes.find( dimension ) == this->entityTypes.cend() )
+            this->entityTypes.emplace( std::make_pair( dimension, type ) );
+         else if( this->entityTypes[ dimension ] != type ) {
+            std::cerr << "Mixed unstructured meshes are not supported. There are elements of dimension " << dimension
+                      << " with type " << this->entityTypes[ dimension ] << " and " << type
+                      << ". The type of all entities with the same dimension must be the same." << std::endl;
+            this->reset();
+            return false;
+         }
+
+         // mapping between TNL and VTK indices
+         auto& map = this->entityIdMappings[ dimension ];
+         map[ map.size() ] = i;
+
+         // copy seed
+         auto& seed = this->entitySeeds[ i ];
+         for( int j = 0; j < points; j++ )
+            seed.push_back( cell->GetPointId( j ) );
+      }
+
+      // std::map is sorted, so the last key is the maximum
+      this->meshDimension = this->verticesInEntities.rbegin()->first;
+
+      if( this->meshDimension > this->worldDimension ) {
+         std::cerr << "Invalid mesh: world dimension is " << this->worldDimension
+                   << ", but mesh dimension is " << this->meshDimension << "." << std::endl;
+         this->reset();
+         return false;
+      }
+
+      return true;
+#else
+      std::cerr << "The VTKReader_libvtk needs to be compiled with the VTK library." << std::endl;
+      return false;
+#endif
+   }
+};
+
+} // namespace Readers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/CMakeLists.txt b/src/TNL/Meshes/Topologies/CMakeLists.txt
index 26d1753a352df8e6d3b363f456b4f42ed1f24aa5..797662306a257537a98fd9c756818be02e1923c6 100644
--- a/src/TNL/Meshes/Topologies/CMakeLists.txt
+++ b/src/TNL/Meshes/Topologies/CMakeLists.txt
@@ -1,9 +1,11 @@
-SET( headers MeshEdgeTopology.h
-             MeshEntityTopology.h
-             MeshHexahedronTopology.h
-             MeshQuadrilateralTopology.h
-             MeshTetrahedronTopology.h
-             MeshTriangleTopology.h
-             MeshVertexTopology.h )
+SET( headers Edge.h
+             Hexahedron.h
+             Quadrilateral.h
+             Simplex.h
+             SubentityVertexMap.h
+             Tetrahedron.h
+             Triangle.h
+             Vertex.h
+)
 
 INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Topologies )
diff --git a/src/TNL/Meshes/Topologies/MeshEdgeTopology.h b/src/TNL/Meshes/Topologies/Edge.h
similarity index 54%
rename from src/TNL/Meshes/Topologies/MeshEdgeTopology.h
rename to src/TNL/Meshes/Topologies/Edge.h
index 34e8778baa434e444a50e01068d06812e44992d1..4c4b8269e51a7de9f709f28868b6fc09d517f757 100644
--- a/src/TNL/Meshes/Topologies/MeshEdgeTopology.h
+++ b/src/TNL/Meshes/Topologies/Edge.h
@@ -1,8 +1,8 @@
 /***************************************************************************
-                          MeshEdgeTopology.h  -  description
+                          Edge.h  -  description
                              -------------------
     begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -16,25 +16,32 @@
 
 #pragma once
 
-#include <TNL/Meshes/Topologies/MeshEntityTopology.h>
-#include <TNL/Meshes/Topologies/MeshVertexTopology.h>
+#include <TNL/Meshes/Topologies/SubentityVertexMap.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
 
 namespace TNL {
 namespace Meshes {
+namespace Topologies {
    
-struct MeshEdgeTopology
+struct Edge
 {
-   static const int dimensions = 1;
+   static constexpr int dimension = 1;
+
+   static String getType()
+   {
+      return "Topologies::Edge";
+   }
 };
 
 
 template<>
-struct MeshSubtopology< MeshEdgeTopology, 0 >
+struct Subtopology< Edge, 0 >
 {
-   typedef MeshVertexTopology Topology;
+   typedef Vertex Topology;
 
-   static const int count = 2;
+   static constexpr int count = 2;
 };
 
+} // namespace Topologies
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Hexahedron.h b/src/TNL/Meshes/Topologies/Hexahedron.h
new file mode 100644
index 0000000000000000000000000000000000000000..db922f3b5bc487a7160e74c471597826e1461584
--- /dev/null
+++ b/src/TNL/Meshes/Topologies/Hexahedron.h
@@ -0,0 +1,185 @@
+/***************************************************************************
+                          Hexahedron.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/Topologies/Quadrilateral.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Topologies {
+
+struct Hexahedron
+{
+   static constexpr int dimension = 3;
+
+   static String getType()
+   {
+      return "Topologies::Hexahedron";
+   }
+};
+
+template<>
+struct Subtopology< Hexahedron, 0 >
+{
+   typedef Vertex Topology;
+
+   static constexpr int count = 8;
+};
+
+template<>
+struct Subtopology< Hexahedron, 1 >
+{
+   typedef Edge Topology;
+
+   static constexpr int count = 12;
+};
+
+template<>
+struct Subtopology< Hexahedron, 2 >
+{
+   typedef Quadrilateral Topology;
+
+   static constexpr int count = 6;
+};
+
+/****
+ * Indexing of the vertices follows the VTK file format
+ *
+ *        7+---------------------------+6
+ *        /|                          /|
+ *       / |                         / |
+ *      /  |                        /  |
+ *     /   |                       /   |
+ *   4+---------------------------+5   |
+ *    |    |                      |    |
+ *    |    |                      |    |
+ *    |   3+----------------------|----+2
+ *    |   /                       |   /
+ *    |  /                        |  /
+ *    | /                         | /
+ *    |/                          |/
+ *   0+---------------------------+1
+ *
+ *
+ * The edges are indexed as follows:
+ *
+ *         +---------------------------+
+ *        /|           10             /|
+ *     11/ |                         / |
+ *      /  |                        /9 |
+ *     /  7|                       /   |6
+ *    +---------------------------+    |
+ *    |    |        8             |    |
+ *    |    |                      |    |
+ *    |    +----------------------|----+
+ *   4|   /           2           |5  /
+ *    | 3/                        |  /
+ *    | /                         | /1
+ *    |/                          |/
+ *    +---------------------------+
+ *                 0
+ *
+ * The faces are indexed as follows (the indexed are positioned to
+ * the opposite corners of given face):
+ *
+ *         +---------------------------+
+ *        /|5                        3/|
+ *       /4|                         /2|
+ *      /  |                        /  |
+ *     /   |                     5 /   |
+ *    +---------------------------+    |
+ *    |1   |                      |    |
+ *    |    |3                     |    |
+ *    |    +----------------------|----+
+ *    |   /                       |  0/
+ *    |  /                        |  /
+ *    |4/                         |2/
+ *    |/0                        1|/
+ *    +---------------------------+
+ *
+ */
+
+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,  1, 0> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  1, 1> { enum { 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,  3, 0> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  3, 1> { enum { 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,  5, 0> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  5, 1> { enum { 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,  7, 0> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  7, 1> { enum { 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,  9, 0> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge,  9, 1> { enum { 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, 11, 0> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Edge, 11, 1> { enum { index = 4 }; };
+
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 0> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 2> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 0, 3> { enum { index = 3 }; };
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 0> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 1> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 2> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 1, 3> { enum { index = 4 }; };
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 0> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 1> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 2> { enum { index = 6 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 2, 3> { enum { index = 5 }; };
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 0> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 1> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 2> { enum { index = 7 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 3, 3> { enum { index = 6 }; };
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 0> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 1> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 2> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 4, 3> { enum { index = 7 }; };
+
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 0> { enum { index = 4 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 1> { enum { index = 5 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 2> { enum { index = 6 }; };
+template<> struct SubentityVertexMap< Hexahedron, Quadrilateral, 5, 3> { enum { index = 7 }; };
+
+} // namespace Topologies
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/MeshEntityTopology.h b/src/TNL/Meshes/Topologies/MeshEntityTopology.h
deleted file mode 100644
index 589bec5db38d2cc7a406b8abd3092251f8247628..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshEntityTopology.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/***************************************************************************
-                          MeshEntityTopology.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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
-
-namespace TNL {
-namespace Meshes{
-
-template< typename MeshEntityTopology,
-          int SubentityDimension >
-struct MeshSubtopology
-{
-};
-
-template< typename MeshEntityTopology,
-          typename SubentityTopology,
-          int SubentityIndex,
-          int SubentityVertexIndex >
-struct tnlSubentityVertex;
-
-
-template< typename MeshConfig,
-          int Dimension >
-class MeshEntityTopology
-{
-   public:
-
-   typedef typename MeshSubtopology< typename MeshConfig::CellTopology,
-                                        Dimension >::Topology Topology;
-};
-
-template< typename MeshConfig >
-class MeshEntityTopology< MeshConfig,
-                             MeshConfig::CellTopology::dimensions >
-{
-   public:
-
-   typedef typename MeshConfig::CellTopology Topology;
-};
-
-} // namespace Meshes
-} // namespace TNL
\ No newline at end of file
diff --git a/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h b/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h
deleted file mode 100644
index 4dc1ff3acae2a5579885bf00963150d86cc52844..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshHexahedronTopology.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/***************************************************************************
-                          MeshHexahedronTopology.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/Topologies/MeshQuadrilateralTopology.h>
-
-namespace TNL {
-namespace Meshes {
-
-struct MeshHexahedronTopology
-{
-   static const int dimensions = 3;
-};
-
-template<>
-struct MeshSubtopology< MeshHexahedronTopology, 0 >
-{
-   typedef MeshVertexTopology Topology;
-
-   static const int count = 8;
-};
-
-template<>
-struct MeshSubtopology< MeshHexahedronTopology, 1 >
-{
-   typedef MeshEdgeTopology Topology;
-
-   static const int count = 12;
-};
-
-template<>
-struct MeshSubtopology< MeshHexahedronTopology, 2 >
-{
-   typedef MeshQuadrilateralTopology Topology;
-
-   static const int count = 6;
-};
-
-/****
- * Indexing of the vertices follows the VTK file format
- *
- *        7+---------------------------+6
- *        /|                          /|
- *       / |                         / |
- *      /  |                        /  |
- *     /   |                       /   |
- *   4+---------------------------+5   |
- *    |    |                      |    |
- *    |    |                      |    |
- *    |   3+----------------------|----+2
- *    |   /                       |   /
- *    |  /                        |  /
- *    | /                         | /
- *    |/                          |/
- *   0+---------------------------+1
- *
- *
- * The edges are indexed as follows:
- *
- *         +---------------------------+
- *        /|           10             /|
- *     11/ |                         / |
- *      /  |                        /9 |
- *     /  7|                       /   |6
- *    +---------------------------+    |
- *    |    |        8             |    |
- *    |    |                      |    |
- *    |    +----------------------|----+
- *   4|   /           2           |5  /
- *    | 3/                        |  /
- *    | /                         | /1
- *    |/                          |/
- *    +---------------------------+
- *                 0
- *
- * The faces are indexed as follows (the indexed are positioned to
- * the opposite corners of given face):
- *
- *         +---------------------------+
- *        /|5                        3/|
- *       /4|                         /2|
- *      /  |                        /  |
- *     /   |                     5 /   |
- *    +---------------------------+    |
- *    |1   |                      |    |
- *    |    |3                     |    |
- *    |    +----------------------|----+
- *    |   /                       |  0/
- *    |  /                        |  /
- *    |4/                         |2/
- *    |/0                        1|/
- *    +---------------------------+
- *
- */
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  0, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  0, 1> { enum { index = 1 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  1, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  1, 1> { enum { index = 2 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  2, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  2, 1> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  3, 0> { enum { index = 3 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  3, 1> { enum { index = 0 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  4, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  4, 1> { enum { index = 4 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  5, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  5, 1> { enum { index = 5 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  6, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  6, 1> { enum { index = 6 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  7, 0> { enum { index = 3 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  7, 1> { enum { index = 7 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  8, 0> { enum { index = 4 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  8, 1> { enum { index = 5 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  9, 0> { enum { index = 5 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology,  9, 1> { enum { index = 6 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 10, 0> { enum { index = 6 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 10, 1> { enum { index = 7 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 11, 0> { enum { index = 7 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshEdgeTopology, 11, 1> { enum { index = 4 }; };
-
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 1> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 2> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 0, 3> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 1> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 2> { enum { index = 5 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 1, 3> { enum { index = 4 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 1> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 2> { enum { index = 6 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 2, 3> { enum { index = 5 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 1> { enum { index = 3 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 2> { enum { index = 7 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 3, 3> { enum { index = 6 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 0> { enum { index = 3 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 1> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 2> { enum { index = 4 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 4, 3> { enum { index = 7 }; };
-
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 0> { enum { index = 4 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 1> { enum { index = 5 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 2> { enum { index = 6 }; };
-template<> struct tnlSubentityVertex< MeshHexahedronTopology, MeshQuadrilateralTopology, 5, 3> { enum { index = 7 }; };
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h b/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h
deleted file mode 100644
index 4dd844e4c9c0b3bd195c9f3387f8bbfa7d3557e2..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshQuadrilateralTopology.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/***************************************************************************
-                          MeshQuadrilateralTopology.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/Topologies/MeshEdgeTopology.h>
-
-namespace TNL {
-namespace Meshes {
-
-struct MeshQuadrilateralTopology
-{
-   static const int dimensions = 2;
-};
-
-
-template<>
-struct MeshSubtopology< MeshQuadrilateralTopology, 0 >
-{
-   typedef MeshVertexTopology Topology;
-
-   static const int count = 4;
-};
-
-template<>
-struct MeshSubtopology< MeshQuadrilateralTopology, 1 >
-{
-   typedef MeshEdgeTopology Topology;
-
-   static const int count = 4;
-};
-
-
-/****
- * Indexing of the vertices follows the VTK file format
- *
- *   3                     2
- *    +-------------------+
- *    |                   |
- *    |                   |
- *    |                   |
- *    |                   |
- *    |                   |
- *    +-------------------+
- *   0                     1
- *
- * The edges are indexed as follows:
- *
- *              2
- *    +-------------------+
- *    |                   |
- *    |                   |
- *  3 |                   | 1
- *    |                   |
- *    |                   |
- *    +-------------------+
- *              0
- *
- */
-
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 0, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 0, 1> { enum { index = 1 }; };
-
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 1, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 1, 1> { enum { index = 2 }; };
-
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 2, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 2, 1> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 3, 0> { enum { index = 3 }; };
-template<> struct tnlSubentityVertex< MeshQuadrilateralTopology, MeshEdgeTopology, 3, 1> { enum { index = 0 }; };
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/MeshSimplexTopology.h b/src/TNL/Meshes/Topologies/MeshSimplexTopology.h
deleted file mode 100644
index 2120a71c7a120ab996e4b68777bcea99bfad5e22..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshSimplexTopology.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/***************************************************************************
-                          MeshSimplexTopology.h  -  description
-                             -------------------
-    begin                : Aug 29, 2015
-    copyright            : (C) 2015 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
-
-namespace TNL {
-namespace Meshes {
-
-template< int dimensions_ >
-class MeshSimplexTopology
-{
-   public:
-	   static const int dimensions = dimensions_;
-};
-
-template< unsigned int n, unsigned int k >
-class tnlStaticNumCombinations;
-
-template<unsigned int n, unsigned int k, unsigned int combinationIndex, unsigned int valueIndex>
-class tnlCombinationValue;
-
-template< int dimensions,
-          int subtopologyDim >
-class MeshSubtopology< MeshSimplexTopology< dimensions >, subtopologyDim >
-{
-	static_assert( 0 < subtopologyDim && subtopologyDim < dim, "invalid subtopology dimension" );
-
-	static const int topologyVertexCount = MeshSubtopology< MeshSimplexTopology< dimensions >, 0 >::count;
-	static const int subtopologyVertexCount = MeshSubtopology< MeshSimplexTopology< subtopologyDim >, 0>::count;
-
-   public:
-	   typedef MeshSimplexTopology< subtopologyDim > Topology;
-
-	   static const int count = tnlNumCombinations< topologyVertexCount, subtopologyVertexCount >::value;
-};
-
-template< int dimensions >
-class MeshSubtopology< MeshSimplexTopology< dimensions >, 0 >
-{
-	static_assert(0 < dim, "invalid dimension");
-
-   public:
-	   typedef MeshVertexTopology Topology;
-
-   	static const int count = dim + 1;
-};
-
-
-template< int dimensions,
-          typename Subtopology,
-          int subtopologyIndex,
-          int vertexIndex >
-struct tnlSubentityVertex< MeshSimplexTopology< dimensions >, Subtopology, subtopologyIndex, vertexIndex >
-{
-   private:
-	   static const int subtopologyCount = Subtopology< MeshSimplexTopology< dimensions >, Subtopology::dimensions >::count;
-	   static const int topologyVertexCount = Subtopology< MeshSimplex< dimensions >, 0 >::count;
-	   static const int subtopologyVertexCount = Subtopology< Subtopology, 0 >::count;
-
-	   static_assert(1 < dimensions, "subtopology vertex can be specified for topologies of dimension 2 or higher");
-	   static_assert(0 <= subtopologyIndex && subtopologyIndex < subtopologyCount, "invalid subtopology index");
-	   static_assert(0 <= vertexIndex && vertexIndex < subtopologyVertexCount, "invalid subtopology vertex index");
-
-   public:
-	   static const int index = CombinationValue< topologyVertexCount, subtopologyVertexCount, subtopologyIndex, vertexIndex>::value;
-};
-
-template< unsigned int n, unsigned int k >
-class tnlStaticNumCombinations
-{
-	static_assert(0 < k && k < n, "invalid argument");
-
-   public:
-	   static const unsigned int value = tnlNumCombinations< n - 1, k - 1 >::value + tnlNumCombinations< n - 1, k >::value;
-};
-
-// Nummber of combinations (n choose k)
-template< unsigned int n >
-class tnlNumCombinations< n, 0 >
-{
-	static_assert(0 <= n, "invalid argument");
-
-   public:
-	   static const unsigned int value = 1;
-};
-
-template< unsigned int n >
-class tnlNumCombinations< n, n >
-{
-	static_assert(0 < n, "invalid argument");
-
-   public:
-	   static const unsigned int value = 1;
-};
-
-//     Compile-time generation of combinations
-// Combinations are generated in lexicographical order. The following example shows generation of 2-combinations from set {0, 1, 2}:
-//   0, 1  <->  CombinationValue<3, 2, 0, 0>::VALUE, CombinationValue<3, 2, 0, 1>::VALUE
-//   0, 2  <->  CombinationValue<3, 2, 1, 0>::VALUE, CombinationValue<3, 2, 1, 1>::VALUE
-//   1, 2  <->  CombinationValue<3, 2, 2, 0>::VALUE, CombinationValue<3, 2, 2, 1>::VALUE
-template< unsigned int n,
-          unsigned int k,
-          unsigned int combinationIndex >
-class tnlCombinationIncrement;
-
-template< unsigned int n,
-          unsigned int k,
-          unsigned int combinationIndex,
-          unsigned int valueIndex >
-class tnlCombinationValue
-{
-	static_assert( combinationIndex < NumCombinations< n, k >::value, "invalid combination index" );
-	static_assert( valueIndex < k, "invalid value index" );
-
-	static const unsigned int incrementValueIndex = tnlCombinationIncrement< n, k, combinationIndex - 1>::valueIndex;
-
-   public:
-	   static const unsigned int value = ( valueIndex < incrementValueIndex ? tnlCombinationValue< n, k, combinationIndex - 1, valueIndex >::value :
-	                                       tnlCombinationValue< n, k, combinationIndex - 1, incrementValueIndex >::value +
-                                          valueIndex - incrementValueIndex + 1);
-};
-
-template< unsigned int n,
-          unsigned int k,
-          unsigned int valueIndex >
-class tnlCombinationValue< n, k, 0, valueIndex >
-{
-	static_assert( valueIndex < k, "invalid value index" );
-
-	static const unsigned int incrementValueIndex = tnlCombinationIncrement< n, k, 0 >::valueIndex;
-
-   public:
-	   static const unsigned int value = valueIndex;
-};
-
-// The CombinationIncrement class determines value index of the particular combination which will be incremented when generating the next combination
-template< unsigned int n,
-          unsigned int k,
-          unsigned int combinationIndex,
-          unsigned int valueIndex >
-class tnlCombinationIncrementImpl
-{
-	static_assert( combinationIndex < tnlNumCombinations< n, k >::value - 1, "nothing to increment" );
-
-	static const bool incrementPossible = ( tnlCombinationValue< n, k, combinationIndex, valueIndex >::value + k - valueIndex < n );
-
-   public:
-	   static const int valueIndex = ( incrementPossible ? valueIndex : tnlCombinationIncrementImpl< n, k, combinationIndex, valueIndex - 1 >::valueIndex );
-};
-
-template< unsigned int n,
-          unsigned int k,
-          unsigned int combinationIndex >
-class tnlCombinationIncrementImpl< n, k, combinationIndex, 0 >
-{
-	static_assert( combinationIndex < tnlNumCombinations<n, k>::value - 1, "nothing to increment" );
-
-   public:
-	   static const int valueIndex = 0;
-};
-
-template< unsigned int n,
-          unsigned int k,
-          unsigned int combinationIndex >
-class tnlCombinationIncrement
-{
-	static_assert( combinationIndex < tnlNumCombinations< n, k >::value - 1, "nothing to increment" );
-
-   public:
-	   static const unsigned int valueIndex = tnlCombinationIncrementImpl< n, k, combinationIndex, k - 1 >::valueIndex;
-};
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/Topologies/MeshSubtopology.h b/src/TNL/Meshes/Topologies/MeshSubtopology.h
deleted file mode 100644
index df9d813302025b4f6373f6ff4dc2f032b72a96ba..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshSubtopology.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
-                          MeshSubtopology.h  -  description
-                             -------------------
-    begin                : Aug 29, 2015
-    copyright            : (C) 2015 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
-
-namespace TNL {
-namespace Meshes {
-
-template< typename Topology,
-          int dimensions >
-class MeshSubtopology;
-
-template< typename Topology,
-          typename Subtopology,
-          int subtopologyIndex,
-          int vertexIndex >
-struct MeshSubtopologyVertex;
-
-} // namespace Meshes
-} // namespace TNL
-
diff --git a/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h b/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h
deleted file mode 100644
index 4f0067c255af28cf33d2dc4c5140053dbc8c8052..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshTetrahedronTopology.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/***************************************************************************
-                          MeshTetrahedronTopology.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/Topologies/MeshTriangleTopology.h>
-
-namespace TNL {
-namespace Meshes {
-
-struct MeshTetrahedronTopology
-{
-   static const int dimensions = 3;
-};
-
-template<>
-struct MeshSubtopology< MeshTetrahedronTopology, 0 >
-{
-   typedef MeshVertexTopology Topology;
-
-   static const int count = 4;
-};
-
-template<>
-struct MeshSubtopology< MeshTetrahedronTopology, 1 >
-{
-   typedef MeshEdgeTopology Topology;
-
-   static const int count = 6;
-};
-
-template<>
-struct MeshSubtopology< MeshTetrahedronTopology, 2 >
-{
-   typedef MeshTriangleTopology Topology;
-
-   static const int count = 4;
-};
-
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1> { enum { index = 2 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1> { enum { index = 0 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1> { enum { index = 1 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1> { enum { index = 3 }; };
-
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2> { enum { index = 2 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2> { enum { index = 3 }; };
-
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 1> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 2> { enum { index = 3 }; };
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/MeshTriangleTopology.h b/src/TNL/Meshes/Topologies/MeshTriangleTopology.h
deleted file mode 100644
index 0305c4355cc289548bf8fe3381f9fd08c71b513a..0000000000000000000000000000000000000000
--- a/src/TNL/Meshes/Topologies/MeshTriangleTopology.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/***************************************************************************
-                          MeshTriangleTopology.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    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/Topologies/MeshEdgeTopology.h>
-
-namespace TNL {
-namespace Meshes {
-
-struct MeshTriangleTopology
-{
-   static const int dimensions = 2;
-};
-
-
-template<>
-struct MeshSubtopology< MeshTriangleTopology, 0 >
-{
-   typedef MeshVertexTopology Topology;
-
-   static const int count = 3;
-};
-
-template<>
-struct MeshSubtopology< MeshTriangleTopology, 1 >
-{
-   typedef MeshEdgeTopology Topology;
-
-   static const int count = 3;
-};
-
-
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0> { enum { index = 1 }; };
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1> { enum { index = 2 }; };
-
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0> { enum { index = 2 }; };
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1> { enum { index = 0 }; };
-
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0> { enum { index = 0 }; };
-template<> struct tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1> { enum { index = 1 }; };
-
-} // namespace Meshes
-} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Quadrilateral.h b/src/TNL/Meshes/Topologies/Quadrilateral.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b5d4eb54b68f01f6fef9932cd66c3c897d1d72d
--- /dev/null
+++ b/src/TNL/Meshes/Topologies/Quadrilateral.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+                          Quadrilateral.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/Topologies/Edge.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Topologies {
+
+struct Quadrilateral
+{
+   static constexpr int dimension = 2;
+
+   static String getType()
+   {
+      return "Topologies::Quadrilateral";
+   }
+};
+
+
+template<>
+struct Subtopology< Quadrilateral, 0 >
+{
+   typedef Vertex Topology;
+
+   static constexpr int count = 4;
+};
+
+template<>
+struct Subtopology< Quadrilateral, 1 >
+{
+   typedef Edge Topology;
+
+   static constexpr int count = 4;
+};
+
+
+/****
+ * Indexing of the vertices follows the VTK file format
+ *
+ *   3                     2
+ *    +-------------------+
+ *    |                   |
+ *    |                   |
+ *    |                   |
+ *    |                   |
+ *    |                   |
+ *    +-------------------+
+ *   0                     1
+ *
+ * The edges are indexed as follows:
+ *
+ *              2
+ *    +-------------------+
+ *    |                   |
+ *    |                   |
+ *  3 |                   | 1
+ *    |                   |
+ *    |                   |
+ *    +-------------------+
+ *              0
+ *
+ */
+
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 0, 0> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 0, 1> { enum { index = 1 }; };
+
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 1, 0> { enum { index = 1 }; };
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 1, 1> { enum { index = 2 }; };
+
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 2, 0> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 2, 1> { enum { index = 3 }; };
+
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 3, 0> { enum { index = 3 }; };
+template<> struct SubentityVertexMap< Quadrilateral, Edge, 3, 1> { enum { index = 0 }; };
+
+} // namespace Topologies
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Simplex.h b/src/TNL/Meshes/Topologies/Simplex.h
new file mode 100644
index 0000000000000000000000000000000000000000..bbdf39b27c73f46f91064df1590dfd7f1c86efd0
--- /dev/null
+++ b/src/TNL/Meshes/Topologies/Simplex.h
@@ -0,0 +1,205 @@
+/***************************************************************************
+                          Simplex.h  -  description
+                             -------------------
+    begin                : Aug 29, 2015
+    copyright            : (C) 2015 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/Topologies/SubentityVertexMap.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Topologies {
+
+template< int dimension_ >
+class Simplex
+{
+   public:
+      static constexpr int dimension = dimension_;
+
+      static String getType()
+      {
+         return String( "Topologies::Simplex< " ) + String( dimension ) + " >";
+      }
+};
+
+namespace SimplexDetails {
+   template< unsigned int n, unsigned int k >
+   class NumCombinations;
+
+   template<unsigned int n, unsigned int k, unsigned int combinationIndex, unsigned int valueIndex>
+   class CombinationValue;
+}
+
+template< int dimension,
+          int subtopologyDim >
+class Subtopology< Simplex< dimension >, subtopologyDim >
+{
+   static_assert( 0 < subtopologyDim && subtopologyDim < dimension, "invalid subtopology dimension" );
+
+   static constexpr int topologyVertexCount = Subtopology< Simplex< dimension >, 0 >::count;
+   static constexpr int subtopologyVertexCount = Subtopology< Simplex< subtopologyDim >, 0>::count;
+
+   public:
+      typedef Simplex< subtopologyDim > Topology;
+
+      static constexpr int count = SimplexDetails::NumCombinations< topologyVertexCount, subtopologyVertexCount >::value;
+};
+
+template< int dimension >
+class Subtopology< Simplex< dimension >, 0 >
+{
+   static_assert(0 < dimension, "invalid dimension");
+
+   public:
+      typedef Vertex Topology;
+
+      static constexpr int count = dimension + 1;
+};
+
+
+template< int dimension,
+          typename Subtopology,
+          int subtopologyIndex,
+          int vertexIndex >
+struct SubentityVertexMap< Simplex< dimension >, Subtopology, subtopologyIndex, vertexIndex >
+{
+   private:
+      static constexpr int subtopologyCount = Topologies::Subtopology< Simplex< dimension >, Subtopology::dimension >::count;
+      static constexpr int topologyVertexCount = Topologies::Subtopology< Simplex< dimension >, 0 >::count;
+      static constexpr int subtopologyVertexCount = Topologies::Subtopology< Subtopology, 0 >::count;
+
+      static_assert(1 < dimension, "subtopology vertex can be specified for topologies of dimension 2 or higher");
+      static_assert(0 <= subtopologyIndex && subtopologyIndex < subtopologyCount, "invalid subtopology index");
+      static_assert(0 <= vertexIndex && vertexIndex < subtopologyVertexCount, "invalid subtopology vertex index");
+
+   public:
+      static constexpr int index = SimplexDetails::CombinationValue< topologyVertexCount, subtopologyVertexCount, subtopologyIndex, vertexIndex>::value;
+};
+
+template< unsigned int n, unsigned int k >
+class NumCombinations
+{
+   static_assert(0 < k && k < n, "invalid argument");
+
+   public:
+      static const unsigned int value = NumCombinations< n - 1, k - 1 >::value + NumCombinations< n - 1, k >::value;
+};
+
+
+namespace SimplexDetails {
+
+// Nummber of combinations (n choose k)
+template< unsigned int n >
+class NumCombinations< n, 0 >
+{
+   static_assert(0 <= n, "invalid argument");
+
+   public:
+      static const unsigned int value = 1;
+};
+
+template< unsigned int n >
+class NumCombinations< n, n >
+{
+   static_assert(0 < n, "invalid argument");
+
+   public:
+      static const unsigned int value = 1;
+};
+
+//     Compile-time generation of combinations
+// Combinations are generated in lexicographical order. The following example shows generation of 2-combinations from set {0, 1, 2}:
+//   0, 1  <->  CombinationValue<3, 2, 0, 0>::VALUE, CombinationValue<3, 2, 0, 1>::VALUE
+//   0, 2  <->  CombinationValue<3, 2, 1, 0>::VALUE, CombinationValue<3, 2, 1, 1>::VALUE
+//   1, 2  <->  CombinationValue<3, 2, 2, 0>::VALUE, CombinationValue<3, 2, 2, 1>::VALUE
+template< unsigned int n,
+          unsigned int k,
+          unsigned int combinationIndex >
+class CombinationIncrement;
+
+template< unsigned int n,
+          unsigned int k,
+          unsigned int combinationIndex,
+          unsigned int valueIndex >
+class CombinationValue
+{
+   static_assert( combinationIndex < NumCombinations< n, k >::value, "invalid combination index" );
+   static_assert( valueIndex < k, "invalid value index" );
+
+   static const unsigned int incrementValueIndex = CombinationIncrement< n, k, combinationIndex - 1>::valueIndex;
+
+   public:
+      static const unsigned int value = ( valueIndex < incrementValueIndex ? CombinationValue< n, k, combinationIndex - 1, valueIndex >::value :
+                                          CombinationValue< n, k, combinationIndex - 1, incrementValueIndex >::value +
+                                          valueIndex - incrementValueIndex + 1);
+};
+
+template< unsigned int n,
+          unsigned int k,
+          unsigned int valueIndex >
+class CombinationValue< n, k, 0, valueIndex >
+{
+   static_assert( valueIndex < k, "invalid value index" );
+
+   static const unsigned int incrementValueIndex = CombinationIncrement< n, k, 0 >::valueIndex;
+
+   public:
+      static const unsigned int value = valueIndex;
+};
+
+// The CombinationIncrement class determines value index of the particular combination which will be incremented when generating the next combination
+template< unsigned int n,
+          unsigned int k,
+          unsigned int combinationIndex,
+          unsigned int valueIndex_ >
+class CombinationIncrementImpl
+{
+   static_assert( combinationIndex < NumCombinations< n, k >::value - 1, "nothing to increment" );
+
+   static const bool incrementPossible = ( CombinationValue< n, k, combinationIndex, valueIndex_ >::value + k - valueIndex_ < n );
+
+   public:
+      static constexpr int valueIndex = ( incrementPossible ? valueIndex_ : CombinationIncrementImpl< n, k, combinationIndex, valueIndex_ - 1 >::valueIndex );
+};
+
+template< unsigned int n,
+          unsigned int k,
+          unsigned int combinationIndex >
+class CombinationIncrementImpl< n, k, combinationIndex, 0 >
+{
+   static_assert( combinationIndex < NumCombinations<n, k>::value - 1, "nothing to increment" );
+
+   public:
+      static constexpr int valueIndex = 0;
+};
+
+template< unsigned int n,
+          unsigned int k,
+          unsigned int combinationIndex >
+class CombinationIncrement
+{
+   static_assert( combinationIndex < NumCombinations< n, k >::value - 1, "nothing to increment" );
+
+   public:
+      static const unsigned int valueIndex = CombinationIncrementImpl< n, k, combinationIndex, k - 1 >::valueIndex;
+};
+
+} // namespace SimplexDetails
+
+} // namespace Topologies
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h b/src/TNL/Meshes/Topologies/SubentityVertexMap.h
similarity index 50%
rename from src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h
rename to src/TNL/Meshes/Topologies/SubentityVertexMap.h
index 2eabfa69e9e72a2b9e3a96aa4c8a3d11d87eaa19..89b5fb57e002f33ab897034927c79889ec1105c5 100644
--- a/src/TNL/Meshes/MeshDetails/MeshEntityIntegrityChecker.h
+++ b/src/TNL/Meshes/Topologies/SubentityVertexMap.h
@@ -1,8 +1,8 @@
 /***************************************************************************
-                          MeshEntityIntegrityChecker.h  -  description
+                          SubentityVertexMap.h  -  description
                              -------------------
-    begin                : Mar 20, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    begin                : Feb 11, 2014
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -17,19 +17,23 @@
 #pragma once
 
 namespace TNL {
-namespace Meshes {
+namespace Meshes{
+namespace Topologies {
 
-template< typename MeshEntity >
-class MeshEntityIntegrityChecker
+template< typename EntityTopology,
+          int SubentityDimension >
+struct Subtopology
 {
-   public:
-
-      static bool checkEntity( const MeshEntity& entity )
-      {
-         return true;
-      }
+};
 
+template< typename EntityTopology,
+          typename SubentityTopology,
+          int SubentityIndex,
+          int SubentityVertexIndex >
+struct SubentityVertexMap
+{
 };
 
+} // namespace Topologies
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Tetrahedron.h b/src/TNL/Meshes/Topologies/Tetrahedron.h
new file mode 100644
index 0000000000000000000000000000000000000000..7722f5ef688ad41cd3b594e8ec3a5484aae17b9e
--- /dev/null
+++ b/src/TNL/Meshes/Topologies/Tetrahedron.h
@@ -0,0 +1,98 @@
+/***************************************************************************
+                          Tetrahedron.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/Topologies/Triangle.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Topologies {
+
+struct Tetrahedron
+{
+   static constexpr int dimension = 3;
+
+   static String getType()
+   {
+      return "Topologies::Tetrahedron";
+   }
+};
+
+template<>
+struct Subtopology< Tetrahedron, 0 >
+{
+   typedef Vertex Topology;
+
+   static constexpr int count = 4;
+};
+
+template<>
+struct Subtopology< Tetrahedron, 1 >
+{
+   typedef Edge Topology;
+
+   static constexpr int count = 6;
+};
+
+template<>
+struct Subtopology< Tetrahedron, 2 >
+{
+   typedef Triangle Topology;
+
+   static constexpr int count = 4;
+};
+
+
+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, 1, 0> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 1, 1> { enum { 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, 3, 0> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 3, 1> { enum { 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, 5, 0> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Tetrahedron, Edge, 5, 1> { enum { 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, 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, 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, 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 }; };
+
+} // namespace Topologies
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/Triangle.h b/src/TNL/Meshes/Topologies/Triangle.h
new file mode 100644
index 0000000000000000000000000000000000000000..11d1c8a846c360f22d46fb676f411146d33662bd
--- /dev/null
+++ b/src/TNL/Meshes/Topologies/Triangle.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+                          Triangle.h  -  description
+                             -------------------
+    begin                : Feb 11, 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/Topologies/Edge.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Topologies {
+
+struct Triangle
+{
+   static constexpr int dimension = 2;
+
+   static String getType()
+   {
+      return "Topologies::Triangle";
+   }
+};
+
+
+template<>
+struct Subtopology< Triangle, 0 >
+{
+   typedef Vertex Topology;
+
+   static constexpr int count = 3;
+};
+
+template<>
+struct Subtopology< Triangle, 1 >
+{
+   typedef Edge Topology;
+
+   static constexpr int count = 3;
+};
+
+
+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, 1, 0> { enum { index = 2 }; };
+template<> struct SubentityVertexMap< Triangle, Edge, 1, 1> { enum { index = 0 }; };
+
+template<> struct SubentityVertexMap< Triangle, Edge, 2, 0> { enum { index = 0 }; };
+template<> struct SubentityVertexMap< Triangle, Edge, 2, 1> { enum { index = 1 }; };
+
+} // namespace Topologies
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Topologies/MeshVertexTopology.h b/src/TNL/Meshes/Topologies/Vertex.h
similarity index 63%
rename from src/TNL/Meshes/Topologies/MeshVertexTopology.h
rename to src/TNL/Meshes/Topologies/Vertex.h
index 5c70978f74687cf8999dd91b1ae811d1e8db9410..cff78e37d6e64f3798791e26510864aaed44955c 100644
--- a/src/TNL/Meshes/Topologies/MeshVertexTopology.h
+++ b/src/TNL/Meshes/Topologies/Vertex.h
@@ -1,8 +1,8 @@
 /***************************************************************************
-                          MeshVertexTopology.h  -  description
+                          Vertex.h  -  description
                              -------------------
     begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -16,13 +16,22 @@
 
 #pragma once
 
+#include <TNL/String.h>
+
 namespace TNL {
 namespace Meshes {
+namespace Topologies {
 
-struct MeshVertexTopology
+struct Vertex
 {
-   static const int dimensions = 0;
+   static constexpr int dimension = 0;
+
+   static String getType()
+   {
+      return "Topologies::Vertex";
+   }
 };
 
+} // namespace Topologies
 } // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Meshes/Traverser.h b/src/TNL/Meshes/Traverser.h
index c9c647cd7314d800c4a56739945284530945b575..ce0e0bf99d818b696c94ed8791dad5717dcb3cde 100644
--- a/src/TNL/Meshes/Traverser.h
+++ b/src/TNL/Meshes/Traverser.h
@@ -2,7 +2,7 @@
                           Traverser.h  -  description
                              -------------------
     begin                : Jul 28, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
+    copyright            : (C) 2014 by Tomas Oberhuber et al.
     email                : tomas.oberhuber@fjfi.cvut.cz
  ***************************************************************************/
 
@@ -10,17 +10,68 @@
 
 #pragma once
 
+#include <TNL/SharedPointer.h>
+#include <TNL/Meshes/Mesh.h>
+
 namespace TNL {
 namespace Meshes {
 
 template< typename Mesh,
           typename MeshEntity,
           int EntitiesDimension = MeshEntity::getEntityDimension() >
-class Traverser{};
+class Traverser
+{
+   public:
+      using MeshType = Mesh;
+      using MeshPointer = SharedPointer< MeshType >;
+      using DeviceType = typename MeshType::DeviceType;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processBoundaryEntities( const MeshPointer& meshPointer,
+                                    SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processInteriorEntities( const MeshPointer& meshPointer,
+                                    SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processAllEntities( const MeshPointer& meshPointer,
+                               SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+};
+
+template< typename MeshConfig,
+          typename MeshEntity,
+          int EntitiesDimension >
+class Traverser< Mesh< MeshConfig, Devices::Cuda >, MeshEntity, EntitiesDimension >
+{
+   public:
+      using MeshType = Mesh< MeshConfig, Devices::Cuda >;
+      using MeshPointer = SharedPointer< MeshType >;
+      using DeviceType = typename MeshType::DeviceType;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processBoundaryEntities( const MeshPointer& meshPointer,
+                                    SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processInteriorEntities( const MeshPointer& meshPointer,
+                                    SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+
+      template< typename UserData,
+                typename EntitiesProcessor >
+      void processAllEntities( const MeshPointer& meshPointer,
+                               SharedPointer< UserData, DeviceType >& userDataPointer ) const;
+};
 
 } // namespace Meshes
 } // namespace TNL
 
+#include <TNL/Meshes/MeshDetails/Traverser_impl.h>
 #include <TNL/Meshes/GridDetails/Traverser_Grid1D.h>
 #include <TNL/Meshes/GridDetails/Traverser_Grid2D.h>
 #include <TNL/Meshes/GridDetails/Traverser_Grid3D.h>
diff --git a/src/TNL/Meshes/TypeResolver/CMakeLists.txt b/src/TNL/Meshes/TypeResolver/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..83c105cd54b89b17e8cecd0a29b030e14fa820b6
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/CMakeLists.txt
@@ -0,0 +1,9 @@
+SET( headers GridTypeResolver.h
+             GridTypeResolver_impl.h
+             MeshTypeResolver.h
+             MeshTypeResolver_impl.h
+             TypeResolver.h
+             TypeResolver_impl.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/TypeResolver )
diff --git a/src/TNL/Meshes/TypeResolver/GridTypeResolver.h b/src/TNL/Meshes/TypeResolver/GridTypeResolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..498ae0f589cb28a40c31b0f382f0e620f1a96a4b
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/GridTypeResolver.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+                          GridTypeResolver.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <type_traits>
+
+#include <TNL/Meshes/BuildConfigTags.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+class GridTypeResolver
+{
+public:
+
+   static bool run( const Reader& reader,
+                    ProblemSetterArgs&&... problemSetterArgs );
+
+protected:
+
+   static bool resolveGridDimension( const Reader& reader,
+                                     ProblemSetterArgs&&... problemSetterArgs );
+
+   // NOTE: We could disable the grids only by the GridTag, but doing the
+   //       resolution for all subtypes is more flexible and also pretty
+   //       good optimization of compilation times.
+
+   // Overload for disabled grid dimensions
+   template< int MeshDimension,
+             typename = typename std::enable_if< ! BuildConfigTags::GridDimensionTag< ConfigTag, MeshDimension >::enabled >::type,
+             typename = void >
+   static bool resolveReal( const Reader& reader,
+                            ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled grid dimensions
+   template< int MeshDimension,
+             typename = typename std::enable_if< BuildConfigTags::GridDimensionTag< ConfigTag, MeshDimension >::enabled >::type >
+   static bool resolveReal( const Reader& reader,
+                            ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled real types
+   template< int MeshDimension,
+             typename Real,
+             typename = typename std::enable_if< ! BuildConfigTags::GridRealTag< ConfigTag, Real >::enabled >::type,
+             typename = void >
+   static bool resolveIndex( const Reader& reader,
+                             ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled real types
+   template< int MeshDimension,
+             typename Real,
+             typename = typename std::enable_if< BuildConfigTags::GridRealTag< ConfigTag, Real >::enabled >::type >
+   static bool resolveIndex( const Reader& reader,
+                             ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled index types
+   template< int MeshDimension,
+             typename Real,
+             typename Index,
+             typename = typename std::enable_if< ! BuildConfigTags::GridIndexTag< ConfigTag, Index >::enabled >::type,
+             typename = void >
+   static bool resolveGridType( const Reader& reader,
+                                ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled index types
+   template< int MeshDimension,
+             typename Real,
+             typename Index,
+             typename = typename std::enable_if< BuildConfigTags::GridIndexTag< ConfigTag, Index >::enabled >::type >
+   static bool resolveGridType( const Reader& reader,
+                                ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled grid types
+   template< typename GridType,
+             typename = typename std::enable_if< ! BuildConfigTags::GridTag< ConfigTag, GridType >::enabled >::type,
+             typename = void >
+   static bool resolveTerminate( const Reader& reader,
+                                 ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled grid types
+   template< typename GridType,
+             typename = typename std::enable_if< BuildConfigTags::GridTag< ConfigTag, GridType >::enabled >::type >
+   static bool resolveTerminate( const Reader& reader,
+                                 ProblemSetterArgs&&... problemSetterArgs );
+};
+
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/TypeResolver/GridTypeResolver_impl.h>
diff --git a/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..20f40c26820e611b3055879ec96445e13656f802
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/GridTypeResolver_impl.h
@@ -0,0 +1,201 @@
+/***************************************************************************
+                          GridTypeResolver_impl.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <utility>
+
+#include <TNL/String.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/TypeResolver/GridTypeResolver.h>
+
+namespace TNL {
+namespace Meshes {   
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+run( const Reader& reader,
+     ProblemSetterArgs&&... problemSetterArgs )
+{
+   return resolveGridDimension( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveGridDimension( const Reader& reader,
+                      ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getMeshDimension() == 1 )
+      return resolveReal< 1 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getMeshDimension() == 2 )
+      return resolveReal< 2 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getMeshDimension() == 3 )
+      return resolveReal< 3 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported mesh dimension: " << reader.getMeshDimension() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename, typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveReal( const Reader& reader,
+             ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The grid dimension " << MeshDimension << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveReal( const Reader& reader,
+             ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getRealType() == "float" )
+      return resolveIndex< MeshDimension, float >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getRealType() == "double" )
+      return resolveIndex< MeshDimension, double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getRealType() == "long-double" )
+      return resolveIndex< MeshDimension, long double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported real type: " << reader.getRealType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename Real,
+             typename, typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveIndex( const Reader& reader,
+              ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The grid real type " << getType< Real >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename Real,
+             typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveIndex( const Reader& reader,
+              ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getGlobalIndexType() == "short int" )
+      return resolveGridType< MeshDimension, Real, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getGlobalIndexType() == "int" )
+      return resolveGridType< MeshDimension, Real, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getGlobalIndexType() == "long int" )
+      return resolveGridType< MeshDimension, Real, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported index type: " << reader.getRealType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename Real,
+             typename Index,
+             typename, typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveGridType( const Reader& reader,
+                 ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The grid index type " << getType< Index >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< int MeshDimension,
+             typename Real,
+             typename Index,
+             typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveGridType( const Reader& reader,
+                 ProblemSetterArgs&&... problemSetterArgs )
+{
+   using GridType = Meshes::Grid< MeshDimension, Real, Device, Index >;
+   return resolveTerminate< GridType >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename GridType,
+             typename, typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveTerminate( const Reader& reader,
+                  ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh type " << TNL::getType< GridType >() << " is disabled in the build configuration." << std::endl;
+   return false;
+};
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename GridType,
+             typename >
+bool
+GridTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveTerminate( const Reader& reader,
+                  ProblemSetterArgs&&... problemSetterArgs )
+{
+   return ProblemSetter< GridType >::run( std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..dfdb0ad1ed312e8a4841361644f5bdb97ee37dd2
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/MeshTypeResolver.h
@@ -0,0 +1,184 @@
+/***************************************************************************
+                          MeshTypeResolver.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <type_traits>
+
+#include <TNL/Meshes/BuildConfigTags.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+class MeshTypeResolver
+{
+public:
+
+   static bool run( const Reader& reader,
+                    ProblemSetterArgs&&... problemSetterArgs );
+
+protected:
+
+   static bool resolveCellTopology( const Reader& reader,
+                                    ProblemSetterArgs&&... problemSetterArgs );
+
+   // NOTE: We could disable the meshes only by the MeshTag, but doing the
+   //       resolution for all subtypes is more flexible and also pretty
+   //       good optimization of compilation times.
+
+   // Overload for disabled cell topologies
+   template< typename CellTopology,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshCellTopologyTag< ConfigTag, CellTopology >::enabled >::type,
+             typename = void >
+   static bool resolveWorldDimension( const Reader& reader,
+                                      ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled cell topologies
+   template< typename CellTopology,
+             typename = typename std::enable_if< BuildConfigTags::MeshCellTopologyTag< ConfigTag, CellTopology >::enabled >::type >
+   static bool resolveWorldDimension( const Reader& reader,
+                                      ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled world dimensions
+   template< typename CellTopology,
+             int WorldDimension,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled >::type,
+             typename = void >
+   static bool resolveReal( const Reader& reader,
+                            ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled world dimensions
+   template< typename CellTopology,
+             int WorldDimension,
+             typename = typename std::enable_if< BuildConfigTags::MeshWorldDimensionTag< ConfigTag, CellTopology, WorldDimension >::enabled >::type >
+   static bool resolveReal( const Reader& reader,
+                            ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled real types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshRealTag< ConfigTag, Real >::enabled >::type,
+             typename = void >
+   static bool resolveGlobalIndex( const Reader& reader,
+                                   ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled real types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename = typename std::enable_if< BuildConfigTags::MeshRealTag< ConfigTag, Real >::enabled >::type >
+   static bool resolveGlobalIndex( const Reader& reader,
+                                   ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled global index types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled >::type,
+             typename = void >
+   static bool resolveLocalIndex( const Reader& reader,
+                                  ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled global index types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename = typename std::enable_if< BuildConfigTags::MeshGlobalIndexTag< ConfigTag, GlobalIndex >::enabled >::type >
+   static bool resolveLocalIndex( const Reader& reader,
+                                  ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled local index types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled >::type,
+             typename = void >
+   static bool resolveId( const Reader& reader,
+                          ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled local index types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename = typename std::enable_if< BuildConfigTags::MeshLocalIndexTag< ConfigTag, LocalIndex >::enabled >::type >
+   static bool resolveId( const Reader& reader,
+                          ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled id types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename Id,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled >::type,
+             typename = void >
+   static bool resolveMeshType( const Reader& reader,
+                                ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled id types
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename Id,
+             typename = typename std::enable_if< BuildConfigTags::MeshIdTag< ConfigTag, GlobalIndex, Id >::enabled >::type >
+   static bool resolveMeshType( const Reader& reader,
+                                ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for disabled mesh types
+   template< typename MeshConfig,
+             typename = typename std::enable_if< ! BuildConfigTags::MeshDeviceTag< ConfigTag, Device >::enabled ||
+                                                 ! BuildConfigTags::MeshTag< ConfigTag,
+                                                                             Device,
+                                                                             typename MeshConfig::CellTopology,
+                                                                             MeshConfig::worldDimension,
+                                                                             typename MeshConfig::RealType,
+                                                                             typename MeshConfig::GlobalIndexType,
+                                                                             typename MeshConfig::LocalIndexType,
+                                                                             typename MeshConfig::IdType
+                                                                           >::enabled >::type,
+             typename = void >
+   static bool resolveTerminate( const Reader& reader,
+                                 ProblemSetterArgs&&... problemSetterArgs );
+
+   // Overload for enabled mesh types
+   template< typename MeshConfig,
+             typename = typename std::enable_if< BuildConfigTags::MeshDeviceTag< ConfigTag, Device >::enabled &&
+                                                 BuildConfigTags::MeshTag< ConfigTag,
+                                                                             Device,
+                                                                             typename MeshConfig::CellTopology,
+                                                                             MeshConfig::worldDimension,
+                                                                             typename MeshConfig::RealType,
+                                                                             typename MeshConfig::GlobalIndexType,
+                                                                             typename MeshConfig::LocalIndexType,
+                                                                             typename MeshConfig::IdType
+                                                                           >::enabled >::type >
+   static bool resolveTerminate( const Reader& reader,
+                                 ProblemSetterArgs&&... problemSetterArgs );
+};
+
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h>
diff --git a/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..46c4e9c58f30f3d7abf9c04de6071d64f5e34977
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/MeshTypeResolver_impl.h
@@ -0,0 +1,358 @@
+/***************************************************************************
+                          MeshTypeResolver_impl.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <utility>
+
+#include <TNL/String.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/TypeResolver/MeshTypeResolver.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
+
+namespace TNL {
+namespace Meshes {
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+run( const Reader& reader,
+     ProblemSetterArgs&&... problemSetterArgs )
+{
+   return resolveCellTopology( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveCellTopology( const Reader& reader,
+                     ProblemSetterArgs&&... problemSetterArgs )
+{
+   using Readers::EntityShape;
+   switch( reader.getCellShape() )
+   {
+      case EntityShape::Line:
+         return resolveWorldDimension< Topologies::Edge >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case EntityShape::Triangle:
+         return resolveWorldDimension< Topologies::Triangle >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case EntityShape::Quad:
+         return resolveWorldDimension< Topologies::Quadrilateral >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case EntityShape::Tetra:
+         return resolveWorldDimension< Topologies::Tetrahedron >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case EntityShape::Hexahedron:
+         return resolveWorldDimension< Topologies::Hexahedron >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      default:
+         std::cerr << "unsupported cell topology: " << reader.getCellShape() << std::endl;
+         return false;
+   }
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveWorldDimension( const Reader& reader,
+                       ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The cell topology " << CellTopology::getType() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveWorldDimension( const Reader& reader,
+                       ProblemSetterArgs&&... problemSetterArgs )
+{
+   switch( reader.getWorldDimension() )
+   {
+      case 1:
+         return resolveReal< CellTopology, 1 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case 2:
+         return resolveReal< CellTopology, 2 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      case 3:
+         return resolveReal< CellTopology, 3 >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      default:
+         std::cerr << "unsupported world dimension: " << reader.getWorldDimension() << std::endl;
+         return false;
+   }
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveReal( const Reader& reader,
+             ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The combination of world dimension (" << WorldDimension
+             << ") and mesh dimension (" << CellTopology::dimension
+             << ") is either invalid or disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveReal( const Reader& reader,
+             ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getRealType() == "float" )
+      return resolveGlobalIndex< CellTopology, WorldDimension, float >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getRealType() == "double" )
+      return resolveGlobalIndex< CellTopology, WorldDimension, double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getRealType() == "long-double" )
+      return resolveGlobalIndex< CellTopology, WorldDimension, long double >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported real type: " << reader.getRealType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveGlobalIndex( const Reader& reader,
+                    ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh real type " << getType< Real >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveGlobalIndex( const Reader& reader,
+                    ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getGlobalIndexType() == "short int" )
+      return resolveLocalIndex< CellTopology, WorldDimension, Real, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getGlobalIndexType() == "int" )
+      return resolveLocalIndex< CellTopology, WorldDimension, Real, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getGlobalIndexType() == "long int" )
+      return resolveLocalIndex< CellTopology, WorldDimension, Real, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported global index type: " << reader.getGlobalIndexType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveLocalIndex( const Reader& reader,
+                   ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh global index type " << getType< GlobalIndex >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveLocalIndex( const Reader& reader,
+                   ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getLocalIndexType() == "short int" )
+      return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getLocalIndexType() == "int" )
+      return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getLocalIndexType() == "long int" )
+      return resolveId< CellTopology, WorldDimension, Real, GlobalIndex, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported local index type: " << reader.getLocalIndexType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveId( const Reader& reader,
+           ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh local index type " << getType< LocalIndex >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveId( const Reader& reader,
+           ProblemSetterArgs&&... problemSetterArgs )
+{
+   if( reader.getIdType() == "short int" )
+      return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, short int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getIdType() == "int" )
+      return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getIdType() == "long int" )
+      return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, long int >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   if( reader.getIdType() == "void" )
+      return resolveMeshType< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, void >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+   std::cerr << "Unsupported id type: " << reader.getIdType() << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename Id,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveMeshType( const Reader& reader,
+                 ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh id type " << getType< Id >() << " is disabled in the build configuration." << std::endl;
+   return false;
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename CellTopology,
+             int WorldDimension,
+             typename Real,
+             typename GlobalIndex,
+             typename LocalIndex,
+             typename Id,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveMeshType( const Reader& reader,
+                 ProblemSetterArgs&&... problemSetterArgs )
+{
+   using MeshConfig = typename BuildConfigTags::MeshConfigTemplateTag< ConfigTag >::template MeshConfig< CellTopology, WorldDimension, Real, GlobalIndex, LocalIndex, Id >;
+   return resolveTerminate< MeshConfig >( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+}
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename MeshConfig,
+             typename, typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveTerminate( const Reader& reader,
+                  ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cerr << "The mesh config type " << TNL::getType< MeshConfig >() << " is disabled in the build configuration for device " << Device::getDeviceType() << "." << std::endl;
+   return false;
+};
+
+template< typename Reader,
+          typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+   template< typename MeshConfig,
+             typename >
+bool
+MeshTypeResolver< Reader, ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+resolveTerminate( const Reader& reader,
+                  ProblemSetterArgs&&... problemSetterArgs )
+{
+   using MeshType = Meshes::Mesh< MeshConfig, Device >;
+   return ProblemSetter< MeshType >::run( std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+};
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver.h b/src/TNL/Meshes/TypeResolver/TypeResolver.h
new file mode 100644
index 0000000000000000000000000000000000000000..a04391af61acc23c1bdc43a12ac3243dbe4b9c25
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/TypeResolver.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+                          MeshResolver.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/String.h>
+
+namespace TNL {
+namespace Meshes {
+
+/*
+ * This function does the following (in pseudo-code):
+ *
+ *    using MeshType = [black magic]
+ *    return ProblemSetter< MeshType >::run( problemSetterArgs... );
+ */
+template< typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool resolveMeshType( const String& fileName,
+                      ProblemSetterArgs&&... problemSetterArgs );
+
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/TypeResolver/TypeResolver_impl.h>
diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..82767a0f02e2862eba1bf0c0849d3367e5806ace
--- /dev/null
+++ b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
@@ -0,0 +1,175 @@
+/***************************************************************************
+                          MeshResolver_impl.h  -  description
+                             -------------------
+    begin                : Nov 22, 2016
+    copyright            : (C) 2016 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <string>
+#include <utility>
+
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+#include <TNL/Meshes/Readers/TNLReader.h>
+#include <TNL/Meshes/Readers/NetgenReader.h>
+#include <TNL/Meshes/Readers/VTKReader.h>
+#include <TNL/Meshes/TypeResolver/GridTypeResolver.h>
+#include <TNL/Meshes/TypeResolver/MeshTypeResolver.h>
+
+// TODO: implement this in TNL::String
+inline bool ends_with( const std::string& value, const std::string& ending )
+{
+   if (ending.size() > value.size())
+      return false;
+   return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
+namespace TNL {
+namespace Meshes {
+
+/*
+ * TODO:
+ * The variadic template parameter pack ProblemSetterArgs will not be necessary
+ * in C++14 as it will be possible to use generic lambda functions to pass
+ * parameters to the ProblemSetter:
+ *
+ *    // wrapper for MeshTypeResolver
+ *    template< typename MeshType >
+ *    using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >;
+ *
+ *    bool run( const Config::ParameterContainer& parameters )
+ *    {
+ *       const String& meshFileName = parameters.getParameter< String >( "mesh" );
+ *       auto wrapper = []( auto&& mesh ) {
+ *           return ProblemSetterWrapper< decltype(mesh) >::run( parameters );
+ *       };
+ *       return MeshTypeResolver< ConfigTag, Device, wrapper >::run( meshFileName );
+ *    }
+ */
+template< typename ConfigTag,
+          typename Device,
+          template< typename MeshType > class ProblemSetter,
+          typename... ProblemSetterArgs >
+bool resolveMeshType( const String& fileName_,
+                      ProblemSetterArgs&&... problemSetterArgs )
+{
+   std::cout << "Detecting mesh from file " << fileName_ << " ..." << std::endl;
+   std::string fileName( fileName_.getString() );
+   if( ends_with( fileName, ".tnl" ) ) {
+      Readers::TNLReader reader;
+      if( ! reader.detectMesh( fileName_ ) )
+         return false;
+      if( reader.getMeshType() == "Meshes::Grid" )
+         return GridTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+            run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      else if( reader.getMeshType() == "Meshes::Mesh" )
+         return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+            run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      else {
+         std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the TNL reader." << std::endl;
+         return false;
+      }
+   }
+   else if( ends_with( fileName, ".ng" ) ) {
+      // FIXME: The Netgen files don't store the real, global index, local index and id types.
+      // The reader has some defaults, but they might be disabled by the BuildConfigTags - in
+      // this case we should use the first enabled type.
+      Readers::NetgenReader reader;
+      if( ! reader.detectMesh( fileName_ ) )
+         return false;
+      if( reader.getMeshType() == "Meshes::Mesh" )
+         return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+            run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      else {
+         std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the Netgen reader." << std::endl;
+         return false;
+      }
+   }
+   else if( ends_with( fileName, ".vtk" ) ) {
+      // FIXME: The VTK files don't store the global index, local index and id types.
+      // The reader has some defaults, but they might be disabled by the BuildConfigTags - in
+      // this case we should use the first enabled type.
+      Readers::VTKReader reader;
+      if( ! reader.detectMesh( fileName_ ) )
+         return false;
+      if( reader.getMeshType() == "Meshes::Mesh" )
+         return MeshTypeResolver< decltype(reader), ConfigTag, Device, ProblemSetter, ProblemSetterArgs... >::
+            run( reader, std::forward<ProblemSetterArgs>(problemSetterArgs)... );
+      else {
+         std::cerr << "The mesh type " << reader.getMeshType() << " is not supported in the VTK reader." << std::endl;
+         return false;
+      }
+   }
+   else {
+      std::cerr << "File '" << fileName << "' has unknown extension. Supported extensions are '.tnl', '.vtk' and '.ng'." << std::endl;
+      return false;
+   }
+}
+
+// TODO: reorganize
+template< typename MeshConfig, typename Device >
+bool
+loadMesh( const String& fileName_, Mesh< MeshConfig, Device >& mesh )
+{
+   std::cout << "Loading mesh from file " << fileName_ << " ..." << std::endl;
+   std::string fileName( fileName_.getString() );
+   bool status = true;
+
+   if( ends_with( fileName, ".tnl" ) )
+      status = mesh.load( fileName_ );
+   else if( ends_with( fileName, ".ng" ) ) {
+      Readers::NetgenReader reader;
+      status = reader.readMesh( fileName_, mesh );
+   }
+   else if( ends_with( fileName, ".vtk" ) ) {
+      Readers::VTKReader reader;
+      status = reader.readMesh( fileName_, mesh );
+   }
+   else {
+      std::cerr << "File '" << fileName << "' has unknown extension. Supported extensions are '.tnl', '.vtk' and '.ng'." << std::endl;
+      return false;
+   }
+
+   if( ! status )
+   {
+      std::cerr << "I am not able to load the mesh from the file " << fileName_ << ". "
+                   "Perhaps the mesh stored in the file is not supported by the mesh "
+                   "passed to the loadMesh function? The mesh type is "
+                << mesh.getType() << std::endl;
+      return false;
+   }
+   return true;
+}
+
+template< typename MeshConfig >
+bool
+loadMesh( const String& fileName, Mesh< MeshConfig, Devices::Cuda >& mesh )
+{
+   Mesh< MeshConfig, Devices::Host > hostMesh;
+   if( ! loadMesh( fileName, hostMesh ) )
+      return false;
+   mesh = hostMesh;
+   return true;
+}
+
+template< int Dimension, typename Real, typename Device, typename Index >
+bool
+loadMesh( const String& fileName, Grid< Dimension, Real, Device, Index >& mesh )
+{
+   std::cout << "Loading mesh from file " << fileName << " ..." << std::endl;
+   if( ! mesh.load( fileName ) )
+   {
+      std::cerr << "I am not able to load the grid from the file " << fileName << ". "
+                   "You may create it with tools like tnl-grid-setup."
+                << std::endl;
+      return false;
+   }
+   return true;
+}
+
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/AsymptoteWriter.h b/src/TNL/Meshes/Writers/AsymptoteWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..96d138b9678ef9d884551ae9e1d1859d0c48a7b1
--- /dev/null
+++ b/src/TNL/Meshes/Writers/AsymptoteWriter.h
@@ -0,0 +1,163 @@
+/***************************************************************************
+                          AsymptoteWriter.h  -  description
+                             -------------------
+    begin                : Oct 22, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+
+template< typename Mesh >
+class AsymptoteWriter
+{
+   static_assert( Mesh::getMeshDimension() <= 3, "The Asymptote format supports only 1D, 2D and 3D meshes." );
+
+public:
+   static void writeAllEntities( const Mesh& mesh, std::ostream& str )
+   {
+      throw "not implemented";
+   }
+
+   template< int EntityDimension = Mesh::getMeshDimension() >
+   static void writeEntities( const Mesh& mesh, std::ostream& str )
+   {
+      throw "not implemented";
+   }
+};
+
+template< typename Real, typename Device, typename Index >
+class AsymptoteWriter< Grid< 2, Real, Device, Index > >
+{
+   using Mesh = Grid< 2, Real, Device, Index >;
+   using CoordinatesType = typename Mesh::CoordinatesType;
+   using PointType = typename Mesh::PointType;
+
+public:
+   static void writeAllEntities( const Mesh& mesh, std::ostream& str )
+   {
+      str << "size( "
+          << mesh.getProportions(). x() << "cm , "
+          << mesh.getProportions(). y() << "cm );"
+          << std::endl << std::endl;
+      typename Mesh::Vertex vertex( mesh );
+      CoordinatesType& vertexCoordinates = vertex.getCoordinates();
+      PointType v;
+      for( Index j = 0; j < mesh.dimensions. y(); j ++ )
+      {
+         str << "draw( ";
+         vertexCoordinates.x() = 0;
+         vertexCoordinates.y() = j;
+         v = vertex.getCenter();
+         str << "( " << v. x() << ", " << v. y() << " )";
+         for( Index i = 0; i < mesh.dimensions. x(); i ++ )
+         {
+            vertexCoordinates.x() = i + 1;
+            vertexCoordinates.y() = j;
+            v = vertex.getCenter();
+            str << "--( " << v. x() << ", " << v. y() << " )";
+         }
+         str << " );" << std::endl;
+      }
+      str << std::endl;
+      for( Index i = 0; i < mesh.dimensions. x(); i ++ )
+      {
+         str << "draw( ";
+         vertexCoordinates.x() = i;
+         vertexCoordinates.y() = 0;
+         v = vertex.getCenter();
+         str << "( " << v. x() << ", " << v. y() << " )";
+         for( Index j = 0; j < mesh.dimensions. y(); j ++ )
+         {
+            vertexCoordinates.x() = i;
+            vertexCoordinates.y() = j + 1;
+            v = vertex.getCenter();
+            str << "--( " << v. x() << ", " << v. y() << " )";
+         }
+         str << " );" << std::endl;
+      }
+      str << std::endl;
+
+      typename Mesh::Cell cell( mesh );
+      CoordinatesType& cellCoordinates = cell.getCoordinates();
+      const Real cellMeasure = mesh.getSpaceSteps().x() * mesh.getSpaceSteps().y();
+      for( Index i = 0; i < mesh.dimensions. x(); i ++ )
+         for( Index j = 0; j < mesh.dimensions. y(); j ++ )
+         {
+            cellCoordinates.x() = i;
+            cellCoordinates.y() = j;
+            v = vertex.getCenter();
+            str << "label( scale(0.33) * Label( \"$" << std::setprecision( 3 ) << cellMeasure << std::setprecision( 8 )
+                << "$\" ), ( " << v. x() << ", " << v. y() << " ), S );" << std::endl;
+         }
+
+      for( Index i = 0; i < mesh.dimensions. x(); i ++ )
+         for( Index j = 0; j < mesh.dimensions. y(); j ++ )
+         {
+            PointType v1, v2, c;
+
+            /****
+             * East edge normal
+             */
+            /*v1 = mesh.getPoint( CoordinatesType( i + 1, j ), v1 );
+            v2 = mesh.getPoint( CoordinatesType( i + 1, j + 1 ), v2 );
+            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
+            mesh.getEdgeNormal< 1, 0 >( CoordinatesType( i, j ), v );
+            v *= 0.5;
+            str << "draw( ( " << c. x() << ", " << c. y() << " )--( "
+                << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl;
+            */
+            /****
+             * West edge normal
+             */
+            /*mesh.getPoint< -1, -1 >( CoordinatesType( i, j ), v1 );
+            mesh.getPoint< -1, 1 >( CoordinatesType( i, j ), v2 );
+            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
+            mesh.getEdgeNormal< -1, 0 >( CoordinatesType( i, j ), v );
+            v *= 0.5;
+            str << "draw( ( " << c. x() << ", " << c. y() << " )--( "
+                << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl;
+            */
+            /****
+             * North edge normal
+             */
+            /*mesh.getPoint< 1, 1 >( CoordinatesType( i, j ), v1 );
+            mesh.getPoint< -1, 1 >( CoordinatesType( i, j ), v2 );
+            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
+            mesh.getEdgeNormal< 0, 1 >( CoordinatesType( i, j ), v );
+            v *= 0.5;
+            str << "draw( ( " << c. x() << ", " << c. y() << " )--( "
+                << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=green);" << std::endl;
+            */
+            /****
+             * South edge normal
+             */
+            /*mesh.getPoint< 1, -1 >( CoordinatesType( i, j ), v1 );
+            mesh.getPoint< -1, -1 >( CoordinatesType( i, j ), v2 );
+            c = ( ( Real ) 0.5 ) * ( v1 + v2 );
+            mesh.getEdgeNormal< 0, -1 >( CoordinatesType( i, j ), v );
+            v *= 0.5;
+            str << "draw( ( " << c. x() << ", " << c. y() << " )--( "
+                << c. x() + v. x() << ", " << c.y() + v. y() << " ), Arrow(size=1mm),p=blue);" << std::endl;
+            */
+         }
+   }
+
+   template< int EntityDimension = Mesh::getMeshDimension() >
+   static void writeEntities( const Mesh& mesh, std::ostream& str )
+   {
+      throw "not implemented";
+   }
+};
+
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/CMakeLists.txt b/src/TNL/Meshes/Writers/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b06a95b0cf7aea43bd9e4d1b3b8fe1d1aded0385
--- /dev/null
+++ b/src/TNL/Meshes/Writers/CMakeLists.txt
@@ -0,0 +1,7 @@
+SET( headers AsymptoteWriter.h
+             NetgenWriter.h
+             VTKWriter.h
+             VTKWriter_impl.h
+)
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/Writers )
diff --git a/src/TNL/Meshes/Writers/NetgenWriter.h b/src/TNL/Meshes/Writers/NetgenWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a3a86f9230ba317505c71d850ed8c86cef87267
--- /dev/null
+++ b/src/TNL/Meshes/Writers/NetgenWriter.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+                          MeshWriterNetgen.h  -  description
+                             -------------------
+    begin                : Feb 22, 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 <ostream>
+#include <iomanip>
+
+#include <TNL/String.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+
+template< typename Mesh >
+class NetgenWriter
+{
+   using GlobalIndexType = typename Mesh::GlobalIndexType;
+   using PointType = typename Mesh::PointType;
+   using Cell = typename Mesh::Cell;
+   static constexpr int meshDimension = Mesh::getMeshDimension();
+
+public:
+   static void writeMesh( const Mesh& mesh, std::ostream& str )
+   {
+      str << std::setprecision( 6 );
+      str << std::fixed;
+
+      const GlobalIndexType numberOfVertices = mesh.template getEntitiesCount< typename Mesh::Vertex >();
+      str << numberOfVertices << std::endl;
+      for( GlobalIndexType i = 0; i < numberOfVertices; i++ )
+      {
+         const PointType& point = mesh.template getEntity< typename Mesh::Vertex >( i ).getPoint();
+         str << " ";
+         for( int d = 0; d < meshDimension; d++ )
+            str << " " << point[ d ];
+         str << std::endl;
+      }
+
+      const GlobalIndexType numberOfCells = mesh.template getEntitiesCount< typename Mesh::Cell >();
+      str << numberOfCells << std::endl;
+      for( GlobalIndexType cellIdx = 0; cellIdx < numberOfCells; cellIdx++ )
+      {
+         const Cell& cell = mesh.template getEntity< typename Mesh::Cell >( cellIdx );
+         str << "   1";
+         for( int cellVertexIdx = 0;
+              cellVertexIdx < meshDimension + 1;
+              cellVertexIdx++ )
+            str << " " << cell.getVertexIndex( cellVertexIdx );
+         str << "\n";
+      }
+   }
+};
+
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/Writers/VTKWriter.h b/src/TNL/Meshes/Writers/VTKWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..4d5ad00e82b259c68849847dd9219d1e2d637588
--- /dev/null
+++ b/src/TNL/Meshes/Writers/VTKWriter.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+                          VTKWriter.h  -  description
+                             -------------------
+    begin                : Mar 04, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <limits>
+
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Mesh.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+
+namespace __impl {
+
+template< typename Mesh, int EntityDimension > struct MeshEntitiesVTKWriter;
+template< typename Mesh, int EntityDimension > struct MeshEntityTypesVTKWriter;
+
+} // namespace __impl
+
+template< typename Mesh >
+class VTKWriter
+{
+   static_assert( Mesh::getMeshDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." );
+   // TODO: check also world dimension when grids allow it
+//   static_assert( Mesh::getWorldDimension() <= 3, "The VTK format supports only 1D, 2D and 3D meshes." );
+
+   template< int EntityDimension >
+   using EntitiesWriter = __impl::MeshEntitiesVTKWriter< Mesh, EntityDimension >;
+
+   template< int EntityDimension >
+   using EntityTypesWriter = __impl::MeshEntityTypesVTKWriter< Mesh, EntityDimension >;
+
+public:
+   using Index = typename Mesh::GlobalIndexType;
+
+   static void writeAllEntities( const Mesh& mesh, std::ostream& str );
+
+   template< int EntityDimension = Mesh::getMeshDimension() >
+   static void writeEntities( const Mesh& mesh, std::ostream& str );
+
+protected:
+   static void writeHeader( const Mesh& mesh, std::ostream& str );
+
+   static void writePoints( const Mesh& mesh, std::ostream& str );
+};
+
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/Writers/VTKWriter_impl.h>
diff --git a/src/TNL/Meshes/Writers/VTKWriter_impl.h b/src/TNL/Meshes/Writers/VTKWriter_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..456429a5a083c58428e5c45b89015d5261e58826
--- /dev/null
+++ b/src/TNL/Meshes/Writers/VTKWriter_impl.h
@@ -0,0 +1,475 @@
+/***************************************************************************
+                          VTKWriter.h  -  description
+                             -------------------
+    begin                : Mar 04, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Writers/VTKWriter.h>
+#include <TNL/Meshes/Readers/EntityShape.h>
+
+namespace TNL {
+namespace Meshes {
+namespace Writers {
+
+namespace __impl {
+
+template< typename Entity >
+struct VerticesPerEntity
+{
+   static constexpr int count = Entity::getVerticesCount();
+};
+
+template< typename MeshConfig, typename Device >
+struct VerticesPerEntity< MeshEntity< MeshConfig, Device, Topologies::Vertex > >
+{
+   static constexpr int count = 1;
+};
+
+template< typename Grid, typename Config >
+struct VerticesPerEntity< GridEntity< Grid, 0, Config > >
+{
+   static constexpr int count = 1;
+};
+
+template< typename Grid, typename Config >
+struct VerticesPerEntity< GridEntity< Grid, 1, Config > >
+{
+   static constexpr int count = 2;
+};
+
+template< typename Grid, typename Config >
+struct VerticesPerEntity< GridEntity< Grid, 2, Config > >
+{
+   static constexpr int count = 4;
+};
+
+template< typename Grid, typename Config >
+struct VerticesPerEntity< GridEntity< Grid, 3, Config > >
+{
+   static constexpr int count = 8;
+};
+
+
+template< typename GridEntity >
+struct GridEntityShape {};
+
+template< typename Grid, typename Config >
+struct GridEntityShape< GridEntity< Grid, 0, Config > >
+{
+   static constexpr Readers::EntityShape shape = Readers::EntityShape::Vertex;
+};
+
+template< typename Grid, typename Config >
+struct GridEntityShape< GridEntity< Grid, 1, Config > >
+{
+   static constexpr Readers::EntityShape shape = Readers::EntityShape::Line;
+};
+
+template< typename Grid, typename Config >
+struct GridEntityShape< GridEntity< Grid, 2, Config > >
+{
+   static constexpr Readers::EntityShape shape = Readers::EntityShape::Pixel;
+};
+
+template< typename Grid, typename Config >
+struct GridEntityShape< GridEntity< Grid, 3, Config > >
+{
+   static constexpr Readers::EntityShape shape = Readers::EntityShape::Voxel;
+};
+
+
+template< typename Mesh >
+typename Mesh::GlobalIndexType
+getAllMeshEntitiesCount( const Mesh& mesh, DimensionTag< 0 > )
+{
+   using EntityType = typename Mesh::template EntityType< 0 >;
+   return mesh.template getEntitiesCount< EntityType >();
+}
+
+// TODO: specialization for disabled entities
+template< typename Mesh,
+          typename DimensionTag = Meshes::DimensionTag< Mesh::getMeshDimension() > >
+typename Mesh::GlobalIndexType
+getAllMeshEntitiesCount( const Mesh& mesh, DimensionTag = DimensionTag() )
+{
+   using EntityType = typename Mesh::template EntityType< DimensionTag::value >;
+   return mesh.template getEntitiesCount< EntityType >() +
+          getAllMeshEntitiesCount( mesh, typename DimensionTag::Decrement() );
+}
+
+
+template< typename Mesh >
+typename Mesh::GlobalIndexType
+getCellsListSize( const Mesh& mesh, DimensionTag< 0 > )
+{
+   using EntityType = typename Mesh::template EntityType< 0 >;
+   return mesh.template getEntitiesCount< EntityType >() * 2;
+}
+
+// TODO: specialization for disabled entities
+template< typename Mesh,
+          typename DimensionTag = Meshes::DimensionTag< Mesh::getMeshDimension() > >
+typename Mesh::GlobalIndexType
+getCellsListSize( const Mesh& mesh, DimensionTag = DimensionTag() )
+{
+   using EntityType = typename Mesh::template EntityType< DimensionTag::value >;
+   const auto verticesPerEntity = VerticesPerEntity< EntityType >::count;
+   return ( mesh.template getEntitiesCount< EntityType >() * ( verticesPerEntity + 1 ) ) +
+          getCellsListSize( mesh, typename DimensionTag::Decrement() );
+}
+
+
+// TODO: specialization for disabled entities
+// Unstructured meshes, entities
+template< typename Mesh, int EntityDimension >
+struct MeshEntitiesVTKWriter
+{
+   static void exec( const Mesh& mesh, std::ostream& str )
+   {
+      using EntityType = typename Mesh::template EntityType< EntityDimension >;
+      using Index = typename Mesh::GlobalIndexType;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      const Index verticesPerEntity = VerticesPerEntity< EntityType >::count;;
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         const auto& entity = mesh.template getEntity< EntityType >( i );
+         str << verticesPerEntity;
+         for( Index j = 0; j < verticesPerEntity; j++ )
+            str << " " << entity.template getSubentityIndex< 0 >( j );
+         str << "\n";
+      }
+   }
+};
+
+// Unstructured meshes, vertices
+template< typename Mesh >
+struct MeshEntitiesVTKWriter< Mesh, 0 >
+{
+   static void exec( const Mesh& mesh, std::ostream& str )
+   {
+      using EntityType = typename Mesh::template EntityType< 0 >;
+      using Index = typename Mesh::GlobalIndexType;
+
+      const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+      const Index verticesPerEntity = 1;
+      for( Index i = 0; i < entitiesCount; i++ ) {
+         str << verticesPerEntity << " " << i << "\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 )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+         str << "2 " << i << " " << i+1 << "\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 )
+   {
+      for( MeshIndex i = 0; i < mesh.getDimensions().x() + 1; i++ )
+         str << "1 " << i << "\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 )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+         for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+            str << "4 " << j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                        << j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                        << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
+                        << (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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 )
+   {
+      for( MeshIndex j = 0; j < mesh.getDimensions().y(); j++ )
+         for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+            str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                        << (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\n";
+
+      for( MeshIndex j = 0; j < (mesh.getDimensions().y()+1); j++ )
+         for( MeshIndex i = 0; i < mesh.getDimensions().x(); i++ )
+            str << "2 " << j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                        << j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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 )
+   {
+      for( MeshIndex j = 0; j < ( mesh.getDimensions().y() + 1 ); j++ )
+         for( MeshIndex i = 0; i < ( mesh.getDimensions().x() + 1 ); i++ )
+            str << "1 " << j * mesh.getDimensions().x() + i << "\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 )
+   {
+      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++ )
+               str << "8 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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 )
+   {
+      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++ )
+               str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\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++ )
+               str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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++ )
+               str << "4 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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 )
+   {
+      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++ )
+               str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i + 1 << "\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++ )
+               str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + (j+1) * ( mesh.getDimensions().x() + 1 ) + i << "\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++ )
+               str << "2 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << " "
+                           << (k+1) * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i << "\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 )
+   {
+      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++ )
+               str << "1 " << k * ( mesh.getDimensions().y() + 1 ) * ( mesh.getDimensions().x() + 1 ) + j * ( mesh.getDimensions().x() + 1 ) + i  << "\n";
+   }
+};
+
+
+// TODO: specialization for disabled entities
+template< typename Mesh, int EntityDimension >
+struct MeshEntityTypesVTKWriter
+{
+   static void exec( const Mesh& mesh, std::ostream& str )
+   {
+      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) Meshes::Readers::TopologyToEntityShape< typename EntityType::EntityTopology >::shape;
+         str << type << "\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 )
+   {
+      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) __impl::GridEntityShape< EntityType >::shape;
+         str << type << "\n";
+      }
+   }
+};
+
+} // namespace __impl
+
+template< typename Mesh >
+void
+VTKWriter< Mesh >::writeAllEntities( const Mesh& mesh, std::ostream& str )
+{
+   writeHeader( mesh, str );
+   writePoints( mesh, str );
+
+   const Index allEntitiesCount = __impl::getAllMeshEntitiesCount( mesh );
+   const Index cellsListSize = __impl::getCellsListSize( mesh );
+
+   str << std::endl << "CELLS " << allEntitiesCount << " " << cellsListSize << std::endl;
+   StaticFor< int, 0, Mesh::getMeshDimension() + 1, EntitiesWriter >::exec( mesh, str );
+
+   str << std::endl << "CELL_TYPES " << allEntitiesCount << std::endl;
+   StaticFor< int, 0, Mesh::getMeshDimension() + 1, EntityTypesWriter >::exec( mesh, str );
+}
+
+template< typename Mesh >
+   template< int EntityDimension >
+void
+VTKWriter< Mesh >::writeEntities( const Mesh& mesh, std::ostream& str )
+{
+   writeHeader( mesh, str );
+   writePoints( mesh, str );
+
+   using EntityType = typename Mesh::template EntityType< EntityDimension >;
+   const Index entitiesCount = mesh.template getEntitiesCount< EntityType >();
+   const Index verticesPerEntity = __impl::VerticesPerEntity< EntityType >::count;
+   const Index cellsListSize = entitiesCount * ( verticesPerEntity + 1 );
+
+   str << std::endl << "CELLS " << entitiesCount << " " << cellsListSize << std::endl;
+   EntitiesWriter< EntityDimension >::exec( mesh, str );
+
+   str << std::endl << "CELL_TYPES " << entitiesCount << std::endl;
+   EntityTypesWriter< EntityDimension >::exec( mesh, str );
+}
+
+template< typename Mesh >
+void
+VTKWriter< Mesh >::writeHeader( const Mesh& mesh, std::ostream& str )
+{
+    str << "# vtk DataFile Version 2.0\n"
+        << "TNL DATA\n"
+        << "ASCII\n"
+        << "DATASET UNSTRUCTURED_GRID\n";
+}
+
+template< typename Mesh >
+void
+VTKWriter< Mesh >::writePoints( const Mesh& mesh, std::ostream& str )
+{
+   const Index verticesCount = mesh.template getEntitiesCount< typename Mesh::Vertex >();
+
+   str << "POINTS " << verticesCount << " " << getType< typename Mesh::RealType >() << std::endl;
+   str.precision( std::numeric_limits< typename Mesh::RealType >::digits10 );
+
+   for( Index i = 0; i < verticesCount; i++ ) {
+      const auto& vertex = mesh.template getEntity< typename Mesh::Vertex >( i );
+      const auto& point = vertex.getPoint();
+      for( Index j = 0; j < point.size; j++ ) {
+         str << point[ j ];
+         if( j < point.size - 1 )
+            str << " ";
+      }
+      // VTK needs zeros for unused dimensions
+      for( Index j = 0; j < 3 - point.size; j++ )
+         str << " 0";
+      str << "\n";
+   }
+}
+
+} // namespace Writers
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Operators/Advection/LaxFridrichs.h b/src/TNL/Operators/Advection/LaxFridrichs.h
index 9dff03402a5bfef768e8ca608bd8dbbd10a38998..5bd51aa72efcaf9b9203f3f54894c9479282ce5f 100644
--- a/src/TNL/Operators/Advection/LaxFridrichs.h
+++ b/src/TNL/Operators/Advection/LaxFridrichs.h
@@ -31,14 +31,14 @@ class LaxFridrichs< Meshes::Grid< 1, MeshReal, Device, MeshIndex >, Real, Index,
       
       typedef Meshes::Grid< 1, MeshReal, Device, MeshIndex > MeshType;
       typedef SharedPointer< MeshType > MeshPointer;
-      static const int Dimensions = MeshType::getMeshDimension();
+      static const int Dimension = MeshType::getMeshDimension();
       typedef typename MeshType::CoordinatesType CoordinatesType;
       typedef Real RealType;
       typedef Device DeviceType;
       typedef Index IndexType;
       typedef Functions::MeshFunction< MeshType > MeshFunctionType;
       typedef VelocityFunction VelocityFunctionType;
-      typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType;
+      typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType;
       typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer;
       
       static void configSetup( Config::ConfigDescription& config,
@@ -123,14 +123,14 @@ class LaxFridrichs< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, Real, Index,
       
       typedef Meshes::Grid< 2, MeshReal, Device, MeshIndex > MeshType;
       typedef SharedPointer< MeshType > MeshPointer;
-      static const int Dimensions = MeshType::getMeshDimension();
+      static const int Dimension = MeshType::getMeshDimension();
       typedef typename MeshType::CoordinatesType CoordinatesType;
       typedef Real RealType;
       typedef Device DeviceType;
       typedef Index IndexType;
       typedef Functions::MeshFunction< MeshType > MeshFunctionType;
       typedef VelocityFunction VelocityFunctionType;
-      typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType;
+      typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType;
       typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer;
       
       static void configSetup( Config::ConfigDescription& config,
@@ -221,14 +221,14 @@ class LaxFridrichs< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, Real, Index,
       
       typedef Meshes::Grid< 3, MeshReal, Device, MeshIndex > MeshType;
       typedef SharedPointer< MeshType > MeshPointer;
-      static const int Dimensions = MeshType::getMeshDimension();
+      static const int Dimension = MeshType::getMeshDimension();
       typedef typename MeshType::CoordinatesType CoordinatesType;
       typedef Real RealType;
       typedef Device DeviceType;
       typedef Index IndexType;
       typedef Functions::MeshFunction< MeshType > MeshFunctionType;
       typedef VelocityFunction VelocityFunctionType;
-      typedef Functions::VectorField< Dimensions, VelocityFunctionType > VelocityFieldType;
+      typedef Functions::VectorField< Dimension, VelocityFunctionType > VelocityFieldType;
       typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer;
       
       static void configSetup( Config::ConfigDescription& config,
diff --git a/src/TNL/Operators/diffusion/LinearDiffusion.h b/src/TNL/Operators/diffusion/LinearDiffusion.h
index ff9c05f03238eb5e10869f4a1dc2d8a6cd2d821a..e31113800f1c790ee630e7a99ae8d046fe039a5c 100644
--- a/src/TNL/Operators/diffusion/LinearDiffusion.h
+++ b/src/TNL/Operators/diffusion/LinearDiffusion.h
@@ -54,7 +54,7 @@ class LinearDiffusion< Meshes::Grid< 1,MeshReal, Device, MeshIndex >, Real, Inde
  
       static const int Dimension = MeshType::getMeshDimension();
  
-      static constexpr int getDimension() { return Dimension; }
+      static constexpr int getMeshDimension() { return Dimension; }
  
       static String getType();
 
@@ -105,7 +105,7 @@ class LinearDiffusion< Meshes::Grid< 2, MeshReal, Device, MeshIndex >, Real, Ind
  
       static const int Dimension = MeshType::getMeshDimension();
  
-      static constexpr int getDimension() { return Dimension; }
+      static constexpr int getMeshDimension() { return Dimension; }
 
       static String getType();
 
@@ -155,7 +155,7 @@ class LinearDiffusion< Meshes::Grid< 3, MeshReal, Device, MeshIndex >, Real, Ind
 
       static const int Dimension = MeshType::getMeshDimension();
  
-      static constexpr int getDimension() { return Dimension; }
+      static constexpr int getMeshDimension() { return Dimension; }
 
       static String getType();
 
diff --git a/src/TNL/Operators/fdm/BackwardFiniteDifference.h b/src/TNL/Operators/fdm/BackwardFiniteDifference.h
index d816499f1e733c4a6cbca7f1a3dc1c0fefe3d320..cceaa807f49961d3efe1cfda844c13ff3daa435e 100644
--- a/src/TNL/Operators/fdm/BackwardFiniteDifference.h
+++ b/src/TNL/Operators/fdm/BackwardFiniteDifference.h
@@ -48,7 +48,7 @@ class BackwardFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, M
       typedef Index IndexType;
       typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType;
  
-      static constexpr int getDimension() { return Dimension; }
+      static constexpr int getMeshDimension() { return Dimension; }
  
       static String getType()
       {
diff --git a/src/TNL/Operators/fdm/CentralFiniteDifference.h b/src/TNL/Operators/fdm/CentralFiniteDifference.h
index 90c9a5887897dd2664e2936514bb9255089c9e2c..feecc62e77800c94b63417aad765b0c404d58a22 100644
--- a/src/TNL/Operators/fdm/CentralFiniteDifference.h
+++ b/src/TNL/Operators/fdm/CentralFiniteDifference.h
@@ -48,7 +48,7 @@ class CentralFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, Me
       typedef Index IndexType;
       typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType;
  
-      //static constexpr int getDimension() { return Dimension; }
+      //static constexpr int getMeshDimension() { return Dimension; }
  
       static String getType()
       {
diff --git a/src/TNL/Operators/fdm/ForwardFiniteDifference.h b/src/TNL/Operators/fdm/ForwardFiniteDifference.h
index 9c75e05dadd03213494d1229fe814771ca0f540d..53602afec21eb7bc1dc416c7647306297895643e 100644
--- a/src/TNL/Operators/fdm/ForwardFiniteDifference.h
+++ b/src/TNL/Operators/fdm/ForwardFiniteDifference.h
@@ -49,7 +49,7 @@ class ForwardFiniteDifference< Meshes::Grid< Dimension, MeshReal, MeshDevice, Me
       typedef Index IndexType;
       typedef ExactDifference< Dimension, XDifference, YDifference, ZDifference > ExactOperatorType;
  
-      static constexpr int getDimension() { return Dimension; }
+      static constexpr int getMeshDimension() { return Dimension; }
  
       static String getType()
       {
diff --git a/src/TNL/Solvers/BuildConfigTags.h b/src/TNL/Solvers/BuildConfigTags.h
index e89aa9d925c7bfe748ec8ab1f98bbc8408787d18..7824f4a18ed44b2cfbb17c1ded32179806bb6fa1 100644
--- a/src/TNL/Solvers/BuildConfigTags.h
+++ b/src/TNL/Solvers/BuildConfigTags.h
@@ -10,7 +10,6 @@
 
 #pragma once
 
-#include <TNL/Meshes/Grid.h>
 #include <TNL/Solvers/ODE/Merson.h>
 #include <TNL/Solvers/ODE/Euler.h>
 #include <TNL/Solvers/Linear/SOR.h>
@@ -26,7 +25,7 @@
 namespace TNL {
 namespace Solvers {   
 
-class DefaultBuildConfigTag{};
+class DefaultBuildConfigTag {};
 
 /****
  * All devices are enabled by default. Those which are not available
@@ -53,29 +52,10 @@ template< typename ConfigTag, typename Index > struct ConfigTagIndex{ enum { ena
 
 /****
  * The mesh type will be resolved by the Solver by default.
+ * (The detailed mesh configuration is in TNL/Meshes/BuildConfigTags.h)
  */
 template< typename ConfigTag > struct ConfigTagMeshResolve{ enum { enabled = true }; };
 
-/****
- * 1, 2, and 3 dimensions are enabled by default
- */
-template< typename ConfigTag, int Dimension > struct ConfigTagDimension{ enum { enabled = ( Dimension > 0 && Dimension <= 3 ) }; };
-
-/****
- * Up to the exceptions enlisted below, all mesh types are disabled by default.
- */
-template< typename ConfigTag, typename MeshType > struct ConfigTagMesh{ enum { enabled = false }; };
-
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-template< typename ConfigTag, int Dimension, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< ConfigTag, Meshes::Grid< Dimension, Real, Device, Index > >
-      { enum { enabled = ConfigTagDimension< ConfigTag, Dimension >::enabled  &&
-                         ConfigTagReal< ConfigTag, Real >::enabled &&
-                         ConfigTagDevice< ConfigTag, Device >::enabled &&
-                         ConfigTagIndex< ConfigTag, Index >::enabled }; };
-
 /****
  * All time discretisations (explicit, semi-impicit and implicit ) are
  * enabled by default.
diff --git a/src/TNL/Solvers/CMakeLists.txt b/src/TNL/Solvers/CMakeLists.txt
index e9cf7268d584ef8228fa371bc82234a48bf5f255..e648956cdb6f9535e77da8ae1e2a3f0e8b6a6818 100644
--- a/src/TNL/Solvers/CMakeLists.txt
+++ b/src/TNL/Solvers/CMakeLists.txt
@@ -7,8 +7,6 @@ SET( headers IterativeSolver.h
              IterativeSolver_impl.h
              BuildConfigTags.h
              FastBuildConfigTag.h
-             MeshTypeResolver.h
-             MeshTypeResolver_impl.h
              Solver.h
              Solver_impl.h
              SolverStarter.h
diff --git a/src/TNL/Solvers/FastBuildConfigTag.h b/src/TNL/Solvers/FastBuildConfigTag.h
index 45ab71b8d84b447a178f3a1c338b1a9f4cf050ca..18e0d80adadff0256668c72d115a9ae707144a13 100644
--- a/src/TNL/Solvers/FastBuildConfigTag.h
+++ b/src/TNL/Solvers/FastBuildConfigTag.h
@@ -11,50 +11,59 @@
 #pragma once
 
 #include <TNL/Solvers/BuildConfigTags.h>
+#include <TNL/Meshes/BuildConfigTags.h>
 
 namespace TNL {
 namespace Solvers {   
 
-class FastBuildConfig
+class FastBuildConfigTag
 {
    public:
 
-      static void print() { std::cerr << "FastBuildConfig" << std::endl; }
+      static void print() { std::cerr << "FastBuildConfigTag" << std::endl; }
 };
 
 /****
  * Turn off support for float and long double.
  */
-template<> struct ConfigTagReal< FastBuildConfig, float > { enum { enabled = false }; };
-template<> struct ConfigTagReal< FastBuildConfig, long double > { enum { enabled = false }; };
+template<> struct ConfigTagReal< FastBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct ConfigTagReal< FastBuildConfigTag, long double > { enum { enabled = false }; };
 
 /****
  * Turn off support for short int and long int indexing.
  */
-template<> struct ConfigTagIndex< FastBuildConfig, short int >{ enum { enabled = false }; };
-template<> struct ConfigTagIndex< FastBuildConfig, long int >{ enum { enabled = false }; };
-
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-template< int Dimension, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< FastBuildConfig, Meshes::Grid< Dimension, Real, Device, Index > >
-      { enum { enabled = ConfigTagDimension< FastBuildConfig, Dimension >::enabled  &&
-                         ConfigTagReal< FastBuildConfig, Real >::enabled &&
-                         ConfigTagDevice< FastBuildConfig, Device >::enabled &&
-                         ConfigTagIndex< FastBuildConfig, Index >::enabled }; };
+template<> struct ConfigTagIndex< FastBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct ConfigTagIndex< FastBuildConfigTag, long int >{ enum { enabled = false }; };
 
 /****
  * Please, chose your preferred time discretisation  here.
  */
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; };
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, SemiImplicitTimeDiscretisationTag >{ enum { enabled = true }; };
-template<> struct ConfigTagTimeDiscretisation< FastBuildConfig, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ExplicitTimeDiscretisationTag >{ enum { enabled = true }; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, SemiImplicitTimeDiscretisationTag >{ enum { enabled = true }; };
+template<> struct ConfigTagTimeDiscretisation< FastBuildConfigTag, ImplicitTimeDiscretisationTag >{ enum { enabled = false }; };
 
 /****
  * Only the Runge-Kutta-Merson solver is enabled by default.
  */
-//template<> struct ConfigTagExplicitSolver< FastBuildConfig, ExplicitEulerSolverTag >{ enum { enabled = false }; };
+//template<> struct ConfigTagExplicitSolver< FastBuildConfigTag, ExplicitEulerSolverTag >{ enum { enabled = false }; };
 
 } // namespace Solvers
+
+namespace Meshes {
+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 }; };
+
+/****
+ * 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 }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
 } // namespace TNL
diff --git a/src/TNL/Solvers/MeshTypeResolver.h b/src/TNL/Solvers/MeshTypeResolver.h
deleted file mode 100644
index d24bd8afa89c8d56257dd7d8d38684a7b853e210..0000000000000000000000000000000000000000
--- a/src/TNL/Solvers/MeshTypeResolver.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/***************************************************************************
-                          MeshTypeResolver.h  -  description
-                             -------------------
-    begin                : Nov 28, 2013
-    copyright            : (C) 2013 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/Config/ParameterContainer.h>
-
-namespace TNL {
-namespace Solvers {   
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag,
-          bool ResolveMesh = ConfigTagMeshResolve< ConfigTag >::enabled >
-class MeshTypeResolver
-{
-};
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-class MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, false >
-{
-   public:
-
-   static bool run( const Config::ParameterContainer& parameters );
-};
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag  >
-class MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >
-{
-   public:
-
-   static bool run( const Config::ParameterContainer& parameters );
-
-   protected:
-
-   static bool resolveMeshDimension( const Config::ParameterContainer& parameters,
-                                      const Containers::List< String >& parsedMeshType );
-
-   // Overload for disabled dimensions
-   template< int MeshDimension,
-             typename = typename std::enable_if< ! ConfigTagDimension<ConfigTag,MeshDimension>::enabled >::type,
-             typename = void >
-   static bool resolveMeshRealType( const Config::ParameterContainer& parameters,
-                                    const Containers::List< String >& parsedMeshType );
-
-   // Overload for enabled dimensions
-   template< int MeshDimension,
-             typename = typename std::enable_if< ConfigTagDimension<ConfigTag,MeshDimension>::enabled >::type >
-   static bool resolveMeshRealType( const Config::ParameterContainer& parameters,
-                                    const Containers::List< String >& parsedMeshType );
-
-   // Overload for disabled real types
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename = typename std::enable_if< ! ConfigTagReal<ConfigTag, MeshRealType>::enabled >::type,
-             typename = void >
-   static bool resolveMeshIndexType( const Config::ParameterContainer& parameters,
-                                     const Containers::List< String >& parsedMeshType );
-
-   // Overload for enabled real types
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename = typename std::enable_if< ConfigTagReal<ConfigTag, MeshRealType>::enabled >::type >
-   static bool resolveMeshIndexType( const Config::ParameterContainer& parameters,
-                                     const Containers::List< String >& parsedMeshType );
-
-   // Overload for disabled index types
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename MeshIndexType,
-             typename = typename std::enable_if< ! ConfigTagIndex<ConfigTag, MeshIndexType>::enabled >::type,
-             typename = void >
-   static bool resolveMeshType( const Config::ParameterContainer& parameters,
-                                const Containers::List< String >& parsedMeshType );
-
-   // Overload for enabled index types
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename MeshIndexType,
-             typename = typename std::enable_if< ConfigTagIndex<ConfigTag, MeshIndexType>::enabled >::type >
-   static bool resolveMeshType( const Config::ParameterContainer& parameters,
-                                const Containers::List< String >& parsedMeshType );
-
-
-
-   template< int Dimension, bool DimensionSupport, typename MeshTypeResolver >
-    friend class MeshTypeResolverDimensionSupportChecker;
-};
-
-/*template< int Dimension, bool DimensionSupport, typename MeshTypeResolver >
-class MeshTypeResolverDimensionSupportChecker
-{
-};
-
-template< int Dimension, typename MeshTypeResolver >
-class MeshTypeResolverDimensionSupportChecker< Dimension, true, MeshTypeResolver >
-{
-   public:
-
-   static bool checkDimension( const Config::ParameterContainer& parameters,
-                                const Containers::List< String >& parsedMeshType );
-};
-
-template< int Dimension, typename MeshTypeResolver >
-class MeshTypeResolverDimensionSupportChecker< Dimension, false, MeshTypeResolver >
-{
-   public:
-
-   static bool checkDimension( const Config::ParameterContainer& parameters,
-                                const Containers::List< String >& parsedMeshType );
-};*/
-
-} // namespace Solvers
-} // namespace TNL
-
-#include <TNL/Solvers/MeshTypeResolver_impl.h>
diff --git a/src/TNL/Solvers/MeshTypeResolver_impl.h b/src/TNL/Solvers/MeshTypeResolver_impl.h
deleted file mode 100644
index c342c58f34204e5e42f163c637bf60aaed2f2df6..0000000000000000000000000000000000000000
--- a/src/TNL/Solvers/MeshTypeResolver_impl.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/***************************************************************************
-                          MeshTypeResolver_impl.h  -  description
-                             -------------------
-    begin                : Nov 28, 2013
-    copyright            : (C) 2013 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <TNL/String.h>
-#include <TNL/Meshes/Grid.h>
-#include <TNL/Meshes/DummyMesh.h>
-#include <TNL/Solvers/SolverStarter.h>
-
-namespace TNL {
-namespace Solvers {   
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename MeshType,
-          typename ConfigTag,
-          bool MeshTypeSupported = ConfigTagMesh< ConfigTag, MeshType >::enabled >
-class MeshResolverTerminator{};
-
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-bool MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, false  >::run( const Config::ParameterContainer& parameters )
-{
-   return ProblemSetter< Real,
-                         Device,
-                         Index,
-                         Meshes::DummyMesh< Real, Device, Index >,
-                         ConfigTag,
-                         SolverStarter< ConfigTag > >::template run< Real, Device, Index, ConfigTag >( parameters );
-};
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-bool MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::run( const Config::ParameterContainer& parameters )
-{
-   const String& meshFileName = parameters.getParameter< String >( "mesh" );
-
-   String meshType;
-   if( ! getObjectType( meshFileName, meshType ) )
-   {
-      std::cerr << "I am not able to detect the mesh type from the file " << meshFileName << "." << std::endl;
-      return EXIT_FAILURE;
-   }
-   std::cout << meshType << " detected in " << meshFileName << " file." << std::endl;
-   Containers::List< String > parsedMeshType;
-   if( ! parseObjectType( meshType, parsedMeshType ) )
-   {
-      std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl;
-      return false;
-   }
-   return resolveMeshDimension( parameters, parsedMeshType );
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshDimension( const Config::ParameterContainer& parameters,
-                       const Containers::List< String >& parsedMeshType )
-{
-   int dimensions = atoi( parsedMeshType[ 1 ].getString() );
-
-   if( dimensions == 1 )
-      return resolveMeshRealType< 1 >( parameters, parsedMeshType );
-   if( dimensions == 2 )
-      return resolveMeshRealType< 2 >( parameters, parsedMeshType );
-   if( dimensions == 3 )
-      return resolveMeshRealType< 3 >( parameters, parsedMeshType );
-   std::cerr << "Dimension higher than 3 are not supported." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension, typename, typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshRealType( const Config::ParameterContainer& parameters,
-                     const Containers::List< String >& parsedMeshType )
-{
-   std::cerr << "Mesh dimension " << MeshDimension << " is not supported." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension, typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshRealType( const Config::ParameterContainer& parameters,
-                     const Containers::List< String >& parsedMeshType )
-{
-   if( parsedMeshType[ 2 ] == "float" )
-      return resolveMeshIndexType< MeshDimension, float >( parameters, parsedMeshType );
-   if( parsedMeshType[ 2 ] == "double" )
-      return resolveMeshIndexType< MeshDimension, double >( parameters, parsedMeshType );
-   if( parsedMeshType[ 2 ] == "long-double" )
-      return resolveMeshIndexType< MeshDimension, long double >( parameters, parsedMeshType );
-   std::cerr << "The type '" << parsedMeshType[ 2 ] << "' is not allowed for real type." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename, typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshIndexType( const Config::ParameterContainer& parameters,
-                      const Containers::List< String >& parsedMeshType )
-{
-   std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for real type." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshIndexType( const Config::ParameterContainer& parameters,
-                      const Containers::List< String >& parsedMeshType )
-{
-   if( parsedMeshType[ 4 ] == "short int" )
-      return resolveMeshType< MeshDimension, MeshRealType, short int >( parameters, parsedMeshType );
-   if( parsedMeshType[ 4 ] == "int" )
-      return resolveMeshType< MeshDimension, MeshRealType, int >( parameters, parsedMeshType );
-   if( parsedMeshType[ 4 ] == "long int" )
-      return resolveMeshType< MeshDimension, MeshRealType, long int >( parameters, parsedMeshType );
-   std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for indexing type." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename MeshIndexType,
-             typename, typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshType( const Config::ParameterContainer& parameters,
-                 const Containers::List< String >& parsedMeshType )
-{
-   std::cerr << "The type '" << parsedMeshType[ 4 ] << "' is not allowed for indexing type." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename ConfigTag >
-   template< int MeshDimension,
-             typename MeshRealType,
-             typename MeshIndexType,
-             typename >
-bool
-MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::
-resolveMeshType( const Config::ParameterContainer& parameters,
-                 const Containers::List< String >& parsedMeshType )
-{
-   if( parsedMeshType[ 0 ] == "Meshes::Grid" )
-   {
-      typedef Meshes::Grid< MeshDimension, MeshRealType, Device, MeshIndexType > MeshType;
-      return MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag >::run( parameters );
-   }
-   std::cerr << "Unknown mesh type " << parsedMeshType[ 0 ] << "." << std::endl;
-   return false;
-}
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename MeshType,
-          typename ConfigTag >
-class MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag, false >
-{
-   public:
-      static bool run( const Config::ParameterContainer& parameters )
-      {
-         std::cerr << "The mesh type " << TNL::getType< MeshType >() << " is not supported." << std::endl;
-         return false;
-      };
-};
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
-          typename Real,
-          typename Device,
-          typename Index,
-          typename MeshType,
-          typename ConfigTag >
-class MeshResolverTerminator< ProblemSetter, Real, Device, Index, MeshType, ConfigTag, true >
-{
-   public:
-      static bool run( const Config::ParameterContainer& parameters )
-      {
-         return ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >::run( parameters );
-      }
-};
-
-} // namespace Solvers
-} // namespace TNL
diff --git a/src/TNL/Solvers/ODE/ExplicitSolver.h b/src/TNL/Solvers/ODE/ExplicitSolver.h
index 36a7118314a442029bd4a7c1fbe6312d42065af9..7ac4f14ecd4bc1eb0ae827a3f67dfd2de4dd1628 100644
--- a/src/TNL/Solvers/ODE/ExplicitSolver.h
+++ b/src/TNL/Solvers/ODE/ExplicitSolver.h
@@ -19,6 +19,7 @@
 #include <TNL/Config/ConfigDescription.h>
 #include <TNL/Config/ParameterContainer.h>
 #include <TNL/SharedPointer.h>
+#include <TNL/Containers/Vector.h>
 
 namespace TNL {
 namespace Solvers {
diff --git a/src/TNL/Solvers/PDE/CMakeLists.txt b/src/TNL/Solvers/PDE/CMakeLists.txt
index 8b5021374834c72d41411df38b20afdd67d62a5d..98f367667d351e9f5dfbcc82b8e0b6a4502acdd2 100644
--- a/src/TNL/Solvers/PDE/CMakeLists.txt
+++ b/src/TNL/Solvers/PDE/CMakeLists.txt
@@ -4,6 +4,7 @@ SET( headers BackwardTimeDiscretisation.h
              ExplicitTimeStepper_impl.h
              ExplicitUpdater.h
              LinearSystemAssembler.h
+             MeshDependentTimeSteps.h
              NoTimeDiscretisation.h
              PDESolver.h
              PDESolver_impl.h
diff --git a/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h b/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h
new file mode 100644
index 0000000000000000000000000000000000000000..143c4b7f02755057238ca878c52b75ae0a57a32e
--- /dev/null
+++ b/src/TNL/Solvers/PDE/MeshDependentTimeSteps.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+                          MeshDependentTimeSteps.h  -  description
+                             -------------------
+    begin                : Jan 26, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/Mesh.h>
+
+namespace TNL {
+namespace Solvers {
+namespace PDE {   
+
+template< typename Mesh, typename Real >
+class MeshDependentTimeSteps
+{
+};
+
+template< int Dimension,
+          typename MeshReal,
+          typename Device,
+          typename MeshIndex,
+          typename Real >
+class MeshDependentTimeSteps< TNL::Meshes::Grid< Dimension, MeshReal, Device, MeshIndex >, Real >
+{
+public:
+   using MeshType = TNL::Meshes::Grid< Dimension, MeshReal, Device, MeshIndex >;
+
+   bool setTimeStepOrder( const Real& timeStepOrder )
+   {
+      if( timeStepOrder < 0 ) {
+         std::cerr << "The time step order for PDESolver must be zero or positive value." << std::endl;
+         return false;
+      }
+      this->timeStepOrder = timeStepOrder;
+      return true;
+   }
+
+   const Real& getTimeStepOrder() const
+   {
+      return timeStepOrder;
+   }
+
+   Real getRefinedTimeStep( const MeshType& mesh, const Real& timeStep )
+   {
+      return timeStep * std::pow( mesh.getSmallestSpaceStep(), this->timeStepOrder );
+   }
+
+protected:
+   Real timeStepOrder = 0.0;
+};
+
+template< typename MeshConfig,
+          typename Device,
+          typename Real >
+class MeshDependentTimeSteps< TNL::Meshes::Mesh< MeshConfig, Device >, Real >
+{
+public:
+   using MeshType = TNL::Meshes::Mesh< MeshConfig >;
+
+   bool setTimeStepOrder( const Real& timeStepOrder )
+   {
+      if( timeStepOrder != 0.0 ) {
+         std::cerr << "Mesh-dependent time stepping is not available on unstructured meshes, so the time step order must be 0." << std::endl;
+         return false;
+      }
+      this->timeStepOrder = timeStepOrder;
+      return true;
+   }
+
+   const Real& getTimeStepOrder() const
+   {
+      return timeStepOrder;
+   }
+
+   Real getRefinedTimeStep( const MeshType& mesh, const Real& timeStep )
+   {
+      return timeStep;
+   }
+
+protected:
+   Real timeStepOrder = 0.0;
+};
+
+} // namespace PDE
+} // namespace Solvers
+} // namespace TNL
diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
index 8b400c994e1b05d560e41c1123aaf3d73c702753..af4889ac329fa032bc71bf355e0044327f79c5bb 100644
--- a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
+++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
@@ -15,6 +15,7 @@
 #include <TNL/Logger.h>
 #include <TNL/SharedPointer.h>
 #include <TNL/Solvers/PDE/PDESolver.h>
+#include <TNL/Solvers/PDE/MeshDependentTimeSteps.h>
 
 namespace TNL {
 namespace Solvers {
@@ -23,8 +24,11 @@ namespace PDE {
 template< typename Problem,
           typename DiscreteSolver,
           typename TimeStepper >
-class TimeDependentPDESolver : public PDESolver< typename Problem::RealType, 
-                                                 typename Problem::IndexType >
+class TimeDependentPDESolver
+   : public PDESolver< typename Problem::RealType, 
+                       typename Problem::IndexType >,
+     public MeshDependentTimeSteps< typename Problem::MeshType,
+                                    typename TimeStepper::RealType >
 {
    public:
 
@@ -68,10 +72,6 @@ class TimeDependentPDESolver : public PDESolver< typename Problem::RealType,
 
       const RealType& getTimeStep() const;
 
-      bool setTimeStepOrder( const RealType& timeStepOrder );
-
-      const RealType& getTimeStepOrder() const;
-
       bool setSnapshotPeriod( const RealType& period );
 
       const RealType& getSnapshotPeriod() const;
@@ -94,7 +94,7 @@ class TimeDependentPDESolver : public PDESolver< typename Problem::RealType,
       
       ProblemType* problem;
 
-      RealType initialTime, finalTime, snapshotPeriod, timeStep, timeStepOrder;
+      RealType initialTime, finalTime, snapshotPeriod, timeStep;
 };
 
 } // namespace PDE
diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
index 991789e8abf1898c5af82653de4875db1d5153e3..a8a01aa9c506e288cedb2d0f366cbbd3d7de366a 100644
--- a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
+++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
@@ -11,6 +11,7 @@
 #pragma once
 
 #include "TimeDependentPDESolver.h"
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
 
 namespace TNL {
 namespace Solvers {
@@ -25,8 +26,7 @@ TimeDependentPDESolver()
   initialTime( 0.0 ),
   finalTime( 0.0 ),
   snapshotPeriod( 0.0 ),
-  timeStep( 1.0 ),
-  timeStepOrder( 0.0 )
+  timeStep( 1.0 )
 {
 }
 
@@ -62,15 +62,8 @@ setup( const Config::ParameterContainer& parameters,
     * Load the mesh from the mesh file
     */
    const String& meshFile = parameters.getParameter< String >( "mesh" );
-   std::cout << "Loading a mesh from the file " << meshFile << "...";
-   if( ! this->meshPointer->load( meshFile ) )
-   {
-      std::cerr << std::endl;
-      std::cerr << "I am not able to load the mesh from the file " << meshFile << "." << std::endl;
-      std::cerr << " You may create it with tools like tnl-grid-setup or tnl-mesh-convert." << std::endl;
+   if( ! Meshes::loadMesh( meshFile, *meshPointer ) )
       return false;
-   }
-  std::cout << " [ OK ] " << std::endl;
 
    /****
     * Setup the problem
@@ -107,11 +100,14 @@ setup( const Config::ParameterContainer& parameters,
    /****
     * Initialize the time discretisation
     */
-   this->setFinalTime( parameters.getParameter< double >( "final-time" ) );
-   this->setInitialTime( parameters.getParameter< double >( "initial-time" ) );
-   this->setSnapshotPeriod( parameters.getParameter< double >( "snapshot-period" ) );
-   this->setTimeStep( parameters.getParameter< double >( "time-step") );
-   this->setTimeStepOrder( parameters.getParameter< double >( "time-step-order" ) );
+   bool status = true;
+   status &= this->setFinalTime( parameters.getParameter< double >( "final-time" ) );
+             this->setInitialTime( parameters.getParameter< double >( "initial-time" ) );
+   status &= this->setSnapshotPeriod( parameters.getParameter< double >( "snapshot-period" ) );
+   status &= this->setTimeStep( parameters.getParameter< double >( "time-step") );
+   status &= this->setTimeStepOrder( parameters.getParameter< double >( "time-step-order" ) );
+   if( ! status )
+      return false;
 
    /****
     * Set-up the discrete solver
@@ -143,7 +139,7 @@ writeProlog( Logger& logger,
    meshPointer->writeProlog( logger );
    logger.writeSeparator();
    logger.writeParameter< String >( "Time discretisation:", "time-discretisation", parameters );
-   logger.writeParameter< double >( "Initial time step:", this->timeStep * std::pow( meshPointer->getSmallestSpaceStep(), this->timeStepOrder ) );
+   logger.writeParameter< double >( "Initial time step:", this->getRefinedTimeStep( this->meshPointer.getData(), this->timeStep ) );
    logger.writeParameter< double >( "Initial time:", "initial-time", parameters );
    logger.writeParameter< double >( "Final time:", "final-time", parameters );
    logger.writeParameter< double >( "Snapshot period:", "snapshot-period", parameters );
@@ -275,32 +271,6 @@ getTimeStep() const
    return this->timeStep;
 }
 
-template< typename Problem,
-          typename DiscreteSolver,   
-          typename TimeStepper >
-bool
-TimeDependentPDESolver< Problem, DiscreteSolver, TimeStepper >::
-setTimeStepOrder( const RealType& timeStepOrder )
-{
-   if( timeStepOrder < 0 )
-   {
-      std::cerr << "The time step order for TimeDependentPDESolver must be zero or positive value." << std::endl;
-      return false;
-   }
-   this->timeStepOrder = timeStepOrder;
-   return true;
-}
-
-template< typename Problem,
-          typename DiscreteSolver,   
-          typename TimeStepper >
-const typename Problem::RealType&
-TimeDependentPDESolver< Problem, DiscreteSolver, TimeStepper >::
-getTimeStepOrder() const
-{
-   return this->timeStepOrder;
-}
-
 template< typename Problem,
           typename DiscreteSolver,   
           typename TimeStepper >
@@ -336,7 +306,7 @@ solve()
     */
    this->timeStepper.setProblem( * ( this->problem ) );
    this->timeStepper.init( this->meshPointer );
-   this->timeStepper.setTimeStep( this->timeStep * std::pow( this->meshPointer.getData().getSmallestSpaceStep(), this->timeStepOrder ) );
+   this->timeStepper.setTimeStep( this->getRefinedTimeStep( this->meshPointer.getData(), this->timeStep ) );
    while( step < allSteps )
    {
       RealType tau = min( this->snapshotPeriod,
diff --git a/src/TNL/Solvers/SolverConfig_impl.h b/src/TNL/Solvers/SolverConfig_impl.h
index 69b895b50164449e8aa255ea52800d314e3e0da5..9da689521d3b0b5b5c0b752e309f89eab8eca8b6 100644
--- a/src/TNL/Solvers/SolverConfig_impl.h
+++ b/src/TNL/Solvers/SolverConfig_impl.h
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <TNL/tnlConfig.h>
+#include <TNL/Solvers/SolverConfig.h>
 #include <TNL/Solvers/BuildConfigTags.h>
 #include <TNL/Solvers/DummyProblem.h>
 #include <TNL/Solvers/PDE/ExplicitTimeStepper.h>
diff --git a/src/TNL/Solvers/SolverInitiator.h b/src/TNL/Solvers/SolverInitiator.h
index 329c4f6d533ad32a21610d9967bdda1625d1893b..40a6d9cddd773c29e58813b996d813373af60b67 100644
--- a/src/TNL/Solvers/SolverInitiator.h
+++ b/src/TNL/Solvers/SolverInitiator.h
@@ -17,8 +17,8 @@
 namespace TNL {
 namespace Solvers {   
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename MeshConfig, typename SolverStarter > class ProblemSetter,
-          typename MeshConfig >
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+          typename ConfigTag >
 class SolverInitiator : public Object
 {
    public:
diff --git a/src/TNL/Solvers/SolverInitiator_impl.h b/src/TNL/Solvers/SolverInitiator_impl.h
index 1b5ddc1a3bd15ccd16cb4bcfa7bc6940f7342134..4736e585705f9c785dfe828cb823e8473d66db4b 100644
--- a/src/TNL/Solvers/SolverInitiator_impl.h
+++ b/src/TNL/Solvers/SolverInitiator_impl.h
@@ -8,16 +8,20 @@
 
 /* See Copyright Notice in tnl/Copyright */
 
+#include <TNL/Solvers/SolverInitiator.h>
+
+#include <TNL/Devices/Host.h>
+#include <TNL/Devices/Cuda.h>
+#include <TNL/Devices/MIC.h>
 #include <TNL/Config/ParameterContainer.h>
-#include <TNL/Solvers/MeshTypeResolver.h>
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
 #include <TNL/Solvers/BuildConfigTags.h>
 #include <TNL/Solvers/Linear/SOR.h>
 #include <TNL/Solvers/Linear/CG.h>
 #include <TNL/Solvers/Linear/BICGStab.h>
 #include <TNL/Solvers/Linear/GMRES.h>
-#include <TNL/Devices/Host.h>
-#include <TNL/Devices/Cuda.h>
-#include <TNL/Devices/MIC.h>
+#include <TNL/Solvers/SolverStarter.h>
+#include <TNL/Meshes/DummyMesh.h>
 
 namespace TNL {
 namespace Solvers {   
@@ -26,14 +30,14 @@ template< template< typename Real, typename Device, typename Index, typename Mes
           typename Real,
           typename ConfigTag,
           bool enabled = ConfigTagReal< ConfigTag, Real >::enabled >
-class SolverInitiatorRealResolver{};
+class SolverInitiatorRealResolver {};
 
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename Real,
           typename Device,
           typename ConfigTag,
           bool enabled = ConfigTagDevice< ConfigTag, Device >::enabled >
-class SolverInitiatorDeviceResolver{};
+class SolverInitiatorDeviceResolver {};
 
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename Real,
@@ -41,7 +45,16 @@ template< template< typename Real, typename Device, typename Index, typename Mes
           typename Index,
           typename ConfigTag,
           bool enabled = ConfigTagIndex< ConfigTag, Index >::enabled >
-class SolverInitiatorIndexResolver{};
+class SolverInitiatorIndexResolver {};
+
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename ConfigTag,
+          bool enabled = ConfigTagMeshResolve< ConfigTag >::enabled >
+class SolverInitiatorMeshResolver {};
+
 
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename ConfigTag  >
@@ -60,6 +73,7 @@ bool SolverInitiator< ProblemSetter, ConfigTag > :: run( const Config::Parameter
    return false;
 };
 
+
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename Real,
           typename ConfigTag >
@@ -96,6 +110,7 @@ class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, false >
       }
 };
 
+
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename Real,
           typename Device,
@@ -133,6 +148,7 @@ class SolverInitiatorDeviceResolver< ProblemSetter, Real, Device, ConfigTag, fal
       }
 };
 
+
 template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
           typename Real,
           typename Device,
@@ -158,10 +174,48 @@ class SolverInitiatorIndexResolver< ProblemSetter, Real, Device, Index, ConfigTa
    public:
       static bool run( const Config::ParameterContainer& parameters )
       {
-         return MeshTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag >::run( parameters );
+         return SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag >::run( parameters );
+      }
+};
+
+
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename ConfigTag >
+class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, false >
+{
+   public:
+      static bool run( const Config::ParameterContainer& parameters )
+      {
+         return ProblemSetter< Real,
+                               Device,
+                               Index,
+                               Meshes::DummyMesh< Real, Device, Index >,
+                               ConfigTag,
+                               SolverStarter< ConfigTag > >::template run< Real, Device, Index, ConfigTag >( parameters );
+      }
+};
+
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename ConfigTag >
+class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >
+{
+   // wrapper for MeshTypeResolver
+   template< typename MeshType >
+   using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >;
+
+   public:
+      static bool run( const Config::ParameterContainer& parameters )
+      {
+         const String& meshFileName = parameters.getParameter< String >( "mesh" );
+         return Meshes::resolveMeshType< ConfigTag, Device, ProblemSetterWrapper >( meshFileName, parameters );
       }
 };
 
 } // namespace Solvers
 } // namespace TNL
-
diff --git a/src/TNL/Solvers/SolverStarter.h b/src/TNL/Solvers/SolverStarter.h
index 8cfbe25ced0ba46f786e464858b76570e280e1d7..aa4604e5f58d11e498366844a534d11d983c736b 100644
--- a/src/TNL/Solvers/SolverStarter.h
+++ b/src/TNL/Solvers/SolverStarter.h
@@ -18,7 +18,7 @@
 namespace TNL {
 namespace Solvers {   
 
-template< typename MeshConfig >
+template< typename ConfigTag >
 class SolverStarter
 {
    public:
diff --git a/src/TNL/param-types.h b/src/TNL/param-types.h
index b73383165d5d023e02c4cc943dc0489b57b6e892..e245ec5c995b2c1f233fdc005a7c74bd53cfeac5 100644
--- a/src/TNL/param-types.h
+++ b/src/TNL/param-types.h
@@ -18,6 +18,7 @@ namespace TNL {
 template< typename T >
 String getType() { return T::getType(); };
 
+template<> inline String getType< void >() { return String( "void" ); };
 template<> inline String getType< bool >() { return String( "bool" ); };
 template<> inline String getType< short int >() { return String( "short int" ); };
 template<> inline String getType< int >() { return String( "int" ); };
diff --git a/src/Tools/CMakeLists.txt b/src/Tools/CMakeLists.txt
index e313ef1f6ee5af61953807ae8d3eab51daa6d18d..c32d49043510fb36b06f3fac0ea8763de34c9e8e 100644
--- a/src/Tools/CMakeLists.txt
+++ b/src/Tools/CMakeLists.txt
@@ -7,8 +7,11 @@ CONFIGURE_FILE( "tnl-bindir.in" "${PROJECT_TOOLS_PATH}/tnl-bindir" @ONLY )
 ADD_EXECUTABLE(tnl-grid-setup tnl-grid-setup.cpp )
 target_link_libraries (tnl-grid-setup tnl )
 
-#ADD_EXECUTABLE(tnl-mesh-convert tnl-mesh-convert.cpp )
-#target_link_libraries (tnl-mesh-convert tnl )
+ADD_EXECUTABLE(tnl-grid-to-mesh tnl-grid-to-mesh.cpp )
+target_link_libraries (tnl-grid-to-mesh tnl )
+
+ADD_EXECUTABLE(tnl-mesh-converter tnl-mesh-converter.cpp )
+target_link_libraries (tnl-mesh-converter tnl )
 
 ADD_EXECUTABLE(tnl-init tnl-init.cpp )
 target_link_libraries (tnl-init tnl )
@@ -42,7 +45,8 @@ INSTALL( TARGETS tnl-init
                  tnl-view
                  tnl-diff
                  tnl-grid-setup
-                 #tnl-mesh-convert
+                 tnl-grid-to-mesh
+                 tnl-mesh-converter
                  tnl-dicom-reader
                  tnl-image-converter
                  tnl-curve2gnuplot
diff --git a/src/Tools/tnl-grid-to-mesh.cpp b/src/Tools/tnl-grid-to-mesh.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2cd56244676ce70f700775943cfe970105ed95cd
--- /dev/null
+++ b/src/Tools/tnl-grid-to-mesh.cpp
@@ -0,0 +1,216 @@
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+
+struct GridToMeshConfigTag {};
+
+namespace TNL {
+namespace Meshes {
+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 }; };
+
+/****
+ * 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 }; };
+
+/****
+ * Unstructured meshes are disabled, only grids can be on input.
+ */
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
+
+
+// FIXME: can't be deduced from GridType
+using LocalIndexType = short int;
+
+template< typename Mesh >
+struct MeshCreator
+{
+   using MeshType = Mesh;
+
+   static bool run( const Mesh& meshIn, Mesh& meshOut )
+   {
+      std::cerr << "Got a mesh on the input." << std::endl;
+      return false;
+   }
+};
+
+template< typename Real, typename Device, typename Index >
+struct MeshCreator< TNL::Meshes::Grid< 1, Real, Device, Index > >
+{
+   using GridType = TNL::Meshes::Grid< 1, Real, Device, Index >;
+   using CellTopology = TNL::Meshes::Topologies::Edge;
+   using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology,
+                                                  CellTopology::dimension,
+                                                  typename GridType::RealType,
+                                                  typename GridType::GlobalIndexType,
+                                                  LocalIndexType,
+                                                  typename GridType::GlobalIndexType >;
+   using MeshType = TNL::Meshes::Mesh< MeshConfig >;
+
+   static bool run( const GridType& grid, MeshType& mesh )
+   {
+      const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >();
+      const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >();
+
+      TNL::Meshes::MeshBuilder< MeshType > meshBuilder;
+      meshBuilder.setPointsCount( numberOfVertices );
+      meshBuilder.setCellsCount( numberOfCells );
+
+      for( Index i = 0; i < numberOfVertices; i++ ) {
+         const auto vertex = grid.template getEntity< typename GridType::Vertex >( i );
+         meshBuilder.setPoint( i, vertex.getCenter() );
+      }
+
+      for( Index i = 0; i < numberOfCells; i++ ) {
+         const auto cell = grid.template getEntity< typename GridType::Cell >( i );
+         const auto neighbors = cell.template getNeighborEntities< 0 >();
+         meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex<  1 >() );
+      }
+
+      return meshBuilder.build( mesh );
+   }
+};
+
+template< typename Real, typename Device, typename Index >
+struct MeshCreator< TNL::Meshes::Grid< 2, Real, Device, Index > >
+{
+   using GridType = TNL::Meshes::Grid< 2, Real, Device, Index >;
+   using CellTopology = TNL::Meshes::Topologies::Quadrilateral;
+   using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology,
+                                                  CellTopology::dimension,
+                                                  typename GridType::RealType,
+                                                  typename GridType::GlobalIndexType,
+                                                  LocalIndexType,
+                                                  typename GridType::GlobalIndexType >;
+   using MeshType = TNL::Meshes::Mesh< MeshConfig >;
+
+   static bool run( const GridType& grid, MeshType& mesh )
+   {
+      const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >();
+      const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >();
+
+      TNL::Meshes::MeshBuilder< MeshType > meshBuilder;
+      meshBuilder.setPointsCount( numberOfVertices );
+      meshBuilder.setCellsCount( numberOfCells );
+
+      for( Index i = 0; i < numberOfVertices; i++ ) {
+         const auto vertex = grid.template getEntity< typename GridType::Vertex >( i );
+         meshBuilder.setPoint( i, vertex.getCenter() );
+      }
+
+      for( Index i = 0; i < numberOfCells; i++ ) {
+         const auto cell = grid.template getEntity< typename GridType::Cell >( i );
+         const auto neighbors = cell.template getNeighborEntities< 0 >();
+         meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex<  1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 2, neighbors.template getEntityIndex<  1,  1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 3, neighbors.template getEntityIndex< -1,  1 >() );
+      }
+
+      return meshBuilder.build( mesh );
+   }
+};
+
+template< typename Real, typename Device, typename Index >
+struct MeshCreator< TNL::Meshes::Grid< 3, Real, Device, Index > >
+{
+   using GridType = TNL::Meshes::Grid< 3, Real, Device, Index >;
+   using CellTopology = TNL::Meshes::Topologies::Hexahedron;
+   using MeshConfig = TNL::Meshes::DefaultConfig< CellTopology,
+                                                  CellTopology::dimension,
+                                                  typename GridType::RealType,
+                                                  typename GridType::GlobalIndexType,
+                                                  LocalIndexType,
+                                                  typename GridType::GlobalIndexType >;
+   using MeshType = TNL::Meshes::Mesh< MeshConfig >;
+
+   static bool run( const GridType& grid, MeshType& mesh )
+   {
+      const Index numberOfVertices = grid.template getEntitiesCount< typename GridType::Vertex >();
+      const Index numberOfCells = grid.template getEntitiesCount< typename GridType::Cell >();
+
+      TNL::Meshes::MeshBuilder< MeshType > meshBuilder;
+      meshBuilder.setPointsCount( numberOfVertices );
+      meshBuilder.setCellsCount( numberOfCells );
+
+      for( Index i = 0; i < numberOfVertices; i++ ) {
+         const auto vertex = grid.template getEntity< typename GridType::Vertex >( i );
+         meshBuilder.setPoint( i, vertex.getCenter() );
+      }
+
+      for( Index i = 0; i < numberOfCells; i++ ) {
+         const auto cell = grid.template getEntity< typename GridType::Cell >( i );
+         const auto neighbors = cell.template getNeighborEntities< 0 >();
+         meshBuilder.getCellSeed( i ).setCornerId( 0, neighbors.template getEntityIndex< -1, -1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 1, neighbors.template getEntityIndex<  1, -1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 2, neighbors.template getEntityIndex<  1,  1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 3, neighbors.template getEntityIndex< -1,  1, -1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 4, neighbors.template getEntityIndex< -1, -1,  1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 5, neighbors.template getEntityIndex<  1, -1,  1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 6, neighbors.template getEntityIndex<  1,  1,  1 >() );
+         meshBuilder.getCellSeed( i ).setCornerId( 7, neighbors.template getEntityIndex< -1,  1,  1 >() );
+      }
+
+      return meshBuilder.build( mesh );
+   }
+};
+
+template< typename Grid >
+struct GridConverter
+{
+   static bool run( const TNL::String& fileName, const TNL::String& outputFileName )
+   {
+      using MeshCreator = MeshCreator< Grid >;
+      using Mesh = typename MeshCreator::MeshType;
+
+      Grid grid;
+      Mesh mesh;
+
+      TNL::Meshes::Readers::TNLReader reader;
+      if( ! reader.readMesh( fileName, grid ) ) {
+         std::cerr << "Failed to load grid from file '" << fileName << "'." << std::endl;
+         return false;
+      }
+
+      if( ! MeshCreator::run( grid, mesh ) ) {
+         std::cerr << "Unable to build mesh from grid." << std::endl;
+         return false;
+      }
+
+      if( ! mesh.save( outputFileName ) ) {
+         std::cerr << "Failed to save the mesh to file '" << outputFileName << "'." << std::endl;
+         return false;
+      }
+
+      return true;
+   }
+};
+
+int
+main( int argc, char* argv[] )
+{
+   using namespace TNL;
+
+   if( argc < 3 ) {
+      std::cerr << "Usage: " << argv[ 0 ] << " input-grid.tnl output-mesh.tnl" << std::endl;
+      return EXIT_FAILURE;
+   }
+
+   String fileName( argv[ 1 ] );
+   String outputFileName( argv[ 2 ] );
+
+   return ! Meshes::resolveMeshType< GridToMeshConfigTag, Devices::Host, GridConverter >
+               ( fileName,
+                 fileName,  // passed to GridConverter::run
+                 outputFileName
+               );
+}
diff --git a/src/Tools/tnl-mesh-convert.cpp b/src/Tools/tnl-mesh-convert.cpp
deleted file mode 100644
index d7de402bc72bc3cc84bd03452837cb7bff40833d..0000000000000000000000000000000000000000
--- a/src/Tools/tnl-mesh-convert.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
-                          tnl-mesh-convert.cpp  -  description
-                             -------------------
-    begin                : Feb 19, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#ifndef __INTEL_COMPILER
-#include "tnl-mesh-convert.h"
-#endif
-#include <TNL/Config/ParameterContainer.h>
-
-void configSetup( Config::ConfigDescription& config )
-{
-   config.addDelimiter                            ( "General settings:" );
-   config.addRequiredEntry< String >( "input-file", "Input file with the mesh." );
-   config.addEntry< String >( "output-file", "Output mesh file in TNL or VTK format.", "mesh.tnl" );
-   //config.addEntry< String >( "output-format", "Output mesh file format.", "vtk" );
-   config.addEntry< int >( "verbose", "Set the verbosity of the program.", 1 );
-   config.addEntry< String >( "mesh-name", "The mesh name.", "tnl-mesh" );
-}
-
-int main( int argc, char* argv[] )
-{
-   Config::ParameterContainer parameters;
-   Config::ConfigDescription conf_desc;
- 
-   configSetup( conf_desc );
-
-   if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
-   {
-      conf_desc.printUsage( argv[ 0 ] );
-      return EXIT_FAILURE;
-   }
-#ifndef __INTEL_COMPILER
-   if( ! convertMesh( parameters ) )
-      return EXIT_FAILURE;
-#endif
-   return EXIT_SUCCESS;
-}
-
-
diff --git a/src/Tools/tnl-mesh-convert.h b/src/Tools/tnl-mesh-convert.h
deleted file mode 100644
index a45e8d0e4b11d14cf5ad7af0a82404b2f6f01162..0000000000000000000000000000000000000000
--- a/src/Tools/tnl-mesh-convert.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/***************************************************************************
-                          tnl-mesh-convert.h  -  description
-                             -------------------
-    begin                : Feb 19, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#ifndef TNL_MESH_CONVERT_H_
-#define TNL_MESH_CONVERT_H_
-
-#include <TNL/Config/ParameterContainer.h>
-#include <TNL/Meshes/MeshDetails/MeshReaderNetgen.h>
-#include <TNL/Meshes/MeshDetails/MeshWriterVTKLegacy.h>
-#include <TNL/Meshes/MeshConfigBase.h>
-#include <TNL/Meshes/Topologies/MeshTriangleTopology.h>
-#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h>
-#include <TNL/Meshes/Mesh.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h>
-#include <TNL/Meshes/MeshDetails/MeshIntegrityChecker.h>
-#include <TNL/FileName.h>
-
-using namespace TNL;
-using namespace TNL::Meshes;
-
-template< typename MeshReader,
-          typename MeshType >
-bool convertMesh( const Config::ParameterContainer& parameters )
-{
-   const String& inputFileName = parameters.getParameter< String >( "input-file" );
-   const String& outputFileName = parameters.getParameter< String >( "output-file" );
-   const String outputFileExt = getFileExtension( outputFileName );
-
-   MeshType mesh;
-   if( ! MeshReader::readMesh( inputFileName, mesh, true ) )
-      return false;
-   /*MeshInitializer< typename MeshType::Config > meshInitializer;
-   meshInitializer.setVerbose( true );
-   if( ! meshInitializer.initMesh( mesh ) )
-      return false;
-   if( ! MeshIntegrityChecker< MeshType >::checkMesh( mesh ) )
-      return false;*/
-  std::cout << mesh << std::endl;
-  std::cout << "Writing the mesh to a file " << outputFileName << "." << std::endl;
-   if( outputFileExt == "tnl" )
-   {
-      if( ! mesh.save( outputFileName ) )
-      {
-         std::cerr << "I am not able to write the mesh into the file " << outputFileName << "." << std::endl;
-         return false;
-      }
-      return true;
-   }
-   if( outputFileExt == "vtk" )
-   {
-      if( ! MeshWriterVTKLegacy::write( outputFileName, mesh, true ) )
-      {
-         std::cerr << "I am not able to write the mesh into the file " << outputFileName << "." << std::endl;
-         return false;
-      }
-      return true;
-   }
-   return false;
-}
-
-bool readNetgenMesh( const Config::ParameterContainer& parameters )
-{
-   const String& inputFileName = parameters.getParameter< String >( "input-file" );
- 
-   MeshReaderNetgen meshReader;
-   if( ! meshReader.detectMesh( inputFileName ) )
-      return false;
-
-  std::cout << "Reading mesh with " << meshReader.getDimension() << " dimensions..." << std::endl;
- 
-   if( meshReader.getDimension() == 2 )
-   {
-      if( meshReader.getVerticesInCell() == 3 )
-      {
-         typedef Mesh< MeshConfigBase< MeshTriangleTopology > > MeshType;
-        std::cout << "Mesh consisting of triangles was detected ... " << std::endl;
-         return convertMesh< MeshReaderNetgen, MeshType >( parameters );
-      }
-      if( meshReader.getVerticesInCell() == 4 )
-      {
-         typedef Mesh< MeshConfigBase< MeshQuadrilateralTopology > > MeshType;
-        std::cout << "Mesh consisting of quadrilaterals was detected ... " << std::endl;
-         return convertMesh< MeshReaderNetgen, MeshType >( parameters );
-      }
-   }
-   if( meshReader.getDimension() == 3 )
-   {
-      if( meshReader.getVerticesInCell() == 4 )
-      {
-         typedef Mesh< MeshConfigBase< MeshTetrahedronTopology > > MeshType;
-        std::cout << "Mesh consisting of tetrahedrons was detected ... " << std::endl;
-         return convertMesh< MeshReaderNetgen, MeshType >( parameters );
-      }
-      if( meshReader.getVerticesInCell() == 8 )
-      {
-         typedef Mesh< MeshConfigBase< MeshHexahedronTopology > > MeshType;
-        std::cout << "Mesh consisting of hexahedrons was detected ... " << std::endl;
-         return convertMesh< MeshReaderNetgen, MeshType >( parameters );
-      }
-   }
-   std::cerr << "Wrong mesh dimensions were detected ( " << meshReader.getDimension() << " )." << std::endl;
-   return false;
-}
-
-bool convertMesh( const Config::ParameterContainer& parameters )
-{
-   String inputFileName = parameters.getParameter< String >( "input-file" );
-
-   const String fileExt = getFileExtension( inputFileName );
-   if( fileExt == "ng" )
-      return readNetgenMesh( parameters );
-   return false;
-}
-
-
-#endif /* TNL_MESH_CONVERT_H_ */
diff --git a/src/Tools/tnl-mesh-converter.cpp b/src/Tools/tnl-mesh-converter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bc4e050f9e1e2ec66f88695f08673e3937bbde8
--- /dev/null
+++ b/src/Tools/tnl-mesh-converter.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+                          tnl-mesh-converter.cpp  -  description
+                             -------------------
+    begin                : Oct 24, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#include <TNL/Config/ParameterContainer.h>
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+#include <TNL/Meshes/Writers/VTKWriter.h>
+#include <TNL/Meshes/Writers/NetgenWriter.h>
+
+using namespace TNL;
+
+struct MeshConverterConfigTag {};
+
+namespace TNL {
+namespace Meshes {
+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 }; };
+
+/****
+ * 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 }; };
+
+/****
+ * 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::Quadrilateral > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MeshConverterConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
+
+// Meshes are enabled only for the world dimension equal to the cell dimension.
+template< typename CellTopology, int WorldDimension >
+struct MeshWorldDimensionTag< MeshConverterConfigTag, CellTopology, WorldDimension >
+{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; };
+
+// Meshes are enabled only for types explicitly listed below.
+template< typename Real > struct MeshRealTag< MeshConverterConfigTag, Real > { enum { enabled = false }; };
+template< typename GlobalIndex > struct MeshGlobalIndexTag< MeshConverterConfigTag, GlobalIndex > { enum { enabled = false }; };
+template< typename LocalIndex > struct MeshLocalIndexTag< MeshConverterConfigTag, LocalIndex > { enum { enabled = false }; };
+template< typename GlobalIndex, typename Id > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, Id > { enum { enabled = false }; };
+template<> struct MeshRealTag< MeshConverterConfigTag, double > { enum { enabled = true }; };
+template<> struct MeshGlobalIndexTag< MeshConverterConfigTag, int > { enum { enabled = true }; };
+template<> struct MeshLocalIndexTag< MeshConverterConfigTag, short int > { enum { enabled = true }; };
+template< typename GlobalIndex > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, void > { enum { enabled = false }; };
+template< typename GlobalIndex > struct MeshIdTag< MeshConverterConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
+
+
+template< typename Mesh >
+struct MeshConverter
+{
+   static bool run( const String& inputFileName, const String& outputFileName, const String& outputFormat )
+   {
+      Mesh mesh;
+      if( ! loadMesh( inputFileName, mesh ) ) {
+         std::cerr << "Failed to load mesh from file '" << inputFileName << "'." << std::endl;
+         return false;
+      }
+
+      if( outputFormat == "tnl" ) {
+         if( ! mesh.save( outputFileName ) ) {
+            std::cerr << "Failed to save the mesh to file '" << outputFileName << "'." << std::endl;
+            return false;
+         }
+      }
+      else if( outputFormat == "vtk" ) {
+         using VTKWriter = Meshes::Writers::VTKWriter< Mesh >;
+         std::fstream file( outputFileName.getString() );
+         VTKWriter::template writeEntities< Mesh::getMeshDimension() >( mesh, file );
+      }
+      // FIXME: NetgenWriter is not specialized for grids
+//      else if( outputFormat == "netgen" ) {
+//         using NetgenWriter = Meshes::Writers::NetgenWriter< Mesh >;
+//         std::fstream file( outputFileName.getString() );
+//         NetgenWriter::writeMesh( mesh, file );
+//      }
+
+      return true;
+   }
+};
+
+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 in TNL or VTK format." );
+   config.addEntry< String >( "output-format", "Output mesh file format." );
+   config.addEntryEnum( "tnl" );
+   config.addEntryEnum( "vtk" );
+//   config.addEntryEnum( "netgen" );
+}
+
+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 String inputFileName = parameters.getParameter< String >( "input-file" );
+   const String outputFileName = parameters.getParameter< String >( "output-file" );
+   const String outputFormat = parameters.getParameter< String >( "output-format" );
+
+   return ! Meshes::resolveMeshType< MeshConverterConfigTag, Devices::Host, MeshConverter >
+               ( inputFileName,
+                 inputFileName,  // passed to MeshConverter::run
+                 outputFileName,
+                 outputFormat
+               );
+}
diff --git a/src/Tools/tnl-view.cpp b/src/Tools/tnl-view.cpp
index 4a5865ac610e5d0713899f9a72678ab878f13d76..453586e65caf917d8952cda8180f5ac811e8aec7 100644
--- a/src/Tools/tnl-view.cpp
+++ b/src/Tools/tnl-view.cpp
@@ -15,6 +15,52 @@
 #include <TNL/Config/ParameterContainer.h>
 #include <TNL/Meshes/DummyMesh.h>
 #include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+
+struct TNLViewBuildConfigTag {};
+
+namespace TNL {
+namespace Meshes {
+namespace BuildConfigTags {
+
+/****
+ * Turn off support for float and long double.
+ */
+template<> struct GridRealTag< TNLViewBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct GridRealTag< TNLViewBuildConfigTag, long double > { enum { enabled = false }; };
+
+/****
+ * Turn off support for short int and long int indexing.
+ */
+template<> struct GridIndexTag< TNLViewBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< TNLViewBuildConfigTag, long int >{ enum { enabled = false }; };
+
+/****
+ * Unstructured meshes.
+ */
+template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Edge > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Triangle > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< TNLViewBuildConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
+
+// Meshes are enabled only for the world dimension equal to the cell dimension.
+template< typename CellTopology, int WorldDimension >
+struct MeshWorldDimensionTag< TNLViewBuildConfigTag, CellTopology, WorldDimension >
+{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; };
+
+// Meshes are enabled only for types explicitly listed below.
+template< typename Real > struct MeshRealTag< TNLViewBuildConfigTag, Real > { enum { enabled = false }; };
+template< typename GlobalIndex > struct MeshGlobalIndexTag< TNLViewBuildConfigTag, GlobalIndex > { enum { enabled = false }; };
+template< typename LocalIndex > struct MeshLocalIndexTag< TNLViewBuildConfigTag, LocalIndex > { enum { enabled = false }; };
+template< typename GlobalIndex, typename Id > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, Id > { enum { enabled = false }; };
+template<> struct MeshRealTag< TNLViewBuildConfigTag, double > { enum { enabled = true }; };
+template<> struct MeshGlobalIndexTag< TNLViewBuildConfigTag, int > { enum { enabled = true }; };
+template<> struct MeshLocalIndexTag< TNLViewBuildConfigTag, short int > { enum { enabled = true }; };
+template< typename GlobalIndex > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, void > { enum { enabled = false }; };
+template< typename GlobalIndex > struct MeshIdTag< TNLViewBuildConfigTag, GlobalIndex, GlobalIndex > { enum { enabled = true }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
 
 void setupConfig( Config::ConfigDescription& config )
 {
@@ -55,64 +101,10 @@ int main( int argc, char* argv[] )
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
 
-
-   int verbose = parameters. getParameter< int >( "verbose" );
-   String meshFile = parameters. getParameter< String >( "mesh" );
-   if( meshFile == "" )
-   {
-      //if( ! processFiles< DummyMesh< double, Devices::Host, int > >( parameters ) )
-      //   return EXIT_FAILURE;
-      //return EXIT_SUCCESS;
-   }
-   String meshType;
-   if( ! getObjectType( meshFile, meshType ) )
-   {
-      std::cerr << "I am not able to detect the mesh type from the file " << meshFile << "." << std::endl;
-      return EXIT_FAILURE;
-   }
-   std::cout << meshType << " detected in " << meshFile << " file." << std::endl;
-   Containers::List< String > parsedMeshType;
-   if( ! parseObjectType( meshType, parsedMeshType ) )
-   {
-      std::cerr << "Unable to parse the mesh type " << meshType << "." << std::endl;
-      return EXIT_FAILURE;
-   }
-   if( parsedMeshType[ 0 ] == "Meshes::Grid" ||
-       parsedMeshType[ 0 ] == "tnlGrid" )   //  TODO: remove deprecated type name
-   {
-      int dimensions = atoi( parsedMeshType[ 1 ].getString() );
-      if( dimensions == 1 )
-      {
-         typedef Meshes::Grid< 1, double, Devices::Host, int > MeshType;
-         if( ! processFiles< MeshType >( parameters ) )
-            return EXIT_FAILURE;
-      }
-      if( dimensions == 2 )
-      {
-         typedef Meshes::Grid< 2, double, Devices::Host, int > MeshType;
-         if( ! processFiles< MeshType >( parameters ) )
-            return EXIT_FAILURE;
-      }
-      if( dimensions == 3 )
-      {
-         typedef Meshes::Grid< 3, double, Devices::Host, int > MeshType;
-         if( ! processFiles< MeshType >( parameters ) )
-            return EXIT_FAILURE;
-      }
-      return EXIT_SUCCESS;
-   }
-   if( parsedMeshType[ 0 ] == "Meshes::Mesh" )
-   {
-      /*String meshFile = parameters. getParameter< String >( "mesh" );
-      struct MeshConfig : public MeshConfigBase< 2 >
-      {
-         typedef MeshTriangleTopology CellType;
-      };
-      Mesh< MeshConfig > mesh;
-      if( ! mesh.load( meshFile ) )
-         return EXIT_FAILURE;
-      if( ! MeshWriterNetgen::writeMesh( "tnl-mesh.ng", mesh, true ) )
-         return EXIT_FAILURE;*/
-   }
-   return EXIT_FAILURE;
+   String meshFile = parameters.getParameter< String >( "mesh" );
+   return ! TNL::Meshes::resolveMeshType< TNLViewBuildConfigTag,
+                                          Devices::Host,
+                                          FilesProcessor >
+                                             ( meshFile,
+                                                parameters );
 }
diff --git a/src/Tools/tnl-view.h b/src/Tools/tnl-view.h
index c4d25f1d5520d2886be390bc41763c1f338e45aa..42f4fd1b300cf7c738efdac37713a77534ce3611 100644
--- a/src/Tools/tnl-view.h
+++ b/src/Tools/tnl-view.h
@@ -117,7 +117,8 @@ bool setMeshFunctionRealType( const MeshPointer& meshPointer,
 
 template< typename MeshPointer,
           int EntityDimension,
-          int VectorFieldSize >
+          int VectorFieldSize,
+          typename = typename std::enable_if< EntityDimension <= MeshPointer::ObjectType::getMeshDimension() >::type >
 bool setMeshEntityType( const MeshPointer& meshPointer,
                         const String& inputFileName,
                         const Containers::List< String >& parsedObjectType,
@@ -133,69 +134,27 @@ bool setMeshEntityType( const MeshPointer& meshPointer,
    return false;
 }
 
-template< typename MeshReal,
-          typename MeshIndex,
-          int VectorFieldSize >
-bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 1, MeshReal, Devices::Host, MeshIndex > >& meshPointer,
-                              const String& inputFileName,
-                              const Containers::List< String >& parsedObjectType,
-                              const Config::ParameterContainer& parameters )
-{
-   typedef Meshes::Grid< 1, MeshReal, Devices::Host, MeshIndex > Mesh;
-   typedef SharedPointer< Mesh > MeshPointer;
-   int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() );
-   switch( meshEntityDimension )
-   {
-      case 0:
-         return setMeshEntityType< MeshPointer, 0, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
-         break;      
-      case 1:
-         return setMeshEntityType< MeshPointer, 1, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
-         break;
-      default:
-         std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl;
-         return false;
-   }
-}
-
-template< typename MeshReal,
-          typename MeshIndex,
-          int VectorFieldSize >
-bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 2, MeshReal, Devices::Host, MeshIndex > >& meshPointer,
-                              const String& inputFileName,
-                              const Containers::List< String >& parsedObjectType,
-                              const Config::ParameterContainer& parameters )
+template< typename MeshPointer,
+          int EntityDimension,
+          int VectorFieldSize,
+          typename = typename std::enable_if< ( EntityDimension > MeshPointer::ObjectType::getMeshDimension() ) >::type,
+          typename = void >
+bool setMeshEntityType( const MeshPointer& meshPointer,
+                        const String& inputFileName,
+                        const Containers::List< String >& parsedObjectType,
+                        const Config::ParameterContainer& parameters )
 {
-   typedef Meshes::Grid< 2, MeshReal, Devices::Host, MeshIndex > Mesh;
-   typedef SharedPointer< Mesh > MeshPointer;
-   int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() );
-   switch( meshEntityDimension )
-   {
-      case 0:
-         return setMeshEntityType< MeshPointer, 0, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
-         break;            
-      case 1:
-         return setMeshEntityType< MeshPointer, 1, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
-         break;
-      case 2:
-         return setMeshEntityType< MeshPointer, 2, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
-         break;
-      default:
-         std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl;
-         return false;
-   }
+   std::cerr << "Unsupported mesh functions entity dimension: " << EntityDimension << "." << std::endl;
+   return false;
 }
 
-template< typename MeshReal,
-          typename MeshIndex,
-          int VectorFieldSize >
-bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 3, MeshReal, Devices::Host, MeshIndex > >& meshPointer,
-                              const String& inputFileName,
-                              const Containers::List< String >& parsedObjectType,
-                              const Config::ParameterContainer& parameters )
+template< int VectorFieldSize,
+          typename MeshPointer >
+bool setMeshEntityDimension( const MeshPointer& meshPointer,
+                             const String& inputFileName,
+                             const Containers::List< String >& parsedObjectType,
+                             const Config::ParameterContainer& parameters )
 {
-   typedef Meshes::Grid< 3, MeshReal, Devices::Host, MeshIndex > Mesh;
-   typedef SharedPointer< Mesh > MeshPointer;
    int meshEntityDimension = atoi( parsedObjectType[ 2 ].getString() );
    switch( meshEntityDimension )
    {
@@ -212,7 +171,7 @@ bool setMeshEntityDimension( const SharedPointer< Meshes::Grid< 3, MeshReal, Dev
          return setMeshEntityType< MeshPointer, 3, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
          break;
       default:
-         std::cerr << "Unsupported mesh functions entity dimension count " << meshEntityDimension << "." << std::endl;
+         std::cerr << "Unsupported mesh functions entity dimension: " << meshEntityDimension << "." << std::endl;
          return false;
    }
 }
@@ -229,9 +188,7 @@ bool setMeshFunction( const MeshPointer& meshPointer,
       std::cerr << "Incompatible mesh type for the mesh function " << inputFileName << "." << std::endl;
       return false;
    }
-   typedef typename MeshPointer::ObjectType::RealType RealType;
-   typedef typename MeshPointer::ObjectType::IndexType IndexType;
-   return setMeshEntityDimension< RealType, IndexType, VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
+   return setMeshEntityDimension< VectorFieldSize >( meshPointer, inputFileName, parsedObjectType, parameters );
 }
 
 template< typename MeshPointer >
@@ -307,14 +264,14 @@ bool convertObject( const MeshPointer& meshPointer,
       grid. setDomain( PointType( 0.0 ), PointType( 1.0 ) );
       grid. setDimensions( CoordinatesType( multiVector. getDimensions() ) );
       const Real spaceStep = grid. getSpaceSteps(). x();
-      if( ! grid. write( multiVector, outputFileName, outputFormat ) )
+//      if( ! grid. write( multiVector, outputFileName, outputFormat ) )
          return false;
    }
    return true;
 }
 
 template< typename MeshPointer, typename Element, typename Real, typename Index >
-bool setDimensions( const MeshPointer& meshPointer,
+bool setDimension( const MeshPointer& meshPointer,
                     const String& inputFileName,
                     const Containers::List< String >& parsedObjectType,
                     const Config::ParameterContainer& parameters )
@@ -358,9 +315,9 @@ bool setIndexType( const MeshPointer& meshPointer,
       indexType = parsedObjectType[ 3 ];
 
    if( indexType == "int" )
-      return setDimensions< MeshPointer, Element, Real, int >( meshPointer, inputFileName, parsedObjectType, parameters );
+      return setDimension< MeshPointer, Element, Real, int >( meshPointer, inputFileName, parsedObjectType, parameters );
    if( indexType == "long-int" )
-      return setDimensions< MeshPointer, Element, Real, long int >( meshPointer, inputFileName, parsedObjectType, parameters );
+      return setDimension< MeshPointer, Element, Real, long int >( meshPointer, inputFileName, parsedObjectType, parameters );
    std::cerr << "Unknown index type " << indexType << "." << std::endl;
    return false;
 }
@@ -456,83 +413,82 @@ bool setElementType( const MeshPointer& meshPointer,
 }
 
 template< typename Mesh >
-bool processFiles( const Config::ParameterContainer& parameters )
+struct FilesProcessor
 {
-   int verbose = parameters. getParameter< int >( "verbose");
-   String meshFile = parameters. getParameter< String >( "mesh" );
-
-   typedef SharedPointer< Mesh > MeshPointer;
-   MeshPointer meshPointer;
-   
-   if( meshFile != "" )
-      if( ! meshPointer->load( meshFile ) )
-      {
-         std::cerr << "I am not able to load mesh from the file " << meshFile << "." << std::endl;
-         return false;
-      }
-   meshPointer->writeMesh( "mesh.asy", "asymptote" );
-
-   bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" );
-   Containers::List< String > inputFiles = parameters. getParameter< Containers::List< String > >( "input-files" );
-   bool error( false );
-//#ifdef HAVE_OPENMP
-//#pragma omp parallel for
-//#endif
-   for( int i = 0; i < inputFiles. getSize(); i ++ )
+   static bool run( const Config::ParameterContainer& parameters )
    {
-      if( verbose )
-        std::cout << "Processing file " << inputFiles[ i ] << " ... " << std::flush;
-
-      String outputFormat = parameters. getParameter< String >( "output-format" );
-      String outputFileName;
-      if( ! getOutputFileName( inputFiles[ i ],
-                               outputFormat,
-                               outputFileName ) )
-      {
-         error = true;
-         continue;
-      }
-      if( checkOutputFile && fileExists( outputFileName ) )
+      int verbose = parameters. getParameter< int >( "verbose");
+      String meshFile = parameters. getParameter< String >( "mesh" );
+
+      typedef SharedPointer< Mesh > MeshPointer;
+      MeshPointer meshPointer;
+      
+      if( meshFile != "" )
+         if( ! loadMesh( meshFile, *meshPointer ) )
+            return false;
+
+      bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" );
+      Containers::List< String > inputFiles = parameters. getParameter< Containers::List< String > >( "input-files" );
+      bool error( false );
+   //#ifdef HAVE_OPENMP
+   //#pragma omp parallel for
+   //#endif
+      for( int i = 0; i < inputFiles. getSize(); i ++ )
       {
          if( verbose )
-           std::cout << " file already exists. Skipping.            \r" << std::flush;
-         continue;
-      }
+           std::cout << "Processing file " << inputFiles[ i ] << " ... " << std::flush;
 
-      String objectType;
-      if( ! getObjectType( inputFiles[ i ], objectType ) )
-          std::cerr << "unknown object ... SKIPPING!" << std::endl;
-      else
-      {
-         if( verbose )
-           std::cout << objectType << " detected ... ";
-
-         Containers::List< String > parsedObjectType;
-         if( ! parseObjectType( objectType, parsedObjectType ) )
+         String outputFormat = parameters. getParameter< String >( "output-format" );
+         String outputFileName;
+         if( ! getOutputFileName( inputFiles[ i ],
+                                  outputFormat,
+                                  outputFileName ) )
          {
-            std::cerr << "Unable to parse object type " << objectType << "." << std::endl;
             error = true;
             continue;
          }
-         if( parsedObjectType[ 0 ] == "Containers::MultiVector" ||
-             parsedObjectType[ 0 ] == "Containers::Vector" ||
-             parsedObjectType[ 0 ] == "tnlMultiVector" ||                     // TODO: remove deprecated type names
-             parsedObjectType[ 0 ] == "tnlSharedMultiVector" ||               // 
-             parsedObjectType[ 0 ] == "tnlSharedVector" ||                    //
-             parsedObjectType[ 0 ] == "tnlVector" )                           //
-            setElementType< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
-         if( parsedObjectType[ 0 ] == "Functions::MeshFunction" ||
-             parsedObjectType[ 0 ] == "tnlMeshFunction" )                     // TODO: remove deprecated type names
-            setMeshFunction< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
-         if( parsedObjectType[ 0 ] == "Functions::VectorField" )
-            setVectorFieldSize< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
-         if( verbose )
-           std::cout << "[ OK ].  " << std::endl;
+         if( checkOutputFile && fileExists( outputFileName ) )
+         {
+            if( verbose )
+              std::cout << " file already exists. Skipping.            \r" << std::flush;
+            continue;
+         }
+
+         String objectType;
+         if( ! getObjectType( inputFiles[ i ], objectType ) )
+             std::cerr << "unknown object ... SKIPPING!" << std::endl;
+         else
+         {
+            if( verbose )
+              std::cout << objectType << " detected ... ";
+
+            Containers::List< String > parsedObjectType;
+            if( ! parseObjectType( objectType, parsedObjectType ) )
+            {
+               std::cerr << "Unable to parse object type " << objectType << "." << std::endl;
+               error = true;
+               continue;
+            }
+            if( parsedObjectType[ 0 ] == "Containers::MultiVector" ||
+                parsedObjectType[ 0 ] == "Containers::Vector" ||
+                parsedObjectType[ 0 ] == "tnlMultiVector" ||                     // TODO: remove deprecated type names
+                parsedObjectType[ 0 ] == "tnlSharedMultiVector" ||               // 
+                parsedObjectType[ 0 ] == "tnlSharedVector" ||                    //
+                parsedObjectType[ 0 ] == "tnlVector" )                           //
+               setElementType< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
+            if( parsedObjectType[ 0 ] == "Functions::MeshFunction" ||
+                parsedObjectType[ 0 ] == "tnlMeshFunction" )                     // TODO: remove deprecated type names
+               setMeshFunction< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
+            if( parsedObjectType[ 0 ] == "Functions::VectorField" )
+               setVectorFieldSize< MeshPointer >( meshPointer, inputFiles[ i ], parsedObjectType, parameters );
+            if( verbose )
+               std::cout << "[ OK ].  " << std::endl;
+         }
       }
+      if( verbose )
+        std::cout << std::endl;
+      return ! error;
    }
-   if( verbose )
-     std::cout << std::endl;
-   return ! error;
-}
+};
 
 #endif /* TNL_VIEW_H_ */
diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt
index 21fef2e5607ea0f6c08d53e8f4d966fb4f236f98..3e17aad5d338f543c176d399e1df62b08f2fd1e8 100644
--- a/src/UnitTests/CMakeLists.txt
+++ b/src/UnitTests/CMakeLists.txt
@@ -3,6 +3,7 @@ if( WITH_TESTS STREQUAL "yes" )
 ADD_SUBDIRECTORY( Containers )
 ADD_SUBDIRECTORY( Matrices )
 ADD_SUBDIRECTORY( Mpi )
+ADD_SUBDIRECTORY( Meshes )
 
 ADD_EXECUTABLE( UniquePointerTest UniquePointerTest.cpp )
 TARGET_COMPILE_OPTIONS( UniquePointerTest PRIVATE ${CXX_TESTS_FLAGS} )
diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt
index 477a161bc1eaa8070dfc29c37367632a4e907f7d..58832b04d4108ede4165995ac9bb818b806afe7d 100644
--- a/src/UnitTests/Containers/CMakeLists.txt
+++ b/src/UnitTests/Containers/CMakeLists.txt
@@ -81,3 +81,6 @@ ADD_TEST( StaticArrayTest ${EXECUTABLE_OUTPUT_PATH}/StaticArrayTest${CMAKE_EXECU
 ADD_TEST( VectorTest ${EXECUTABLE_OUTPUT_PATH}/VectorTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( StaticVectorTest ${EXECUTABLE_OUTPUT_PATH}/StaticVectorTest${CMAKE_EXECUTABLE_SUFFIX} )
 #ADD_TEST( MultiArrayTest ${EXECUTABLE_OUTPUT_PATH}/MultiArrayTest${CMAKE_EXECUTABLE_SUFFIX} )
+
+
+ADD_SUBDIRECTORY( Multimaps )
diff --git a/src/UnitTests/Containers/Multimaps/CMakeLists.txt b/src/UnitTests/Containers/Multimaps/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5fb63a52191ede8885ca920420a991175f867823
--- /dev/null
+++ b/src/UnitTests/Containers/Multimaps/CMakeLists.txt
@@ -0,0 +1,14 @@
+ADD_EXECUTABLE( MultimapTest MultimapTest.cpp )
+TARGET_COMPILE_OPTIONS( MultimapTest PRIVATE ${CXX_TESTS_FLAGS} )
+TARGET_LINK_LIBRARIES( MultimapTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+ADD_EXECUTABLE( StaticMultimapTest StaticMultimapTest.cpp )
+TARGET_COMPILE_OPTIONS( StaticMultimapTest PRIVATE ${CXX_TESTS_FLAGS} )
+TARGET_LINK_LIBRARIES( StaticMultimapTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+ADD_TEST( MultimapTest ${EXECUTABLE_OUTPUT_PATH}/MultimapTest${CMAKE_EXECUTABLE_SUFFIX} )
+ADD_TEST( StaticMultimapTest ${EXECUTABLE_OUTPUT_PATH}/MultimapTest${CMAKE_EXECUTABLE_SUFFIX} )
diff --git a/src/UnitTests/Containers/Multimaps/MultimapTest.cpp b/src/UnitTests/Containers/Multimaps/MultimapTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..95fe0d68df1cb1bdf003bfb07189e20c5aba8a4b
--- /dev/null
+++ b/src/UnitTests/Containers/Multimaps/MultimapTest.cpp
@@ -0,0 +1,154 @@
+#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h>
+
+using namespace TNL;
+
+using IndexType = int;
+using Device = Devices::Host;
+using LocalIndexType = short;
+
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+TEST( MultimapTest, TestTypedefs )
+{
+   using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >;
+   const bool same_index = std::is_same< typename MultimapType::IndexType, IndexType >::value;
+   ASSERT_TRUE( same_index );
+   const bool same_device = std::is_same< typename MultimapType::DeviceType, Device >::value;
+   ASSERT_TRUE( same_device );
+   const bool same_localindex = std::is_same< typename MultimapType::LocalIndexType, LocalIndexType >::value;
+   ASSERT_TRUE( same_localindex );
+}
+
+TEST( MultimapTest, TestSettingSizes )
+{
+   using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >;
+
+   IndexType inputs = 10;
+   LocalIndexType valuesGlobalMax = 3;
+   LocalIndexType valuesLocalMax = 2;
+
+   MultimapType map;
+   map.setKeysRange( inputs );
+   ASSERT_EQ( map.getKeysRange(), inputs );
+
+   typename MultimapType::ValuesAllocationVectorType allocationRanges;
+   allocationRanges.setSize( inputs );
+   allocationRanges.setValue( valuesGlobalMax );
+   allocationRanges[ 0 ] = 0;
+   allocationRanges[ 1 ] = 1;
+   map.allocate( allocationRanges );
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      const auto constValues = ( (const MultimapType) map ).getValues( i );
+
+      // uninitialized should be equal to the value from the allocation vector
+      ASSERT_EQ( values.getSize(), allocationRanges[ i ] );
+      ASSERT_EQ( constValues.getSize(), allocationRanges[ i ] );
+
+      // setting lower sizes
+      values.setSize( valuesLocalMax );
+      ASSERT_EQ( values.getSize(), valuesLocalMax );
+      ASSERT_EQ( constValues.getSize(), valuesLocalMax );
+
+      // setting global max
+      values.setSize( valuesGlobalMax );
+      ASSERT_EQ( values.getSize(), valuesGlobalMax );
+      ASSERT_EQ( constValues.getSize(), valuesGlobalMax );
+   }
+}
+
+TEST( MultimapTest, TestSettingValues )
+{
+   using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >;
+
+   IndexType inputs = 10;
+   LocalIndexType allocatedValues = 2;
+
+   MultimapType map;
+   map.setKeysRange( inputs );
+   ASSERT_EQ( map.getKeysRange(), inputs );
+
+   typename MultimapType::ValuesAllocationVectorType allocationRanges;
+   allocationRanges.setSize( inputs );
+   allocationRanges.setValue( allocatedValues );
+   map.allocate( allocationRanges );
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      const auto constValues = ( (const MultimapType) map ).getValues( i );
+
+      values.setSize( allocatedValues );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values.setValue( o, i + o );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values.getValue( o ), i + o );
+         ASSERT_EQ( values[ o ], i + o );
+         ASSERT_EQ( constValues.getValue( o ), i + o );
+         ASSERT_EQ( constValues[ o ], i + o );
+      }
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values[ o ] = i * o;
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values.getValue( o ), i * o );
+         ASSERT_EQ( values[ o ], i * o );
+         ASSERT_EQ( constValues.getValue( o ), i * o );
+         ASSERT_EQ( constValues[ o ], i * o );
+      }
+   }
+}
+
+TEST( MultimapTest, TestSaveAndLoad )
+{
+   using MultimapType = TNL::EllpackIndexMultimap< IndexType, Device, LocalIndexType >;
+
+   IndexType inputs = 10;
+   LocalIndexType allocatedValues = 2;
+
+   MultimapType map, map2;
+   map.setKeysRange( inputs );
+   ASSERT_EQ( map.getKeysRange(), inputs );
+
+   typename MultimapType::ValuesAllocationVectorType allocationRanges;
+   allocationRanges.setSize( inputs );
+   allocationRanges.setValue( allocatedValues );
+   map.allocate( allocationRanges );
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values.setValue( o, i + o );
+   }
+
+   ASSERT_TRUE( map.save( "multimap-test.tnl" ) );
+   ASSERT_TRUE( map2.load( "multimap-test.tnl" ) );
+
+   EXPECT_EQ( map, map2 );
+   EXPECT_EQ( map.getKeysRange(), map2.getKeysRange() );
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      auto values2 = map2.getValues( i );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values[ o ], i + o );
+         ASSERT_EQ( values2[ o ], i + o );
+      }
+   }
+}
+#endif
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp b/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3ea42293e0d048b43257c2179018c0de418683e
--- /dev/null
+++ b/src/UnitTests/Containers/Multimaps/StaticMultimapTest.cpp
@@ -0,0 +1,105 @@
+#include <TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h>
+
+using namespace TNL;
+
+using IndexType = int;
+using Device = Devices::Host;
+using LocalIndexType = short;
+
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+TEST( MultimapTest, TestTypedefs )
+{
+   using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >;
+   const bool same_index = std::is_same< typename MultimapType::IndexType, IndexType >::value;
+   ASSERT_TRUE( same_index );
+   const bool same_device = std::is_same< typename MultimapType::DeviceType, Device >::value;
+   ASSERT_TRUE( same_device );
+   const bool same_localindex = std::is_same< typename MultimapType::LocalIndexType, LocalIndexType >::value;
+   ASSERT_TRUE( same_localindex );
+}
+
+TEST( MultimapTest, TestSettingValues )
+{
+   using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >;
+
+   const IndexType inputs = 10;
+   const LocalIndexType allocatedValues = 4;
+
+   MultimapType map;
+   map.setKeysRange( inputs );
+   ASSERT_EQ( map.getKeysRange(), inputs );
+   map.allocate();
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      const auto constValues = ( (const MultimapType) map ).getValues( i );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values.setValue( o, i + o );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values.getValue( o ), i + o );
+         ASSERT_EQ( values[ o ], i + o );
+         ASSERT_EQ( constValues.getValue( o ), i + o );
+         ASSERT_EQ( constValues[ o ], i + o );
+      }
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values[ o ] = i * o;
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values.getValue( o ), i * o );
+         ASSERT_EQ( values[ o ], i * o );
+         ASSERT_EQ( constValues.getValue( o ), i * o );
+         ASSERT_EQ( constValues[ o ], i * o );
+      }
+   }
+}
+
+TEST( MultimapTest, TestSaveAndLoad )
+{
+   using MultimapType = TNL::StaticEllpackIndexMultimap< 4, IndexType, Device, LocalIndexType >;
+
+   const IndexType inputs = 10;
+   const LocalIndexType allocatedValues = 4;
+
+   MultimapType map, map2;
+   map.setKeysRange( inputs );
+   ASSERT_EQ( map.getKeysRange(), inputs );
+   map.allocate();
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      for( LocalIndexType o = 0; o < allocatedValues; o++ )
+         values.setValue( o, i + o );
+   }
+
+   ASSERT_TRUE( map.save( "multimap-test.tnl" ) );
+   ASSERT_TRUE( map2.load( "multimap-test.tnl" ) );
+
+   EXPECT_EQ( map, map2 );
+   EXPECT_EQ( map.getKeysRange(), map2.getKeysRange() );
+
+   for( IndexType i = 0; i < inputs; i++ ) {
+      auto values = map.getValues( i );
+      auto values2 = map2.getValues( i );
+
+      for( LocalIndexType o = 0; o < allocatedValues; o++ ) {
+         ASSERT_EQ( values[ o ], i + o );
+         ASSERT_EQ( values2[ o ], i + o );
+      }
+   }
+}
+#endif
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/BoundaryTagsTest.cpp b/src/UnitTests/Meshes/BoundaryTagsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..274ef974b78a2c41fa27ca08654723778bb95f9b
--- /dev/null
+++ b/src/UnitTests/Meshes/BoundaryTagsTest.cpp
@@ -0,0 +1,11 @@
+#include "BoundaryTagsTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/BoundaryTagsTest.h b/src/UnitTests/Meshes/BoundaryTagsTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7eccf5f24b16927a4cd211b876f24bd5d9512ed
--- /dev/null
+++ b/src/UnitTests/Meshes/BoundaryTagsTest.h
@@ -0,0 +1,117 @@
+#pragma once
+
+#ifdef HAVE_GTEST
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Quadrilateral.h>
+#include <TNL/Meshes/MeshBuilder.h>
+
+namespace BoundaryTagsTest {
+
+using namespace TNL;
+using namespace TNL::Meshes;
+
+using RealType = double;
+using Device = Devices::Host;
+using IndexType = int;
+
+class TestQuadrilateralMeshConfig : public DefaultConfig< Topologies::Quadrilateral >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool boundaryTagsStorage( EntityTopology ) { return true; }
+};
+
+TEST( MeshTest, RegularMeshOfQuadrilateralsTest )
+{
+   using QuadrilateralMeshEntityType = MeshEntity< TestQuadrilateralMeshConfig, Devices::Host, Topologies::Quadrilateral >;
+   using EdgeMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   const IndexType xSize( 3 ), ySize( 4 );
+   const RealType width( 1.0 ), height( 1.0 );
+   const RealType hx( width / ( RealType ) xSize ),
+                  hy( height / ( RealType ) ySize );
+   const IndexType numberOfCells = xSize * ySize;
+   const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 );
+
+   typedef Mesh< TestQuadrilateralMeshConfig > TestQuadrilateralMesh;
+   TestQuadrilateralMesh mesh, mesh2;
+   MeshBuilder< TestQuadrilateralMesh > meshBuilder;
+   meshBuilder.setPointsCount( numberOfVertices );
+   meshBuilder.setCellsCount( numberOfCells );
+
+   /****
+    * Setup vertices
+    */
+   for( IndexType j = 0; j <= ySize; j++ )
+      for( IndexType i = 0; i <= xSize; i++ )
+         meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) );
+
+   /****
+    * Setup cells
+    */
+   IndexType cellIdx( 0 );
+   for( IndexType j = 0; j < ySize; j++ )
+      for( IndexType i = 0; i < xSize; i++ )
+      {
+         const IndexType vertex0 = j * ( xSize + 1 ) + i;
+         const IndexType vertex1 = j * ( xSize + 1 ) + i + 1;
+         const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1;
+         const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i;
+
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex0 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex1 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 2, vertex2 );
+         meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 3, vertex3 );
+      }
+
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   std::vector< IndexType > boundaryCells = {0, 1, 2, 3, 5, 6, 8, 9, 10, 11};
+   std::vector< IndexType > interiorCells = {4, 7};
+
+   // Test boundary cells
+   EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 2 >(), (int) boundaryCells.size() );
+   for( size_t i = 0; i < boundaryCells.size(); i++ ) {
+      EXPECT_TRUE( mesh.template isBoundaryEntity< 2 >( boundaryCells[ i ] ) );
+      EXPECT_EQ( mesh.template getBoundaryEntityIndex< 2 >( i ), boundaryCells[ i ] );
+   }
+   // Test interior cells
+   EXPECT_EQ( mesh.template getInteriorEntitiesCount< 2 >(), (int) interiorCells.size() );
+   for( size_t i = 0; i < interiorCells.size(); i++ ) {
+      EXPECT_FALSE( mesh.template isBoundaryEntity< 2 >( interiorCells[ i ] ) );
+      EXPECT_EQ( mesh.template getInteriorEntityIndex< 2 >( i ), interiorCells[ i ] );
+   }
+
+   std::vector< IndexType > boundaryFaces = {0, 3, 4, 7, 8, 12, 15, 19, 22, 25, 26, 28, 29, 30};
+   std::vector< IndexType > interiorFaces = {1, 2, 5, 6, 9, 10, 11, 13, 14, 16, 17, 18, 20, 21, 23, 24, 27};
+
+   // Test boundary faces
+   EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 1 >(), (int) boundaryFaces.size() );
+   for( size_t i = 0; i < boundaryFaces.size(); i++ ) {
+      EXPECT_TRUE( mesh.template isBoundaryEntity< 1 >( boundaryFaces[ i ] ) );
+      EXPECT_EQ( mesh.template getBoundaryEntityIndex< 1 >( i ), boundaryFaces[ i ] );
+   }
+   // Test interior faces
+   EXPECT_EQ( mesh.template getInteriorEntitiesCount< 1 >(), (int) interiorFaces.size() );
+   for( size_t i = 0; i < interiorFaces.size(); i++ ) {
+      EXPECT_FALSE( mesh.template isBoundaryEntity< 1 >( interiorFaces[ i ] ) );
+      EXPECT_EQ( mesh.template getInteriorEntityIndex< 1 >( i ), interiorFaces[ i ] );
+   }
+}
+
+} // namespace BoundaryTagsTest
+
+#endif
diff --git a/src/UnitTests/Meshes/CMakeLists.txt b/src/UnitTests/Meshes/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..97cdc0333d747c2e6162a6b9ecb115b6c91a001a
--- /dev/null
+++ b/src/UnitTests/Meshes/CMakeLists.txt
@@ -0,0 +1,74 @@
+ADD_EXECUTABLE( BoundaryTagsTest BoundaryTagsTest.cpp )
+TARGET_COMPILE_OPTIONS( BoundaryTagsTest PRIVATE ${CXX_TESTS_FLAGS} )
+TARGET_LINK_LIBRARIES( BoundaryTagsTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+if( BUILD_CUDA AND ${CMAKE_CXX_COMPILER} MATCHES ".*clang\\+\\+" )
+   CUDA_ADD_EXECUTABLE( MeshTest MeshTest.cu
+                        OPTIONS ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( MeshTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+   CUDA_ADD_EXECUTABLE( MeshOrderingTest MeshOrderingTest.cu
+                        OPTIONS ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( MeshOrderingTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+else()
+   ADD_EXECUTABLE( MeshTest MeshTest.cpp )
+   TARGET_COMPILE_OPTIONS( MeshTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( MeshTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+   ADD_EXECUTABLE( MeshOrderingTest MeshOrderingTest.cpp )
+   TARGET_COMPILE_OPTIONS( MeshOrderingTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( MeshOrderingTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+endif()
+
+ADD_EXECUTABLE( MeshEntityTest MeshEntityTest.cpp )
+TARGET_COMPILE_OPTIONS( MeshEntityTest PRIVATE ${CXX_TESTS_FLAGS} )
+TARGET_LINK_LIBRARIES( MeshEntityTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           tnl )
+
+
+ADD_TEST( BoundaryTagsTest ${EXECUTABLE_OUTPUT_PATH}/BoundaryTagsTest${CMAKE_EXECUTABLE_SUFFIX} )
+ADD_TEST( MeshTest ${EXECUTABLE_OUTPUT_PATH}/MeshTest${CMAKE_EXECUTABLE_SUFFIX} )
+ADD_TEST( MeshOrderingTest ${EXECUTABLE_OUTPUT_PATH}/MeshOrderingTest${CMAKE_EXECUTABLE_SUFFIX} )
+ADD_TEST( MeshEntityTest ${EXECUTABLE_OUTPUT_PATH}/MeshEntityTest${CMAKE_EXECUTABLE_SUFFIX} )
+
+
+
+##
+## Tests with VTK
+##
+
+find_package( VTK )
+if( VTK_FOUND )
+   include(${VTK_USE_FILE})
+
+   AddCompilerFlag( "-DHAVE_VTK " )
+   SET( VTK_COMMON_LIBRARIES vtkCommonCore ; vtkIOLegacy )
+endif( VTK_FOUND )
+
+# FIXME: compilation fails with nvcc (CUDA 9.0)
+#if( BUILD_CUDA AND ${CMAKE_CXX_COMPILER} MATCHES ".*clang\\+\\+" )
+#   CUDA_ADD_EXECUTABLE( MeshReaderTest MeshReaderTest.cu
+#                        OPTIONS ${CXX_TESTS_FLAGS} )
+#   TARGET_LINK_LIBRARIES( MeshReaderTest
+#                           ${GTEST_BOTH_LIBRARIES}
+#                           ${VTK_COMMON_LIBRARIES}
+#                           tnl )
+#else()
+   ADD_EXECUTABLE( MeshReaderTest MeshReaderTest.cpp )
+   TARGET_COMPILE_OPTIONS( MeshReaderTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( MeshReaderTest
+                           ${GTEST_BOTH_LIBRARIES}
+                           ${VTK_COMMON_LIBRARIES}
+                           tnl )
+#endif()
diff --git a/src/UnitTests/Meshes/MeshEntityTest.cpp b/src/UnitTests/Meshes/MeshEntityTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3f87a32bf81d05898c1451dc88488b71df8dc31
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshEntityTest.cpp
@@ -0,0 +1,11 @@
+#include "MeshEntityTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/MeshEntityTest.h b/src/UnitTests/Meshes/MeshEntityTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..5360fd6a8b9151972c798f8f2abb97bf6e31d6eb
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshEntityTest.h
@@ -0,0 +1,794 @@
+#pragma once
+
+#ifdef HAVE_GTEST
+#include <gtest/gtest.h>
+
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+ 
+namespace MeshEntityTest {
+
+using namespace TNL;
+using namespace TNL::Meshes;
+
+using RealType = double;
+using Device = Devices::Host;
+using IndexType = int;
+
+using TestEdgeMeshConfig = DefaultConfig< Topologies::Edge,   2, RealType, IndexType, IndexType, void >;
+
+class TestTriangleMeshConfig : public DefaultConfig< Topologies::Triangle >
+{
+public:
+   template< typename EntityTopology >
+   static constexpr bool subentityStorage( EntityTopology entity, int subentityDimensions )
+   {
+      return true;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool superentityStorage( EntityTopology entity, int superentityDimensions )
+   {
+      return true;
+   }
+};
+
+class TestTetrahedronMeshConfig : public DefaultConfig< Topologies::Tetrahedron >
+{
+public:
+   template< typename EntityTopology >
+   static constexpr bool subentityStorage( EntityTopology entity, int subentityDimensions )
+   {
+      return true;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool superentityStorage( EntityTopology entity, int superentityDimensions )
+   {
+      return true;
+   }
+};
+
+template< typename MeshConfig, typename EntityTopology, int Dimensions >
+using SubentityStorage = typename MeshSubentityTraits< MeshConfig, Devices::Host, EntityTopology, Dimensions >::StorageNetworkType;
+
+template< typename MeshConfig, typename EntityTopology, int Dimensions >
+using SuperentityStorage = typename MeshSuperentityTraits< MeshConfig, Devices::Host, EntityTopology, Dimensions >::StorageNetworkType;
+
+// stupid wrapper around MeshEntity to expose protected members needed for tests
+template< typename MeshConfig, typename EntityTopology >
+class TestMeshEntity
+   : public MeshEntity< MeshConfig, Devices::Host, EntityTopology >
+{
+   using BaseType = MeshEntity< MeshConfig, Devices::Host, EntityTopology >;
+
+public:
+   template< int Subdimensions, typename Storage >
+   void bindSubentitiesStorageNetwork( const Storage& storage )
+   {
+      BaseType::template bindSubentitiesStorageNetwork< Subdimensions >( storage );
+   }
+
+   template< int Subdimensions >
+   void setSubentityIndex( const typename BaseType::LocalIndexType& localIndex,
+                           const typename BaseType::GlobalIndexType& globalIndex )
+   {
+      BaseType::template setSubentityIndex< Subdimensions >( localIndex, globalIndex );
+   }
+
+   using BaseType::bindSuperentitiesStorageNetwork;
+   using BaseType::setNumberOfSuperentities;
+   using BaseType::setSuperentityIndex;
+   using BaseType::setIndex;
+};
+
+template< typename Entity >
+void generalTestSubentities( const Entity& entity )
+{
+   Entity copy1( entity );
+   Entity copy2 = entity;
+
+   // check that subentity accessors have been rebound, at least for the 0th subvertex
+   EXPECT_EQ( copy1.template getSubentityIndex< 0 >( 0 ), entity.template getSubentityIndex< 0 >( 0 ) );
+   EXPECT_EQ( copy2.template getSubentityIndex< 0 >( 0 ), entity.template getSubentityIndex< 0 >( 0 ) );
+}
+ 
+template< typename Entity >
+void generalTestSuperentities( const Entity& entity )
+{
+   Entity copy1( entity );
+   Entity copy2 = entity;
+
+   // check that subentity accessors have been rebound, at least for the 0th superentity
+   EXPECT_EQ( copy1.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ), entity.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ) );
+   EXPECT_EQ( copy2.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ), entity.template getSuperentityIndex< Entity::getEntityDimension() + 1 >( 0 ) );
+}
+ 
+TEST( MeshEntityTest, VertexMeshEntityTest )
+{
+   using EdgeMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, Topologies::Edge >;
+   using VertexMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, typename EdgeMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(),  ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   VertexMeshEntityType vertexEntity;
+   PointType point;
+   point.x() = 1.0;
+   point.y() = 2.0;
+   vertexEntity.setPoint( point );
+   EXPECT_EQ( vertexEntity.getPoint(),  point );
+}
+
+TEST( MeshEntityTest, EdgeMeshEntityTest )
+{
+   using EdgeMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, Topologies::Edge >;
+   using VertexMeshEntityType = TestMeshEntity< TestEdgeMeshConfig, typename EdgeMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(),  ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   /****
+    *
+    * Here we test the following simple example:
+    *
+
+             point2
+                |\
+                | \
+                |  \
+                |   \
+
+                  ....
+             edge1     edge0
+                  ....
+
+
+                |                 \
+                |                  \
+                ---------------------
+             point0   edge2        point1
+
+    */
+
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 );
+
+   Containers::StaticArray< 3, VertexMeshEntityType > vertexEntities;
+   vertexEntities[ 0 ].setPoint( point0 );
+   vertexEntities[ 1 ].setPoint( point1 );
+   vertexEntities[ 2 ].setPoint( point2 );
+
+   EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 );
+   EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 );
+   EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 );
+
+   Containers::StaticArray< 3, EdgeMeshEntityType > edgeEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities;
+   edgeVertexSubentities.setKeysRange( 3 );
+   edgeVertexSubentities.allocate();
+
+   edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, 0 );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, 1 );
+   edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, 1 );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, 2 );
+   edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, 2 );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, 0 );
+   edgeEntities[ 0 ].setIndex( 0 );
+   edgeEntities[ 1 ].setIndex( 1 );
+   edgeEntities[ 2 ].setIndex( 2 );
+
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 0 ) ].getPoint(), point0 );
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 1 ) ].getPoint(), point1 );
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 0 ) ].getPoint(), point1 );
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 1 ) ].getPoint(), point2 );
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 0 ) ].getPoint(), point2 );
+   EXPECT_EQ( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 1 ) ].getPoint(), point0 );
+
+
+   generalTestSubentities( edgeEntities[ 0 ] );
+   generalTestSubentities( edgeEntities[ 1 ] );
+   generalTestSubentities( edgeEntities[ 2 ] );
+}
+
+TEST( MeshEntityTest, TriangleMeshEntityTest )
+{
+   using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >;
+   using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >;
+   using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+
+   static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(), ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   /****
+    * We set-up the same situation as in the test above
+    */
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 );
+
+   Containers::StaticArray< 3, VertexMeshEntityType > vertexEntities;
+   vertexEntities[ 0 ].setPoint( point0 );
+   vertexEntities[ 1 ].setPoint( point1 );
+   vertexEntities[ 2 ].setPoint( point2 );
+
+   EXPECT_EQ( vertexEntities[ 0 ].getPoint(), point0 );
+   EXPECT_EQ( vertexEntities[ 1 ].getPoint(), point1 );
+   EXPECT_EQ( vertexEntities[ 2 ].getPoint(), point2 );
+
+   Containers::StaticArray< 3, EdgeMeshEntityType > edgeEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities;
+   edgeVertexSubentities.setKeysRange( 3 );
+   edgeVertexSubentities.allocate();
+
+   edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 0 >::index );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 1 >::index );
+   edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 0 >::index );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 1 >::index );
+   edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 0 >::index );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 1 >::index );
+
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 0, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 1, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ), ( Topologies::SubentityVertexMap< Topologies::Triangle, Topologies::Edge, 2, 1 >::index ) );
+
+   TriangleMeshEntityType triangleEntity;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities;
+   triangleVertexSubentities.setKeysRange( 1 );
+   triangleEdgeSubentities.setKeysRange( 1 );
+   triangleVertexSubentities.allocate();
+   triangleEdgeSubentities.allocate();
+
+   triangleEntity.template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) );
+   triangleEntity.template setSubentityIndex< 0 >( 0 , 0 );
+   triangleEntity.template setSubentityIndex< 0 >( 1 , 1 );
+   triangleEntity.template setSubentityIndex< 0 >( 2 , 2 );
+
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 0 ), 0 );
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 1 ), 1 );
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 0 >( 2 ), 2 );
+
+   triangleEntity.template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 0 ) );
+   triangleEntity.template setSubentityIndex< 1 >( 0 , 0 );
+   triangleEntity.template setSubentityIndex< 1 >( 1 , 1 );
+   triangleEntity.template setSubentityIndex< 1 >( 2 , 2 );
+
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 0 ), 0 );
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 1 ), 1 );
+   EXPECT_EQ( triangleEntity.template getSubentityIndex< 1 >( 2 ), 2 );
+}
+
+TEST( MeshEntityTest, TetrahedronMeshEntityTest )
+{
+   using TetrahedronMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, Topologies::Tetrahedron >;
+   using TriangleMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 2 >::SubentityTopology >;
+   using EdgeMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 1 >::SubentityTopology >;
+   using VertexMeshEntityType = TestMeshEntity< TestTetrahedronMeshConfig, typename TetrahedronMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+
+   static_assert( TetrahedronMeshEntityType::SubentityTraits< 2 >::storageEnabled, "Testing tetrahedron entity does not store triangles as required." );
+   static_assert( TetrahedronMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing tetrahedron entity does not store edges as required." );
+   static_assert( TetrahedronMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing tetrahedron entity does not store vertices as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(),  ( Containers::StaticVector< 3, RealType >::getType() ) );
+
+   /****
+    * We set-up similar situation as above but with
+    * tetrahedron.
+    */
+   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 );
+
+   Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 0 >::count,
+                   VertexMeshEntityType > vertexEntities;
+
+   vertexEntities[ 0 ].setPoint( point0 );
+   vertexEntities[ 1 ].setPoint( point1 );
+   vertexEntities[ 2 ].setPoint( point2 );
+   vertexEntities[ 3 ].setPoint( point3 );
+
+   EXPECT_EQ( vertexEntities[ 0 ].getPoint(),  point0 );
+   EXPECT_EQ( vertexEntities[ 1 ].getPoint(),  point1 );
+   EXPECT_EQ( vertexEntities[ 2 ].getPoint(),  point2 );
+   EXPECT_EQ( vertexEntities[ 3 ].getPoint(),  point3 );
+
+   Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 1 >::count,
+                            EdgeMeshEntityType > edgeEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities;
+   edgeVertexSubentities.setKeysRange( 6 );
+   edgeVertexSubentities.allocate();
+
+   edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 0 >::index );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 1 >::index );
+   edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 0 >::index );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 1 >::index );
+   edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 0 >::index );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 1 >::index );
+   edgeEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 3 ) );
+   edgeEntities[ 3 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 0 >::index );
+   edgeEntities[ 3 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 1 >::index );
+   edgeEntities[ 4 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 4 ) );
+   edgeEntities[ 4 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 0 >::index );
+   edgeEntities[ 4 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 1 >::index );
+   edgeEntities[ 5 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 5 ) );
+   edgeEntities[ 5 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 0 >::index );
+   edgeEntities[ 5 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 1 >::index );
+
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 0, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 1, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 2, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 3, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 4, 1 >::index ) );
+   EXPECT_EQ( edgeEntities[ 5 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 0 >::index ) );
+   EXPECT_EQ( edgeEntities[ 5 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Edge, 5, 1 >::index ) );
+
+   Containers::StaticArray< Topologies::Subtopology< Topologies::Tetrahedron, 2 >::count,
+                            TriangleMeshEntityType > triangleEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities;
+   triangleVertexSubentities.setKeysRange( 4 );
+   triangleVertexSubentities.allocate();
+
+   triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 0 >::index );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 1 >::index );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 2 >::index );
+   triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 1 ) );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 0 >::index );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 1 >::index );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 2 >::index );
+   triangleEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 2 ) );
+   triangleEntities[ 2 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 0 >::index );
+   triangleEntities[ 2 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 1 >::index );
+   triangleEntities[ 2 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 2 >::index );
+   triangleEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 3 ) );
+   triangleEntities[ 3 ].template setSubentityIndex< 0 >( 0, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 0 >::index );
+   triangleEntities[ 3 ].template setSubentityIndex< 0 >( 1, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 1 >::index );
+   triangleEntities[ 3 ].template setSubentityIndex< 0 >( 2, Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 3, 2 >::index );
+
+   EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 0 >::index ) );
+   EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 1 >::index ) );
+   EXPECT_EQ( triangleEntities[ 0 ].getVertexIndex( 2 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 0, 2 >::index ) );
+   EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 0 >::index ) );
+   EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 1 >::index ) );
+   EXPECT_EQ( triangleEntities[ 1 ].getVertexIndex( 2 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 1, 2 >::index ) );
+   EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 0 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 0 >::index ) );
+   EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 1 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 1 >::index ) );
+   EXPECT_EQ( triangleEntities[ 2 ].getVertexIndex( 2 ),  ( Topologies::SubentityVertexMap< Topologies::Tetrahedron, Topologies::Triangle, 2, 2 >::index ) );
+
+   TetrahedronMeshEntityType tetrahedronEntity;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 0 > tetrahedronVertexSubentities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 1 > tetrahedronEdgeSubentities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Tetrahedron, 2 > tetrahedronTriangleSubentities;
+   tetrahedronVertexSubentities.setKeysRange( 1 );
+   tetrahedronEdgeSubentities.setKeysRange( 1 );
+   tetrahedronTriangleSubentities.setKeysRange( 1 );
+   tetrahedronVertexSubentities.allocate();
+   tetrahedronEdgeSubentities.allocate();
+   tetrahedronTriangleSubentities.allocate();
+
+   tetrahedronEntity.template bindSubentitiesStorageNetwork< 0 >( tetrahedronVertexSubentities.getValues( 0 ) );
+   tetrahedronEntity.template setSubentityIndex< 0 >( 0, 0 );
+   tetrahedronEntity.template setSubentityIndex< 0 >( 1, 1 );
+   tetrahedronEntity.template setSubentityIndex< 0 >( 2, 2 );
+   tetrahedronEntity.template setSubentityIndex< 0 >( 3, 3 );
+
+   EXPECT_EQ( tetrahedronEntity.getVertexIndex( 0 ),  0 );
+   EXPECT_EQ( tetrahedronEntity.getVertexIndex( 1 ),  1 );
+   EXPECT_EQ( tetrahedronEntity.getVertexIndex( 2 ),  2 );
+   EXPECT_EQ( tetrahedronEntity.getVertexIndex( 3 ),  3 );
+
+   tetrahedronEntity.template bindSubentitiesStorageNetwork< 2 >( tetrahedronTriangleSubentities.getValues( 0 ) );
+   tetrahedronEntity.template setSubentityIndex< 2 >( 0, 0 );
+   tetrahedronEntity.template setSubentityIndex< 2 >( 1, 1 );
+   tetrahedronEntity.template setSubentityIndex< 2 >( 2, 2 );
+   tetrahedronEntity.template setSubentityIndex< 2 >( 3, 3 );
+
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 0 ),  0 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 1 ),  1 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 2 ),  2 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 2 >( 3 ),  3 );
+
+   tetrahedronEntity.template bindSubentitiesStorageNetwork< 1 >( tetrahedronEdgeSubentities.getValues( 0 ) );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 0, 0 );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 1, 1 );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 2, 2 );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 3, 3 );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 4, 4 );
+   tetrahedronEntity.template setSubentityIndex< 1 >( 5, 5 );
+
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 0 ),  0 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 1 ),  1 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 2 ),  2 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 3 ),  3 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 4 ),  4 );
+   EXPECT_EQ( tetrahedronEntity.template getSubentityIndex< 1 >( 5 ),  5 );
+
+
+   generalTestSubentities( edgeEntities[ 0 ] );
+   generalTestSubentities( edgeEntities[ 1 ] );
+   generalTestSubentities( edgeEntities[ 2 ] );
+   generalTestSubentities( tetrahedronEntity );
+}
+
+TEST( MeshEntityTest, TwoTrianglesMeshEntityTest )
+{
+   using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >;
+   using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >;
+   using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+
+   static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(),  ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   /****
+    * 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 );
+
+   Containers::StaticArray< 4, VertexMeshEntityType > vertexEntities;
+   vertexEntities[ 0 ].setPoint( point0 );
+   vertexEntities[ 1 ].setPoint( point1 );
+   vertexEntities[ 2 ].setPoint( point2 );
+   vertexEntities[ 3 ].setPoint( point3 );
+
+   EXPECT_EQ( vertexEntities[ 0 ].getPoint(),  point0 );
+   EXPECT_EQ( vertexEntities[ 1 ].getPoint(),  point1 );
+   EXPECT_EQ( vertexEntities[ 2 ].getPoint(),  point2 );
+   EXPECT_EQ( vertexEntities[ 3 ].getPoint(),  point3 );
+
+   Containers::StaticArray< 5, EdgeMeshEntityType > edgeEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities;
+   edgeVertexSubentities.setKeysRange( 5 );
+   edgeVertexSubentities.allocate();
+
+   edgeEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 0, 1 );
+   edgeEntities[ 0 ].template setSubentityIndex< 0 >( 1, 2 );
+   edgeEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 0, 2 );
+   edgeEntities[ 1 ].template setSubentityIndex< 0 >( 1, 0 );
+   edgeEntities[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 0, 0 );
+   edgeEntities[ 2 ].template setSubentityIndex< 0 >( 1, 1 );
+   edgeEntities[ 3 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 3 ) );
+   edgeEntities[ 3 ].template setSubentityIndex< 0 >( 0, 2 );
+   edgeEntities[ 3 ].template setSubentityIndex< 0 >( 1, 3 );
+   edgeEntities[ 4 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 4 ) );
+   edgeEntities[ 4 ].template setSubentityIndex< 0 >( 0, 3 );
+   edgeEntities[ 4 ].template setSubentityIndex< 0 >( 1, 1 );
+
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 0 ),  1 );
+   EXPECT_EQ( edgeEntities[ 0 ].getVertexIndex( 1 ),  2 );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 0 ),  2 );
+   EXPECT_EQ( edgeEntities[ 1 ].getVertexIndex( 1 ),  0 );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 0 ),  0 );
+   EXPECT_EQ( edgeEntities[ 2 ].getVertexIndex( 1 ),  1 );
+   EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 0 ),  2 );
+   EXPECT_EQ( edgeEntities[ 3 ].getVertexIndex( 1 ),  3 );
+   EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 0 ),  3 );
+   EXPECT_EQ( edgeEntities[ 4 ].getVertexIndex( 1 ),  1 );
+
+   Containers::StaticArray< 2, TriangleMeshEntityType > triangleEntities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities;
+   triangleVertexSubentities.setKeysRange( 2 );
+   triangleVertexSubentities.allocate();
+   triangleEdgeSubentities.setKeysRange( 2 );
+   triangleEdgeSubentities.allocate();
+
+   triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0 , 0 );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1 , 1 );
+   triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2 , 2 );
+   triangleEntities[ 0 ].template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 0 ) );
+   triangleEntities[ 0 ].template setSubentityIndex< 1 >( 0 , 0 );
+   triangleEntities[ 0 ].template setSubentityIndex< 1 >( 1 , 1 );
+   triangleEntities[ 0 ].template setSubentityIndex< 1 >( 2 , 2 );
+   triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 1 ) );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0 , 1 );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1 , 2 );
+   triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2 , 3 );
+   triangleEntities[ 1 ].template bindSubentitiesStorageNetwork< 1 >( triangleEdgeSubentities.getValues( 1 ) );
+   triangleEntities[ 1 ].template setSubentityIndex< 1 >( 0 , 3 );
+   triangleEntities[ 1 ].template setSubentityIndex< 1 >( 1 , 4 );
+   triangleEntities[ 1 ].template setSubentityIndex< 1 >( 2 , 0 );
+
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 0 ),  0 );
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 1 ),  1 );
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 2 ),  2 );
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 0 ),  0 );
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 1 ),  1 );
+   EXPECT_EQ( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 2 ),  2 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 0 ),  1 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 1 ),  2 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 2 ),  3 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 0 ),  3 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 1 ),  4 );
+   EXPECT_EQ( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 2 ),  0 );
+
+
+   /*
+    * Tests for the superentities layer.
+    */
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 1 > vertexEdgeSuperentities;
+   vertexEdgeSuperentities.setKeysRange( 4 );
+   vertexEdgeSuperentities.allocate( 3 );
+
+   vertexEntities[ 0 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 0 ) );
+   vertexEntities[ 0 ].template setNumberOfSuperentities< 1 >( 2 );
+   vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 0, 2 );
+   vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 1, 1 );
+
+   EXPECT_EQ( vertexEntities[ 0 ].template getSuperentitiesCount< 1 >(),  2 );
+   EXPECT_EQ( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 0 ),    2 );
+   EXPECT_EQ( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 1 ),    1 );
+
+   vertexEntities[ 1 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 1 ) );
+   vertexEntities[ 1 ].template setNumberOfSuperentities< 1 >( 3 );
+   vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 0, 0 );
+   vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 1, 2 );
+   vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 2, 4 );
+
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentitiesCount< 1 >(),  3 );
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 0 ),    0 );
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 1 ),    2 );
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 2 ),    4 );
+
+
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 2 > vertexCellSuperentities;
+   vertexCellSuperentities.setKeysRange( 4 );
+   vertexCellSuperentities.allocate( 2 );
+
+   vertexEntities[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 1 ) );
+   vertexEntities[ 1 ].template setNumberOfSuperentities< 2 >( 2 );
+   vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 0, 0 );
+   vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 1, 1 );
+
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 0 ),    0 );
+   EXPECT_EQ( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 1 ),    1 );
+
+
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Edge, 2 > edgeCellSuperentities;
+   edgeCellSuperentities.setKeysRange( 5 );
+   edgeCellSuperentities.allocate( 2 );
+
+   edgeEntities[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 0 ) );
+   edgeEntities[ 0 ].template setNumberOfSuperentities< 2 >( 2 );
+   edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 0, 0 );
+   edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 1, 1 );
+
+   EXPECT_EQ( edgeEntities[ 0 ].template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 0 ),    0 );
+   EXPECT_EQ( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 1 ),    1 );
+
+
+   generalTestSuperentities( vertexEntities[ 0 ] );
+   generalTestSuperentities( vertexEntities[ 1 ] );
+   generalTestSuperentities( edgeEntities[ 0 ] );
+   generalTestSubentities( edgeEntities[ 0 ] );
+   generalTestSubentities( edgeEntities[ 1 ] );
+   generalTestSubentities( edgeEntities[ 2 ] );
+   generalTestSubentities( edgeEntities[ 3 ] );
+   generalTestSubentities( edgeEntities[ 4 ] );
+   generalTestSubentities( triangleEntities[ 0 ] );
+   generalTestSubentities( triangleEntities[ 1 ] );
+}
+
+TEST( MeshEntityTest, OneTriangleComparisonTest )
+{
+   using TriangleMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, Topologies::Triangle >;
+   using EdgeMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityTopology >;
+   using VertexMeshEntityType = TestMeshEntity< TestTriangleMeshConfig, typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityTopology >;
+
+   static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   EXPECT_EQ( PointType::getType(),  ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 );
+
+   Containers::StaticArray< 3, VertexMeshEntityType > vertices;
+   vertices[ 0 ].setPoint( point0 );
+   vertices[ 1 ].setPoint( point1 );
+   vertices[ 2 ].setPoint( point2 );
+
+   Containers::StaticArray< 3, EdgeMeshEntityType > edges;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Edge, 0 > edgeVertexSubentities;
+   edgeVertexSubentities.setKeysRange( 3 );
+   edgeVertexSubentities.allocate();
+
+   edges[ 0 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 0 ) );
+   edges[ 0 ].template setSubentityIndex< 0 >( 0, 1 );
+   edges[ 0 ].template setSubentityIndex< 0 >( 1, 2 );
+   edges[ 1 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 1 ) );
+   edges[ 1 ].template setSubentityIndex< 0 >( 0, 2 );
+   edges[ 1 ].template setSubentityIndex< 0 >( 1, 0 );
+   edges[ 2 ].template bindSubentitiesStorageNetwork< 0 >( edgeVertexSubentities.getValues( 2 ) );
+   edges[ 2 ].template setSubentityIndex< 0 >( 0, 0 );
+   edges[ 2 ].template setSubentityIndex< 0 >( 1, 1 );
+
+   TriangleMeshEntityType triangle;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 0 > triangleVertexSubentities;
+   SubentityStorage< TestTriangleMeshConfig, Topologies::Triangle, 1 > triangleEdgeSubentities;
+   triangleVertexSubentities.setKeysRange( 1 );
+   triangleEdgeSubentities.setKeysRange( 1 );
+   triangleVertexSubentities.allocate();
+   triangleEdgeSubentities.allocate();
+
+   triangle.template bindSubentitiesStorageNetwork< 0 >( triangleVertexSubentities.getValues( 0 ) );
+   triangle.template setSubentityIndex< 0 >( 0 , 0 );
+   triangle.template setSubentityIndex< 0 >( 1 , 1 );
+   triangle.template setSubentityIndex< 0 >( 2 , 2 );
+   triangle.template bindSubentitiesStorageNetwork< 1 >( triangleVertexSubentities.getValues( 0 ) );
+   triangle.template setSubentityIndex< 1 >( 0 , 0 );
+   triangle.template setSubentityIndex< 1 >( 1 , 1 );
+   triangle.template setSubentityIndex< 1 >( 2 , 2 );
+
+
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 1 > vertexEdgeSuperentities;
+   vertexEdgeSuperentities.setKeysRange( 3 );
+   vertexEdgeSuperentities.allocate( 2 );
+
+   vertices[ 0 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 0 ) );
+   vertices[ 0 ].template setNumberOfSuperentities< 1 >( 2 );
+   vertices[ 0 ].template setSuperentityIndex< 1 >( 0, 2 );
+   vertices[ 0 ].template setSuperentityIndex< 1 >( 1, 1 );
+
+   vertices[ 1 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 1 ) );
+   vertices[ 1 ].template setNumberOfSuperentities< 1 >( 2 );
+   vertices[ 1 ].template setSuperentityIndex< 1 >( 0, 0 );
+   vertices[ 1 ].template setSuperentityIndex< 1 >( 1, 2 );
+
+   vertices[ 2 ].template bindSuperentitiesStorageNetwork< 1 >( vertexEdgeSuperentities.getValues( 2 ) );
+   vertices[ 2 ].template setNumberOfSuperentities< 1 >( 2 );
+   vertices[ 2 ].template setSuperentityIndex< 1 >( 0, 0 );
+   vertices[ 2 ].template setSuperentityIndex< 1 >( 1, 1 );
+
+
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Vertex, 2 > vertexCellSuperentities;
+   vertexCellSuperentities.setKeysRange( 3 );
+   vertexCellSuperentities.allocate( 1 );
+
+   vertices[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 0 ) );
+   vertices[ 0 ].template setNumberOfSuperentities< 2 >( 1 );
+   vertices[ 0 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+   vertices[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 1 ) );
+   vertices[ 1 ].template setNumberOfSuperentities< 2 >( 1 );
+   vertices[ 1 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+   vertices[ 2 ].template bindSuperentitiesStorageNetwork< 2 >( vertexCellSuperentities.getValues( 2 ) );
+   vertices[ 2 ].template setNumberOfSuperentities< 2 >( 1 );
+   vertices[ 2 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+
+   SuperentityStorage< TestTriangleMeshConfig, Topologies::Edge, 2 > edgeCellSuperentities;
+   edgeCellSuperentities.setKeysRange( 3 );
+   edgeCellSuperentities.allocate( 1 );
+
+   edges[ 0 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 0 ) );
+   edges[ 0 ].template setNumberOfSuperentities< 2 >( 1 );
+   edges[ 0 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+   edges[ 1 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 1 ) );
+   edges[ 1 ].template setNumberOfSuperentities< 2 >( 1 );
+   edges[ 1 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+   edges[ 2 ].template bindSuperentitiesStorageNetwork< 2 >( edgeCellSuperentities.getValues( 2 ) );
+   edges[ 2 ].template setNumberOfSuperentities< 2 >( 1 );
+   edges[ 2 ].template setSuperentityIndex< 2 >( 0, 0 );
+
+
+   /*
+    * Tests for MeshEntity::operator==
+    */
+   EXPECT_EQ( vertices[ 0 ], vertices[ 0 ] );
+   EXPECT_NE( vertices[ 0 ], vertices[ 1 ] );
+   vertices[ 0 ].setPoint( point1 );
+   vertices[ 0 ].template setSuperentityIndex< 1 >( 0, 0 );
+   vertices[ 0 ].template setSuperentityIndex< 1 >( 1, 2 );
+   EXPECT_EQ( vertices[ 0 ], vertices[ 1 ] );
+   vertices[ 0 ].template setSuperentityIndex< 2 >( 0, 1 );
+   EXPECT_NE( vertices[ 0 ], vertices[ 1 ] );
+   vertices[ 1 ].template setSuperentityIndex< 2 >( 0, 1 );
+   EXPECT_EQ( vertices[ 0 ], vertices[ 1 ] );
+
+   EXPECT_EQ( edges[ 0 ], edges[ 0 ] );
+   EXPECT_NE( edges[ 0 ], edges[ 1 ] );
+   edges[ 0 ].template setSubentityIndex< 0 >( 0, 2 );
+   edges[ 0 ].template setSubentityIndex< 0 >( 1, 0 );
+   EXPECT_EQ( edges[ 0 ], edges[ 1 ] );
+   edges[ 0 ].template setSuperentityIndex< 2 >( 0, 1 );
+   EXPECT_NE( edges[ 0 ], edges[ 1 ] );
+   edges[ 1 ].template setSuperentityIndex< 2 >( 0, 1 );
+   EXPECT_EQ( edges[ 0 ], edges[ 1 ] );
+
+
+   /*
+    * Tests for copy-assignment
+    */
+   VertexMeshEntityType v1( vertices[ 0 ] );
+   EXPECT_EQ( v1, vertices[ 0 ] );
+   VertexMeshEntityType v2 = vertices[ 0 ];
+   EXPECT_EQ( v2, vertices[ 0 ] );
+
+   EdgeMeshEntityType e1( edges[ 0 ] );
+   EXPECT_EQ( e1, edges[ 0 ] );
+   EdgeMeshEntityType e2 = edges[ 0 ];
+   EXPECT_EQ( e2, edges[ 0 ] );
+
+   TriangleMeshEntityType t1( triangle );
+   EXPECT_EQ( t1, triangle );
+   TriangleMeshEntityType t2 = triangle;
+   EXPECT_EQ( t2, triangle );
+}
+
+} // namespace MeshEntityTest
+
+#endif
diff --git a/src/UnitTests/Meshes/MeshOrderingTest.cpp b/src/UnitTests/Meshes/MeshOrderingTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fc03c92cc71ee9d8fa3ca554651e20ff19b170c2
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshOrderingTest.cpp
@@ -0,0 +1,11 @@
+#include "MeshOrderingTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/MeshOrderingTest.cu b/src/UnitTests/Meshes/MeshOrderingTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..fc03c92cc71ee9d8fa3ca554651e20ff19b170c2
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshOrderingTest.cu
@@ -0,0 +1,11 @@
+#include "MeshOrderingTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/MeshOrderingTest.h b/src/UnitTests/Meshes/MeshOrderingTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..054e4309eedd85563d95bf18ba5e9de74beff01d
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshOrderingTest.h
@@ -0,0 +1,328 @@
+#pragma once
+
+#ifdef HAVE_GTEST
+#include <gtest/gtest.h>
+
+#include <array>
+
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/MeshBuilder.h>
+
+namespace MeshOrderingTest {
+
+using namespace TNL;
+using namespace TNL::Meshes;
+
+class TestTriangleMeshConfig
+   : public DefaultConfig< Topologies::Triangle, 2, double, int, short int, int >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   //template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+};
+
+template< typename Device >
+bool buildTriangleMesh( Mesh< TestTriangleMeshConfig, Device >& mesh )
+{
+   using TriangleMesh = Mesh< TestTriangleMeshConfig, Device >;
+   using TriangleMeshEntityType = typename TriangleMesh::template EntityType< 2 >;
+   using EdgeMeshEntityType = typename TriangleMesh::template EntityType< 1 >;
+   using VertexMeshEntityType = typename TriangleMesh::template EntityType< 0 >;
+
+   static_assert( TriangleMeshEntityType::template SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::template SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::template SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::template SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::template SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::template SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   static_assert( std::is_same< PointType, Containers::StaticVector< 2, double > >::value, "" );
+
+   /****
+    * 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< TriangleMesh > meshBuilder;
+   meshBuilder.setPointsCount( 4 );
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+
+   meshBuilder.setCellsCount( 2 );
+   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 );
+   return meshBuilder.build( mesh );
+}
+
+template< typename PermutationVector >
+void testMesh( const Mesh< TestTriangleMeshConfig, Devices::Host >& mesh,
+               const PermutationVector& vertexPermutation,
+               const PermutationVector& edgePermutation,
+               const PermutationVector& cellPermutation )
+{
+   using MeshType = Mesh< TestTriangleMeshConfig, Devices::Host >;
+   using PointType = typename MeshType::PointType;
+
+   ASSERT_EQ( vertexPermutation.getSize(), 4 );
+   ASSERT_EQ( edgePermutation.getSize(),   5 );
+   ASSERT_EQ( cellPermutation.getSize(),   2 );
+
+   EXPECT_EQ( mesh.getEntitiesCount< 0 >(),  4 );
+   EXPECT_EQ( mesh.getEntitiesCount< 1 >(),  5 );
+   EXPECT_EQ( mesh.getEntitiesCount< 2 >(),  2 );
+
+   // test points
+   PointType point0( 0.0, 0.0 ),
+             point1( 1.0, 0.0 ),
+             point2( 0.0, 1.0 ),
+             point3( 1.0, 1.0 );
+
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).getPoint(),  point0 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).getPoint(),  point1 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).getPoint(),  point2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).getPoint(),  point3 );
+
+
+   // test getIndex
+   for( int i = 0; i < 4; i++ )
+      EXPECT_EQ( mesh.template getEntity< 0 >( i ).getIndex(), i );
+   for( int i = 0; i < 5; i++ )
+      EXPECT_EQ( mesh.template getEntity< 1 >( i ).getIndex(), i );
+   for( int i = 0; i < 2; i++ )
+      EXPECT_EQ( mesh.template getEntity< 2 >( i ).getIndex(), i );
+
+
+   // test subentities
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).getVertexIndex( 0 ),  vertexPermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).getVertexIndex( 1 ),  vertexPermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).getVertexIndex( 0 ),  vertexPermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).getVertexIndex( 1 ),  vertexPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).getVertexIndex( 0 ),  vertexPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).getVertexIndex( 1 ),  vertexPermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).getVertexIndex( 0 ),  vertexPermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).getVertexIndex( 1 ),  vertexPermutation[ 3 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).getVertexIndex( 0 ),  vertexPermutation[ 3 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).getVertexIndex( 1 ),  vertexPermutation[ 1 ] );
+
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 0 ),  vertexPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 1 ),  vertexPermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 0 >( 2 ),  vertexPermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 0 ),  edgePermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 1 ),  edgePermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 0 ] ).template getSubentityIndex< 1 >( 2 ),  edgePermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 0 ),  vertexPermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 1 ),  vertexPermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 0 >( 2 ),  vertexPermutation[ 3 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 0 ),  edgePermutation[ 3 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 1 ),  edgePermutation[ 4 ] );
+   EXPECT_EQ( mesh.template getEntity< 2 >( cellPermutation[ 1 ] ).template getSubentityIndex< 1 >( 2 ),  edgePermutation[ 0 ] );
+
+
+   // test superentities
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentitiesCount< 1 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 1 >( 0 ),  edgePermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 1 >( 1 ),  edgePermutation[ 2 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentitiesCount< 1 >(),  3 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 0 ),  edgePermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 1 ),  edgePermutation[ 2 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 1 >( 2 ),  edgePermutation[ 4 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentitiesCount< 1 >(),  3 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 0 ),  edgePermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 1 ),  edgePermutation[ 1 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 1 >( 2 ),  edgePermutation[ 3 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentitiesCount< 1 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 1 >( 0 ),  edgePermutation[ 3 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 1 >( 1 ),  edgePermutation[ 4 ] );
+
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 0 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 1 ] ).template getSuperentityIndex< 2 >( 1 ),  cellPermutation[ 1 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 2 ] ).template getSuperentityIndex< 2 >( 1 ),  cellPermutation[ 1 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( vertexPermutation[ 3 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 1 ] );
+
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 0 ] ).template getSuperentityIndex< 2 >( 1 ),  cellPermutation[ 1 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 1 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 2 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 0 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 3 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 1 ] );
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).template getSuperentitiesCount< 2 >(),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( edgePermutation[ 4 ] ).template getSuperentityIndex< 2 >( 0 ),  cellPermutation[ 1 ] );
+
+
+   // test boundary tags
+   const std::vector< int > boundaryFaces = {1, 2, 3, 4};
+   const std::vector< int > interiorFaces = {0};
+   EXPECT_EQ( mesh.template getBoundaryEntitiesCount< 1 >(), (int) boundaryFaces.size() );
+   for( size_t i = 0; i < boundaryFaces.size(); i++ ) {
+      EXPECT_TRUE( mesh.template isBoundaryEntity< 1 >( edgePermutation[ boundaryFaces[ i ] ] ) );
+      // boundary indices are always sorted so we can't test this
+//      EXPECT_EQ( mesh.template getBoundaryEntityIndex< 1 >( i ), edgePermutation[ boundaryFaces[ i ] ] );
+   }
+   // Test interior faces
+   EXPECT_EQ( mesh.template getInteriorEntitiesCount< 1 >(), (int) interiorFaces.size() );
+   for( size_t i = 0; i < interiorFaces.size(); i++ ) {
+      EXPECT_FALSE( mesh.template isBoundaryEntity< 1 >( edgePermutation[ interiorFaces[ i ] ] ) );
+      // boundary indices are always sorted so we can't test this
+//      EXPECT_EQ( mesh.template getInteriorEntityIndex< 1 >( i ), edgePermutation[ interiorFaces[ i ] ] );
+   }
+}
+
+// hack due to TNL::Containers::Vector not supporting initilizer lists
+const std::array< int, 4 > _vertexIdentity { { 0, 1, 2, 3 } };
+const std::array< int, 5 > _edgeIdentity   { { 0, 1, 2, 3, 4 } };
+const std::array< int, 2 > _cellIdentity   { { 0, 1 } };
+
+const std::array< int, 4 > _vertexPermutation { { 3, 2, 0, 1 } };
+const std::array< int, 5 > _edgePermutation   { { 2, 0, 4, 1, 3 } };
+const std::array< int, 2 > _cellPermutation   { { 1, 0 } };
+
+const std::array< int, 4 > _vertexInversePermutation { { 2, 3, 1, 0 } };
+const std::array< int, 5 > _edgeInversePermutation   { { 1, 3, 0, 4, 2 } };
+const std::array< int, 2 > _cellInversePermutation   { { 1, 0 } };
+
+template< typename TNLVector, typename STDArray >
+void setPermutation( TNLVector& perm, const STDArray& stdperm )
+{
+   perm.setSize( stdperm.size() );
+   for( int i = 0; i < perm.getSize(); i++ )
+      perm.setElement( i, stdperm[ i ] );
+}
+
+TEST( MeshOrderingTest, OrderingOnHost )
+{
+   using MeshHost = Mesh< TestTriangleMeshConfig, Devices::Host >;
+
+   MeshHost mesh;
+   ASSERT_TRUE( buildTriangleMesh( mesh ) );
+
+   using PermutationVector = typename MeshHost::GlobalIndexVector;
+   PermutationVector vertexIdentity, edgeIdentity, cellIdentity,
+                     vertexPermutation, edgePermutation, cellPermutation,
+                     vertexInversePermutation, edgeInversePermutation, cellInversePermutation;
+   setPermutation( vertexIdentity, _vertexIdentity );
+   setPermutation( edgeIdentity, _edgeIdentity );
+   setPermutation( cellIdentity, _cellIdentity );
+   setPermutation( vertexPermutation, _vertexPermutation );
+   setPermutation( edgePermutation, _edgePermutation );
+   setPermutation( cellPermutation, _cellPermutation );
+   setPermutation( vertexInversePermutation, _vertexInversePermutation );
+   setPermutation( edgeInversePermutation, _edgeInversePermutation );
+   setPermutation( cellInversePermutation, _cellInversePermutation );
+
+   mesh.template reorderEntities< 0 >( vertexPermutation, vertexInversePermutation );
+   testMesh( mesh, vertexInversePermutation, edgeIdentity, cellIdentity );
+
+   mesh.template reorderEntities< 2 >( cellPermutation, cellInversePermutation );
+   testMesh( mesh, vertexInversePermutation, edgeIdentity, cellInversePermutation );
+
+   mesh.template reorderEntities< 1 >( edgePermutation, edgeInversePermutation );
+   testMesh( mesh, vertexInversePermutation, edgeInversePermutation, cellInversePermutation );
+};
+
+#ifdef HAVE_CUDA
+TEST( MeshOrderingTest, OrderingOnCuda )
+{
+   using MeshHost = Mesh< TestTriangleMeshConfig, Devices::Host >;
+   using MeshCuda = Mesh< TestTriangleMeshConfig, Devices::Cuda >;
+
+   MeshHost meshHost;
+   MeshCuda mesh;
+   ASSERT_TRUE( buildTriangleMesh( meshHost ) );
+   mesh = meshHost;
+
+   using PermutationCuda = typename MeshCuda::GlobalIndexVector;
+   PermutationCuda vertexIdentity, edgeIdentity, cellIdentity,
+                   vertexPermutation, edgePermutation, cellPermutation,
+                   vertexInversePermutation, edgeInversePermutation, cellInversePermutation;
+   setPermutation( vertexIdentity, _vertexIdentity );
+   setPermutation( edgeIdentity, _edgeIdentity );
+   setPermutation( cellIdentity, _cellIdentity );
+   setPermutation( vertexPermutation, _vertexPermutation );
+   setPermutation( edgePermutation, _edgePermutation );
+   setPermutation( cellPermutation, _cellPermutation );
+   setPermutation( vertexInversePermutation, _vertexInversePermutation );
+   setPermutation( edgeInversePermutation, _edgeInversePermutation );
+   setPermutation( cellInversePermutation, _cellInversePermutation );
+
+   mesh.template reorderEntities< 0 >( vertexPermutation, vertexInversePermutation );
+   mesh.template reorderEntities< 1 >( edgePermutation, edgeInversePermutation );
+   mesh.template reorderEntities< 2 >( cellPermutation, cellInversePermutation );
+
+   // test is on host
+   {
+      // local scope so we can use the same names
+      using PermutationVector = typename MeshHost::GlobalIndexVector;
+      PermutationVector vertexIdentity, edgeIdentity, cellIdentity,
+                        vertexPermutation, edgePermutation, cellPermutation,
+                        vertexInversePermutation, edgeInversePermutation, cellInversePermutation;
+      setPermutation( vertexIdentity, _vertexIdentity );
+      setPermutation( edgeIdentity, _edgeIdentity );
+      setPermutation( cellIdentity, _cellIdentity );
+      setPermutation( vertexPermutation, _vertexPermutation );
+      setPermutation( edgePermutation, _edgePermutation );
+      setPermutation( cellPermutation, _cellPermutation );
+      setPermutation( vertexInversePermutation, _vertexInversePermutation );
+      setPermutation( edgeInversePermutation, _edgeInversePermutation );
+      setPermutation( cellInversePermutation, _cellInversePermutation );
+
+      meshHost = mesh;
+      testMesh( meshHost, vertexInversePermutation, edgeInversePermutation, cellInversePermutation );
+   }
+};
+#endif
+
+} // namespace MeshOrderingTest
+
+#endif
diff --git a/src/UnitTests/Meshes/MeshReaderTest.cpp b/src/UnitTests/Meshes/MeshReaderTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ac1b0314a166f798dd4c518b278844c2ecbcb964
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshReaderTest.cpp
@@ -0,0 +1 @@
+#include "MeshReaderTest.h"
diff --git a/src/UnitTests/Meshes/MeshReaderTest.cu b/src/UnitTests/Meshes/MeshReaderTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..ac1b0314a166f798dd4c518b278844c2ecbcb964
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshReaderTest.cu
@@ -0,0 +1 @@
+#include "MeshReaderTest.h"
diff --git a/src/UnitTests/Meshes/MeshReaderTest.h b/src/UnitTests/Meshes/MeshReaderTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..64fe92cc190656001ed066fa46d4a2e917bd4239
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshReaderTest.h
@@ -0,0 +1,194 @@
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/BuildConfigTags.h>
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+
+#ifdef HAVE_VTK
+#include <TNL/Meshes/Readers/VTKReader_libvtk.h>
+#endif
+
+#include <TNL/Debugging/MemoryUsage.h>
+
+#include "MeshTest.h"
+
+// TODO: remove this after refactoring with clang-rename
+#include "MeshEntityTest.h"
+#include "BoundaryTagsTest.h"
+
+using namespace TNL;
+using namespace TNL::Meshes;
+
+
+template< typename Cell,
+          int WorldDimension = Cell::dimension,
+          typename Real = double,
+          typename GlobalIndex = int,
+          typename LocalIndex = GlobalIndex,
+          typename Id = void >
+struct MyMeshConfig
+   : public DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >
+{
+   static constexpr bool entityStorage( int dimension )
+   {
+      return true;
+//      return dimension == 0 || dimension == Cell::dimension;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool subentityStorage( EntityTopology, int SubentityDimension )
+   {
+//      return entityStorage( EntityTopology::dimension );
+      return entityStorage( EntityTopology::dimension ) &&
+             SubentityDimension == 0;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimension ) 
+   {
+      return false;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool superentityStorage( EntityTopology, int SuperentityDimension )
+   {
+//      return entityStorage( EntityTopology::dimension );
+      return entityStorage( EntityTopology::dimension ) &&
+             SuperentityDimension == Cell::dimension;
+   }
+
+   template< typename EntityTopology >
+   static constexpr bool boundaryTagsStorage( EntityTopology )
+   {
+      using BaseType = DefaultConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >;
+      using FaceTopology = typename Topologies::Subtopology< Cell, BaseType::meshDimension - 1 >::Topology;
+      return entityStorage( BaseType::meshDimension - 1 ) &&
+             superentityStorage( FaceTopology(), BaseType::meshDimension ) &&
+             ( EntityTopology::dimension >= BaseType::meshDimension - 1 || subentityStorage( FaceTopology(), EntityTopology::dimension ) );
+      //return false;
+   }
+};
+
+
+// specialization of BuildConfigTags
+struct MyBuildConfigTag {};
+
+namespace TNL {
+namespace Meshes {
+namespace BuildConfigTags {
+
+// disable grids
+template< int Dimension, typename Real, typename Device, typename Index >
+struct GridTag< MyBuildConfigTag, Grid< Dimension, Real, Device, Index > >
+{ enum { enabled = false }; };
+
+// enable all cell topologies
+template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Edge > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Triangle > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Quadrilateral > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Tetrahedron > { enum { enabled = true }; };
+template<> struct MeshCellTopologyTag< MyBuildConfigTag, Topologies::Hexahedron > { enum { enabled = true }; };
+
+template< typename CellTopology, int WorldDimension >
+struct MeshWorldDimensionTag< MyBuildConfigTag, CellTopology, WorldDimension >
+{ enum { enabled = ( WorldDimension == CellTopology::dimension ) }; };
+
+template< typename Real > struct MeshRealTag< MyBuildConfigTag, Real > { enum { enabled = false }; };
+template<> struct MeshRealTag< MyBuildConfigTag, float > { enum { enabled = true }; };
+template<> struct MeshRealTag< MyBuildConfigTag, double > { enum { enabled = true }; };
+
+template< typename GlobalIndex > struct MeshGlobalIndexTag< MyBuildConfigTag, GlobalIndex > { enum { enabled = false }; };
+template<> struct MeshGlobalIndexTag< MyBuildConfigTag, int > { enum { enabled = true }; };
+
+template< typename LocalIndex > struct MeshLocalIndexTag< MyBuildConfigTag, LocalIndex > { enum { enabled = false }; };
+template<> struct MeshLocalIndexTag< MyBuildConfigTag, short int > { enum { enabled = true }; };
+
+template<>
+struct MeshConfigTemplateTag< MyBuildConfigTag >
+{
+   template< typename Cell, int WorldDimension, typename Real, typename GlobalIndex, typename LocalIndex, typename Id >
+   using MeshConfig = MyMeshConfig< Cell, WorldDimension, Real, GlobalIndex, LocalIndex, Id >;
+};
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
+
+
+template< typename MeshType >
+class MeshTester
+{
+public:
+   static bool run( const String& fileName )
+   {
+      std::cout << "pre-init\t";
+      Debugging::printMemoryUsage();
+
+#ifdef HAVE_VTK
+      MeshType mesh_libvtk;
+      Readers::VTKReader_libvtk<> reader;
+      if( ! reader.readMesh( fileName, mesh_libvtk ) )
+         return false;
+
+      std::cout << "libvtk vertices: " << mesh_libvtk.template getEntitiesCount< 0 >() << std::endl;
+      std::cout << "libvtk faces: " << mesh_libvtk.template getEntitiesCount< MeshType::getMeshDimension() - 1 >() << std::endl;
+      std::cout << "libvtk cells: " << mesh_libvtk.template getEntitiesCount< MeshType::getMeshDimension() >() << std::endl;
+#endif
+
+      Timer timer;
+      timer.start();
+
+      MeshType mesh;
+      if( ! loadMesh( fileName, mesh ) )
+         return false;
+
+      timer.stop();
+      std::cout << "Loading took " << timer.getRealTime() << " seconds." << std::endl;
+
+      std::cout << "vertices: " << mesh.template getEntitiesCount< 0 >() << std::endl;
+      std::cout << "faces: " << mesh.template getEntitiesCount< MeshType::getMeshDimension() - 1 >() << std::endl;
+      std::cout << "cells: " << mesh.template getEntitiesCount< MeshType::getMeshDimension() >() << std::endl;
+
+      std::cout << "post-init\t";
+      Debugging::printMemoryUsage();
+
+#ifdef HAVE_VTK
+      std::cout << "mesh_libvtk == mesh: " << std::boolalpha << (mesh_libvtk == mesh) << std::endl;
+      if( mesh_libvtk != mesh ) {
+         std::cerr << "mesh_libvtk:\n" << mesh_libvtk << "\n\nmesh:\n" << mesh << std::endl;
+         return false;
+      }
+#endif
+
+#ifdef HAVE_GTEST 
+      std::cout << "Running basic I/O tests..." << std::endl;
+      MeshTest::testFinishedMesh( mesh );
+#endif
+//      mesh.save( "mesh-test.tnl" );
+
+      return true;
+   }
+};
+
+int main( int argc, char* argv[] )
+{
+   if( argc < 2 ) {
+      std::cerr << "Usage: " << argv[ 0 ] << " filename.[tnl|ng|vtk] ..." << std::endl;
+      return EXIT_FAILURE;
+   }
+
+   bool result = true;
+
+   for( int i = 1; i < argc; i++ ) {
+      String fileName = argv[ i ];
+      
+      result &= resolveMeshType< MyBuildConfigTag, Devices::Host, MeshTester >
+                  ( fileName,
+                    fileName  // passed to MeshTester::run
+                  );
+   }
+
+   std::cout << "final\t";
+   Debugging::printMemoryUsage();
+
+   return ! result;
+}
diff --git a/src/UnitTests/Meshes/MeshTest.cpp b/src/UnitTests/Meshes/MeshTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..93004f18d5245073d8d6811c1253acfd6cf7a509
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshTest.cpp
@@ -0,0 +1,11 @@
+#include "MeshTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/MeshTest.cu b/src/UnitTests/Meshes/MeshTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..93004f18d5245073d8d6811c1253acfd6cf7a509
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshTest.cu
@@ -0,0 +1,11 @@
+#include "MeshTest.h"
+
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   return EXIT_FAILURE;
+#endif
+}
diff --git a/src/UnitTests/Meshes/MeshTest.h b/src/UnitTests/Meshes/MeshTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..3835df28d5cae1ac07d952ed861474561f03c4f9
--- /dev/null
+++ b/src/UnitTests/Meshes/MeshTest.h
@@ -0,0 +1,811 @@
+#pragma once
+
+#ifdef HAVE_GTEST
+#include <gtest/gtest.h>
+
+#include <sstream>
+
+#include <TNL/Meshes/Mesh.h>
+#include <TNL/Meshes/MeshEntity.h>
+#include <TNL/Meshes/DefaultConfig.h>
+#include <TNL/Meshes/Topologies/Vertex.h>
+#include <TNL/Meshes/Topologies/Edge.h>
+#include <TNL/Meshes/Topologies/Triangle.h>
+#include <TNL/Meshes/Topologies/Quadrilateral.h>
+#include <TNL/Meshes/Topologies/Tetrahedron.h>
+#include <TNL/Meshes/Topologies/Hexahedron.h>
+#include <TNL/Meshes/MeshBuilder.h>
+
+namespace MeshTest {
+
+using namespace TNL;
+using namespace TNL::Meshes;
+
+using RealType = double;
+using Device = Devices::Host;
+using IndexType = int;
+
+class TestTriangleMeshConfig : public DefaultConfig< Topologies::Triangle >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   //template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+};
+
+class TestQuadrilateralMeshConfig : public DefaultConfig< Topologies::Quadrilateral >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) { return ( SubentityDimensions % 2 != 0 ); }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+};
+
+class TestTetrahedronMeshConfig : public DefaultConfig< Topologies::Tetrahedron >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) {  return ( SubentityDimensions % 2 != 0 ); }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+};
+
+class TestHexahedronMeshConfig : public DefaultConfig< Topologies::Hexahedron >
+{
+public:
+   static constexpr bool entityStorage( int dimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityStorage( EntityTopology, int SubentityDimensions ) { return true; }
+   template< typename EntityTopology > static constexpr bool subentityOrientationStorage( EntityTopology, int SubentityDimensions ) {  return ( SubentityDimensions % 2 != 0 ); }
+   template< typename EntityTopology > static constexpr bool superentityStorage( EntityTopology, int SuperentityDimensions ) { return true; }
+};
+
+template< typename Object1, typename Object2 >
+void compareStringRepresentation( const Object1& obj1, const Object2& obj2 )
+{
+   std::stringstream str1, str2;
+   str1 << obj1;
+   str2 << obj2;
+   EXPECT_EQ( str1.str(), str2.str() );
+}
+
+template< typename Object >
+void testCopyAssignment( const Object& obj )
+{
+   static_assert( std::is_copy_constructible< Object >::value, "" );
+   static_assert( std::is_copy_assignable< Object >::value, "" );
+
+   Object new_obj_1( obj );
+   EXPECT_EQ( new_obj_1, obj );
+   Object new_obj_2;
+   new_obj_2 = obj;
+   EXPECT_EQ( new_obj_2, obj );
+}
+
+template< typename Mesh >
+void testMeshOnCuda( const Mesh& mesh )
+{
+#ifdef HAVE_CUDA
+   using DeviceMesh = Meshes::Mesh< typename Mesh::Config, Devices::Cuda >;
+
+   // test host->CUDA copy
+   DeviceMesh dmesh1( mesh );
+   EXPECT_EQ( dmesh1, mesh );
+   DeviceMesh dmesh2;
+   dmesh2 = mesh;
+   EXPECT_EQ( dmesh2, mesh );
+
+   // test CUDA->CUDA copy
+   testCopyAssignment( dmesh1 );
+
+   // copy CUDA->host copy
+   Mesh mesh2( dmesh1 );
+   EXPECT_EQ( mesh2, mesh );
+   Mesh mesh3;
+   mesh3 = dmesh1;
+   EXPECT_EQ( mesh2, mesh );
+
+   // test load from file to CUDA
+   ASSERT_TRUE( mesh.save( "mesh.tnl" ) );
+   ASSERT_TRUE( dmesh1.load( "mesh.tnl" ) );
+   EXPECT_EQ( dmesh1, mesh );
+
+   // test save into file from CUDA
+   ASSERT_TRUE( dmesh1.save( "mesh.tnl" ) );
+   ASSERT_TRUE( mesh2.load( "mesh.tnl" ) );
+   EXPECT_EQ( mesh2, mesh );
+
+   EXPECT_EQ( std::remove( "mesh.tnl" ), 0 );
+#endif
+}
+
+template< typename Mesh >
+void testEntities( const Mesh& mesh )
+{
+   using IndexType = typename Mesh::GlobalIndexType;
+
+   // test that superentity accessors have been correctly bound
+   for( IndexType i = 0; i < mesh.template getEntitiesCount< 0 >(); i++ ) {
+      auto v1 = mesh.template getEntity< 0 >( i );
+      auto& v2 = mesh.template getEntity< 0 >( i );
+      EXPECT_EQ( v1, v2 );
+      EXPECT_EQ( v1.template getSuperentitiesCount< Mesh::getMeshDimension() >(),
+                 v2.template getSuperentitiesCount< Mesh::getMeshDimension() >() );
+      for( IndexType s = 0; s < v1.template getSuperentitiesCount< Mesh::getMeshDimension() >(); s++ )
+         EXPECT_EQ( v1.template getSuperentityIndex< Mesh::getMeshDimension() >( s ),
+                    v2.template getSuperentityIndex< Mesh::getMeshDimension() >( s ) );
+   }
+
+   // test that subentity accessors have been correctly bound
+   for( IndexType i = 0; i < mesh.template getEntitiesCount< Mesh::getMeshDimension() >(); i++ ) {
+      auto c1 = mesh.template getEntity< Mesh::getMeshDimension() >( i );
+      auto& c2 = mesh.template getEntity< Mesh::getMeshDimension() >( i );
+      EXPECT_EQ( c1, c2 );
+      EXPECT_EQ( c1.template getSubentitiesCount< 0 >(),
+                 c2.template getSubentitiesCount< 0 >() );
+      for( IndexType s = 0; s < c1.template getSubentitiesCount< 0 >(); s++ )
+         EXPECT_EQ( c1.template getSubentityIndex< 0 >( s ),
+                    c2.template getSubentityIndex< 0 >( s ) );
+   }
+}
+
+template< typename Mesh >
+void testFinishedMesh( const Mesh& mesh )
+{
+   Mesh mesh2;
+   ASSERT_TRUE( mesh.save( "mesh.tnl" ) );
+   ASSERT_TRUE( mesh2.load( "mesh.tnl" ) );
+   EXPECT_EQ( std::remove( "mesh.tnl" ), 0 );
+   ASSERT_EQ( mesh, mesh2 );
+   compareStringRepresentation( mesh, mesh2 );
+   testCopyAssignment( mesh );
+   testMeshOnCuda( mesh );
+   testEntities( mesh );
+}
+
+TEST( MeshTest, TwoTrianglesTest )
+{
+   using TriangleMeshEntityType = MeshEntity< TestTriangleMeshConfig, Devices::Host, Topologies::Triangle >;
+   using EdgeMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangle entity does not store edges as required." );
+   static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing triangle entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SubentityTraits< 0 >::storageEnabled, "Testing edge entity does not store vertices as required." );
+   static_assert( EdgeMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing edge entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 2 >::storageEnabled, "Testing vertex entity does not store triangles as required." );
+   static_assert( VertexMeshEntityType::SuperentityTraits< 1 >::storageEnabled, "Testing vertex entity does not store edges as required." );
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   /****
+    * 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 );
+
+   typedef Mesh< TestTriangleMeshConfig > TriangleTestMesh;
+   TriangleTestMesh mesh;
+   MeshBuilder< TriangleTestMesh > meshBuilder;
+   meshBuilder.setPointsCount( 4 );
+   meshBuilder.setPoint( 0, point0 );
+   meshBuilder.setPoint( 1, point1 );
+   meshBuilder.setPoint( 2, point2 );
+   meshBuilder.setPoint( 3, point3 );
+
+   meshBuilder.setCellsCount( 2 );
+   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 );
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   EXPECT_EQ( mesh.getEntitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.getEntitiesCount< 1 >(),  5 );
+   EXPECT_EQ( mesh.getEntitiesCount< 0 >(),  4 );
+
+   EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).getPoint(),  point0 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).getPoint(),  point1 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 2 ).getPoint(),  point2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 3 ).getPoint(),  point3 );
+
+   EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).getVertexIndex( 0 ),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).getVertexIndex( 1 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 1 ).getVertexIndex( 0 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 1 ).getVertexIndex( 1 ),  0 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 2 ).getVertexIndex( 0 ),  0 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 2 ).getVertexIndex( 1 ),  1 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 3 ).getVertexIndex( 0 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 3 ).getVertexIndex( 1 ),  3 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 4 ).getVertexIndex( 0 ),  3 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 4 ).getVertexIndex( 1 ),  1 );
+
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 0 ),  0 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 1 ),  1 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 0 >( 2 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 0 ),  0 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 1 ),  1 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 0 ).template getSubentityIndex< 1 >( 2 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 0 ),  1 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 1 ),  2 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 0 >( 2 ),  3 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 0 ),  3 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 1 ),  4 );
+   EXPECT_EQ( mesh.template getEntity< 2 >( 1 ).template getSubentityIndex< 1 >( 2 ),  0 );
+
+   /*
+    * Tests for the superentities layer.
+    */
+   ASSERT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentitiesCount< 1 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentityIndex< 1 >( 0 ),    1 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 0 ).template getSuperentityIndex< 1 >( 1 ),    2 );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentitiesCount< 1 >(),  3 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 0 ),    0 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 1 ),    2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 1 >( 2 ),    4 );
+
+   ASSERT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 2 >( 0 ),    0 );
+   EXPECT_EQ( mesh.template getEntity< 0 >( 1 ).template getSuperentityIndex< 2 >( 1 ),    1 );
+
+   ASSERT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentitiesCount< 2 >(),  2 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentityIndex< 2 >( 0 ),    0 );
+   EXPECT_EQ( mesh.template getEntity< 1 >( 0 ).template getSuperentityIndex< 2 >( 1 ),    1 );
+
+
+   testFinishedMesh( mesh );
+};
+
+TEST( MeshTest, TetrahedronsTest )
+{
+   using TetrahedronMeshEntityType = MeshEntity< TestTetrahedronMeshConfig, Devices::Host, Topologies::Tetrahedron >;
+   using TriangleMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 2 >::SubentityType;
+   using EdgeMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename TetrahedronMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 3, RealType >::getType() ) );
+
+   typedef Mesh< TestTetrahedronMeshConfig > TestTetrahedronMesh;
+   TestTetrahedronMesh mesh;
+   MeshBuilder< TestTetrahedronMesh > meshBuilder;
+   meshBuilder.setPointsCount( 13 );
+   meshBuilder.setPoint(  0, PointType(  0.000000, 0.000000, 0.000000 ) );
+   meshBuilder.setPoint(  1, PointType(  0.000000, 0.000000, 8.000000 ) );
+   meshBuilder.setPoint(  2, PointType(  0.000000, 8.000000, 0.000000 ) );
+   meshBuilder.setPoint(  3, PointType( 15.000000, 0.000000, 0.000000 ) );
+   meshBuilder.setPoint(  4, PointType(  0.000000, 8.000000, 8.000000 ) );
+   meshBuilder.setPoint(  5, PointType( 15.000000, 0.000000, 8.000000 ) );
+   meshBuilder.setPoint(  6, PointType( 15.000000, 8.000000, 0.000000 ) );
+   meshBuilder.setPoint(  7, PointType( 15.000000, 8.000000, 8.000000 ) );
+   meshBuilder.setPoint(  8, PointType(  7.470740, 8.000000, 8.000000 ) );
+   meshBuilder.setPoint(  9, PointType(  7.470740, 0.000000, 8.000000 ) );
+   meshBuilder.setPoint( 10, PointType(  7.504125, 8.000000, 0.000000 ) );
+   meshBuilder.setPoint( 11, PointType(  7.212720, 0.000000, 0.000000 ) );
+   meshBuilder.setPoint( 12, PointType( 11.184629, 3.987667, 3.985835 ) );
+
+   /****
+    * Setup the following tetrahedrons:
+    * ( Generated by Netgen )
+    *
+    *  12        8        7        5
+    *  12        7        8       10
+    *  12       11        8        9
+    *  10       11        2        8
+    *  12        7        6        5
+    *   9       12        5        8
+    *  12       11        9        3
+    *   9        4       11        8
+    *  12        9        5        3
+    *   1        2        0       11
+    *   8       11        2        4
+    *   1        2       11        4
+    *   9        4        1       11
+    *  10       11        8       12
+    *  12        6        7       10
+    *  10       11       12        3
+    *  12        6        3        5
+    *  12        3        6       10
+    */
+
+   meshBuilder.setCellsCount( 18 );
+    //  12        8        7        5
+   meshBuilder.getCellSeed( 0 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 1, 8 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 2, 7 );
+   meshBuilder.getCellSeed( 0 ).setCornerId( 3, 5 );
+
+    //  12        7        8       10
+   meshBuilder.getCellSeed( 1 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 1, 7 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 2, 8 );
+   meshBuilder.getCellSeed( 1 ).setCornerId( 3, 10 );
+
+    //  12       11        8        9
+   meshBuilder.getCellSeed( 2 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 2 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 2 ).setCornerId( 2, 8 );
+   meshBuilder.getCellSeed( 2 ).setCornerId( 3, 9 );
+
+    //  10       11        2        8
+   meshBuilder.getCellSeed( 3 ).setCornerId( 0, 10 );
+   meshBuilder.getCellSeed( 3 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 3 ).setCornerId( 2, 2 );
+   meshBuilder.getCellSeed( 3 ).setCornerId( 3, 8 );
+
+    //  12        7        6        5
+   meshBuilder.getCellSeed( 4 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 4 ).setCornerId( 1, 7 );
+   meshBuilder.getCellSeed( 4 ).setCornerId( 2, 6 );
+   meshBuilder.getCellSeed( 4 ).setCornerId( 3, 5 );
+
+    //   9       12        5        8
+   meshBuilder.getCellSeed( 5 ).setCornerId( 0, 9 );
+   meshBuilder.getCellSeed( 5 ).setCornerId( 1, 12 );
+   meshBuilder.getCellSeed( 5 ).setCornerId( 2, 5 );
+   meshBuilder.getCellSeed( 5 ).setCornerId( 3, 8 );
+
+    //  12       11        9        3
+   meshBuilder.getCellSeed( 6 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 6 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 6 ).setCornerId( 2, 9 );
+   meshBuilder.getCellSeed( 6 ).setCornerId( 3, 3 );
+
+    //   9        4       11        8
+   meshBuilder.getCellSeed( 7 ).setCornerId( 0, 9 );
+   meshBuilder.getCellSeed( 7 ).setCornerId( 1, 4 );
+   meshBuilder.getCellSeed( 7 ).setCornerId( 2, 11 );
+   meshBuilder.getCellSeed( 7 ).setCornerId( 3, 8 );
+
+    //  12        9        5        3
+   meshBuilder.getCellSeed( 8 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 8 ).setCornerId( 1, 9 );
+   meshBuilder.getCellSeed( 8 ).setCornerId( 2, 5 );
+   meshBuilder.getCellSeed( 8 ).setCornerId( 3, 3 );
+
+    //   1        2        0       11
+   meshBuilder.getCellSeed( 9 ).setCornerId( 0, 1 );
+   meshBuilder.getCellSeed( 9 ).setCornerId( 1, 2 );
+   meshBuilder.getCellSeed( 9 ).setCornerId( 2, 0 );
+   meshBuilder.getCellSeed( 9 ).setCornerId( 3, 11 );
+
+    //   8       11        2        4
+   meshBuilder.getCellSeed( 10 ).setCornerId( 0, 8 );
+   meshBuilder.getCellSeed( 10 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 10 ).setCornerId( 2, 2 );
+   meshBuilder.getCellSeed( 10 ).setCornerId( 3, 4 );
+
+    //   1        2       11        4
+   meshBuilder.getCellSeed( 11 ).setCornerId( 0, 1 );
+   meshBuilder.getCellSeed( 11 ).setCornerId( 1, 2 );
+   meshBuilder.getCellSeed( 11 ).setCornerId( 2, 11 );
+   meshBuilder.getCellSeed( 11 ).setCornerId( 3, 4 );
+
+    //   9        4        1       11
+   meshBuilder.getCellSeed( 12 ).setCornerId( 0, 9 );
+   meshBuilder.getCellSeed( 12 ).setCornerId( 1, 4 );
+   meshBuilder.getCellSeed( 12 ).setCornerId( 2, 1 );
+   meshBuilder.getCellSeed( 12 ).setCornerId( 3, 11 );
+
+    //  10       11        8       12
+   meshBuilder.getCellSeed( 13 ).setCornerId( 0, 10 );
+   meshBuilder.getCellSeed( 13 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 13 ).setCornerId( 2, 8 );
+   meshBuilder.getCellSeed( 13 ).setCornerId( 3, 12 );
+
+    //  12        6        7       10
+   meshBuilder.getCellSeed( 14 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 14 ).setCornerId( 1, 6 );
+   meshBuilder.getCellSeed( 14 ).setCornerId( 2, 7 );
+   meshBuilder.getCellSeed( 14 ).setCornerId( 3, 10 );
+
+    //  10       11       12        3
+   meshBuilder.getCellSeed( 15 ).setCornerId( 0, 10 );
+   meshBuilder.getCellSeed( 15 ).setCornerId( 1, 11 );
+   meshBuilder.getCellSeed( 15 ).setCornerId( 2, 12 );
+   meshBuilder.getCellSeed( 15 ).setCornerId( 3, 3 );
+
+    //  12        6        3        5
+   meshBuilder.getCellSeed( 16 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 16 ).setCornerId( 1, 6 );
+   meshBuilder.getCellSeed( 16 ).setCornerId( 2, 3 );
+   meshBuilder.getCellSeed( 16 ).setCornerId( 3, 5 );
+
+    //  12        3        6       10
+   meshBuilder.getCellSeed( 17 ).setCornerId( 0, 12 );
+   meshBuilder.getCellSeed( 17 ).setCornerId( 1, 3 );
+   meshBuilder.getCellSeed( 17 ).setCornerId( 2, 6 );
+   meshBuilder.getCellSeed( 17 ).setCornerId( 3, 10 );
+
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   testFinishedMesh( mesh );
+}
+
+TEST( MeshTest, RegularMeshOfTrianglesTest )
+{
+   using TriangleMeshEntityType = MeshEntity< TestTriangleMeshConfig, Devices::Host, Topologies::Triangle >;
+   using EdgeMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename TriangleMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   const IndexType xSize( 5 ), ySize( 5 );
+   const RealType width( 1.0 ), height( 1.0 );
+   const RealType hx( width / ( RealType ) xSize ),
+                  hy( height / ( RealType ) ySize );
+   const IndexType numberOfCells = 2 * xSize * ySize;
+   const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 );
+
+   typedef Mesh< TestTriangleMeshConfig > TestTriangleMesh;
+   Mesh< TestTriangleMeshConfig > mesh;
+   MeshBuilder< TestTriangleMesh > meshBuilder;
+   meshBuilder.setPointsCount( numberOfVertices );
+   meshBuilder.setCellsCount( numberOfCells );
+
+   /****
+    * Setup vertices
+    */
+   for( IndexType j = 0; j <= ySize; j++ )
+      for( IndexType i = 0; i <= xSize; i++ )
+         meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) );
+
+   /****
+    * Setup cells
+    */
+   IndexType cellIdx( 0 );
+   for( IndexType j = 0; j < ySize; j++ )
+      for( IndexType i = 0; i < xSize; i++ )
+      {
+         const IndexType vertex0 = j * ( xSize + 1 ) + i;
+         const IndexType vertex1 = j * ( xSize + 1 ) + i + 1;
+         const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i;
+         const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i + 1;
+
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex0 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex1 );
+         meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex2 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex1 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex2 );
+         meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex3 );
+      }
+
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   // Test cells -> vertices subentities
+   cellIdx = 0;
+   for( IndexType j = 0; j < ySize; j++ )
+      for( IndexType i = 0; i < xSize; i++ )
+      {
+         const IndexType vertex0 = j * ( xSize + 1 ) + i;
+         const IndexType vertex1 = j * ( xSize + 1 ) + i + 1;
+         const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i;
+         const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i + 1;
+
+         const TriangleMeshEntityType& leftCell = mesh.template getEntity< 2 >( cellIdx++ );
+         EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 0 ), vertex0 );
+         EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 1 ), vertex1 );
+         EXPECT_EQ( leftCell.template getSubentityIndex< 0 >( 2 ), vertex2 );
+
+         const TriangleMeshEntityType& rightCell = mesh.template getEntity< 2 >( cellIdx++ );
+         EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 0 ), vertex1 );
+         EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 1 ), vertex2 );
+         EXPECT_EQ( rightCell.template getSubentityIndex< 0 >( 2 ), vertex3 );
+      }
+
+   // Test vertices -> cells superentities
+   for( IndexType j = 0; j <= ySize; j++ )
+      for( IndexType i = 0; i <= xSize; i++ )
+      {
+         const IndexType vertexIndex = j * ( xSize + 1 ) + i;
+         const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex );
+
+         if( ( i == 0 && j == 0 ) || ( i == xSize && j == ySize ) ) {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 2 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 1 );
+         }
+         else if( ( i == 0 && j == ySize ) || ( i == xSize && j == 0 ) ) {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 2 );
+         }
+         else if( i == 0 || i == xSize || j == 0 || j == ySize ) {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 3 );
+         }
+         else {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 6 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 6 );
+         }
+      }
+
+   testFinishedMesh( mesh );
+}
+
+TEST( MeshTest, RegularMeshOfQuadrilateralsTest )
+{
+   using QuadrilateralMeshEntityType = MeshEntity< TestQuadrilateralMeshConfig, Devices::Host, Topologies::Quadrilateral >;
+   using EdgeMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename QuadrilateralMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) );
+
+   const IndexType xSize( 3 ), ySize( 4 );
+   const RealType width( 1.0 ), height( 1.0 );
+   const RealType hx( width / ( RealType ) xSize ),
+                  hy( height / ( RealType ) ySize );
+   const IndexType numberOfCells = xSize * ySize;
+   const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 );
+
+   typedef Mesh< TestQuadrilateralMeshConfig > TestQuadrilateralMesh;
+   TestQuadrilateralMesh mesh;
+   MeshBuilder< TestQuadrilateralMesh > meshBuilder;
+   meshBuilder.setPointsCount( numberOfVertices );
+   meshBuilder.setCellsCount( numberOfCells );
+
+   /****
+    * Setup vertices
+    */
+   for( IndexType j = 0; j <= ySize; j++ )
+      for( IndexType i = 0; i <= xSize; i++ )
+         meshBuilder.setPoint( j * ( xSize + 1 ) + i, PointType( i * hx, j * hy ) );
+
+   /****
+    * Setup cells
+    */
+   IndexType cellIdx( 0 );
+   for( IndexType j = 0; j < ySize; j++ )
+      for( IndexType i = 0; i < xSize; i++ )
+      {
+         const IndexType vertex0 = j * ( xSize + 1 ) + i;
+         const IndexType vertex1 = j * ( xSize + 1 ) + i + 1;
+         const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1;
+         const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i;
+
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex0 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex1 );
+         meshBuilder.getCellSeed( cellIdx   ).setCornerId( 2, vertex2 );
+         meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 3, vertex3 );
+      }
+
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   // Test cells -> vertices subentities
+   cellIdx = 0;
+   for( IndexType j = 0; j < ySize; j++ )
+      for( IndexType i = 0; i < xSize; i++ )
+      {
+         const IndexType vertex0 = j * ( xSize + 1 ) + i;
+         const IndexType vertex1 = j * ( xSize + 1 ) + i + 1;
+         const IndexType vertex2 = ( j + 1 ) * ( xSize + 1 ) + i + 1;
+         const IndexType vertex3 = ( j + 1 ) * ( xSize + 1 ) + i;
+
+         const QuadrilateralMeshEntityType& cell = mesh.template getEntity< 2 >( cellIdx++ );
+         EXPECT_EQ( cell.template getSubentityIndex< 0 >( 0 ), vertex0 );
+         EXPECT_EQ( cell.template getSubentityIndex< 0 >( 1 ), vertex1 );
+         EXPECT_EQ( cell.template getSubentityIndex< 0 >( 2 ), vertex2 );
+         EXPECT_EQ( cell.template getSubentityIndex< 0 >( 3 ), vertex3 );
+      }
+
+   // Test vertices -> cells superentities
+   for( IndexType j = 0; j <= ySize; j++ )
+      for( IndexType i = 0; i <= xSize; i++ )
+      {
+         const IndexType vertexIndex = j * ( xSize + 1 ) + i;
+         const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex );
+
+         if( ( i == 0 || i == xSize ) && ( j == 0 || j == ySize ) ) {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 2 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 1 );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ),   ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) );
+         }
+         else if( i == 0 || i == xSize || j == 0 || j == ySize ) {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 2 );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ),   ( j - ( j == ySize || i == 0 || i == xSize ) ) * xSize + i - ( i == xSize ) - ( j == 0 || j == ySize ) );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 1 ),   ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) );
+         }
+         else {
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 );
+            EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 4 );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 0 ),   ( j - 1 ) * xSize + i - 1 );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 1 ),   ( j - 1 ) * xSize + i     );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 2 ),   ( j     ) * xSize + i - 1 );
+            EXPECT_EQ( vertex.template getSuperentityIndex< 2 >( 3 ),   ( j     ) * xSize + i     );
+         }
+      }
+
+   testFinishedMesh( mesh );
+}
+
+TEST( MeshTest, RegularMeshOfHexahedronsTest )
+{
+   using HexahedronMeshEntityType = MeshEntity< TestHexahedronMeshConfig, Devices::Host, Topologies::Hexahedron >;
+   using QuadrilateralMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 2 >::SubentityType;
+   using EdgeMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 1 >::SubentityType;
+   using VertexMeshEntityType = typename HexahedronMeshEntityType::SubentityTraits< 0 >::SubentityType;
+
+   using PointType = typename VertexMeshEntityType::PointType;
+   ASSERT_TRUE( PointType::getType() == ( Containers::StaticVector< 3, RealType >::getType() ) );
+
+   const IndexType xSize( 3 ), ySize( 4 ), zSize( 5 );
+   const RealType width( 1.0 ), height( 1.0 ), depth( 1.0 );
+   const RealType hx( width / ( RealType ) xSize ),
+                  hy( height / ( RealType ) ySize ),
+                  hz( depth / ( RealType ) zSize );
+   const IndexType numberOfCells = xSize * ySize * zSize;
+   const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ) * ( zSize + 1 );
+
+   typedef Mesh< TestHexahedronMeshConfig > TestHexahedronMesh;
+   TestHexahedronMesh mesh;
+   MeshBuilder< TestHexahedronMesh > meshBuilder;
+   meshBuilder.setPointsCount( numberOfVertices );
+   meshBuilder.setCellsCount( numberOfCells );
+
+   /****
+    * Setup vertices
+    */
+   for( IndexType k = 0; k <= zSize; k++ )
+      for( IndexType j = 0; j <= ySize; j++ )
+         for( IndexType i = 0; i <= xSize; i++ )
+            meshBuilder.setPoint( k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i, PointType( i * hx, j * hy, k * hz ) );
+
+   /****
+    * Setup cells
+    */
+   IndexType cellIdx( 0 );
+   for( IndexType k = 0; k < zSize; k++ )
+      for( IndexType j = 0; j < ySize; j++ )
+         for( IndexType i = 0; i < xSize; i++ )
+         {
+            const IndexType vertex0 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i;
+            const IndexType vertex1 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1;
+            const IndexType vertex2 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1;
+            const IndexType vertex3 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i;
+            const IndexType vertex4 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i;
+            const IndexType vertex5 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1;
+            const IndexType vertex6 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1;
+            const IndexType vertex7 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i;
+
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex0 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex1 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 2, vertex2 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 3, vertex3 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 4, vertex4 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 5, vertex5 );
+            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 6, vertex6 );
+            meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 7, vertex7 );
+         }
+
+   ASSERT_TRUE( meshBuilder.build( mesh ) );
+
+   // Test cells -> vertices subentities
+   cellIdx = 0;
+   for( IndexType k = 0; k < zSize; k++ )
+      for( IndexType j = 0; j < ySize; j++ )
+         for( IndexType i = 0; i < xSize; i++ )
+         {
+            const IndexType vertex0 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i;
+            const IndexType vertex1 = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1;
+            const IndexType vertex2 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1;
+            const IndexType vertex3 = k * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i;
+            const IndexType vertex4 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i;
+            const IndexType vertex5 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i + 1;
+            const IndexType vertex6 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i + 1;
+            const IndexType vertex7 = ( k + 1 ) * ( xSize + 1 ) * ( ySize + 1 ) + ( j + 1 ) * ( xSize + 1 ) + i;
+
+            const HexahedronMeshEntityType& cell = mesh.template getEntity< 3 >( cellIdx++ );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 0 ), vertex0 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 1 ), vertex1 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 2 ), vertex2 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 3 ), vertex3 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 4 ), vertex4 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 5 ), vertex5 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 6 ), vertex6 );
+            EXPECT_EQ( cell.template getSubentityIndex< 0 >( 7 ), vertex7 );
+         }
+
+   // Test vertices -> cells superentities
+   for( IndexType k = 0; k < zSize; k++ )
+      for( IndexType j = 0; j <= ySize; j++ )
+         for( IndexType i = 0; i <= xSize; i++ )
+         {
+            const IndexType vertexIndex = k * ( xSize + 1 ) * ( ySize + 1 ) + j * ( xSize + 1 ) + i;
+            const VertexMeshEntityType& vertex = mesh.template getEntity< 0 >( vertexIndex );
+
+            if( ( i == 0 || i == xSize ) && ( j == 0 || j == ySize ) && ( k == 0 || k == zSize ) ) {
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 3 );
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 3 );
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 1 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) );
+            }
+            else if( i == 0 || i == xSize || j == 0 || j == ySize || k == 0 || k == zSize ) {
+               if( ( i != 0 && i != xSize && j != 0 && j != ySize ) ||
+                   ( i != 0 && i != xSize && k != 0 && k != zSize ) ||
+                   ( j != 0 && j != ySize && k != 0 && k != zSize ) )
+               {
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 5 );
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 8 );
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 4 );
+                  if( k == 0 || k == zSize ) {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i     );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j     ) * xSize + i - 1 );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j     ) * xSize + i     );
+                  }
+                  else if( j == 0 || j == ySize ) {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i     );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ),   ( k     ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ),   ( k     ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i     );
+                  }
+                  else {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - 1 ) * xSize * ySize + ( j     ) * xSize + i - ( i == xSize ) );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ),   ( k     ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ),   ( k     ) * xSize * ySize + ( j     ) * xSize + i - ( i == xSize ) );
+                  }
+               }
+               else {
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 4 );
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 5 );
+                  EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 2 );
+                  if( k != 0 && k != zSize ) {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - 1 ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k     ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - ( i == xSize ) );
+                  }
+                  else if( j != 0 && j != ySize ) {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - 1 ) * xSize + i - ( i == xSize ) );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j     ) * xSize + i - ( i == xSize ) );
+                  }
+                  else {
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i - 1 );
+                     EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - ( k == zSize ) ) * xSize * ySize + ( j - ( j == ySize ) ) * xSize + i     );
+                  }
+               }
+            }
+            else {
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 1 >(), 6 );
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 2 >(), 12 );
+               EXPECT_EQ( vertex.template getSuperentitiesCount< 3 >(), 8 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 0 ),   ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 1 ),   ( k - 1 ) * xSize * ySize + ( j - 1 ) * xSize + i     );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 2 ),   ( k - 1 ) * xSize * ySize + ( j     ) * xSize + i - 1 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 3 ),   ( k - 1 ) * xSize * ySize + ( j     ) * xSize + i     );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 4 ),   ( k     ) * xSize * ySize + ( j - 1 ) * xSize + i - 1 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 5 ),   ( k     ) * xSize * ySize + ( j - 1 ) * xSize + i     );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 6 ),   ( k     ) * xSize * ySize + ( j     ) * xSize + i - 1 );
+               EXPECT_EQ( vertex.template getSuperentityIndex< 3 >( 7 ),   ( k     ) * xSize * ySize + ( j     ) * xSize + i     );
+            }
+         }
+
+   testFinishedMesh( mesh );
+}
+
+} // namespace MeshTest
+
+#endif
diff --git a/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp
index 7f62d6df15b3daef7c67a59706b196f78c9af91b..77dbc74663330dd2d8d4d7fa32576d99c933c485 100644
--- a/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp
+++ b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp
@@ -21,6 +21,8 @@ using namespace TNL::Functions;
 using namespace TNL::Devices;
 
 
+#define FILENAME "./test-file.tnl"
+
 //=====================================TEST CLASS==============================================
 
 template <int dim>
@@ -60,9 +62,9 @@ class TestSaveAndLoadMeshfunction
             linearFunctionEvaluator.evaluateAllEntities(localMeshFunctionptr , linearFunctionPtr);
 
             File file;
-            file.open( String( "./test-file.tnl"), IOMode::write );        
-            localMeshFunctionptr->save(file);        
-            file.close();
+            ASSERT_TRUE( file.open( String( FILENAME), IOMode::write ));        
+            ASSERT_TRUE( localMeshFunctionptr->save(file));        
+            ASSERT_TRUE( file.close() );
 
             //load other meshfunction on same localgrid from created file
             SharedPointer<MeshType>  loadGridptr;
@@ -78,15 +80,17 @@ class TestSaveAndLoadMeshfunction
                 loadDof[i]=-1;
             }
 
-            file.open( String( "./test-file.tnl" ), IOMode::read );
-            loadMeshFunctionptr->boundLoad(file);
-            file.close();
+            ASSERT_TRUE(  file.open( String( FILENAME ), IOMode::read ));
+            ASSERT_TRUE( loadMeshFunctionptr->boundLoad(file));
+            ASSERT_TRUE( file.close());
 
             for(int i=0;i<localDof.getSize();i++)
             {
                 EXPECT_EQ( localDof[i], loadDof[i]) << "Compare Loaded and evaluated Dof Failed for: "<< i;
             }
 
+            EXPECT_EQ( std::remove( FILENAME ), 0 );
+
         };
 };
 
diff --git a/tests/benchmarks/CMakeLists.txt b/tests/benchmarks/CMakeLists.txt
index b4a926ac3fae4d68feab1d4a2d74f0cba25e6bda..12fe883c8c50bb59fd1724a528197fc3a394cf2f 100644
--- a/tests/benchmarks/CMakeLists.txt
+++ b/tests/benchmarks/CMakeLists.txt
@@ -3,9 +3,7 @@ ADD_SUBDIRECTORY( heat-equation-benchmark )
 
 IF( BUILD_CUDA )
     CUDA_ADD_EXECUTABLE( tnl-benchmark-blas tnl-benchmark-blas.cu )
-    if( HAVE_CUBLAS STREQUAL "yes" )
-        CUDA_ADD_CUBLAS_TO_TARGET( tnl-benchmark-blas )
-    endif()
+    CUDA_ADD_CUBLAS_TO_TARGET( tnl-benchmark-blas )
     TARGET_LINK_LIBRARIES( tnl-benchmark-blas tnl ${CUSPARSE_LIBRARY} )
 
     CUDA_ADD_EXECUTABLE( tnl-benchmark-spmv tnl-benchmark-spmv.cu )
diff --git a/tests/benchmarks/cublasWrappers.h b/tests/benchmarks/cublasWrappers.h
index a7520a34d5d13ced796d8b2366b0382887f09a49..6b71a4ed7befc12664440cf5425f5975e6feec0c 100644
--- a/tests/benchmarks/cublasWrappers.h
+++ b/tests/benchmarks/cublasWrappers.h
@@ -1,7 +1,6 @@
 #pragma once
 
 #ifdef HAVE_CUDA
-#ifdef HAVE_CUBLAS
 
 #include <cublas_v2.h>
 
@@ -120,4 +119,3 @@ cublasGscal( cublasHandle_t handle, int n,
 }
 
 #endif
-#endif
diff --git a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h
index 96a18586f5a8f03b149f9227b776dca6396be9e6..8bdf9634ebea6a9951b4bcfea2adcdbbc070d2a9 100644
--- a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h
+++ b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkBuildConfigTag.h
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <TNL/Solvers/BuildConfigTags.h>
+#include <TNL/Meshes/BuildConfigTags.h>
 
 namespace TNL {
 
@@ -20,16 +21,6 @@ template<> struct ConfigTagReal< HeatEquationBenchmarkBuildConfigTag, long doubl
 template<> struct ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, short int >{ enum { enabled = false }; };
 template<> struct ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, long int >{ enum { enabled = false }; };
 
-/****
- * Use of Grid is enabled for allowed dimensions and Real, Device and Index types.
- */
-template< int Dimension, typename Real, typename Device, typename Index >
-   struct ConfigTagMesh< HeatEquationBenchmarkBuildConfigTag, Meshes::Grid< Dimension, Real, Device, Index > >
-      { enum { enabled = ( Dimension == 2 )  &&
-                         ConfigTagReal< HeatEquationBenchmarkBuildConfigTag, Real >::enabled &&
-                         ConfigTagDevice< HeatEquationBenchmarkBuildConfigTag, Device >::enabled &&
-                         ConfigTagIndex< HeatEquationBenchmarkBuildConfigTag, Index >::enabled }; };
-
 /****
  * Please, chose your preferred time discretisation  here.
  */
@@ -44,5 +35,24 @@ template<> struct ConfigTagExplicitSolver< HeatEquationBenchmarkBuildConfigTag,
 template<> struct ConfigTagExplicitSolver< HeatEquationBenchmarkBuildConfigTag, ExplicitMersonSolverTag >{ enum { enabled = false }; };
 
 } // namespace Solvers
-} // namespace TNL
 
+namespace Meshes {
+namespace BuildConfigTags {
+
+template< int Dimensions > struct GridDimensionTag< HeatEquationBenchmarkBuildConfigTag, Dimensions >{ enum { enabled = ( Dimensions == 2 ) }; };
+
+/****
+ * Turn off support for float and long double.
+ */
+template<> struct GridRealTag< HeatEquationBenchmarkBuildConfigTag, float > { enum { enabled = false }; };
+template<> struct GridRealTag< HeatEquationBenchmarkBuildConfigTag, long double > { enum { enabled = false }; };
+
+/****
+ * Turn off support for short int and long int indexing.
+ */
+template<> struct GridIndexTag< HeatEquationBenchmarkBuildConfigTag, short int >{ enum { enabled = false }; };
+template<> struct GridIndexTag< HeatEquationBenchmarkBuildConfigTag, long int >{ enum { enabled = false }; };
+
+} // namespace BuildConfigTags
+} // namespace Meshes
+} // namespace TNL
diff --git a/tests/benchmarks/vector-operations.h b/tests/benchmarks/vector-operations.h
index 2a1f51465bc6ecd93820933b01c51dc9d12c2213..cdf2443964a5bb33354de6e0ec0688018c7128a1 100644
--- a/tests/benchmarks/vector-operations.h
+++ b/tests/benchmarks/vector-operations.h
@@ -18,7 +18,7 @@
 
 #include <TNL/Containers/Vector.h>
 
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
 #include "cublasWrappers.h"
 #endif
 
@@ -51,7 +51,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
 
     Real resultHost, resultDevice;
 
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     cublasHandle_t cublasHandle;
     cublasCreate( &cublasHandle );
 #endif
@@ -153,7 +153,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto absMaxCuda = [&]() {
         resultDevice = deviceVector.absMax();
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto absMaxCublas = [&]() {
         int index = 0;
         cublasIgamax( cublasHandle, size,
@@ -167,10 +167,8 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU (general)", absMaxHostGeneral );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", absMaxCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", absMaxCublas );
 #endif
-#endif
 
 
     auto absMinHost = [&]() {
@@ -190,7 +188,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto absMinCuda = [&]() {
         resultDevice = deviceVector.absMin();
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto absMinCublas = [&]() {
         int index = 0;
         cublasIgamin( cublasHandle, size,
@@ -204,10 +202,8 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU (general)", absMinHostGeneral );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", absMinCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", absMinCublas );
 #endif
-#endif
 
 
     auto sumHost = [&]() {
@@ -252,7 +248,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto l1normCuda = [&]() {
         resultDevice = deviceVector.lpNorm( 1.0 );
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto l1normCublas = [&]() {
         cublasGasum( cublasHandle, size,
                      deviceVector.getData(), 1,
@@ -264,10 +260,8 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU (general)", l1normHostGeneral );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", l1normCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", l1normCublas );
 #endif
-#endif
 
 
     auto l2normHost = [&]() {
@@ -287,7 +281,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto l2normCuda = [&]() {
         resultDevice = deviceVector.lpNorm( 2.0 );
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto l2normCublas = [&]() {
         cublasGnrm2( cublasHandle, size,
                      deviceVector.getData(), 1,
@@ -299,10 +293,8 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU (general)", l2normHostGeneral );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", l2normCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", l2normCublas );
 #endif
-#endif
 
 
     auto l3normHost = [&]() {
@@ -348,7 +340,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto scalarProductCuda = [&]() {
         resultDevice = deviceVector.scalarProduct( deviceVector2 );
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto scalarProductCublas = [&]() {
         cublasGdot( cublasHandle, size,
                     deviceVector.getData(), 1,
@@ -361,9 +353,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU (general)", scalarProductHostGeneral );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", scalarProductCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", scalarProductCublas );
-#endif
 #endif
 
     /*
@@ -402,7 +392,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto multiplyCuda = [&]() {
         deviceVector *= 0.5;
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto multiplyCublas = [&]() {
         const Real alpha = 0.5;
         cublasGscal( cublasHandle, size,
@@ -414,10 +404,8 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU", multiplyHost );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", multiplyCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", multiplyCublas );
 #endif
-#endif
 
 
     auto addVectorHost = [&]() {
@@ -426,7 +414,7 @@ benchmarkVectorOperations( Benchmark & benchmark,
     auto addVectorCuda = [&]() {
         deviceVector.addVector( deviceVector2 );
     };
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     auto addVectorCublas = [&]() {
         const Real alpha = 1.0;
         cublasGaxpy( cublasHandle, size,
@@ -439,13 +427,11 @@ benchmarkVectorOperations( Benchmark & benchmark,
     benchmark.time( reset1, "CPU", addVectorHost );
 #ifdef HAVE_CUDA
     benchmark.time( reset1, "GPU", addVectorCuda );
-#ifdef HAVE_CUBLAS
     benchmark.time( reset1, "cuBLAS", addVectorCublas );
 #endif
-#endif
 
 
-#ifdef HAVE_CUBLAS
+#ifdef HAVE_CUDA
     cublasDestroy( cublasHandle );
 #endif
 
diff --git a/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp b/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp
index ec475d71e5014fe7e4b71a141477b26887f725b2..89eabd1314015c26f45b175cca92cbe60daf093f 100644
--- a/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp
+++ b/tests/unit-tests/core/multimaps/tnlEllpackIndexMultimapTest.cpp
@@ -12,7 +12,7 @@
 #include <TNL/Devices/Host.h>
 #include <cstdlib>
 
-#include <TNL/Experimental/Multimaps/EllpackIndexMultimap.h>
+#include <TNL/Containers/Multimaps/EllpackIndexMultimap.h>
 #include "tnlIndexMultimapTester.h"
 #include "../../tnlUnitTestStarter.h"
 
diff --git a/tests/unit-tests/mesh/CMakeLists.txt b/tests/unit-tests/mesh/CMakeLists.txt
index d21424d8158129d097665bae61176556cae09048..1d2f3cba628067eaeb6de6ffc98bfc7101c0b560 100644
--- a/tests/unit-tests/mesh/CMakeLists.txt
+++ b/tests/unit-tests/mesh/CMakeLists.txt
@@ -1,17 +1,4 @@
-set( headers tnlGridTester.h
-             tnlMeshEntityTester.h
-             tnlMeshTester.h )
+set( headers tnlGridTester.h )
 
-ADD_EXECUTABLE( tnlGridTest${mpiExt} ${headers} tnlGridTest.cpp )
-TARGET_LINK_LIBRARIES( tnlGridTest${mpiExt} ${CPPUNIT_LIBRARIES}
-                                                       tnl${mpiExt} )
-
-#ADD_EXECUTABLE( tnlMeshEntityTest${mpiExt} ${headers} tnlMeshEntityTest.cpp )
-#TARGET_LINK_LIBRARIES( MeshEntityTest${mpiExt} ${CPPUNIT_LIBRARIES}
-#                                                              tnl${mpiExt} )
-
-ADD_EXECUTABLE( tnlMeshTest${mpiExt} ${headers} tnlMeshTest.cpp )
-TARGET_LINK_LIBRARIES( tnlMeshTest${mpiExt} ${CPPUNIT_LIBRARIES}
-                                                              tnl${mpiExt} )
-
-                                                              
+ADD_EXECUTABLE( tnlGridTest ${headers} tnlGridTest.cpp )
+TARGET_LINK_LIBRARIES( tnlGridTest ${CPPUNIT_LIBRARIES} tnl )
diff --git a/tests/unit-tests/mesh/tnlMeshEntityTest.cpp b/tests/unit-tests/mesh/tnlMeshEntityTest.cpp
deleted file mode 100644
index a5333f1a64f27240e4bebfce95ea322cb765ad0c..0000000000000000000000000000000000000000
--- a/tests/unit-tests/mesh/tnlMeshEntityTest.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
-                          MeshEntityTest.cpp  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#include <TNL/tnlConfig.h>
-#include <TNL/Devices/Host.h>
-#include <cstdlib>
-
-#ifndef HAVE_NOT_CXX11
-#include "MeshEntityTester.h"
-#endif
-#include "../tnlUnitTestStarter.h"
-
-int main( int argc, char* argv[] )
-{
-#ifndef HAVE_NOT_CXX11
-#ifdef HAVE_CPPUNIT
-   if( ! tnlUnitTestStarter :: run< MeshEntityTester< double, Devices::Host, long int > >()
-       )
-     return EXIT_FAILURE;
-   return EXIT_SUCCESS;
-#else
-   return EXIT_FAILURE;
-#endif
-#endif
-}
-
-
diff --git a/tests/unit-tests/mesh/tnlMeshEntityTester.h b/tests/unit-tests/mesh/tnlMeshEntityTester.h
deleted file mode 100644
index a62dd4eefeb73154a114a0491783cf2f9a6e300b..0000000000000000000000000000000000000000
--- a/tests/unit-tests/mesh/tnlMeshEntityTester.h
+++ /dev/null
@@ -1,494 +0,0 @@
-/***************************************************************************
-                          MeshEntityTester.h  -  description
-                             -------------------
-    begin                : Feb 11, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#ifndef TNLMESHENTITYTESTER_H_
-#define TNLMESHENTITYTESTER_H_
-
-#ifdef HAVE_CPPUNIT
-#include <cppunit/TestSuite.h>
-#include <cppunit/TestResult.h>
-#include <cppunit/TestCaller.h>
-#include <cppunit/TestCase.h>
-#include <cppunit/Message.h>
-#include <TNL/Meshes/MeshEntity.h>
-#include <TNL/Meshes/MeshDetails/config/MeshConfigBase.h>
-#include <TNL/Meshes/Topologies/MeshVertexTopology.h>
-#include <TNL/Meshes/Topologies/MeshEdgeTopology.h>
-#include <TNL/Meshes/Topologies/MeshTriangleTopology.h>
-#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h>
- 
-using namespace TNL;
-
-//typedef MeshConfigBase< MeshTriangleTopology, 2, double, int, int, void > TestTriangleEntityTopology;
-typedef MeshConfigBase< MeshEdgeTopology, 2, double, int, int, void > TestEdgeEntityTopology;
-typedef MeshConfigBase< MeshVertexTopology, 2, double, int, int, void > TestVertexEntityTopology;
-
-class TestTriangleMeshConfig : public MeshConfigBase< MeshTriangleTopology >
-{
-   public:
- 
-      template< typename MeshEntity >
-      static constexpr bool subentityStorage( MeshEntity entity, int subentityDimension )
-      {
-         return true;
-      }
- 
-      template< typename MeshEntity >
-      static constexpr bool superentityStorage( MeshEntity entity, int superentityDimension )
-      {
-         return true;
-      }
-};
-
-class TestTetrahedronMeshConfig : public MeshConfigBase< MeshTetrahedronTopology >
-{
-   public:
- 
-      template< typename MeshEntity >
-      static constexpr bool subentityStorage( MeshEntity entity, int subentityDimension )
-      {
-         return true;
-      }
- 
-      template< typename MeshEntity >
-      static constexpr bool superentityStorage( MeshEntity entity, int superentityDimension )
-      {
-         return true;
-      }
-};
-
-template< typename RealType, typename Device, typename IndexType >
-class MeshEntityTester : public CppUnit :: TestCase
-{
-   public:
-   typedef MeshEntityTester< RealType, Device, IndexType > TesterType;
-   typedef typename CppUnit::TestCaller< TesterType > TestCallerType;
-
-   MeshEntityTester(){};
-
-   virtual
-   ~MeshEntityTester(){};
-
-   static CppUnit :: Test* suite()
-   {
-      CppUnit :: TestSuite* suiteOfTests = new CppUnit :: TestSuite( "MeshEntityTester" );
-      CppUnit :: TestResult result;
-
-      suiteOfTests -> addTest( new TestCallerType( "vertexMeshEntityTest", &TesterType::vertexMeshEntityTest ) );
-      suiteOfTests -> addTest( new TestCallerType( "edgeMeshEntityTest", &TesterType::edgeMeshEntityTest ) );
-      suiteOfTests -> addTest( new TestCallerType( "triangleMeshEntityTest", &TesterType::triangleMeshEntityTest ) );
-      suiteOfTests -> addTest( new TestCallerType( "tetrahedronMeshEntityTest", &TesterType::tetrahedronMeshEntityTest ) );
-      suiteOfTests -> addTest( new TestCallerType( "twoTrianglesTest", &TesterType::twoTrianglesTest ) );
-
-      return suiteOfTests;
-   }
- 
-
-   void vertexMeshEntityTest()
-   {
-      typedef MeshConfigBase< MeshEdgeTopology, 2, RealType, IndexType, IndexType, void > TestEntityTopology;
-      typedef MeshEntity< TestEntityTopology, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-
-      CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) );
-      VertexMeshEntityType vertexEntity;
-      PointType point;
-
-      point.x() = 1.0;
-      point.y() = 2.0;
-      vertexEntity.setPoint( point );
-      CPPUNIT_ASSERT( vertexEntity.getPoint() == point );
-   }
-
-   void edgeMeshEntityTest()
-   {
-      typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestEdgeEntityTopology, MeshVertexTopology > VertexMeshEntityType;
- 
-      typedef typename VertexMeshEntityType::PointType PointType;
-      CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) );
-
-      /****
-       *
-       * Here we test the following simple example:
-       *
- 
-                point2
-                   |\
-                   | \
-                   |  \
-                   |   \
- 
-                     ....
-                edge1     edge0
-                     ....
-
-
-                   |                 \
-                   |                  \
-                   ---------------------
-                point0   edge2        point1
-
-       */
- 
-      PointType point0( 0.0, 0.0 ),
-                point1( 1.0, 0.0 ),
-                point2( 0.0, 1.0 );
- 
-      StaticArray< 3, VertexMeshEntityType > vertexEntities;
-      vertexEntities[ 0 ].setPoint( point0 );
-      vertexEntities[ 1 ].setPoint( point1 );
-      vertexEntities[ 2 ].setPoint( point2 );
-
-      CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 );
-      CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 );
-      CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 );
-
-      StaticArray< 3, EdgeMeshEntityType > edgeEntities;
-      edgeEntities[ 0 ].setVertexIndex( 0, 0 );
-      edgeEntities[ 0 ].setVertexIndex( 1, 1 );
-      edgeEntities[ 1 ].setVertexIndex( 0, 1 );
-      edgeEntities[ 1 ].setVertexIndex( 1, 2 );
-      edgeEntities[ 2 ].setVertexIndex( 0, 2 );
-      edgeEntities[ 2 ].setVertexIndex( 1, 0 );
-      edgeEntities[ 0 ].setId( 0 );
-      edgeEntities[ 1 ].setId( 1 );
-      edgeEntities[ 2 ].setId( 2 );
-
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 0 ) ].getPoint() == point0 );
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 0 ].getVertexIndex( 1 ) ].getPoint() == point1 );
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 0 ) ].getPoint() == point1 );
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 1 ].getVertexIndex( 1 ) ].getPoint() == point2 );
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 0 ) ].getPoint() == point2 );
-      CPPUNIT_ASSERT( vertexEntities[ edgeEntities[ 2 ].getVertexIndex( 1 ) ].getPoint() == point0 );
-   }
-
-   void triangleMeshEntityTest()
-   {
-      typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-
-      static_assert( TriangleMeshEntityType::SubentityTraits< 1 >::storageEnabled, "Testing triangular mesh does not store edges as required." );
-      static_assert( TriangleMeshEntityType::SubentityTraits< 0 >::storageEnabled, "" );
-      typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestVertexEntityTopology, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-      CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) );
-
-      /****
-       * We set-up the same situation as in the test above
-       */
-      PointType point0( 0.0, 0.0 ),
-                point1( 1.0, 0.0 ),
-                point2( 0.0, 1.0 );
-
-      StaticArray< 3, VertexMeshEntityType > vertexEntities;
-      vertexEntities[ 0 ].setPoint( point0 );
-      vertexEntities[ 1 ].setPoint( point1 );
-      vertexEntities[ 2 ].setPoint( point2 );
-
-      CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 );
-      CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 );
-      CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 );
-
-      StaticArray< 3, EdgeMeshEntityType > edgeEntities;
-      edgeEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0 >::index );
-      edgeEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1 >::index );
-      edgeEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0 >::index );
-      edgeEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1 >::index );
-      edgeEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0 >::index );
-      edgeEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1 >::index );
-
-      CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 0, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 1, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTriangleTopology, MeshEdgeTopology, 2, 1 >::index ) );
-
-      TriangleMeshEntityType triangleEntity;
-
-      triangleEntity.template setSubentityIndex< 0 >( 0 , 0 );
-      triangleEntity.template setSubentityIndex< 0 >( 1 , 1 );
-      triangleEntity.template setSubentityIndex< 0 >( 2 , 2 );
-
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 0 ) == 0 );
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 1 ) == 1 );
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 0 >( 2 ) == 2 );
-
-      triangleEntity.template setSubentityIndex< 1 >( 0 , 0 );
-      triangleEntity.template setSubentityIndex< 1 >( 1 , 1 );
-      triangleEntity.template setSubentityIndex< 1 >( 2 , 2 );
-
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 0 ) == 0 );
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 1 ) == 1 );
-      CPPUNIT_ASSERT( triangleEntity.template getSubentityIndex< 1 >( 2 ) == 2 );
-   };
-
-   void tetrahedronMeshEntityTest()
-   {
-      //typedef MeshConfigBase< MeshTetrahedronTopology, 3, RealType, IndexType, IndexType, void > TestTetrahedronEntityTopology;
-      typedef MeshConfigBase< MeshTriangleTopology, 3, RealType, IndexType, IndexType, void > TestTriangleEntityTopology;
-      typedef MeshConfigBase< MeshEdgeTopology, 3, RealType, IndexType, IndexType, void > TestEdgeEntityTopology;
-      typedef MeshConfigBase< MeshVertexTopology, 3, RealType, IndexType, IndexType, void > TestVertexEntityTopology;
-
-      typedef MeshEntity< TestTetrahedronMeshConfig, MeshTetrahedronTopology > TetrahedronMeshEntityType;
-      typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-      typedef MeshEntity< TestEdgeEntityTopology, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestVertexEntityTopology, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-      CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 3, RealType >::getType() ) );
-
-      /****
-       * We set-up similar situation as above but with
-       * tetrahedron.
-       */
-      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 );
- 
-      StaticArray< MeshSubtopology< MeshTetrahedronTopology, 0 >::count,
-                      VertexMeshEntityType > vertexEntities;
-
-      vertexEntities[ 0 ].setPoint( point0 );
-      vertexEntities[ 1 ].setPoint( point1 );
-      vertexEntities[ 2 ].setPoint( point2 );
-      vertexEntities[ 3 ].setPoint( point3 );
-
-      CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 );
-      CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 );
-      CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 );
-      CPPUNIT_ASSERT( vertexEntities[ 3 ].getPoint() == point3 );
-
-      StaticArray< MeshSubtopology< MeshTetrahedronTopology, 1 >::count,
-                      EdgeMeshEntityType > edgeEntities;
-      edgeEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0 >::index );
-      edgeEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1 >::index );
-      edgeEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0 >::index );
-      edgeEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1 >::index );
-      edgeEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0 >::index );
-      edgeEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1 >::index );
-      edgeEntities[ 3 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0 >::index );
-      edgeEntities[ 3 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1 >::index );
-      edgeEntities[ 4 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0 >::index );
-      edgeEntities[ 4 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1 >::index );
-      edgeEntities[ 5 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0 >::index );
-      edgeEntities[ 5 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1 >::index );
-
-      CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 0, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 1, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 2, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 3, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 4, 1 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 5 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 0 >::index ) );
-      CPPUNIT_ASSERT( edgeEntities[ 5 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshEdgeTopology, 5, 1 >::index ) );
-
-      StaticArray< MeshSubtopology< MeshTetrahedronTopology, 2 >::count,
-                      TriangleMeshEntityType > triangleEntities;
-      triangleEntities[ 0 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0 >::index );
-      triangleEntities[ 0 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1 >::index );
-      triangleEntities[ 0 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2 >::index );
-      triangleEntities[ 1 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0 >::index );
-      triangleEntities[ 1 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1 >::index );
-      triangleEntities[ 1 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2 >::index );
-      triangleEntities[ 2 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0 >::index );
-      triangleEntities[ 2 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1 >::index );
-      triangleEntities[ 2 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2 >::index );
-      triangleEntities[ 3 ].setVertexIndex( 0, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 0 >::index );
-      triangleEntities[ 3 ].setVertexIndex( 1, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 1 >::index );
-      triangleEntities[ 3 ].setVertexIndex( 2, tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 3, 2 >::index );
-
-      CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 0 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 1 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 0 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 0, 2 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 0 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 1 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 1 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 1, 2 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 0 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 0 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 1 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 1 >::index ) );
-      CPPUNIT_ASSERT( triangleEntities[ 2 ].getVertexIndex( 2 ) == ( tnlSubentityVertex< MeshTetrahedronTopology, MeshTriangleTopology, 2, 2 >::index ) );
-
-      TetrahedronMeshEntityType tetrahedronEntity;
-      tetrahedronEntity.setVertexIndex( 0, 0 );
-      tetrahedronEntity.setVertexIndex( 1, 1 );
-      tetrahedronEntity.setVertexIndex( 2, 2 );
-      tetrahedronEntity.setVertexIndex( 3, 3 );
-
-      CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 0 ) == 0 );
-      CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 1 ) == 1 );
-      CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 2 ) == 2 );
-      CPPUNIT_ASSERT( tetrahedronEntity.getVertexIndex( 3 ) == 3 );
-
-      tetrahedronEntity.template setSubentityIndex< 2 >( 0, 0 );
-      tetrahedronEntity.template setSubentityIndex< 2 >( 1, 1 );
-      tetrahedronEntity.template setSubentityIndex< 2 >( 2, 2 );
-      tetrahedronEntity.template setSubentityIndex< 2 >( 3, 3 );
-
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 0 ) == 0 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 1 ) == 1 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 2 ) == 2 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 2 >( 3 ) == 3 );
-
-      tetrahedronEntity.template setSubentityIndex< 1 >( 0, 0 );
-      tetrahedronEntity.template setSubentityIndex< 1 >( 1, 1 );
-      tetrahedronEntity.template setSubentityIndex< 1 >( 2, 2 );
-      tetrahedronEntity.template setSubentityIndex< 1 >( 3, 3 );
-      tetrahedronEntity.template setSubentityIndex< 1 >( 4, 4 );
-      tetrahedronEntity.template setSubentityIndex< 1 >( 5, 5 );
-
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 0 ) == 0 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 1 ) == 1 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 2 ) == 2 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 3 ) == 3 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 4 ) == 4 );
-      CPPUNIT_ASSERT( tetrahedronEntity.template getSubentityIndex< 1 >( 5 ) == 5 );
-   };
-
-   void twoTrianglesTest()
-   {
-
-       typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-       typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-       typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-       typedef typename VertexMeshEntityType::PointType PointType;
-       CPPUNIT_ASSERT( PointType::getType() == ( StaticVector< 2, RealType >::getType() ) );
-
-       /****
-        * 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 );
-
-       StaticArray< 4, VertexMeshEntityType > vertexEntities;
-       vertexEntities[ 0 ].setPoint( point0 );
-       vertexEntities[ 1 ].setPoint( point1 );
-       vertexEntities[ 2 ].setPoint( point2 );
-       vertexEntities[ 3 ].setPoint( point3 );
-
-       CPPUNIT_ASSERT( vertexEntities[ 0 ].getPoint() == point0 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].getPoint() == point1 );
-       CPPUNIT_ASSERT( vertexEntities[ 2 ].getPoint() == point2 );
-       CPPUNIT_ASSERT( vertexEntities[ 3 ].getPoint() == point3 );
-
-       StaticArray< 5, EdgeMeshEntityType > edgeEntities;
-       edgeEntities[ 0 ].setVertexIndex( 0, 1 );
-       edgeEntities[ 0 ].setVertexIndex( 1, 2 );
-       edgeEntities[ 1 ].setVertexIndex( 0, 2 );
-       edgeEntities[ 1 ].setVertexIndex( 1, 0 );
-       edgeEntities[ 2 ].setVertexIndex( 0, 0 );
-       edgeEntities[ 2 ].setVertexIndex( 1, 1 );
-       edgeEntities[ 3 ].setVertexIndex( 0, 2 );
-       edgeEntities[ 3 ].setVertexIndex( 1, 3 );
-       edgeEntities[ 4 ].setVertexIndex( 0, 3 );
-       edgeEntities[ 4 ].setVertexIndex( 1, 1 );
-
-       CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 0 ) == 1 );
-       CPPUNIT_ASSERT( edgeEntities[ 0 ].getVertexIndex( 1 ) == 2 );
-       CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 0 ) == 2 );
-       CPPUNIT_ASSERT( edgeEntities[ 1 ].getVertexIndex( 1 ) == 0 );
-       CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 0 ) == 0 );
-       CPPUNIT_ASSERT( edgeEntities[ 2 ].getVertexIndex( 1 ) == 1 );
-       CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 0 ) == 2 );
-       CPPUNIT_ASSERT( edgeEntities[ 3 ].getVertexIndex( 1 ) == 3 );
-       CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 0 ) == 3 );
-       CPPUNIT_ASSERT( edgeEntities[ 4 ].getVertexIndex( 1 ) == 1 );
-
-       StaticArray< 2, TriangleMeshEntityType > triangleEntities;
-
-       triangleEntities[ 0 ].template setSubentityIndex< 0 >( 0 , 0 );
-       triangleEntities[ 0 ].template setSubentityIndex< 0 >( 1 , 1 );
-       triangleEntities[ 0 ].template setSubentityIndex< 0 >( 2 , 2 );
-       triangleEntities[ 0 ].template setSubentityIndex< 1 >( 0 , 0 );
-       triangleEntities[ 0 ].template setSubentityIndex< 1 >( 1 , 1 );
-       triangleEntities[ 0 ].template setSubentityIndex< 1 >( 2 , 2 );
-       triangleEntities[ 1 ].template setSubentityIndex< 0 >( 0 , 0 );
-       triangleEntities[ 1 ].template setSubentityIndex< 0 >( 1 , 2 );
-       triangleEntities[ 1 ].template setSubentityIndex< 0 >( 2 , 3 );
-       triangleEntities[ 1 ].template setSubentityIndex< 1 >( 0 , 0 );
-       triangleEntities[ 1 ].template setSubentityIndex< 1 >( 1 , 3 );
-       triangleEntities[ 1 ].template setSubentityIndex< 1 >( 2 , 4 );
-
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 1 ) == 1 );
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 0 >( 2 ) == 2 );
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 1 ) == 1 );
-       CPPUNIT_ASSERT( triangleEntities[ 0 ].template getSubentityIndex< 1 >( 2 ) == 2 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 1 ) == 2 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 0 >( 2 ) == 3 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 1 ) == 3 );
-       CPPUNIT_ASSERT( triangleEntities[ 1 ].template getSubentityIndex< 1 >( 2 ) == 4 );
- 
-       /*vertexEntities[ 0 ].template setNumberOfSuperentities< 1 >( 2 );
-       vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 0, 2 );
-       vertexEntities[ 0 ].template setSuperentityIndex< 1 >( 1, 1 );
-
-       vertexEntities[ 1 ].template setNumberOfSuperentities< 1 >( 3 );
-       vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 0, 0 );
-       vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 1, 2 );
-       vertexEntities[ 1 ].template setSuperentityIndex< 1 >( 2, 4 );
-
-       vertexEntities[ 1 ].template setNumberOfSuperentities< 2 >( 2 );
-       vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 0, 0 );
-       vertexEntities[ 1 ].template setSuperentityIndex< 2 >( 1, 1 );*/
-
-       CPPUNIT_ASSERT( vertexEntities[ 0 ].template getNumberOfSuperentities< 1 >() == 2 );
-       CPPUNIT_ASSERT( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 0 ) == 2 );
-       CPPUNIT_ASSERT( vertexEntities[ 0 ].template getSuperentityIndex< 1 >( 1 ) == 1 );
-
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getNumberOfSuperentities< 1 >() == 3 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 1 ) == 2 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 1 >( 2 ) == 4 );
-
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getNumberOfSuperentities< 2 >() == 2 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 0 ) == 0 );
-       CPPUNIT_ASSERT( vertexEntities[ 1 ].template getSuperentityIndex< 2 >( 1 ) == 1 );
-
-       /*edgeEntities[ 0 ].template setNumberOfSuperentities< 2 >( 2 );
-       edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 0, 0 );
-       edgeEntities[ 0 ].template setSuperentityIndex< 2 >( 1, 1 );*/
-
-       /*CPPUNIT_ASSERT( edgeEntities[ 0 ].template getNumberOfSuperentities< 2 >() == 2  );
-       CPPUNIT_ASSERT( edgeEntities[ 0 ].template getSuperentityIndex< 2 >( 0 ) == 0 );*/
-    };
-
-};
-
-#endif
-
-
-
-#endif /* TNLMESHENTITYTESTER_H_ */
diff --git a/tests/unit-tests/mesh/tnlMeshTest.cpp b/tests/unit-tests/mesh/tnlMeshTest.cpp
deleted file mode 100644
index 554fc0e6f335bffd6e070f5def2b4761a0b4998c..0000000000000000000000000000000000000000
--- a/tests/unit-tests/mesh/tnlMeshTest.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
-                          MeshTest.cpp  -  description
-                             -------------------
-    begin                : Feb 18, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#include <TNL/tnlConfig.h>
-#include <TNL/Devices/Host.h>
-#include <cstdlib>
-
-#ifndef HAVE_NOT_CXX11
-#include "tnlMeshTester.h"
-#endif
-#include "../tnlUnitTestStarter.h"
-
-int main( int argc, char* argv[] )
-{
-#ifndef HAVE_NOT_CXX11
-#ifdef HAVE_CPPUNIT
-   MeshTester< double, Devices::Host, long int > t;
-   //t.regularMeshOfHexahedronsTest();
-   if( ! tnlUnitTestStarter :: run< MeshTester< double, Devices::Host, long int > >()
-       )
-     return EXIT_FAILURE;
-   return EXIT_SUCCESS;
-#else
-   return EXIT_FAILURE;
-#endif
-#endif
-}
-
-
diff --git a/tests/unit-tests/mesh/tnlMeshTester.h b/tests/unit-tests/mesh/tnlMeshTester.h
deleted file mode 100644
index 39aaaf43d79776ecc2ae756ffa97005d0c45363f..0000000000000000000000000000000000000000
--- a/tests/unit-tests/mesh/tnlMeshTester.h
+++ /dev/null
@@ -1,500 +0,0 @@
-/***************************************************************************
-                          MeshTester.h  -  description
-                             -------------------
-    begin                : Feb 18, 2014
-    copyright            : (C) 2014 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#ifndef TNLMESHTESTER_H_
-#define TNLMESHTESTER_H_
-
-#ifdef HAVE_CPPUNIT
-#include <cppunit/TestSuite.h>
-#include <cppunit/TestResult.h>
-#include <cppunit/TestCaller.h>
-#include <cppunit/TestCase.h>
-#include <cppunit/Message.h>
-#include <TNL/Meshes/Mesh.h>
-#include <TNL/Meshes/MeshEntity.h>
-#include <TNL/Meshes/MeshConfigBase.h>
-#include <TNL/Meshes/Topologies/MeshVertexTopology.h>
-#include <TNL/Meshes/Topologies/MeshEdgeTopology.h>
-#include <TNL/Meshes/Topologies/MeshTriangleTopology.h>
-#include <TNL/Meshes/Topologies/MeshQuadrilateralTopology.h>
-#include <TNL/Meshes/Topologies/MeshTetrahedronTopology.h>
-#include <TNL/Meshes/Topologies/MeshHexahedronTopology.h>
-#include <TNL/Meshes/MeshDetails/initializer/MeshInitializer.h>
-#include <TNL/Meshes/MeshBuilder.h>
-
-using namespace TNL;
-using namespace TNL::Meshes;
-
-class TestTriangleMeshConfig : public MeshConfigBase< MeshTriangleTopology >
-{
-   public:
-
-      static constexpr bool entityStorage( int dimensions ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; };
-      //template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return true; };
-      template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; };
-};
-
-class TestQuadrilateralMeshConfig : public MeshConfigBase< MeshQuadrilateralTopology >
-{
-   public:
- 
-      static constexpr bool entityStorage( int dimensions ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) { return ( SubentityDimension % 2 != 0 ); };
-      template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; };
-};
-
-class TestTetrahedronMeshConfig : public MeshConfigBase< MeshTetrahedronTopology >
-{
-   public:
-
-      static constexpr bool entityStorage( int dimensions ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) {  return ( SubentityDimension % 2 != 0 ); };
-      template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; };
-};
-
-class TestHexahedronMeshConfig : public MeshConfigBase< MeshHexahedronTopology >
-{
-   public:
-
-      static constexpr bool entityStorage( int dimensions ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityStorage( MeshEntity, int SubentityDimension ) { return true; };
-      template< typename MeshEntity > static constexpr bool subentityOrientationStorage( MeshEntity, int SubentityDimension ) {  return ( SubentityDimension % 2 != 0 ); };
-      template< typename MeshEntity > static constexpr bool superentityStorage( MeshEntity, int SuperentityDimension ) { return true; };
-};
-
-template< typename RealType, typename Device, typename IndexType >
-class MeshTester : public CppUnit :: TestCase
-{
-   public:
-   typedef MeshTester< RealType, Device, IndexType > TesterType;
-   typedef typename CppUnit::TestCaller< TesterType > TestCallerType;
-
-   MeshTester(){};
-
-   virtual
-   ~MeshTester(){};
-
-   static CppUnit :: Test* suite()
-   {
-      CppUnit :: TestSuite* suiteOfTests = new CppUnit :: TestSuite( "MeshTester" );
-      CppUnit :: TestResult result;
-
-      suiteOfTests->addTest( new TestCallerType( "twoTrianglesTest", &TesterType::twoTrianglesTest ) );
-      suiteOfTests->addTest( new TestCallerType( "tetrahedronsTest", &TesterType::tetrahedronsTest ) );
-      suiteOfTests->addTest( new TestCallerType( "regularMeshOfTrianglesTest", &TesterType::regularMeshOfTrianglesTest ) );
-      suiteOfTests->addTest( new TestCallerType( "regularMeshOfQuadrilateralsTest", &TesterType::regularMeshOfQuadrilateralsTest ) );
-      suiteOfTests->addTest( new TestCallerType( "regularMeshOfHexahedronsTest", &TesterType::regularMeshOfHexahedronsTest ) );
-      return suiteOfTests;
-   }
-
-   void twoTrianglesTest()
-   {
-       typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-       typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-       typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-       typedef typename VertexMeshEntityType::PointType PointType;
-       CPPUNIT_ASSERT( PointType::getType() == ( Containers::StaticVector< 2, RealType >::getType() ) );
-
-       /****
-        * We set-up the following situation
-                point2   edge3       point3
-                   |\-------------------|
-                   | \                  |
-                   |  \   triangle1     |
-                   |   \                |
-
-                          ....
-                edge1     edge0        edge4
-                          ....
-
-
-                   |   triangle0     \  |
-                   |                  \ |
-                   ---------------------|
-                point0   edge2        point1
-        */
-
-       typedef Mesh< TestTriangleMeshConfig > TriangleTestMesh;
-       TriangleTestMesh mesh, mesh2;
-       MeshBuilder< TriangleTestMesh > meshBuilder;
-       meshBuilder.setPointsCount( 4 );
-       meshBuilder.setPoint( 0, PointType( 0.0, 0.0 ) );
-       meshBuilder.setPoint( 1, PointType( 1.0, 0.0 ) );
-       meshBuilder.setPoint( 2, PointType( 0.0, 1.0 ) );
-       meshBuilder.setPoint( 3, PointType( 1.0, 1.0 ) );
- 
-       meshBuilder.setCellsCount( 2 );
-       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 );
-       meshBuilder.build( mesh );
- 
-       CPPUNIT_ASSERT( mesh.getNumberOfEntities< 2 >() == 2 );
-       CPPUNIT_ASSERT( mesh.getNumberOfEntities< 1 >() == 5 );
-       CPPUNIT_ASSERT( mesh.getNumberOfEntities< 0 >() == 4 );
-
-       //CPPUNIT_ASSERT( mesh.save( "mesh.tnl" ) );
-       //CPPUNIT_ASSERT( mesh2.load( "mesh.tnl" ) );
-       //CPPUNIT_ASSERT( mesh == mesh2 );
-
-       //mesh.print(std::cout );
-       //mesh2.print(std::cout );
-    };
-
-   void tetrahedronsTest()
-   {
-      typedef MeshEntity< TestTetrahedronMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-      typedef MeshEntity< TestTetrahedronMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestTetrahedronMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-      typedef Mesh< TestTetrahedronMeshConfig > TestTetrahedronMesh;
-      TestTetrahedronMesh mesh;
-      MeshBuilder< TestTetrahedronMesh > meshBuilder;
-      meshBuilder.setPointsCount( 13 );
-      meshBuilder.setPoint(  0, PointType(  0.000000, 0.000000, 0.000000 ) );
-      meshBuilder.setPoint(  1, PointType(  0.000000, 0.000000, 8.000000 ) );
-      meshBuilder.setPoint(  2, PointType(  0.000000, 8.000000, 0.000000 ) );
-      meshBuilder.setPoint(  3, PointType( 15.000000, 0.000000, 0.000000 ) );
-      meshBuilder.setPoint(  4, PointType(  0.000000, 8.000000, 8.000000 ) );
-      meshBuilder.setPoint(  5, PointType( 15.000000, 0.000000, 8.000000 ) );
-      meshBuilder.setPoint(  6, PointType( 15.000000, 8.000000, 0.000000 ) );
-      meshBuilder.setPoint(  7, PointType( 15.000000, 8.000000, 8.000000 ) );
-      meshBuilder.setPoint(  8, PointType(  7.470740, 8.000000, 8.000000 ) );
-      meshBuilder.setPoint(  9, PointType(  7.470740, 0.000000, 8.000000 ) );
-      meshBuilder.setPoint( 10, PointType(  7.504125, 8.000000, 0.000000 ) );
-      meshBuilder.setPoint( 11, PointType(  7.212720, 0.000000, 0.000000 ) );
-      meshBuilder.setPoint( 12, PointType( 11.184629, 3.987667, 3.985835 ) );
-
-      /****
-       * Setup the following tetrahedrons:
-       * ( Generated by Netgen )
-       *
-       *  12        8        7        5
-       *  12        7        8       10
-       *  12       11        8        9
-       *  10       11        2        8
-       *  12        7        6        5
-       *   9       12        5        8
-       *  12       11        9        3
-       *   9        4       11        8
-       *  12        9        5        3
-       *   1        2        0       11
-       *   8       11        2        4
-       *   1        2       11        4
-       *   9        4        1       11
-       *  10       11        8       12
-       *  12        6        7       10
-       *  10       11       12        3
-       *  12        6        3        5
-       *  12        3        6       10
-       */
- 
-      meshBuilder.setCellsCount( 18 );
-       //  12        8        7        5
-      meshBuilder.getCellSeed( 0 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 0 ).setCornerId( 1, 8 );
-      meshBuilder.getCellSeed( 0 ).setCornerId( 2, 7 );
-      meshBuilder.getCellSeed( 0 ).setCornerId( 3, 5 );
-
-       //  12        7        8       10
-      meshBuilder.getCellSeed( 1 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 1 ).setCornerId( 1, 7 );
-      meshBuilder.getCellSeed( 1 ).setCornerId( 2, 8 );
-      meshBuilder.getCellSeed( 1 ).setCornerId( 3, 10 );
- 
-       //  12       11        8        9
-      meshBuilder.getCellSeed( 2 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 2 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 2 ).setCornerId( 2, 8 );
-      meshBuilder.getCellSeed( 2 ).setCornerId( 3, 9 );
- 
-       //  10       11        2        8
-      meshBuilder.getCellSeed( 3 ).setCornerId( 0, 10 );
-      meshBuilder.getCellSeed( 3 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 3 ).setCornerId( 2, 2 );
-      meshBuilder.getCellSeed( 3 ).setCornerId( 3, 8 );
- 
-       //  12        7        6        5
-      meshBuilder.getCellSeed( 4 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 4 ).setCornerId( 1, 7 );
-      meshBuilder.getCellSeed( 4 ).setCornerId( 2, 6 );
-      meshBuilder.getCellSeed( 4 ).setCornerId( 3, 5 );
- 
-       //   9       12        5        8
-      meshBuilder.getCellSeed( 5 ).setCornerId( 0, 9 );
-      meshBuilder.getCellSeed( 5 ).setCornerId( 1, 12 );
-      meshBuilder.getCellSeed( 5 ).setCornerId( 2, 5 );
-      meshBuilder.getCellSeed( 5 ).setCornerId( 3, 8 );
- 
-       //  12       11        9        3
-      meshBuilder.getCellSeed( 6 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 6 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 6 ).setCornerId( 2, 9 );
-      meshBuilder.getCellSeed( 6 ).setCornerId( 3, 3 );
- 
-       //   9        4       11        8
-      meshBuilder.getCellSeed( 7 ).setCornerId( 0, 9 );
-      meshBuilder.getCellSeed( 7 ).setCornerId( 1, 4 );
-      meshBuilder.getCellSeed( 7 ).setCornerId( 2, 11 );
-      meshBuilder.getCellSeed( 7 ).setCornerId( 3, 8 );
- 
-       //  12        9        5        3
-      meshBuilder.getCellSeed( 8 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 8 ).setCornerId( 1, 9 );
-      meshBuilder.getCellSeed( 8 ).setCornerId( 2, 5 );
-      meshBuilder.getCellSeed( 8 ).setCornerId( 3, 3 );
- 
-       //   1        2        0       11
-      meshBuilder.getCellSeed( 9 ).setCornerId( 0, 1 );
-      meshBuilder.getCellSeed( 9 ).setCornerId( 1, 2 );
-      meshBuilder.getCellSeed( 9 ).setCornerId( 2, 0 );
-      meshBuilder.getCellSeed( 9 ).setCornerId( 3, 11 );
- 
-       //   8       11        2        4
-      meshBuilder.getCellSeed( 10 ).setCornerId( 0, 8 );
-      meshBuilder.getCellSeed( 10 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 10 ).setCornerId( 2, 2 );
-      meshBuilder.getCellSeed( 10 ).setCornerId( 3, 4 );
- 
-       //   1        2       11        4
-      meshBuilder.getCellSeed( 11 ).setCornerId( 0, 1 );
-      meshBuilder.getCellSeed( 11 ).setCornerId( 1, 2 );
-      meshBuilder.getCellSeed( 11 ).setCornerId( 2, 11 );
-      meshBuilder.getCellSeed( 11 ).setCornerId( 3, 4 );
- 
-       //   9        4        1       11
-      meshBuilder.getCellSeed( 12 ).setCornerId( 0, 9 );
-      meshBuilder.getCellSeed( 12 ).setCornerId( 1, 4 );
-      meshBuilder.getCellSeed( 12 ).setCornerId( 2, 1 );
-      meshBuilder.getCellSeed( 12 ).setCornerId( 3, 11 );
- 
-       //  10       11        8       12
-      meshBuilder.getCellSeed( 13 ).setCornerId( 0, 10 );
-      meshBuilder.getCellSeed( 13 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 13 ).setCornerId( 2, 8 );
-      meshBuilder.getCellSeed( 13 ).setCornerId( 3, 12 );
- 
-       //  12        6        7       10
-      meshBuilder.getCellSeed( 14 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 14 ).setCornerId( 1, 6 );
-      meshBuilder.getCellSeed( 14 ).setCornerId( 2, 7 );
-      meshBuilder.getCellSeed( 14 ).setCornerId( 3, 10 );
- 
-       //  10       11       12        3
-      meshBuilder.getCellSeed( 15 ).setCornerId( 0, 10 );
-      meshBuilder.getCellSeed( 15 ).setCornerId( 1, 11 );
-      meshBuilder.getCellSeed( 15 ).setCornerId( 2, 12 );
-      meshBuilder.getCellSeed( 15 ).setCornerId( 3, 3 );
-
-       //  12        6        3        5
-      meshBuilder.getCellSeed( 16 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 16 ).setCornerId( 1, 6 );
-      meshBuilder.getCellSeed( 16 ).setCornerId( 2, 3 );
-      meshBuilder.getCellSeed( 16 ).setCornerId( 3, 5 );
- 
-       //  12        3        6       10
-      meshBuilder.getCellSeed( 17 ).setCornerId( 0, 12 );
-      meshBuilder.getCellSeed( 17 ).setCornerId( 1, 3 );
-      meshBuilder.getCellSeed( 17 ).setCornerId( 2, 6 );
-      meshBuilder.getCellSeed( 17 ).setCornerId( 3, 10 );
- 
-      meshBuilder.build( mesh );
-
-      /*CPPUNIT_ASSERT( mesh.save( "mesh.tnl" ) );
-      CPPUNIT_ASSERT( mesh2.load( "mesh.tnl" ) );
-      CPPUNIT_ASSERT( mesh == mesh2 );*/
-      //mesh.print(std::cout );
-   }
-
-   void regularMeshOfTrianglesTest()
-   {
-      typedef MeshEntity< TestTriangleMeshConfig, MeshTriangleTopology > TriangleMeshEntityType;
-      typedef MeshEntity< TestTriangleMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestTriangleMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-
-      const IndexType xSize( 5 ), ySize( 5 );
-      const RealType width( 1.0 ), height( 1.0 );
-      const RealType hx( width / ( RealType ) xSize ),
-                     hy( height / ( RealType ) ySize );
-      const IndexType numberOfCells = 2*xSize * ySize;
-      const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 );
-
-      typedef Mesh< TestTriangleMeshConfig > TestTriangleMesh;
-      Mesh< TestTriangleMeshConfig > mesh;
-      MeshBuilder< TestTriangleMesh > meshBuilder;
-      meshBuilder.setPointsCount( numberOfVertices );
-      meshBuilder.setCellsCount( numberOfCells );
-
-      /****
-       * Setup vertices
-       */
-      for( IndexType i = 0; i <= xSize; i++ )
-         for( IndexType j = 0; j <= ySize; j++ )
-            meshBuilder.setPoint(  j*xSize + i, PointType( i * hx, j * hy ) );
-
-      /****
-       * Setup cells
-       */
-      IndexType cellIdx( 0 );
-      for( IndexType i = 0; i < xSize; i++ )
-         for( IndexType j = 0; j < ySize; j++ )
-         {
-            IndexType vertex0 = j * xSize + i;
-            IndexType vertex1 = j * xSize + i + 1;
-            IndexType vertex2 = ( j + 1 ) * xSize + i;
-            IndexType vertex3 = ( j + 1 ) * xSize + i + 1;
-            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex0 );
-            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex1 );
-            meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex2 );
-            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 0, vertex1 );
-            meshBuilder.getCellSeed( cellIdx   ).setCornerId( 1, vertex2 );
-            meshBuilder.getCellSeed( cellIdx++ ).setCornerId( 2, vertex3 );
-         }
-
-      meshBuilder.build( mesh );
-      //CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) );
-      //CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) );
-      //CPPUNIT_ASSERT( mesh == mesh2 );
-      //mesh.print(std::cout );
-   }
-
-   void regularMeshOfQuadrilateralsTest()
-   {
-#ifdef UNDEF
-      typedef MeshEntity< TestQuadrilateralMeshConfig, MeshQuadrilateralTopology > QuadrilateralMeshEntityType;
-      typedef MeshEntity< TestQuadrilateralMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestQuadrilateralMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-
-      const IndexType xSize( 5 ), ySize( 5 );
-      const RealType width( 1.0 ), height( 1.0 );
-      const RealType hx( width / ( RealType ) xSize ),
-                     hy( height / ( RealType ) ySize );
-      const IndexType numberOfCells = xSize * ySize;
-      const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 );
-
-      Mesh< TestQuadrilateralMeshConfig > mesh, mesh2;
-      mesh.setNumberOfCells( numberOfCells );
-      mesh.setNumberOfVertices( numberOfVertices );
-
-      /****
-       * Setup vertices
-       */
-      for( IndexType i = 0; i <= xSize; i++ )
-         for( IndexType j = 0; j <= ySize; j++ )
-            mesh.setVertex(  j*xSize + i, PointType( i * hx, j * hy ) );
-
-      /****
-       * Setup cells
-       */
-      IndexType cellIdx( 0 );
-      for( IndexType i = 0; i < xSize; i++ )
-         for( IndexType j = 0; j < ySize; j++ )
-         {
-            IndexType vertex0 = j * xSize + i;
-            IndexType vertex1 = j * xSize + i + 1;
-            IndexType vertex2 = ( j + 1 ) * xSize + i;
-            IndexType vertex3 = ( j + 1 ) * xSize + i + 1;
-            mesh.getEntities< 2 >()[ cellIdx   ].getVerticesIndices()[ 0 ] = vertex0;
-            mesh.getEntities< 2 >()[ cellIdx   ].getVerticesIndices()[ 1 ] = vertex1;
-            mesh.getEntities< 2 >()[ cellIdx   ].getVerticesIndices()[ 2 ] = vertex2;
-            mesh.getEntities< 2 >()[ cellIdx++ ].getVerticesIndices()[ 3 ] = vertex3;
-         }
-
-      MeshInitializer< TestQuadrilateralMeshConfig > meshInitializer;
-      //meshInitializer.initMesh( mesh );
-      CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) );
-      CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) );
-      CPPUNIT_ASSERT( mesh == mesh2 );
-      //mesh.print(std::cout );
-#endif
-   }
-
-   void regularMeshOfHexahedronsTest()
-   {
-#ifdef UNDEF
-      typedef MeshEntity< TestHexahedronMeshConfig, MeshHexahedronTopology > HexahedronMeshEntityType;
-      typedef MeshEntity< TestHexahedronMeshConfig, MeshEdgeTopology > EdgeMeshEntityType;
-      typedef MeshEntity< TestHexahedronMeshConfig, MeshVertexTopology > VertexMeshEntityType;
-      typedef typename VertexMeshEntityType::PointType PointType;
-
-      const IndexType xSize( 5 ), ySize( 5 ), zSize( 5 );
-      const RealType width( 1.0 ), height( 1.0 ), depth( 1.0 );
-      const RealType hx( width / ( RealType ) xSize ),
-                     hy( height / ( RealType ) ySize ),
-                     hz( depth / ( RealType ) zSize );
-      const IndexType numberOfCells = xSize * ySize * zSize;
-      const IndexType numberOfVertices = ( xSize + 1 ) * ( ySize + 1 ) * ( zSize + 1 );
-
-      Mesh< TestHexahedronMeshConfig > mesh, mesh2;
-      mesh.setNumberOfCells( numberOfCells );
-      mesh.setNumberOfVertices( numberOfVertices );
-
-      /****
-       * Setup vertices
-       */
-      for( IndexType i = 0; i <= xSize; i++ )
-         for( IndexType j = 0; j <= ySize; j++ )
-            for( IndexType k = 0; k <= zSize; k++ )
-               mesh.setVertex(  k * xSize * ySize + j * xSize + i, PointType( i * hx, j * hy, k * hz ) );
-
-      /****
-       * Setup cells
-       */
-      IndexType cellIdx( 0 );
-      for( IndexType i = 0; i < xSize; i++ )
-         for( IndexType j = 0; j < ySize; j++ )
-            for( IndexType k = 0; k < zSize; k++ )
-            {
-               IndexType vertex0 = k * xSize * ySize + j * xSize + i;
-               IndexType vertex1 = k * xSize * ySize + j * xSize + i + 1;
-               IndexType vertex2 = k * xSize * ySize + ( j + 1 ) * xSize + i;
-               IndexType vertex3 = k * xSize * ySize + ( j + 1 ) * xSize + i + 1;
-               IndexType vertex4 = ( k + 1 ) * xSize * ySize + j * xSize + i;
-               IndexType vertex5 = ( k + 1 ) * xSize * ySize + j * xSize + i + 1;
-               IndexType vertex6 = ( k + 1 ) * xSize * ySize + ( j + 1 ) * xSize + i;
-               IndexType vertex7 = ( k + 1 )* xSize * ySize + ( j + 1 ) * xSize + i + 1;
-
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 0 ] = vertex0;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 1 ] = vertex1;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 2 ] = vertex2;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 3 ] = vertex3;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 4 ] = vertex4;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 5 ] = vertex5;
-               mesh.getEntities< 3 >()[ cellIdx   ].getVerticesIndices()[ 6 ] = vertex6;
-               mesh.getEntities< 3 >()[ cellIdx++ ].getVerticesIndices()[ 7 ] = vertex7;
-            }
-
-      MeshInitializer< TestHexahedronMeshConfig > meshInitializer;
-      //meshInitializer.initMesh( mesh );
-      /*CPPUNIT_ASSERT( mesh.save( "mesh-test.tnl" ) );
-      CPPUNIT_ASSERT( mesh2.load( "mesh-test.tnl" ) );
-      CPPUNIT_ASSERT( mesh == mesh2 );*/
-      //mesh.print(std::cout );
-#endif
-   }
-
-
-};
-
-#endif
-
-
-
-
-
-#endif /* TNLMESHTESTER_H_ */
diff --git a/tnlConfig.h.in b/tnlConfig.h.in
index 197065ae1ab93b1a09fa22709af278d0563763a4..1775037c4412fdc3e927f9f821b1a9f3b97993fd 100644
--- a/tnlConfig.h.in
+++ b/tnlConfig.h.in
@@ -5,8 +5,6 @@
 @HAVE_SYS_IOCTL_H@
 
 #ifdef HAVE_CUDA
-    @HAVE_CUBLAS@
-
     @HAVE_CUSP@
 
     @HAVE_CUSPARSE@