diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 48e304c9b736a0587cefc313ba0a3d4b35438232..50697564b0d47c4327776fa48d1702adf6dd9812 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -41,7 +41,7 @@ stages:
                 -DWITH_COVERAGE=${WITH_COVERAGE}
                 -DWITH_EXAMPLES=${WITH_EXAMPLES}
         - make
-        - make test
+        - make test CTEST_OUTPUT_ON_FAILURE=1
         - make install
         - popd
     variables:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c8ec69cdd89b9c0801416001d7134b8c45fdbfb7..a35e94e07823e22d0405525ed08a5a2a7a387188 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,7 +50,7 @@ endif()
 
 # set Debug/Release options
 set( CMAKE_CXX_FLAGS "-std=c++11 -pthread -Wall -Wno-unused-local-typedefs -Wno-unused-variable" )
-set( CMAKE_CXX_FLAGS_DEBUG "-g" )
+set( CMAKE_CXX_FLAGS_DEBUG "-g -rdynamic -ftemplate-backtrace-limit=0" )
 set( CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -DNDEBUG" )
 #set( CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -mtune=native -DNDEBUG -ftree-vectorizer-verbose=1 -ftree-vectorize -fopt-info-vec-missed -funroll-loops" )
 # pass -rdynamic only in Debug mode
@@ -63,7 +63,7 @@ if( CXX_COMPILER_NAME MATCHES "icpc" )
    message( "Intel compiler detected..."    )
    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_ICPC -wd2568 -wd2571 -wd2570")
    #####
-   #  Ckeck for MIC 
+   #  Check for MIC 
    #
    if( WITH_MIC STREQUAL "yes" )
        message( "Compile MIC support..."    )
@@ -86,6 +86,27 @@ if( DEFINED ENV{CI_JOB_NAME} )
    endif()
 endif()
 
+#####
+# Check for MPI -- poznej podle vraperu compileru -- da se testovat preklad bez MPI
+#
+if( ${CXX_COMPILER_NAME} STREQUAL "mpic++" )
+   message( "MPI compiler detected."    )
+   set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" )
+   set( CUDA_HOST_COMPILER "mpic++" )
+
+endif()
+
+####
+# Check for MPI -- not working
+#
+#find_package( MPI )
+#if( MPI_CXX_FOUND )
+   # set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" )
+   # message( "MPI headers found -- ${MPI_CXX_INCLUDE_PATH}")
+   # message( "MPI link flags  -- ${MPI_CXX_LINK_FLAGS}")
+   # message( "MPI libraries-- ${MPI_CXX_LIBRARIES}")
+#endif()
+
 #####
 # Check for CUDA
 #
@@ -181,7 +202,7 @@ if( WITH_CUDA STREQUAL "yes" )
         if( NOT WITH_CUSPARSE STREQUAL "no" )
            find_path( CUSPARSE_INCLUDE_DIR cusparse.h
                       /usr/local/cuda/include                   
-                      ${CUDA_INCLUDE_DIR}  
+                      ${CUDA_INCLUDE_DIRS}  
                       DOC "CUSPARSE headers." )
            if( ${CUSPARSE_INCLUDE_DIR} STREQUAL "CUSPARSE_INCLUDE_DIR-NOTFOUND" )
                message( "CUSPARSE not found." )
@@ -205,15 +226,6 @@ if( OPENMP_FOUND AND WITH_OPENMP STREQUAL "yes" )
    set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENMP ${OpenMP_CXX_FLAGS}" )
 endif()
 
-####
-# Check for MPI
-#
-#find_package( MPI )
-#if( MPI_CXX_FOUND )
-#    set( BUILD_MPI TRUE )
-#    message( "MPI headers found -- ${MPI_CXX_INCLUDE_PATH}")
-#endif()
-
 find_package( DCMTK )
 if( DCMTK_FOUND )
    set( HAVE_DCMTK_H "#define HAVE_DCMTK_H 1" )
diff --git a/build b/build
index 305a7e5d1ab69130e561afe16046e6329736c45e..328a3fe1f251aa3fa62f04ffa4b508a7b8f739ff 100755
--- a/build
+++ b/build
@@ -162,7 +162,7 @@ fi
 
 if test ${WITH_TESTS} = "yes";
 then
-    make test
+    make test CTEST_OUTPUT_ON_FAILURE=1
     if test $? != 0; then
         echo "Error: Some test did not pass successfuly."
     fi
diff --git a/examples/heat-equation/tnl-heat-equation-eoc.h b/examples/heat-equation/tnl-heat-equation-eoc.h
index 57ec6536fee8c43add54c4122a1c328ca489b508..593d90b710cf9e2c7e1a5b2e27b145bba22ec1e8 100644
--- a/examples/heat-equation/tnl-heat-equation-eoc.h
+++ b/examples/heat-equation/tnl-heat-equation-eoc.h
@@ -44,7 +44,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename MeshConfig,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType >
 class heatEquationSetter
 {
    public:
@@ -64,7 +65,7 @@ class heatEquationSetter
       typedef HeatEquationEocRhs< ExactOperator, TestFunction > RightHandSide;
       typedef Containers::StaticVector < MeshType::getMeshDimension(), Real > Point;
       typedef Operators::DirichletBoundaryConditions< MeshType, TestFunction, Dimension, Real, Index > BoundaryConditions;
-      typedef HeatEquationEocProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Solver;
+      typedef HeatEquationEocProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Solver;
       SolverStarter solverStarter;
       return solverStarter.template run< Solver >( parameters );
    };
diff --git a/examples/heat-equation/tnl-heat-equation.h b/examples/heat-equation/tnl-heat-equation.h
index 048abb409ac0d4567a22d87817edca057120b328..dea5fce6ac2f1c1d1fa7bf9e18bcdd37b58728cf 100644
--- a/examples/heat-equation/tnl-heat-equation.h
+++ b/examples/heat-equation/tnl-heat-equation.h
@@ -56,7 +56,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename MeshConfig,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType >
 class heatEquationSetter
 {
    public:
@@ -78,12 +79,12 @@ class heatEquationSetter
          if( boundaryConditionsType == "dirichlet" )
          {
             typedef Operators::DirichletBoundaryConditions< MeshType, Constant > BoundaryConditions;
-            typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+            typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide,CommunicatorType, ApproximateOperator > Problem;
             SolverStarter solverStarter;
             return solverStarter.template run< Problem >( parameters );
          }
          typedef Operators::NeumannBoundaryConditions< MeshType, Constant, Real, Index > BoundaryConditions;
-         typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+         typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
          SolverStarter solverStarter;
          return solverStarter.template run< Problem >( parameters );
       }
@@ -91,12 +92,12 @@ class heatEquationSetter
       if( boundaryConditionsType == "dirichlet" )
       {
          typedef Operators::DirichletBoundaryConditions< MeshType, MeshFunction > BoundaryConditions;
-         typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+         typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide,CommunicatorType, ApproximateOperator > Problem;
          SolverStarter solverStarter;
          return solverStarter.template run< Problem >( parameters );
       }
       typedef Operators::NeumannBoundaryConditions< MeshType, MeshFunction, Real, Index > BoundaryConditions;
-      typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+      typedef HeatEquationProblem< MeshType, BoundaryConditions, RightHandSide,CommunicatorType, ApproximateOperator > Problem;
       SolverStarter solverStarter;
       return solverStarter.template run< Problem >( parameters );
    };
diff --git a/examples/inviscid-flow/euler.h b/examples/inviscid-flow/euler.h
index 162cff09e9db0855a9a0c59e649d04f62850ed11..67bd825ff700fb5ef9e851607133047a5357dc13 100644
--- a/examples/inviscid-flow/euler.h
+++ b/examples/inviscid-flow/euler.h
@@ -51,7 +51,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename ConfigTag,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType >
 class eulerSetter
 {
    public:
@@ -79,12 +80,12 @@ class eulerSetter
              if( boundaryConditionsType == "dirichlet" )
              {
                 typedef Operators::DirichletBoundaryConditions< MeshType, Constant, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-                typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+                typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
                 SolverStarter solverStarter;
                 return solverStarter.template run< Problem >( parameters );
              }
              typedef Operators::NeumannBoundaryConditions< MeshType, Constant, Real, Index > BoundaryConditions;
-             typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+             typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
              SolverStarter solverStarter;
              return solverStarter.template run< Problem >( parameters );
           }
@@ -92,12 +93,12 @@ class eulerSetter
           if( boundaryConditionsType == "dirichlet" )
           {
              typedef Operators::DirichletBoundaryConditions< MeshType, MeshFunction, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-             typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+             typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide,  CommunicatorType, ApproximateOperator> Problem;
              SolverStarter solverStarter;
              return solverStarter.template run< Problem >( parameters );
           }
           typedef Operators::NeumannBoundaryConditions< MeshType, MeshFunction, Real, Index > BoundaryConditions;
-          typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+          typedef eulerProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType ,ApproximateOperator > Problem;
           SolverStarter solverStarter;
           return solverStarter.template run< Problem >( parameters );
       }
diff --git a/examples/inviscid-flow/eulerProblem.h b/examples/inviscid-flow/eulerProblem.h
index ea9e3155641613eb0cb20712fbc1416d883e1de5..21b831096610708ac3e9e70f22616f664c63af0b 100644
--- a/examples/inviscid-flow/eulerProblem.h
+++ b/examples/inviscid-flow/eulerProblem.h
@@ -22,6 +22,7 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 class eulerProblem:
    public PDEProblem< Mesh,
@@ -35,6 +36,8 @@ class eulerProblem:
       typedef typename Mesh::DeviceType DeviceType;
       typedef typename InviscidOperators::IndexType IndexType;
       typedef PDEProblem< Mesh, RealType, DeviceType, IndexType > BaseType;
+
+      typedef CommType CommunicatorType;
       
       using typename BaseType::MeshType;
       using typename BaseType::MeshPointer;
diff --git a/examples/inviscid-flow/eulerProblem_impl.h b/examples/inviscid-flow/eulerProblem_impl.h
index f0ab4e553aba1672a2649061c1d51e9d71ccb201..e2a6023d3145af7d23ce72f81e5e8dfcc39e3ee6 100644
--- a/examples/inviscid-flow/eulerProblem_impl.h
+++ b/examples/inviscid-flow/eulerProblem_impl.h
@@ -33,9 +33,10 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 String
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 getTypeStatic()
 {
    return String( "eulerProblem< " ) + Mesh :: getTypeStatic() + " >";
@@ -44,9 +45,10 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 String
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 getPrologHeader() const
 {
    return String( "Inviscid flow solver" );
@@ -55,9 +57,10 @@ getPrologHeader() const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 void
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) const
 {
    /****
@@ -69,9 +72,10 @@ writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) cons
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 bool
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
@@ -89,9 +93,10 @@ setup( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
-typename eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::IndexType
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+typename eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::IndexType
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 getDofs( const MeshPointer& mesh ) const
 {
    /****
@@ -104,9 +109,10 @@ getDofs( const MeshPointer& mesh ) const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 void
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 bindDofs( const MeshPointer& mesh,
           DofVectorPointer& dofVector )
 {
@@ -116,9 +122,10 @@ bindDofs( const MeshPointer& mesh,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 bool
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 setInitialCondition( const Config::ParameterContainer& parameters,
                      const MeshPointer& mesh,
                      DofVectorPointer& dofs,
@@ -142,10 +149,11 @@ setInitialCondition( const Config::ParameterContainer& parameters,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
    template< typename Matrix >
 bool
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 setupLinearSystem( const MeshPointer& mesh,
                    Matrix& matrix )
 {
@@ -168,9 +176,10 @@ setupLinearSystem( const MeshPointer& mesh,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 bool
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 makeSnapshot( const RealType& time,
               const IndexType& step,
               const MeshPointer& mesh,
@@ -209,9 +218,10 @@ makeSnapshot( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 void
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 getExplicitUpdate( const RealType& time,
                    const RealType& tau,
                    const MeshPointer& mesh,
@@ -256,7 +266,7 @@ getExplicitUpdate( const RealType& time,
    explicitUpdaterContinuity.setDifferentialOperator( this->inviscidOperatorsPointer->getContinuityOperator() );
    explicitUpdaterContinuity.setBoundaryConditions( this->boundaryConditionPointer );
    explicitUpdaterContinuity.setRightHandSide( this->rightHandSidePointer );
-   explicitUpdaterContinuity.template update< typename Mesh::Cell >( time, tau, mesh, 
+   explicitUpdaterContinuity.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh, 
                                                                      this->conservativeVariables->getDensity(),
                                                                      this->conservativeVariablesRHS->getDensity() );
 
@@ -267,7 +277,7 @@ getExplicitUpdate( const RealType& time,
    explicitUpdaterMomentumX.setDifferentialOperator( this->inviscidOperatorsPointer->getMomentumXOperator() );
    explicitUpdaterMomentumX.setBoundaryConditions( this->boundaryConditionPointer );
    explicitUpdaterMomentumX.setRightHandSide( this->rightHandSidePointer );   
-   explicitUpdaterMomentumX.template update< typename Mesh::Cell >( time, tau, mesh,
+   explicitUpdaterMomentumX.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh,
                                                            ( *this->conservativeVariables->getMomentum() )[ 0 ], // uRhoVelocityX,
                                                            ( *this->conservativeVariablesRHS->getMomentum() )[ 0 ] ); //, fuRhoVelocityX );
 
@@ -277,7 +287,7 @@ getExplicitUpdate( const RealType& time,
       explicitUpdaterMomentumY.setDifferentialOperator( this->inviscidOperatorsPointer->getMomentumYOperator() );
       explicitUpdaterMomentumY.setBoundaryConditions( this->boundaryConditionPointer );
       explicitUpdaterMomentumY.setRightHandSide( this->rightHandSidePointer );         
-      explicitUpdaterMomentumY.template update< typename Mesh::Cell >( time, tau, mesh,
+      explicitUpdaterMomentumY.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh,
                                                               ( *this->conservativeVariables->getMomentum() )[ 1 ], // uRhoVelocityX,
                                                               ( *this->conservativeVariablesRHS->getMomentum() )[ 1 ] ); //, fuRhoVelocityX );
    }
@@ -288,7 +298,7 @@ getExplicitUpdate( const RealType& time,
       explicitUpdaterMomentumZ.setDifferentialOperator( this->inviscidOperatorsPointer->getMomentumZOperator() );
       explicitUpdaterMomentumZ.setBoundaryConditions( this->boundaryConditionPointer );
       explicitUpdaterMomentumZ.setRightHandSide( this->rightHandSidePointer );               
-      explicitUpdaterMomentumZ.template update< typename Mesh::Cell >( time, tau, mesh,
+      explicitUpdaterMomentumZ.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh,
                                                               ( *this->conservativeVariables->getMomentum() )[ 2 ], // uRhoVelocityX,
                                                               ( *this->conservativeVariablesRHS->getMomentum() )[ 2 ] ); //, fuRhoVelocityX );
    }
@@ -301,7 +311,7 @@ getExplicitUpdate( const RealType& time,
    explicitUpdaterEnergy.setDifferentialOperator( this->inviscidOperatorsPointer->getEnergyOperator() );
    explicitUpdaterEnergy.setBoundaryConditions( this->boundaryConditionPointer );
    explicitUpdaterEnergy.setRightHandSide( this->rightHandSidePointer );                  
-   explicitUpdaterEnergy.template update< typename Mesh::Cell >( time, tau, mesh,
+   explicitUpdaterEnergy.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh,
                                                            this->conservativeVariables->getEnergy(), // uRhoVelocityX,
                                                            this->conservativeVariablesRHS->getEnergy() ); //, fuRhoVelocityX );
    
@@ -315,10 +325,11 @@ getExplicitUpdate( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
    template< typename Matrix >
 void
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 assemblyLinearSystem( const RealType& time,
                       const RealType& tau,
                       const MeshPointer& mesh,
@@ -351,9 +362,10 @@ assemblyLinearSystem( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename InviscidOperators >
 bool
-eulerProblem< Mesh, BoundaryCondition, RightHandSide, InviscidOperators >::
+eulerProblem< Mesh, BoundaryCondition, RightHandSide, CommType, InviscidOperators >::
 postIterate( const RealType& time,
              const RealType& tau,
              const MeshPointer& mesh,
diff --git a/examples/transport-equation/tnl-transport-equation-eoc.h b/examples/transport-equation/tnl-transport-equation-eoc.h
index 98a38425290f06eef37fd6606a2619fb898c6908..fc2eda33336e8c93d196a3aad5643697c80863ef 100644
--- a/examples/transport-equation/tnl-transport-equation-eoc.h
+++ b/examples/transport-equation/tnl-transport-equation-eoc.h
@@ -72,7 +72,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename ConfigTag,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType  >
 class advectionSetter
 {
    public:
@@ -98,13 +99,13 @@ class advectionSetter
          if( boundaryConditionsType == "dirichlet" )
          {
             typedef Operators::DirichletBoundaryConditions< MeshType, ConstantFunctionType, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-            typedef transportEquationProblemEoc< MeshType, BoundaryConditions, ConstantFunctionType, DifferentialOperatorType > Problem;
+            typedef transportEquationProblemEoc< MeshType, BoundaryConditions, ConstantFunctionType, CommunicatorType, DifferentialOperatorType > Problem;
             return callSolverStarter< Problem >( parameters );
          }
          if( boundaryConditionsType == "neumann" )
          {
             typedef Operators::DirichletBoundaryConditions< MeshType, ConstantFunctionType, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-            typedef transportEquationProblemEoc< MeshType, BoundaryConditions, ConstantFunctionType, DifferentialOperatorType > Problem;
+            typedef transportEquationProblemEoc< MeshType, BoundaryConditions, ConstantFunctionType, CommunicatorType, DifferentialOperatorType > Problem;
             return callSolverStarter< Problem >( parameters );
          }
          std::cerr << "Unknown boundary conditions type: " << boundaryConditionsType << "." << std::endl;
diff --git a/examples/transport-equation/tnl-transport-equation.h b/examples/transport-equation/tnl-transport-equation.h
index be0083153b91c87142888d4a5174c331f06b8e8b..c52555b46dab233b57b34ee76f21557ca9f039f2 100644
--- a/examples/transport-equation/tnl-transport-equation.h
+++ b/examples/transport-equation/tnl-transport-equation.h
@@ -59,7 +59,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename ConfigTag,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType  >
 class advectionSetter
 {
    public:
@@ -85,13 +86,13 @@ class advectionSetter
          if( boundaryConditionsType == "dirichlet" )
          {
             typedef Operators::DirichletBoundaryConditions< MeshType, ConstantFunctionType, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-            typedef transportEquationProblem< MeshType, BoundaryConditions, ConstantFunctionType, DifferentialOperatorType > Problem;
+            typedef transportEquationProblem< MeshType, BoundaryConditions, ConstantFunctionType, CommunicatorType, DifferentialOperatorType > Problem;
             return callSolverStarter< Problem >( parameters );
          }
          if( boundaryConditionsType == "neumann" )
          {
             typedef Operators::DirichletBoundaryConditions< MeshType, ConstantFunctionType, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-            typedef transportEquationProblem< MeshType, BoundaryConditions, ConstantFunctionType, DifferentialOperatorType > Problem;
+            typedef transportEquationProblem< MeshType, BoundaryConditions, ConstantFunctionType, CommunicatorType, DifferentialOperatorType > Problem;
             return callSolverStarter< Problem >( parameters );
          }
          std::cerr << "Unknown boundary conditions type: " << boundaryConditionsType << "." << std::endl;
diff --git a/examples/transport-equation/transportEquationProblem.h b/examples/transport-equation/transportEquationProblem.h
index a9fc1482075afd51b4e5490dae2c67c3572e451e..1de9750e4dd6ce25331afe241386ee82781a316c 100644
--- a/examples/transport-equation/transportEquationProblem.h
+++ b/examples/transport-equation/transportEquationProblem.h
@@ -21,6 +21,7 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 class transportEquationProblem:
 public PDEProblem< Mesh,
@@ -42,6 +43,8 @@ public PDEProblem< Mesh,
       typedef typename DifferentialOperator::VelocityFieldType VelocityFieldType;
       typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer;
 
+      typedef CommType CommunicatorType;
+
       using typename BaseType::MeshType;
       using typename BaseType::MeshPointer;
       using typename BaseType::DofVectorType;
diff --git a/examples/transport-equation/transportEquationProblemEoc.h b/examples/transport-equation/transportEquationProblemEoc.h
index cd851bd3005ea5eac669ad6779f56fdccb9dbe11..2bf30f508c4a24d10a3f041bb339709f14216ec5 100644
--- a/examples/transport-equation/transportEquationProblemEoc.h
+++ b/examples/transport-equation/transportEquationProblemEoc.h
@@ -22,9 +22,10 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 class transportEquationProblemEoc:
-public transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >
+public transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >
 {
    public:
 
@@ -32,7 +33,7 @@ public transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, Differe
       typedef typename Mesh::DeviceType DeviceType;
       typedef typename DifferentialOperator::IndexType IndexType;
       typedef Functions::MeshFunction< Mesh > MeshFunctionType;
-      typedef transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator > BaseType;
+      typedef transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator > BaseType;
       typedef SharedPointer< MeshFunctionType, DeviceType > MeshFunctionPointer;
       typedef SharedPointer< DifferentialOperator > DifferentialOperatorPointer;
       typedef SharedPointer< BoundaryCondition > BoundaryConditionPointer;
@@ -40,7 +41,8 @@ public transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, Differe
       typedef typename DifferentialOperator::VelocityFieldType VelocityFieldType;
       typedef SharedPointer< VelocityFieldType, DeviceType > VelocityFieldPointer;
       
-
+      
+      typedef CommType CommunicatorType;
       using typename BaseType::MeshType;
       using typename BaseType::MeshPointer;
       using typename BaseType::DofVectorType;
diff --git a/examples/transport-equation/transportEquationProblemEoc_impl.h b/examples/transport-equation/transportEquationProblemEoc_impl.h
index 7e2accc3a1413d43b6bdd993916660f54e857b83..c3f4f6e68d9fe1a9f6791bc8d6f0f97a025a3f7a 100644
--- a/examples/transport-equation/transportEquationProblemEoc_impl.h
+++ b/examples/transport-equation/transportEquationProblemEoc_impl.h
@@ -26,9 +26,10 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getTypeStatic()
 {
    return String( "transportEquationProblemEoc< " ) + Mesh :: getTypeStatic() + " >";
@@ -37,9 +38,10 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getPrologHeader() const
 {
    return String( "Transport Equation EOC" );
@@ -49,9 +51,10 @@ getPrologHeader() const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
@@ -126,9 +129,10 @@ setup( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblemEoc< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setInitialCondition( const Config::ParameterContainer& parameters,
                      const MeshPointer& meshPointer,
                      DofVectorPointer& dofs,
diff --git a/examples/transport-equation/transportEquationProblem_impl.h b/examples/transport-equation/transportEquationProblem_impl.h
index 698a7bc687dc4c3b4df49a48fef2f5a73566ecbc..cf5864477c6a79deea1fe579877656669d39512a 100644
--- a/examples/transport-equation/transportEquationProblem_impl.h
+++ b/examples/transport-equation/transportEquationProblem_impl.h
@@ -23,9 +23,10 @@ namespace TNL {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getTypeStatic()
 {
    return String( "transportEquationProblem< " ) + Mesh :: getTypeStatic() + " >";
@@ -34,9 +35,10 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getPrologHeader() const
 {
    return String( "Transport Equation" );
@@ -45,9 +47,10 @@ getPrologHeader() const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) const
 {
    /****
@@ -59,9 +62,10 @@ writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) cons
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
@@ -76,9 +80,10 @@ setup( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
-typename transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::IndexType
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+typename transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::IndexType
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getDofs( const MeshPointer& mesh ) const
 {
    /****
@@ -91,9 +96,10 @@ getDofs( const MeshPointer& mesh ) const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 bindDofs( const MeshPointer& meshPointer,
           DofVectorPointer& dofVector )
 {
@@ -104,9 +110,10 @@ bindDofs( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setInitialCondition( const Config::ParameterContainer& parameters,
                      const MeshPointer& meshPointer,
                      DofVectorPointer& dofs,
@@ -125,10 +132,11 @@ setInitialCondition( const Config::ParameterContainer& parameters,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
    template< typename Matrix >
 bool
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setupLinearSystem( const MeshPointer& mesh,
                    Matrix& matrix )
 {
@@ -151,9 +159,10 @@ setupLinearSystem( const MeshPointer& mesh,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 makeSnapshot( const RealType& time,
               const IndexType& step,
               const MeshPointer& mesh,
@@ -174,9 +183,10 @@ makeSnapshot( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getExplicitUpdate( const RealType& time,
                 const RealType& tau,
                 const MeshPointer& mesh,
@@ -203,16 +213,17 @@ getExplicitUpdate( const RealType& time,
    explicitUpdater.setDifferentialOperator( this->differentialOperatorPointer );
    explicitUpdater.setBoundaryConditions( this->boundaryConditionPointer );
    explicitUpdater.setRightHandSide( this->rightHandSidePointer );
-   explicitUpdater.template update< typename Mesh::Cell >( time, tau, mesh, u, fu );
+   explicitUpdater.template update< typename Mesh::Cell, CommType >( time, tau, mesh, u, fu );
 }
 
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
    template< typename Matrix >
 void
-transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+transportEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 assemblyLinearSystem( const RealType& time,
                       const RealType& tau,
                       const MeshPointer& mesh,
diff --git a/src/Python/pytnl/tnl_indexing.h b/src/Python/pytnl/tnl_indexing.h
index 29663d66b553d8095ca0a67f980b346fac04e712..795226537dd4caf98f64ec0e478e511b814ad16e 100644
--- a/src/Python/pytnl/tnl_indexing.h
+++ b/src/Python/pytnl/tnl_indexing.h
@@ -68,7 +68,7 @@ void tnl_slice_indexing( Scope & scope )
             if (!slice.compute(a.getSize(), &start, &stop, &step, &slicelength))
                 throw py::error_already_set();
 
-            if (slicelength != value.getSize())
+            if (slicelength != (size_t) 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) {
diff --git a/src/TNL/Assert.h b/src/TNL/Assert.h
index f3befbaa0edfaddab1c11c33a6833718f7b25956..ae1758a19bf3e6250335e448b223453354401cb2 100644
--- a/src/TNL/Assert.h
+++ b/src/TNL/Assert.h
@@ -50,6 +50,7 @@
 #include <stdio.h>
 
 #include <TNL/Devices/CudaCallable.h>
+#include <TNL/Debugging/StackBacktrace.h>
 
 namespace TNL {
 namespace Assert {
@@ -88,6 +89,9 @@ printDiagnosticsHost( const char* assertion,
        << "Function: " << function << "\n"
        << "Line: " << line << "\n"
        << "Diagnostics:\n" << diagnostics << std::endl;
+
+	PrintStackBacktrace;
+
    throw AssertionError( str.str() );
 }
 
@@ -108,6 +112,8 @@ printDiagnosticsHost( const char* assertion,
              << "Function: " << function << "\n"
              << "Line: " << line << "\n"
              << "Diagnostics:\n" << diagnostics << std::endl;
+
+	PrintStackBacktrace;
 }
 #endif // TNL_THROW_ASSERTION_ERROR
 
diff --git a/src/TNL/CMakeLists.txt b/src/TNL/CMakeLists.txt
index 54551e7d8bc8dc2fe1b4fd6b5217826932e2c9ac..13113f9c3fa6b04c3e485eb836e149f48a1c91d7 100644
--- a/src/TNL/CMakeLists.txt
+++ b/src/TNL/CMakeLists.txt
@@ -1,5 +1,6 @@
 ADD_SUBDIRECTORY( Config )
 ADD_SUBDIRECTORY( Containers )
+ADD_SUBDIRECTORY( Communicators )
 ADD_SUBDIRECTORY( Debugging )
 ADD_SUBDIRECTORY( Devices )
 ADD_SUBDIRECTORY( Exceptions )
@@ -31,7 +32,6 @@ set( headers
      Logger.h
      Logger_impl.h
      Math.h
-     mpi-supp.h
      ParallelFor.h
      param-types.h
      SharedPointer.h
diff --git a/src/TNL/Communicators/CMakeLists.txt b/src/TNL/Communicators/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..271f5a2d64003a51f47d877e70c0701f129d6242
--- /dev/null
+++ b/src/TNL/Communicators/CMakeLists.txt
@@ -0,0 +1,4 @@
+SET( headers MpiCommunicator.h
+             NoDistrCommunicator.h )
+
+INSTALL( FILES ${headers} DESTINATION include/tnl-${tnlVersion}/TNL/Communicators )
diff --git a/src/TNL/Communicators/MpiCommunicator.h b/src/TNL/Communicators/MpiCommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..421c9e2a6fd36b6e73bb1024ca98737fb987c315
--- /dev/null
+++ b/src/TNL/Communicators/MpiCommunicator.h
@@ -0,0 +1,192 @@
+/***************************************************************************
+                          MpiCommunicator.h  -  description
+                             -------------------
+    begin                : 2005/04/23
+    copyright            : (C) 2005 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+
+
+#ifdef HAVE_MPI
+
+#include <mpi.h>
+#include <TNL/String.h>
+#include <iostream>
+#include <fstream>
+
+namespace TNL {
+namespace Communicators {
+
+    class MpiCommunicator
+    {
+
+        private:
+        inline static MPI_Datatype MPIDataType( const signed char* ) { return MPI_CHAR; };
+        inline static MPI_Datatype MPIDataType( const signed short int* ) { return MPI_SHORT; };
+        inline static MPI_Datatype MPIDataType( const signed int* ) { return MPI_INT; };
+        inline static MPI_Datatype MPIDataType( const signed long int* ) { return MPI_LONG; };
+        inline static MPI_Datatype MPIDataType( const unsigned char *) { return MPI_UNSIGNED_CHAR; };
+        inline static MPI_Datatype MPIDataType( const unsigned short int* ) { return MPI_UNSIGNED_SHORT; };
+        inline static MPI_Datatype MPIDataType( const unsigned int* ) { return MPI_UNSIGNED; };
+        inline static MPI_Datatype MPIDataType( const unsigned long int* ) { return MPI_UNSIGNED_LONG; };
+        inline static MPI_Datatype MPIDataType( const float* ) { return MPI_FLOAT; };
+        inline static MPI_Datatype MPIDataType( const double* ) { return MPI_DOUBLE; };
+        inline static MPI_Datatype MPIDataType( const long double* ) { return MPI_LONG_DOUBLE; };
+        
+        public:
+
+        //can be call before init
+        static bool isAvailable()
+        {
+            return true;
+        }
+
+        //can be called only after init 
+        static bool isDistributed()
+        {
+            return GetSize()>1;
+        };
+
+        typedef MPI::Request Request;
+        static MPI::Request NullRequest;
+        static std::streambuf *psbuf;
+        static std::streambuf *backup;
+        static std::ofstream filestr;
+
+        static void Init(int argc, char **argv,bool redirect=false)
+        {
+            MPI::Init(argc,argv);
+            NullRequest=MPI::REQUEST_NULL;
+
+            if(isDistributed() && redirect)
+            {
+                //redirect all stdout to files, only 0 take to go to console
+                backup=std::cout.rdbuf();
+
+                //redirect output to files...
+                if(MPI::COMM_WORLD.Get_rank()!=0)
+                {
+                    std::cout<< GetRank() <<": Redirecting std::out to file" <<std::endl;
+                    String stdoutfile;
+                    stdoutfile=String( "./stdout-")+convertToString(MPI::COMM_WORLD.Get_rank())+String(".txt");
+                    filestr.open (stdoutfile.getString()); 
+                    psbuf = filestr.rdbuf(); 
+                    std::cout.rdbuf(psbuf);
+                }
+            }
+        };
+
+        static void Finalize()
+        {
+            if(isDistributed())
+            {
+                if(MPI::COMM_WORLD.Get_rank()!=0)
+                { 
+                    std::cout.rdbuf(backup);
+                    filestr.close(); 
+                }
+            }
+            MPI::Finalize();
+        };
+
+        static bool IsInitialized()
+        {
+            return MPI::Is_initialized();
+        };
+
+        static int GetRank()
+        {
+            return MPI::COMM_WORLD.Get_rank();
+        };
+
+        static int GetSize()
+        {
+            return MPI::COMM_WORLD.Get_size();
+        };
+
+        //dim-number of dimesions, distr array of guess distr - 0 for computation
+        //distr array will be filled by computed distribution
+        //more information in MPI documentation
+        static void DimsCreate(int nproc, int dim, int *distr)
+        {
+            /***HACK for linear distribution***/
+           int sum=0;
+           for(int i=0;i<dim;i++)
+                sum+=distr[i];
+           if(sum==0) //uživatel neovlivňuje distribuci
+           {
+               std::cout << "vynucuji distribuci" <<std::endl;
+               for(int i=0;i<dim-1;i++)
+               {
+                    distr[i]=1;
+               }
+               distr[dim-1]=0;
+            }
+            /***END OF HACK***/
+
+            MPI_Dims_create(nproc, dim, distr);
+        };
+
+        static void Barrier()
+        {
+            MPI::COMM_WORLD.Barrier();
+        };
+
+        template <typename T>
+        static Request ISend( const T *data, int count, int dest)
+        {
+                return MPI::COMM_WORLD.Isend((void*) data, count, MPIDataType(data) , dest, 0);
+        }    
+
+        template <typename T>
+        static Request IRecv( const T *data, int count, int src)
+        {
+                return MPI::COMM_WORLD.Irecv((void*) data, count, MPIDataType(data) , src, 0);
+        }
+
+        static void WaitAll(Request *reqs, int length)
+        {
+                MPI::Request::Waitall(length, reqs);
+        };
+
+        template< typename T > 
+        static void Bcast(  T& data, int count, int root)
+        {
+                MPI::COMM_WORLD.Bcast((void*) &data, count,  MPIDataType(data), root);
+        }
+
+      /*  template< typename T >
+        static void Allreduce( T& data,
+                     T& reduced_data,
+                     int count,
+                     const MPI_Op &op)
+        {
+                MPI::COMM_WORLD.Allreduce((void*) &data, (void*) &reduced_data,count,MPIDataType(data),op);
+        };
+
+        template< typename T >
+        static void Reduce( T& data,
+                    T& reduced_data,
+                    int count,
+                    MPI_Op &op,
+                    int root)
+        {
+             MPI::COMM_WORLD.Reduce((void*) &data, (void*) &reduced_data,count,MPIDataType(data),op,root);
+        };*/
+    };
+
+    MPI::Request MpiCommunicator::NullRequest;
+    std::streambuf *MpiCommunicator::psbuf;
+    std::streambuf *MpiCommunicator::backup;
+    std::ofstream MpiCommunicator::filestr;
+
+}//namespace Communicators
+} // namespace TNL
+#endif
+
+
diff --git a/src/TNL/Communicators/NoDistrCommunicator.h b/src/TNL/Communicators/NoDistrCommunicator.h
new file mode 100644
index 0000000000000000000000000000000000000000..480be330fd50506fd06ede7608083f97cb5622ce
--- /dev/null
+++ b/src/TNL/Communicators/NoDistrCommunicator.h
@@ -0,0 +1,117 @@
+/***************************************************************************
+                          NoDistrCommunicator.h  -  description
+                             -------------------
+    begin                : 2018/01/09
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+namespace TNL {
+namespace Communicators {
+        
+    class NoDistrCommunicator
+    {
+
+
+        public:
+
+        typedef int Request;
+        static Request NullRequest;
+
+        static bool isAvailable()
+        {
+            return true;
+        }
+
+        static void Init(int argc, char **argv, bool redirect=false)
+        {
+            NullRequest=-1;
+        };
+
+        static void Finalize()
+        {
+        };
+
+        static bool IsInitialized()
+        {   
+            return true;
+        };
+
+        static bool isDistributed()
+        {
+            return false;
+        };
+
+        static int GetRank()
+        {
+            return 0;
+        };
+
+        static int GetSize()
+        {
+            return 1;
+        };
+
+        static void DimsCreate(int nproc, int dim, int *distr)
+        {
+            for(int i=0;i<dim;i++)
+            {
+                distr[i]=1;
+            }
+        };
+
+        static void Barrier()
+        {
+        };
+
+        template <typename T>
+        static Request ISend( const T *data, int count, int dest)
+        {
+            return 1;
+        };    
+
+        template <typename T>
+        static Request IRecv( const T *data, int count, int src)
+        {
+            return 1;
+        };
+
+        static void WaitAll(Request *reqs, int length)
+        {
+        };
+
+        template< typename T > 
+        static void Bcast(  T& data, int count, int root)
+        {
+        };
+
+       /* template< typename T >
+        static void Allreduce( T& data,
+                     T& reduced_data,
+                     int count,
+                     const MPI_Op &op)
+        {
+                MPI::COMM_WORLD.Allreduce((void*) &data, (void*) &reduced_data,count,MPIDataType(data),op);
+        };
+
+        template< typename T >
+        static void Reduce( T& data,
+                    T& reduced_data,
+                    int count,
+                    MPI_Op &op,
+                    int root)
+        {
+             MPI::COMM_WORLD.Reduce((void*) &data, (void*) &reduced_data,count,MPIDataType(data),op,root);
+        };*/
+    };
+
+    int NoDistrCommunicator::NullRequest;
+
+} // namespace Communicators
+} // namespace TNL
+
+
diff --git a/src/TNL/Config/ParameterContainer.cpp b/src/TNL/Config/ParameterContainer.cpp
index 11f3a816152123c7df77c819a9263bc5b918c46a..e1b451bd651c32457947b293ce9e426252331456 100644
--- a/src/TNL/Config/ParameterContainer.cpp
+++ b/src/TNL/Config/ParameterContainer.cpp
@@ -93,9 +93,9 @@ ParameterContainer::
    parameters. DeepEraseAll();
 }
 
-void ParameterContainer::MPIBcast( int root, MPI_Comm mpi_comm )
+/*void ParameterContainer::MPIBcast( int root, MPI_Comm mpi_comm )
 {
-#ifdef HAVE_MPI
+#ifdef USE_MPI
    int i;
    int size = parameters. getSize();
    :: MPIBcast( size, 1, root, mpi_comm );
@@ -161,7 +161,7 @@ void ParameterContainer::MPIBcast( int root, MPI_Comm mpi_comm )
    }
 #endif
 }
-
+*/
 bool
 parseCommandLine( int argc, char* argv[],
                   const Config::ConfigDescription& config_description,
diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h
index 0fe07d424a5a60f03f9f162995e6f9b7295bee01..0cb866a0e1cf9d0e95d419e7e29fcd9cd68fcbdf 100644
--- a/src/TNL/Config/ParameterContainer.h
+++ b/src/TNL/Config/ParameterContainer.h
@@ -12,7 +12,6 @@
 
 #include <TNL/Containers/List.h>
 #include <TNL/Config/ConfigDescription.h>
-#include <TNL/mpi-supp.h>
 #include <TNL/param-types.h>
 //#include <TNL/Debugging/StackBacktrace.h>
 
@@ -94,7 +93,7 @@ class ParameterContainer
    }
  
    //! Broadcast to other nodes in MPI cluster
-   void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD );
+  // void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD );
 
    ~ParameterContainer();
 
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsHost_impl.h b/src/TNL/Containers/Algorithms/ArrayOperationsHost_impl.h
index 7390cfdb0e317a036f45c1db7b58d09a18afac0f..02eab36d7147c290f6417076fb11008450b7d7d6 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsHost_impl.h
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsHost_impl.h
@@ -101,7 +101,18 @@ copyMemory( DestinationElement* destination,
    if( std::is_same< DestinationElement, SourceElement >::value &&
        ( std::is_fundamental< DestinationElement >::value ||
          std::is_pointer< DestinationElement >::value ) )
+   {
+      // GCC 8.1 complains that we bypass a non-trivial copy-constructor
+      // (in C++17 we could use constexpr if to avoid compiling this branch in that case)
+      #if defined(__GNUC__) && !defined(__clang__) && !defined(__NVCC__)
+         #pragma GCC diagnostic push
+         #pragma GCC diagnostic ignored "-Wclass-memaccess"
+      #endif
       memcpy( destination, source, size * sizeof( DestinationElement ) );
+      #if defined(__GNUC__) && !defined(__clang__) && !defined(__NVCC__)
+         #pragma GCC diagnostic pop
+      #endif
+   }
    else
       for( Index i = 0; i < size; i ++ )
          destination[ i ] = ( DestinationElement ) source[ i ];
diff --git a/src/TNL/Containers/Array_impl.h b/src/TNL/Containers/Array_impl.h
index 568df2f5136e0b4a0a1258f7254518152f7d71c7..11c546c664fbe2468485f11755d2709ed0d6c7f2 100644
--- a/src/TNL/Containers/Array_impl.h
+++ b/src/TNL/Containers/Array_impl.h
@@ -547,6 +547,7 @@ boundLoad( File& file )
    return true;
 }
 
+
 template< typename Element,
           typename Device,
           typename Index >
diff --git a/src/TNL/Containers/StaticVector.h b/src/TNL/Containers/StaticVector.h
index 9d5fa6471dbf26d6c95dd9c34ec86dd02df3641b..b6c89eefaf88e72ea1586aec469b43e95b1c1b45 100644
--- a/src/TNL/Containers/StaticVector.h
+++ b/src/TNL/Containers/StaticVector.h
@@ -477,6 +477,39 @@ Real tnlScalarProduct( const StaticVector< 3, Real >& u,
    return u[ 0 ] * v[ 0 ] + u[ 1 ] * v[ 1 ] + u[ 2 ] * v[ 2 ];
 }
 
+template< typename T1,
+          typename T2>
+StaticVector<1, T1> tnlDotProduct( const StaticVector< 1, T1 >& u,
+                       const StaticVector< 1, T2 >& v )
+{
+   StaticVector<1, T1> ret;
+   ret[0]=u[0]*v[0];
+   return ret;
+}
+
+template< typename T1,
+          typename T2>
+StaticVector<2, T1> tnlDotProduct( const StaticVector< 2, T1 >& u,
+                       const StaticVector< 2, T2 >& v )
+{
+   StaticVector<2, T1> ret;
+   ret[0]=u[0]*v[0];
+   ret[1]=u[1]*v[1];
+   return ret;
+}
+
+template< typename T1,
+          typename T2>
+StaticVector<3, T1> tnlDotProduct( const StaticVector< 3, T1 >& u,
+                       const StaticVector< 3, T2 >& v )
+{
+   StaticVector<3, T1> ret;
+   ret[0]=u[0]*v[0];
+   ret[1]=u[1]*v[1];
+   ret[2]=u[2]*v[2];
+   return ret;
+}
+
 template< typename Real >
 Real tnlTriangleArea( const StaticVector< 2, Real >& a,
                       const StaticVector< 2, Real >& b,
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 c4055d95df7afe453337e592de0f9ef224226b52..6eca7bc281e3b18c361ad96279df23d19e6e2509 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
@@ -42,7 +42,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename MeshConfig,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType>
 class tnlDirectEikonalSolverSetter
 {
    public:
diff --git a/src/TNL/Functions/MeshFunction.h b/src/TNL/Functions/MeshFunction.h
index 2c8d41a564c3af16ad406fbf9dca5cf95f3e98e5..adcde3fc48a2cd89548ca7191abed096b992794f 100644
--- a/src/TNL/Functions/MeshFunction.h
+++ b/src/TNL/Functions/MeshFunction.h
@@ -13,6 +13,8 @@
 #include <TNL/Functions/MeshFunctionGnuplotWriter.h>
 #include <TNL/Functions/MeshFunctionVTKWriter.h>
 #include <TNL/SharedPointer.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMeshSynchronizer.h>
 
 #pragma once
 
@@ -37,6 +39,8 @@ class MeshFunction :
       typedef Real RealType;
       typedef Containers::Vector< RealType, DeviceType, IndexType > VectorType;
       typedef Functions::MeshFunction< Mesh, MeshEntityDimension, Real > ThisType;
+      typedef Meshes::DistributedMeshes::DistributedMesh<MeshType> DistributedMeshType;
+      typedef Meshes::DistributedMeshes::DistributedMeshSynchronizer<ThisType> DistributedMeshSynchronizerType;
  
       static constexpr int getEntitiesDimension() { return MeshEntityDimension; }
       
@@ -155,14 +159,24 @@ class MeshFunction :
       using Object::load;
  
       using Object::boundLoad;
+
+      template< typename CommunicatorType>
+      void Synchronize();    
+
  
    protected:
+
+      DistributedMeshSynchronizerType synchronizer;    
       
       MeshPointer meshPointer;
       
       VectorType data;
  
       template< typename, typename > friend class MeshFunctionEvaluator;
+
+   private:
+      void SetupSynchronizer(DistributedMeshType *distrMesh);
+   
 };
 
 } // namespace Functions
diff --git a/src/TNL/Functions/MeshFunction_impl.h b/src/TNL/Functions/MeshFunction_impl.h
index d87cbadb30953137cedc4008d78e2b54d58dc59d..037d014dede9cbcaffbc7ecec2d85c9e399e6c74 100644
--- a/src/TNL/Functions/MeshFunction_impl.h
+++ b/src/TNL/Functions/MeshFunction_impl.h
@@ -34,8 +34,11 @@ template< typename Mesh,
           typename Real >
 MeshFunction< Mesh, MeshEntityDimension, Real >::
 MeshFunction( const MeshPointer& meshPointer )
-: meshPointer( meshPointer )
 {
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
    this->data.setSize( getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
    TNL_ASSERT( this->data.getSize() == this->getMesh().template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >(), 
                std::cerr << "this->data.getSize() = " << this->data.getSize() << std::endl
@@ -47,8 +50,11 @@ template< typename Mesh,
           typename Real >
 MeshFunction< Mesh, MeshEntityDimension, Real >::
 MeshFunction( const ThisType& meshFunction )
-: meshPointer( meshFunction.meshPointer )
 {
+
+    SetupSynchronizer(meshFunction.meshPointer->GetDistMesh());
+
+   this->meshPointer=meshFunction.meshPointer;
    this->data.bind( meshFunction.getData() );
 }
 
@@ -60,10 +66,17 @@ MeshFunction< Mesh, MeshEntityDimension, Real >::
 MeshFunction( const MeshPointer& meshPointer,
               Vector& data,
               const IndexType& offset )
-: meshPointer( meshPointer )
+//: meshPointer( meshPointer )
 {
+<<<<<<< HEAD
    TNL_ASSERT_GE( data.getSize(), meshPointer->template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >(),
                   "The input vector is not large enough for binding to the mesh function." );      
+=======
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
+>>>>>>> origin/mpi-explosive
    this->data.bind( data, offset, getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
 }
 
@@ -76,10 +89,17 @@ MeshFunction< Mesh, MeshEntityDimension, Real >::
 MeshFunction( const MeshPointer& meshPointer,
               SharedPointer< Vector >& data,
               const IndexType& offset )
-: meshPointer( meshPointer )
+//: meshPointer( meshPointer )
 {
+<<<<<<< HEAD
    TNL_ASSERT_GE( data->getSize(), offset + meshPointer->template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >(),
                   "The input vector is not large enough for binding to the mesh function." );      
+=======
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
+>>>>>>> origin/mpi-explosive
    this->data.bind( *data, offset, getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
 }
 
@@ -174,7 +194,10 @@ void
 MeshFunction< Mesh, MeshEntityDimension, Real >::
 bind( ThisType& meshFunction )
 {
-   this->meshPointer = meshFunction.getMeshPointer();
+
+    SetupSynchronizer(meshFunction.meshPointer->GetDistMesh());
+
+   this->meshPointer=meshFunction.meshPointer;
    this->data.bind( meshFunction.getData() );
 }
 
@@ -188,9 +211,16 @@ bind( const MeshPointer& meshPointer,
       const Vector& data,
       const IndexType& offset )
 {
+<<<<<<< HEAD
    TNL_ASSERT_GE( data.getSize(), offset + meshPointer->template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >(), 
                   "The input vector is not large enough for binding to the mesh function." );      
    this->meshPointer = meshPointer;
+=======
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
+>>>>>>> origin/mpi-explosive
    this->data.bind( data, offset, getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
 }
 
@@ -204,9 +234,16 @@ bind( const MeshPointer& meshPointer,
       const SharedPointer< Vector >& data,
       const IndexType& offset )
 {
+<<<<<<< HEAD
    TNL_ASSERT_GE( data->getSize(), offset + meshPointer->template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >(), 
                    "The input vector is not large enough for binding to the mesh function." );      
    this->meshPointer = meshPointer;
+=======
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
+>>>>>>> origin/mpi-explosive
    this->data.bind( *data, offset, getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
 }
 
@@ -218,7 +255,10 @@ void
 MeshFunction< Mesh, MeshEntityDimension, Real >::
 setMesh( const MeshPointer& meshPointer )
 {
-   this->meshPointer = meshPointer;
+
+    SetupSynchronizer(meshPointer->GetDistMesh());
+
+   this->meshPointer=meshPointer;
    this->data.setSize( getMesh().template getEntitiesCount< typename Mesh::template EntityType< MeshEntityDimension > >() );
 }
 
@@ -444,7 +484,7 @@ save( File& file ) const
                std::cerr << "this->data.getSize() = " << this->data.getSize() << std::endl
                          << "this->getMesh().template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >() = " << this->getMesh().template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >() );
    if( ! Object::save( file ) )
-      return false;
+      return false;              
    return this->data.save( file );
 }
 
@@ -456,7 +496,7 @@ MeshFunction< Mesh, MeshEntityDimension, Real >::
 load( File& file )
 {
    if( ! Object::load( file ) )
-      return false;
+      return false;   
    if( ! this->data.load( file ) )
       return false;
    const IndexType meshSize = this->getMesh().template getEntitiesCount< typename MeshType::template EntityType< MeshEntityDimension > >();
@@ -506,6 +546,38 @@ write( const String& fileName,
    }
    return true;
 }
+
+template< typename Mesh,
+          int MeshEntityDimension,
+          typename Real >
+template< typename CommunicatorType>
+void
+MeshFunction< Mesh, MeshEntityDimension, Real >:: 
+Synchronize()
+{
+    auto distrMesh = this->getMesh().GetDistMesh();
+    if(distrMesh != NULL && distrMesh->IsDistributed())
+    {
+        this->synchronizer.template Synchronize<CommunicatorType>(*this);
+    }
+}
+
+template< typename Mesh,
+          int MeshEntityDimension,
+          typename Real >
+void
+MeshFunction< Mesh, MeshEntityDimension, Real >:: 
+SetupSynchronizer(DistributedMeshType *distrMesh )
+{
+    if(distrMesh)//pokud síť kterou se snaží uživatel nastavit je distruibuovaná
+    {
+        if(this->getMesh().GetDistMesh()!=distrMesh)//pokud má nová síť jinou distribuovanou síť než předchozí
+        {
+            this->synchronizer.SetDistributedGrid(distrMesh);
+        }
+    }
+}
+
  
 } // namespace Functions
 } // namespace TNL
diff --git a/src/TNL/Meshes/CMakeLists.txt b/src/TNL/Meshes/CMakeLists.txt
index 2f3f3f634dc0b80c16312b9d703c08bd1975b94a..9dd51e9b858050cb095d3a3cb68b672a3ba263ae 100644
--- a/src/TNL/Meshes/CMakeLists.txt
+++ b/src/TNL/Meshes/CMakeLists.txt
@@ -1,6 +1,7 @@
 ADD_SUBDIRECTORY( Geometry )
 ADD_SUBDIRECTORY( GridDetails )
 ADD_SUBDIRECTORY( MeshDetails )
+ADD_SUBDIRECTORY( DistributedMeshes )
 ADD_SUBDIRECTORY( Readers )
 ADD_SUBDIRECTORY( Topologies )
 ADD_SUBDIRECTORY( TypeResolver )
@@ -24,3 +25,4 @@ SET( tnl_mesh_SOURCES ${tnl_mesh_griddetails_SOURCES}
      PARENT_SCOPE )
 
 INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes )
+
diff --git a/src/TNL/Meshes/DistributedMeshes/BufferEntitiesHelper.h b/src/TNL/Meshes/DistributedMeshes/BufferEntitiesHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..7655bc67937d99645370e3380782f1957bf3a4a8
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/BufferEntitiesHelper.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+                          BufferEntittiesHelper.h  -  description
+                             -------------------
+    begin                : March 1, 2018
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Devices/Host.h>
+#include <TNL/Devices/Cuda.h>
+#include <TNL/ParallelFor.h>
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes { 
+
+
+template < typename MeshFunctionType,
+           int dim,
+           typename RealType=typename MeshFunctionType::MeshType::RealType,
+           typename Device=typename MeshFunctionType::MeshType::DeviceType,
+           typename Index=typename MeshFunctionType::MeshType::GlobalIndexType >
+class BufferEntitiesHelper
+{
+};
+
+//======================================== 1D ====================================================
+
+//host
+template < typename MeshFunctionType, typename RealType, typename Device, typename Index >
+class BufferEntitiesHelper<MeshFunctionType,1,RealType,Device,Index>
+{
+    public:
+    static void BufferEntities(MeshFunctionType meshFunction, RealType * buffer, Index beginx, Index sizex, bool tobuffer)
+    {
+        auto mesh = meshFunction.getMesh();
+        RealType* meshFunctionData = meshFunction.getData().getData();
+        auto kernel = [tobuffer, mesh, buffer, meshFunctionData, beginx] __cuda_callable__ ( Index j )
+        {
+            typename MeshFunctionType::MeshType::Cell entity(mesh);
+            entity.getCoordinates().x()=beginx+j;
+            entity.refresh();
+            if(tobuffer)
+                buffer[j]=meshFunctionData[entity.getIndex()];
+            else
+                meshFunctionData[entity.getIndex()]=buffer[j];
+        };
+        ParallelFor< Device >::exec( 0, sizex, kernel );
+    };  
+};
+
+
+//======================================== 2D ====================================================
+template <typename MeshFunctionType, typename RealType, typename Device, typename Index  > 
+class BufferEntitiesHelper<MeshFunctionType,2,RealType,Device,Index>
+{
+    public:
+    static void BufferEntities(MeshFunctionType meshFunction, RealType * buffer, Index beginx, Index beginy, Index sizex, Index sizey,bool tobuffer)
+    {
+        auto mesh=meshFunction.getMesh();
+        RealType *meshFunctionData=meshFunction.getData().getData();
+        auto kernel = [tobuffer, mesh, buffer, meshFunctionData, beginx, sizex, beginy] __cuda_callable__ ( Index i, Index j )
+        {
+            typename MeshFunctionType::MeshType::Cell entity(mesh);
+            entity.getCoordinates().x()=beginx+j;
+            entity.getCoordinates().y()=beginy+i;				
+            entity.refresh();
+            if(tobuffer)
+                    buffer[i*sizex+j]=meshFunctionData[entity.getIndex()];
+            else
+                    meshFunctionData[entity.getIndex()]=buffer[i*sizex+j];
+        };
+        
+        ParallelFor2D< Device >::exec( 0, 0, sizey, sizex, kernel );       
+        
+    };
+};
+
+
+//======================================== 3D ====================================================
+template <typename MeshFunctionType, typename RealType, typename Device, typename Index >
+class BufferEntitiesHelper<MeshFunctionType,3,RealType,Device,Index>
+{
+    public:
+    static void BufferEntities(MeshFunctionType meshFunction, RealType * buffer, Index beginx, Index beginy, Index beginz, Index sizex, Index sizey, Index sizez, bool tobuffer)
+    {
+
+        auto mesh=meshFunction.getMesh();
+        RealType * meshFunctionData=meshFunction.getData().getData();
+        auto kernel = [tobuffer, mesh, buffer, meshFunctionData, beginx, sizex, beginy, sizey, beginz] __cuda_callable__ ( Index k, Index i, Index j )
+        {
+            typename MeshFunctionType::MeshType::Cell entity(mesh);
+            entity.getCoordinates().x()=beginx+j;
+            entity.getCoordinates().z()=beginz+k;
+            entity.getCoordinates().y()=beginy+i;
+            entity.refresh();
+            if(tobuffer)
+                    buffer[k*sizex*sizey+i*sizex+j]=meshFunctionData[entity.getIndex()];
+            else
+                    meshFunctionData[entity.getIndex()]=buffer[k*sizex*sizey+i*sizex+j];
+        };
+
+        ParallelFor3D< Device >::exec( 0, 0, 0, sizez, sizey, sizex, kernel ); 
+
+        /*for(int k=0;k<sizez;k++)
+        {
+            for(int i=0;i<sizey;i++)
+            {
+                for(int j=0;j<sizex;j++)
+                {
+                        kernel(k,i,j);
+                }
+            }
+        }*/
+    };
+};
+
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/DistributedMeshes/CMakeLists.txt b/src/TNL/Meshes/DistributedMeshes/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..abe91d0d467a222ea7868740d3726115842d2572
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/CMakeLists.txt
@@ -0,0 +1,10 @@
+SET( headers DistributedMesh.h
+             DistributedMeshSynchronizer.h
+             DistributedGrid_1D.h
+             DistributedGrid_2D.h
+             DistributedGrid_3D.h
+             DistributedGridSynchronizer.h
+             DistributedGridIO.h
+             )
+
+INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Meshes/DistributedMesh )
diff --git a/src/TNL/Meshes/DistributedMeshes/CopyEntitiesHelper.h b/src/TNL/Meshes/DistributedMeshes/CopyEntitiesHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe2f82cffe1a54fb03f51e3aa6b85e8952397718
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/CopyEntitiesHelper.h
@@ -0,0 +1,136 @@
+/***************************************************************************
+                          CopyEntitiesHelper.h  -  description
+                             -------------------
+    begin                : March 8, 2018
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Devices/Host.h>
+#include <TNL/Devices/Cuda.h>
+#include <TNL/ParallelFor.h>
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes { 
+
+template<typename MeshFunctionType,
+         int dim=MeshFunctionType::getMeshDimension()>
+class CopyEntitiesHelper
+{
+    public:
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    static void Copy(MeshFunctionType &from, MeshFunctionType &to, CoordinatesType &fromBegin, CoordinatesType &toBegin, CoordinatesType &size)
+    {
+    }
+
+};
+
+
+template<typename MeshFunctionType>
+class CopyEntitiesHelper<MeshFunctionType, 1>
+{
+    public:
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshFunctionType::MeshType::Cell Cell;
+    typedef typename MeshFunctionType::MeshType::GlobalIndexType Index;
+
+    static void Copy(MeshFunctionType &from, MeshFunctionType &to, CoordinatesType &fromBegin, CoordinatesType &toBegin, CoordinatesType &size)
+    {        
+        auto toData=to.getData().getData();
+        auto fromData=from.getData().getData();
+        auto fromMesh=from.getMesh();
+        auto toMesh=to.getMesh();
+        auto kernel = [fromData,toData, fromMesh, toMesh, fromBegin, toBegin] __cuda_callable__ ( Index i )
+        {
+            Cell fromEntity(fromMesh);
+            Cell toEntity(toMesh);
+            toEntity.getCoordinates().x()=toBegin.x()+i;            
+            toEntity.refresh();
+            fromEntity.getCoordinates().x()=fromBegin.x()+i;            
+            fromEntity.refresh();
+            toData[toEntity.getIndex()]=fromData[fromEntity.getIndex()];
+        };
+        ParallelFor< typename MeshFunctionType::MeshType::DeviceType >::exec( (Index)0, (Index)size.x(), kernel );
+
+    }
+
+};
+
+
+template<typename MeshFunctionType>
+
+class CopyEntitiesHelper<MeshFunctionType,2>
+{
+    public:
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshFunctionType::MeshType::Cell Cell;
+    typedef typename MeshFunctionType::MeshType::GlobalIndexType Index;
+
+    static void Copy(MeshFunctionType &from, MeshFunctionType &to, CoordinatesType &fromBegin, CoordinatesType &toBegin, CoordinatesType &size)
+    {
+        auto toData=to.getData().getData();
+        auto fromData=from.getData().getData();
+        auto fromMesh=from.getMesh();
+        auto toMesh=to.getMesh();
+        auto kernel = [fromData,toData, fromMesh, toMesh, fromBegin, toBegin] __cuda_callable__ ( Index j, Index i )
+        {
+            Cell fromEntity(fromMesh);
+            Cell toEntity(toMesh);
+            toEntity.getCoordinates().x()=toBegin.x()+i;
+            toEntity.getCoordinates().y()=toBegin.y()+j;            
+            toEntity.refresh();
+            fromEntity.getCoordinates().x()=fromBegin.x()+i;
+            fromEntity.getCoordinates().y()=fromBegin.y()+j;            
+            fromEntity.refresh();
+            toData[toEntity.getIndex()]=fromData[fromEntity.getIndex()];
+        };
+        ParallelFor2D< typename MeshFunctionType::MeshType::DeviceType >::exec( (Index)0,(Index)0,(Index)size.y(), (Index)size.x(), kernel );
+
+    }
+
+};
+
+
+template<typename MeshFunctionType>
+class CopyEntitiesHelper<MeshFunctionType,3>
+{
+    public:
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshFunctionType::MeshType::Cell Cell;
+    typedef typename MeshFunctionType::MeshType::GlobalIndexType Index;
+
+    static void Copy(MeshFunctionType &from, MeshFunctionType &to, CoordinatesType &fromBegin, CoordinatesType &toBegin, CoordinatesType &size)
+    {
+        auto toData=to.getData().getData();
+        auto fromData=from.getData().getData();
+        auto fromMesh=from.getMesh();
+        auto toMesh=to.getMesh();
+        auto kernel = [fromData,toData, fromMesh, toMesh, fromBegin, toBegin] __cuda_callable__ ( Index k, Index j, Index i )
+        {
+            Cell fromEntity(fromMesh);
+            Cell toEntity(toMesh);
+            toEntity.getCoordinates().x()=toBegin.x()+i;
+            toEntity.getCoordinates().y()=toBegin.y()+j;
+            toEntity.getCoordinates().z()=toBegin.z()+k;                                
+            toEntity.refresh();
+            fromEntity.getCoordinates().x()=fromBegin.x()+i;
+            fromEntity.getCoordinates().y()=fromBegin.y()+j;
+            fromEntity.getCoordinates().z()=fromBegin.z()+k;            
+            fromEntity.refresh();
+            toData[toEntity.getIndex()]=fromData[fromEntity.getIndex()];
+        };
+        ParallelFor3D< typename MeshFunctionType::MeshType::DeviceType >::exec( (Index)0,(Index)0,(Index)0,(Index)size.z() ,(Index)size.y(), (Index)size.x(), kernel );
+    }
+};
+
+
+
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGridIO.h b/src/TNL/Meshes/DistributedMeshes/DistributedGridIO.h
new file mode 100644
index 0000000000000000000000000000000000000000..931252d53f857163b71afb03ae76b8066443f846
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedGridIO.h
@@ -0,0 +1,401 @@
+/***************************************************************************
+                          DistributedGrid.h  -  description
+                             -------------------
+    begin                : October 5, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/File.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Meshes/DistributedMeshes/CopyEntitiesHelper.h>
+#include <TNL/Functions/MeshFunction.h>
+
+
+#include <iostream>
+
+#ifdef MPIIO
+#include <TNL/Communicators/MpiCommunicator.h>
+#endif
+
+namespace TNL {
+namespace Meshes {   
+namespace DistributedMeshes {
+
+enum DistrGridIOTypes { Dummy = 0 , LocalCopy = 1, MpiIO=2 };
+    
+template<typename MeshFunctionType,
+         DistrGridIOTypes type = LocalCopy> 
+class DistributedGridIO
+{
+};
+
+template<typename MeshFunctionType> 
+class DistributedGridIO<MeshFunctionType,Dummy>
+{
+    bool save(const String& fileName, MeshFunctionType &meshFunction)
+    {
+        return true;
+    };
+            
+    bool load(const String& fileName, MeshFunctionType &meshFunction) 
+    {
+        return true;
+    };
+};
+
+
+/*
+ * This variant cerate copy of MeshFunction but smaler, reduced to local entites, without overlap. 
+ * It slow and has high RAM consupation
+ */
+template<typename MeshFunctionType> 
+class DistributedGridIO<MeshFunctionType,LocalCopy>
+{
+
+    public:
+
+    typedef typename MeshFunctionType::MeshType MeshType;
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshFunctionType::MeshType::PointType PointType;
+    typedef typename MeshFunctionType::VectorType VectorType;
+    //typedef DistributedGrid< MeshType,MeshFunctionType::getMeshDimension()> DistributedGridType;
+    
+    static bool save(const String& fileName, MeshFunctionType &meshFunction)
+    {
+        auto *distrGrid=meshFunction.getMesh().GetDistMesh();
+        
+        if(distrGrid==NULL) //not distributed
+        {
+            return meshFunction.save(fileName);
+        }
+
+        MeshType mesh=meshFunction.getMesh();
+        
+        PointType spaceSteps=mesh.getSpaceSteps();
+        PointType origin=mesh.getOrigin();
+                
+        CoordinatesType localSize=distrGrid->getLocalSize();
+        CoordinatesType localBegin=distrGrid->getLocalBegin();
+ 
+        SharedPointer<MeshType> newMesh;
+        newMesh->setDimensions(localSize);
+        newMesh->setSpaceSteps(spaceSteps);
+        newMesh->setOrigin(origin+TNL::Containers::tnlDotProduct(spaceSteps,localBegin));
+        
+        File meshFile;
+        meshFile.open( fileName+String("-mesh-")+distrGrid->printProcessCoords()+String(".tnl"),IOMode::write);
+        newMesh->save( meshFile );
+        meshFile.close();
+
+        VectorType newDof(newMesh-> template getEntitiesCount< typename MeshType::Cell >());
+
+        MeshFunctionType newMeshFunction;
+        newMeshFunction.bind(newMesh,newDof);        
+
+        CoordinatesType zeroCoord;
+        zeroCoord.setValue(0);
+
+        CopyEntitiesHelper<MeshFunctionType>::Copy(meshFunction,newMeshFunction,localBegin,zeroCoord,localSize);
+
+        File file;
+        file.open( fileName+String("-")+distrGrid->printProcessCoords()+String(".tnl"), IOMode::write );
+        bool ret=newMeshFunction.save(file);
+        file.close();
+
+        return ret;
+        
+    };
+            
+    static bool load(const String& fileName,MeshFunctionType &meshFunction) 
+    {
+        auto *distrGrid=meshFunction.getMesh().GetDistMesh();
+        if(distrGrid==NULL) //not distributed
+        {
+            return meshFunction.boundLoad(fileName);
+        }
+
+        MeshType mesh=meshFunction.getMesh();
+        
+        PointType spaceSteps=mesh.getSpaceSteps();
+        PointType origin=mesh.getOrigin();
+                
+        CoordinatesType localSize=distrGrid->getLocalSize();
+        CoordinatesType localBegin=distrGrid->getLocalBegin();
+
+        SharedPointer<MeshType> newMesh;
+        newMesh->setDimensions(localSize);
+        newMesh->setSpaceSteps(spaceSteps);
+        newMesh->setOrigin(origin+TNL::Containers::tnlDotProduct(spaceSteps,localBegin));
+        
+        VectorType newDof(newMesh-> template getEntitiesCount< typename MeshType::Cell >());
+        MeshFunctionType newMeshFunction;
+        newMeshFunction.bind(newMesh,newDof); 
+
+        CoordinatesType zeroCoord;
+        zeroCoord.setValue(0);        
+
+        File file;
+        file.open( fileName+String("-")+distrGrid->printProcessCoords()+String(".tnl"), IOMode::read );
+        bool result=newMeshFunction.boundLoad(file);
+        file.close();
+        CopyEntitiesHelper<MeshFunctionType>::Copy(newMeshFunction,meshFunction,zeroCoord,localBegin,localSize);
+        
+        return result;
+    };
+    
+};
+
+/*
+ * Save distributed data into single file without overlaps using MPIIO and MPI datatypes, 
+ * EXPLOSIVE: works with only Grids and MPI
+ * BAD IMPLEMENTTION creating MPI-Types at every save! -- I dont want contamine more places by MPI..
+ */
+
+#ifdef MPIIO
+template<typename MeshFunctionType> 
+class DistributedGridIO<MeshFunctionType,MpiIO>
+{
+
+    public:
+
+    typedef typename MeshFunctionType::MeshType MeshType;
+    typedef typename MeshFunctionType::MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshFunctionType::MeshType::PointType PointType;
+    typedef typename MeshFunctionType::VectorType VectorType;
+    //typedef DistributedGrid< MeshType,MeshFunctionType::getMeshDimension()> DistributedGridType;
+    
+    static bool save(const String& fileName, MeshFunctionType &meshFunction)
+    {
+        auto *distrGrid=meshFunction.getMesh().GetDistMesh();
+        
+        if(distrGrid==NULL) //not distributed
+        {
+            return meshFunction.save(fileName);
+        }
+
+       MPI_Datatype ftype;
+       MPI_Datatype atype;
+       int dataCount=CreateDataTypes(distrGrid,&ftype,&atype);
+
+       double * data=meshFunction.getData().getData();//TYP
+
+       //write 
+       MPI_File file;
+       MPI_File_open(MPI_COMM_WORLD,fileName.getString(),
+        	   MPI_MODE_CREATE|MPI_MODE_WRONLY,
+               MPI_INFO_NULL, &file);
+
+       int headerSize=0;
+
+       if(Communicators::MpiCommunicator::GetRank()==0)
+       {
+            headerSize=writeMeshFunctionHeader(file,meshFunction,dataCount);
+       }
+       MPI_Bcast(&headerSize, 1, MPI_INT,0, MPI_COMM_WORLD);
+
+       MPI_File_set_view(file,headerSize,MPI_DOUBLE,ftype,"native",MPI_INFO_NULL);//TYP
+       MPI_Status wstatus;
+
+       MPI_File_write(file,data,1,atype,&wstatus);
+
+       MPI_File_close(&file);
+
+       MPI_Type_free(&atype);
+       MPI_Type_free(&ftype);
+
+       return true;
+    };
+
+    template<typename DitsributedGridType>
+    static int CreateDataTypes(DitsributedGridType *distrGrid,MPI_Datatype *ftype,MPI_Datatype *atype)
+    {
+        int dim=distrGrid->getMeshDimension();
+
+        int fstarts[dim];
+        int flsize[dim];
+        int fgsize[dim];
+        
+        hackArray(dim,fstarts,distrGrid->getGlobalBegin().getData());
+        hackArray(dim,flsize,distrGrid->getLocalSize().getData());
+        hackArray(dim,fgsize,distrGrid->getGlobalSize().getData());
+
+        MPI_Type_create_subarray(dim,
+            fgsize,flsize,fstarts,
+            MPI_ORDER_C,MPI_DOUBLE,ftype); //TYP
+        MPI_Type_commit(ftype);
+
+       int agsize[dim];
+       int alsize[dim];
+       int astarts[dim]; 
+
+       hackArray(dim,astarts,distrGrid->getLocalBegin().getData());
+       hackArray(dim,alsize,distrGrid->getLocalSize().getData());
+       hackArray(dim,agsize,distrGrid->getLocalGridSize().getData());
+
+       MPI_Type_create_subarray(dim,
+            agsize,alsize,astarts,
+            MPI_ORDER_C,MPI_DOUBLE,atype); //TYP
+       MPI_Type_commit(atype);
+
+        int dataCount=1;
+        for(int i=0;i<dim;i++)
+            dataCount*=fgsize[i];
+
+        return dataCount;
+
+    }
+
+    template<typename Index>
+    static void hackArray(int dim, int* out, Index* in)
+    {
+        if(dim==1)
+        {
+            out[0]=in[0];
+        }
+
+        if(dim==2)
+        {
+           out[1]=in[0];
+           out[0]=in[1];
+        }
+
+        if(dim==3)
+        {
+           out[0]=in[2];
+           out[1]=in[1];
+           out[2]=in[0];
+        }
+    }
+
+    static unsigned int writeMeshFunctionHeader(MPI_File file,MeshFunctionType &meshFunction, int length )
+    {
+
+        unsigned int size=0;
+        int count;
+        MPI_Status wstatus;
+
+        //Magic
+        MPI_File_write(file,"TNLMN",5,MPI_CHAR,&wstatus);
+        MPI_Get_count(&wstatus,MPI_CHAR,&count);
+        size+=count*sizeof(char);
+
+        //Meshfunction type
+        String meshFunctionSerializationType=meshFunction.getSerializationTypeVirtual();
+        int meshFunctionSerializationTypeLength=meshFunctionSerializationType.getLength();
+        MPI_File_write(file,&meshFunctionSerializationTypeLength,1,MPI_INT,&wstatus);
+        MPI_Get_count(&wstatus,MPI_INT,&count);
+        size+=count*sizeof(int);
+        MPI_File_write(file,meshFunctionSerializationType.getString(),meshFunctionSerializationType.getLength(),MPI_CHAR,&wstatus);
+        MPI_Get_count(&wstatus,MPI_CHAR,&count);
+        size+=count*sizeof(char);
+
+        //Magic
+        MPI_File_write(file,"TNLMN",5,MPI_CHAR,&wstatus);
+        MPI_Get_count(&wstatus,MPI_CHAR,&count);
+        size+=count*sizeof(char);
+        //Vector Type
+        String dataSerializationType=meshFunction.getData().getSerializationTypeVirtual();
+        int dataSerializationTypeLength=dataSerializationType.getLength();
+        MPI_File_write(file,&dataSerializationTypeLength,1,MPI_INT,&wstatus);
+        MPI_Get_count(&wstatus,MPI_INT,&count);
+        size+=count*sizeof(int);
+        MPI_File_write(file,dataSerializationType.getString(),dataSerializationType.getLength(),MPI_CHAR,&wstatus);
+        MPI_Get_count(&wstatus,MPI_CHAR,&count);
+        size+=count*sizeof(char);
+        //Data count
+        MPI_File_write(file,&(length),1,MPI_INT,&wstatus);
+        MPI_Get_count(&wstatus,MPI_INT,&count);
+        size+=count*sizeof(int);
+
+        return size;
+    };
+            
+    /* Funky bomb - no checks - only dirty load */
+    static bool load(const String& fileName,MeshFunctionType &meshFunction) 
+    {
+        auto *distrGrid=meshFunction.getMesh().GetDistMesh();
+        if(distrGrid==NULL) //not distributed
+        {
+            return meshFunction.boundLoad(fileName);
+        }
+
+       MPI_Datatype ftype;
+       MPI_Datatype atype;
+       int dataCount=CreateDataTypes(distrGrid,&ftype,&atype);
+
+       double * data=meshFunction.getData().getData();//TYP
+
+       //write 
+       MPI_File file;
+       MPI_File_open(MPI_COMM_WORLD,fileName.getString(),
+        	   MPI_MODE_RDONLY,
+               MPI_INFO_NULL, &file);
+       
+       int headerSize=0;
+
+       if(Communicators::MpiCommunicator::GetRank()==0)
+       {
+            headerSize=readMeshFunctionHeader(file,meshFunction,dataCount);
+       }
+       MPI_Bcast(&headerSize, 1, MPI_INT,0, MPI_COMM_WORLD);
+       
+       if(headerSize<0)
+            return false;
+
+       MPI_File_set_view(file,headerSize,MPI_DOUBLE,ftype,"native",MPI_INFO_NULL);//TYP
+       MPI_Status wstatus;
+       MPI_File_read(file,(void*)data,1,atype,&wstatus);
+       MPI_File_close(&file);
+        
+       MPI_Type_free(&atype);
+       MPI_Type_free(&ftype);
+
+       return true;
+    };
+
+    //tak mohlo by to něco kontrolovat...ale nic to nekontroluje
+    static int readMeshFunctionHeader(MPI_File file,MeshFunctionType &meshFunction, int length)
+    {
+        MPI_Status rstatus;
+        char buffer[255];
+        int size=0;
+        int count=0;
+
+        MPI_File_read(file, (void *)buffer,5, MPI_CHAR, &rstatus);//MAGIC
+        size+=5*sizeof(char);
+        MPI_File_read(file, (void *)&count,1, MPI_INT, &rstatus);//SIZE OF DATATYPE
+        size+=1*sizeof(int);
+        MPI_File_read(file, (void *)&buffer,count, MPI_CHAR, &rstatus);//DATATYPE
+        size+=count*sizeof(char);
+
+        MPI_File_read(file, (void *)buffer,5, MPI_CHAR, &rstatus);//MAGIC
+        size+=5*sizeof(char);
+        MPI_File_read(file, (void *)&count,1, MPI_INT, &rstatus);//SIZE OF DATATYPE
+        size+=1*sizeof(int);
+        MPI_File_read(file, (void *)&buffer,count, MPI_CHAR, &rstatus);//DATATYPE
+        size+=count*sizeof(char);
+        MPI_File_read(file, (void *)&count,1, MPI_INT, &rstatus);//DATACOUNT
+        size+=1*sizeof(int);
+        
+        if(count!=length)
+        {
+            std::cerr<<"Chyba načítání MeshFunction, délka dat v souboru neodpovídá očekávané délce" << std::endl;
+            size=-1;
+        }
+
+        return size;
+    };
+    
+};
+
+#endif
+
+
+}
+}
+}
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h b/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h
new file mode 100644
index 0000000000000000000000000000000000000000..fcf4c35ec772f46a61e5c4661aa424d5aa5c6082
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h
@@ -0,0 +1,542 @@
+/***************************************************************************
+                          DistributedGrid.h  -  description
+                             -------------------
+    begin                : March 17, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Containers/Array.h>
+#include <TNL/Meshes/DistributedMeshes/BufferEntitiesHelper.h>
+
+
+namespace TNL {
+namespace Functions{
+template< typename Mesh,
+          int MeshEntityDimension,
+          typename Real  >
+class MeshFunction;
+}//Functions
+}//TNL
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes { 
+
+
+//=============================================1D==================================
+
+template <typename RealType,
+          int EntityDimension,
+          typename Index,
+          typename Device,
+          typename GridReal>  
+class DistributedMeshSynchronizer< Functions::MeshFunction< Grid< 1, GridReal, Device, Index >,EntityDimension, RealType>>
+{
+
+public:
+        typedef typename Grid< 1, GridReal, Device, Index >::Cell Cell;
+        typedef typename Functions::MeshFunction< Grid< 1, GridReal, Device, Index >,EntityDimension, RealType> MeshFunctionType;
+        typedef typename Grid< 1, GridReal, Device, Index >::DistributedMeshType DistributedGridType; 
+        typedef RealType Real;
+
+
+private:  
+        Containers::Array<RealType, Device> sendbuffs[2];
+        Containers::Array<RealType, Device> rcvbuffs[2];
+        int overlapSize;
+
+        DistributedGridType *distributedgrid;
+
+        bool isSet;
+
+    
+    public:
+    DistributedMeshSynchronizer()
+    {
+        isSet=false;
+    };
+
+    DistributedMeshSynchronizer(DistributedGridType *distrgrid)
+    {
+        isSet=false;
+        SetDistributedGrid(distrgrid);
+    };
+
+    void SetDistributedGrid(DistributedGridType *distrgrid)
+    {
+        isSet=true;
+
+        this->distributedgrid=distrgrid;
+
+        overlapSize = distributedgrid->getOverlap().x();
+
+        sendbuffs[0].setSize(overlapSize);
+        sendbuffs[1].setSize(overlapSize);
+        rcvbuffs[0].setSize(overlapSize);
+        rcvbuffs[1].setSize(overlapSize);      
+    };
+
+    template<typename CommunicatorType>
+    void Synchronize(MeshFunctionType &meshfunction)
+    {
+        TNL_ASSERT_TRUE(isSet,"Synchronizer is not set, but used to Synchronize");
+
+        if(!distributedgrid->IsDistributed())
+                return;
+
+        int leftN=distributedgrid->getLeft();
+        int rightN=distributedgrid->getRight();
+
+        int totalSize = meshfunction.getMesh().getDimensions().x();
+
+        CopyBuffers(meshfunction, sendbuffs, true,
+                overlapSize, totalSize-2*overlapSize, overlapSize,
+                leftN, rightN);
+
+        //async send
+        typename CommunicatorType::Request req[4];
+
+        //send everithing, recieve everything 
+        if(leftN!=-1)
+        {
+            req[0]=CommunicatorType::ISend(sendbuffs[Left].getData(), overlapSize, leftN);
+            req[2]=CommunicatorType::IRecv(rcvbuffs[Left].getData(), overlapSize, leftN);
+        }
+        else
+        {
+            req[0]=CommunicatorType::NullRequest;
+            req[2]=CommunicatorType::NullRequest;
+        }        
+
+        if(rightN!=-1)
+        {
+            req[1]=CommunicatorType::ISend(sendbuffs[Right].getData(), overlapSize, rightN);
+            req[3]=CommunicatorType::IRecv(rcvbuffs[Right].getData(), overlapSize, rightN);
+        }
+        else
+        {
+            req[1]=CommunicatorType::NullRequest;
+            req[3]=CommunicatorType::NullRequest;
+        }
+
+        //wait until send and recv is done
+        CommunicatorType::WaitAll(req, 4);
+
+        CopyBuffers(meshfunction, rcvbuffs, false,
+                0, totalSize-overlapSize, overlapSize,
+                leftN, rightN);
+    }
+
+    private:
+    template <typename Real>
+    void CopyBuffers(MeshFunctionType meshfunction, TNL::Containers::Array<Real,Device> * buffers, bool toBuffer,
+            int left, int right,
+            int size,
+            int leftNeighbor, int rightNeighbor)
+    {
+        if(leftNeighbor!=-1)
+            BufferEntitiesHelper<MeshFunctionType,1,Real,Device>::BufferEntities(meshfunction,buffers[Left].getData(),left,size,toBuffer);
+        if(rightNeighbor!=-1)
+            BufferEntitiesHelper<MeshFunctionType,1,Real,Device>::BufferEntities(meshfunction,buffers[Right].getData(),right,size,toBuffer);  
+    }
+
+};
+
+//=========================2D=================================================
+template <typename RealType,
+          int EntityDimension,
+          typename Index,
+          typename Device,
+          typename GridReal>  
+class DistributedMeshSynchronizer< Functions::MeshFunction< Grid< 2, GridReal, Device, Index >,EntityDimension, RealType>>
+{
+
+    public:
+        typedef typename Grid< 2, GridReal, Device, Index >::Cell Cell;
+        typedef typename Functions::MeshFunction< Grid< 2, GridReal, Device, Index >,EntityDimension, RealType> MeshFunctionType;
+        typedef typename Grid< 2, GridReal, Device, Index >::DistributedMeshType DistributedGridType; 
+        typedef typename MeshFunctionType::RealType Real;
+        typedef typename DistributedGridType::CoordinatesType CoordinatesType;
+
+    private:
+        DistributedGridType *distributedgrid;
+
+        Containers::Array<RealType, Device, Index> sendbuffs[8];
+        Containers::Array<RealType, Device, Index> rcvbuffs[8];
+        int sizes[8];
+        
+        int leftSrc;
+        int rightSrc;
+        int upSrc;
+        int downSrc;
+        int xcenter;
+        int ycenter;
+        int leftDst;
+        int rightDst;
+        int upDst;
+        int downDst;
+        
+        CoordinatesType overlap;
+        CoordinatesType localsize;
+
+        bool isSet;
+
+    public:
+    DistributedMeshSynchronizer()
+    {
+        isSet=false;
+    };
+
+    DistributedMeshSynchronizer(DistributedGridType *distrgrid)
+    {
+        isSet=false;
+        SetDistributedGrid(distrgrid);
+    };
+
+    void SetDistributedGrid(DistributedGridType *distrgrid)
+    {
+        isSet=true;
+        
+        this->distributedgrid=distrgrid;
+
+        overlap = distributedgrid->getOverlap();
+        localsize = distributedgrid->getLocalSize();
+        
+        CoordinatesType localgridsize = this->distributedgrid->getLocalGridSize();
+        CoordinatesType localbegin=this->distributedgrid->getLocalBegin();
+
+        int updownsize=localsize.x()*overlap.y();
+        int leftrightsize=localsize.y()*overlap.x();
+        int connersize=overlap.x()*overlap.y();
+
+        sizes[Left]=leftrightsize;
+        sizes[Right]=leftrightsize;
+        sizes[Up]=updownsize;
+        sizes[Down]=updownsize;
+        sizes[UpLeft]=connersize;
+        sizes[DownLeft]=connersize;
+        sizes[UpRight]=connersize;
+        sizes[DownRight]=connersize;
+
+        for(int i=0;i<8;i++)
+        {
+            sendbuffs[i].setSize(sizes[i]);
+            rcvbuffs[i].setSize(sizes[i]);
+        }
+
+        leftSrc=localbegin.x();
+        rightSrc=localgridsize.x()-2*overlap.x();
+        upSrc=localbegin.y();
+        downSrc=localgridsize.y()-2*overlap.y();
+            
+        xcenter=localbegin.x();
+        ycenter=localbegin.y();
+        
+        leftDst=0;
+        rightDst=localgridsize.x()-overlap.x();
+        upDst=0;
+        downDst=localgridsize.y()-overlap.y();                       
+    }
+       
+    template<typename CommunicatorType>
+    void Synchronize( MeshFunctionType &meshfunction)
+    {
+
+        TNL_ASSERT_TRUE(isSet,"Synchronizer is not set, but used to Synchronize");
+
+	    if(!distributedgrid->IsDistributed())
+            return;
+
+        int *neighbor=distributedgrid->getNeighbors();
+
+        CopyBuffers(meshfunction, sendbuffs, true,
+            leftSrc, rightSrc, upSrc, downSrc,
+            xcenter, ycenter,
+            overlap,localsize,
+            neighbor);
+	
+        //async send and rcv
+        typename CommunicatorType::Request req[16];
+		                
+        //send everithing, recieve everything 
+        for(int i=0;i<8;i++)	
+           if(neighbor[i]!=-1)
+           {
+               req[i]=CommunicatorType::ISend(sendbuffs[i].getData(), sizes[i], neighbor[i]);
+               req[8+i]=CommunicatorType::IRecv(rcvbuffs[i].getData(), sizes[i], neighbor[i]);
+           }
+		   else
+      	   {
+               req[i]=CommunicatorType::NullRequest;
+               req[8+i]=CommunicatorType::NullRequest;
+           }
+
+        //wait until send is done
+        CommunicatorType::WaitAll(req,16);
+        
+        //copy data form rcv buffers
+        CopyBuffers(meshfunction, rcvbuffs, false,
+            leftDst, rightDst, upDst, downDst,
+            xcenter, ycenter,
+            overlap,localsize,
+            neighbor);
+    }
+    
+    private:
+    template <typename Real>
+    void CopyBuffers(MeshFunctionType meshfunction, Containers::Array<Real, Device, Index> * buffers, bool toBuffer,
+            int left, int right, int up, int down,
+            int xcenter, int ycenter,
+            CoordinatesType shortDim, CoordinatesType longDim,
+            int *neighbor)
+    {
+       	if(neighbor[Left]!=-1)        
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[Left].getData(),left,ycenter,shortDim.x(),longDim.y(),toBuffer);
+        if(neighbor[Right]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[Right].getData(),right,ycenter,shortDim.x(),longDim.y(),toBuffer);
+        if(neighbor[Up]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[Up].getData(),xcenter,up,longDim.x(),shortDim.y(),toBuffer);
+        if(neighbor[Down]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[Down].getData(),xcenter,down,longDim.x(),shortDim.y(),toBuffer);
+        if(neighbor[UpLeft]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[UpLeft].getData(),left,up,shortDim.x(),shortDim.y(),toBuffer);
+        if(neighbor[UpRight]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[UpRight].getData(),right,up,shortDim.x(),shortDim.y(),toBuffer);
+        if(neighbor[DownLeft]!=-1)        
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[DownLeft].getData(),left,down,shortDim.x(),shortDim.y(),toBuffer);
+        if(neighbor[DownRight]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,2,Real,Device>::BufferEntities(meshfunction,buffers[DownRight].getData(),right,down,shortDim.x(),shortDim.y(),toBuffer);
+    }
+};
+
+
+//=========================3D=================================================
+template <typename RealType,
+          int EntityDimension,
+          typename Index,
+          typename Device,
+          typename GridReal>  
+class DistributedMeshSynchronizer< Functions::MeshFunction< Grid< 3, GridReal, Device, Index >,EntityDimension, RealType>>
+{
+
+    public:
+        typedef typename Grid< 3, GridReal, Device, Index >::Cell Cell;
+        typedef typename Functions::MeshFunction< Grid< 3, GridReal, Device, Index >,EntityDimension, RealType> MeshFunctionType;
+        typedef typename Grid< 3, GridReal, Device, Index >::DistributedMeshType DistributedGridType; 
+        typedef typename MeshFunctionType::RealType Real;
+        typedef typename DistributedGridType::CoordinatesType CoordinatesType;
+      
+    private:
+        Containers::Array<RealType, Device, Index> sendbuffs[26];
+        Containers::Array<RealType, Device, Index> rcvbuffs[26];
+        int sizes[26];
+        DistributedGridType *distributedgrid;
+        
+        int westSrc;
+        int eastSrc;
+        int nordSrc;
+        int southSrc;
+        int bottomSrc;
+        int topSrc;
+        int xcenter;
+        int ycenter;
+        int zcenter;
+        int westDst;
+        int eastDst;
+        int nordDst;
+        int southDst;
+        int bottomDst;
+        int topDst;
+        
+        CoordinatesType overlap;
+        CoordinatesType localsize;
+
+        bool isSet;
+    
+    public:
+    
+    DistributedMeshSynchronizer()
+    {
+        isSet=false;
+    };
+
+    DistributedMeshSynchronizer(DistributedGridType *distrgrid)
+    {
+        isSet=false;
+        SetDistributedGrid(distrgrid);
+    };
+
+    void SetDistributedGrid(DistributedGridType *distrgrid)
+    {
+        isSet=true;
+
+        this->distributedgrid=distrgrid;        
+        overlap = this->distributedgrid->getOverlap();
+        localsize = this->distributedgrid->getLocalSize();
+        
+        CoordinatesType localbegin=this->distributedgrid->getLocalBegin();
+        CoordinatesType localgridsize = this->distributedgrid->getLocalGridSize();
+
+        sizes[West]=sizes[East]=localsize.y()*localsize.z()*overlap.x();
+        sizes[Nord]=sizes[South]=localsize.x()*localsize.z()*overlap.y();
+        sizes[Bottom]=sizes[Top]=localsize.x()*localsize.y()*overlap.z();
+        
+        sizes[NordWest]=sizes[NordEast]=sizes[SouthWest]=sizes[SouthEast]=localsize.z()*overlap.x()*overlap.y();
+        sizes[BottomWest]=sizes[BottomEast]=sizes[TopWest]=sizes[TopEast]=localsize.y()*overlap.x()*overlap.z();
+        sizes[BottomNord]=sizes[BottomSouth]=sizes[TopNord]=sizes[TopSouth]=localsize.x()*overlap.y()*overlap.z();
+        
+        sizes[BottomNordWest]=sizes[BottomNordEast]=sizes[BottomSouthWest]=sizes[BottomSouthEast]=
+                sizes[TopNordWest]=sizes[TopNordEast]=sizes[TopSouthWest]=sizes[TopSouthEast]= 
+                overlap.x()*overlap.y()*overlap.z();
+
+        for(int i=0;i<26;i++)
+        {
+                sendbuffs[i].setSize(sizes[i]);
+                rcvbuffs[i].setSize(sizes[i]);
+        }
+        
+        westSrc=localbegin.x();
+        eastSrc=localgridsize.x()-2*overlap.x();
+        nordSrc=localbegin.y();
+        southSrc=localgridsize.y()-2*overlap.y();
+        bottomSrc=localbegin.z();
+        topSrc=localgridsize.z()-2*overlap.z();
+            
+        xcenter=localbegin.x();
+        ycenter=localbegin.y();
+        zcenter=localbegin.z();
+        
+        westDst=0;
+        eastDst=localgridsize.x()-overlap.x();
+        nordDst=0;
+        southDst=localgridsize.y()-overlap.y();
+        bottomDst=0;
+        topDst=localgridsize.z()-overlap.z();
+        
+    }
+        
+    template<typename CommunicatorType>
+    void Synchronize(MeshFunctionType &meshfunction)
+    {
+
+        TNL_ASSERT_TRUE(isSet,"Synchronizer is not set, but used to Synchronize");
+
+    	if(!distributedgrid->IsDistributed())
+            return;
+        
+        int *neighbor=distributedgrid->getNeighbors();
+        
+        //fill send buffers
+        CopyBuffers(meshfunction, sendbuffs, true,
+            westSrc, eastSrc, nordSrc, southSrc, bottomSrc, topSrc,
+            xcenter, ycenter, zcenter,
+            overlap, localsize,
+            neighbor);
+        
+        //async send and rcv
+        typename CommunicatorType::Request req[52];
+		                
+        //send everithing, recieve everything 
+        for(int i=0;i<26;i++)	
+           if(neighbor[i]!=-1)
+           {
+               req[i]=CommunicatorType::ISend(sendbuffs[i].getData(), sizes[i], neighbor[i]);
+               req[26+i]=CommunicatorType::IRecv(rcvbuffs[i].getData(), sizes[i], neighbor[i]);
+           }
+		   else
+      	   {
+               req[i]=CommunicatorType::NullRequest;
+               req[26+i]=CommunicatorType::NullRequest;
+           }
+
+        //wait until send is done
+        CommunicatorType::WaitAll(req,52);
+
+        //copy data form rcv buffers
+        CopyBuffers(meshfunction, rcvbuffs, false,
+            westDst, eastDst, nordDst, southDst, bottomDst, topDst,
+            xcenter, ycenter, zcenter,
+            overlap, localsize,
+            neighbor); 
+ 
+    }
+    
+    private:    
+    template <typename Real>
+    void CopyBuffers(MeshFunctionType meshfunction, Containers::Array<Real, Device, Index> * buffers, bool toBuffer,
+            int west, int east, int nord, int south, int bottom, int top,
+            int xcenter, int ycenter, int zcenter,
+            CoordinatesType shortDim, CoordinatesType longDim,
+            int *neighbor)
+    {
+       //X-Y-Z
+        if(neighbor[West]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[West].getData(),west,ycenter,zcenter,shortDim.x(),longDim.y(),longDim.z(),toBuffer);
+        if(neighbor[East]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[East].getData(),east,ycenter,zcenter,shortDim.x(),longDim.y(),longDim.z(),toBuffer);
+        if(neighbor[Nord]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[Nord].getData(),xcenter,nord,zcenter,longDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        if(neighbor[South]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[South].getData(),xcenter,south,zcenter,longDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        if(neighbor[Bottom]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[Bottom].getData(),xcenter,ycenter,bottom,longDim.x(),longDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[Top]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[Top].getData(),xcenter,ycenter,top,longDim.x(),longDim.y(),shortDim.z(),toBuffer);	
+        //XY
+        if(neighbor[NordWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[NordWest].getData(),west,nord,zcenter,shortDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        if(neighbor[NordEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[NordEast].getData(),east,nord,zcenter,shortDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        if(neighbor[SouthWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[SouthWest].getData(),west,south,zcenter,shortDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        if(neighbor[SouthEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[SouthEast].getData(),east,south,zcenter,shortDim.x(),shortDim.y(),longDim.z(),toBuffer);
+        //XZ
+        if(neighbor[BottomWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomWest].getData(),west,ycenter,bottom,shortDim.x(),longDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[BottomEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomEast].getData(),east,ycenter,bottom,shortDim.x(),longDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopWest].getData(),west,ycenter,top,shortDim.x(),longDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopEast].getData(),east,ycenter,top,shortDim.x(),longDim.y(),shortDim.z(),toBuffer);   
+        //YZ
+        if(neighbor[BottomNord]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomNord].getData(),xcenter,nord,bottom,longDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[BottomSouth]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomSouth].getData(),xcenter,south,bottom,longDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopNord]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopNord].getData(),xcenter,nord,top,longDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopSouth]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopSouth].getData(),xcenter,south,top,longDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        //XYZ
+        if(neighbor[BottomNordWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomNordWest].getData(),west,nord,bottom,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[BottomNordEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomNordEast].getData(),east,nord,bottom,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[BottomSouthWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomSouthWest].getData(),west,south,bottom,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[BottomSouthEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[BottomSouthEast].getData(),east,south,bottom,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopNordWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopNordWest].getData(),west,nord,top,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopNordEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopNordEast].getData(),east,nord,top,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopSouthWest]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopSouthWest].getData(),west,south,top,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);
+        if(neighbor[TopSouthEast]!=-1)
+            BufferEntitiesHelper<MeshFunctionType,3,Real,Device>::BufferEntities(meshfunction,buffers[TopSouthEast].getData(),east,south,top,shortDim.x(),shortDim.y(),shortDim.z(),toBuffer);   
+
+    }
+};
+
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGrid_1D.h b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_1D.h
new file mode 100644
index 0000000000000000000000000000000000000000..874955452346be5429fa5948d8fb209d5357051c
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_1D.h
@@ -0,0 +1,232 @@
+/***************************************************************************
+                          DistributedGrid_1D.h  -  description
+                             -------------------
+    begin                : January 09, 2018
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes {
+
+template<typename RealType, typename Device, typename Index >     
+class DistributedMesh<Grid< 1, RealType, Device, Index >>
+{
+
+    public:
+    
+    typedef Index IndexType;
+    typedef Grid< 1, RealType, Device, IndexType > GridType;
+    typedef typename GridType::PointType PointType;
+    typedef Containers::StaticVector< 1, IndexType > CoordinatesType;
+    
+    static constexpr int getMeshDimension() { return 1; };    
+
+    private : 
+
+        PointType localorigin;
+        CoordinatesType localbegin;
+        CoordinatesType localsize;
+        CoordinatesType localgridsize;
+        CoordinatesType overlap;
+        CoordinatesType globalsize;
+        CoordinatesType globalbegin;
+        PointType spaceSteps;
+        
+        
+        IndexType Dimensions;        
+        bool isDistributed;
+        
+        int rank;
+        int nproc;
+        
+        int numberoflarger;
+        
+        int left;
+        int right;
+
+        bool isSet;
+        
+     
+   public:
+       
+       DistributedMesh()
+       {
+            isSet=false;
+       };
+
+       //compute everithing 
+       template<typename CommunicatorType>
+       void setGlobalGrid(GridType globalGrid, CoordinatesType overlap, int *distribution=NULL)
+       {
+           isSet=true;
+
+           this->overlap=overlap;
+           
+           left=-1;
+           right=-1;
+           
+           Dimensions= GridType::getMeshDimension();
+           spaceSteps=globalGrid.getSpaceSteps();
+
+           isDistributed=false;
+           if(CommunicatorType::IsInitialized())
+           {
+               rank=CommunicatorType::GetRank();
+               this->nproc=CommunicatorType::GetSize();
+               //use only if have more than one process
+               if(this->nproc>1)
+               {
+                   isDistributed=true;
+               }
+           }
+           
+           if(!isDistributed)
+           {
+               //Without distribution
+
+               std::cout <<"BEZ Distribuce"<<std::endl;
+               rank=0;
+               localorigin=globalGrid.getOrigin();
+               localsize=globalGrid.getDimensions();
+               localgridsize=globalGrid.getDimensions();
+               globalsize=globalGrid.getDimensions();
+               globalbegin=CoordinatesType(0);
+               
+               localbegin=CoordinatesType(0);
+               return;
+           }
+           else
+           { 
+               //nearnodes
+               if(rank!=0)
+                   left=rank-1;
+               if(rank!=nproc-1)
+                   right=rank+1;
+
+               globalsize=globalGrid.getDimensions();                 
+
+               //compute local mesh size               
+               numberoflarger=globalGrid.getDimensions().x()%nproc;
+
+               localsize.x()=(globalGrid.getDimensions().x()/nproc);               
+               if(numberoflarger>rank)
+                    localsize.x()+=1;                      
+                                  
+               if(numberoflarger>rank)
+               {
+                   globalbegin.x()=rank*localsize.x();
+                   localorigin.x()=globalGrid.getOrigin().x()
+                                +(globalbegin.x()-overlap.x())*globalGrid.getSpaceSteps().x();
+               }
+               else
+               {
+                   globalbegin.x()=numberoflarger*(localsize.x()+1)+(rank-numberoflarger)*localsize.x();
+                   localorigin.x()=(globalGrid.getOrigin().x()-overlap.x())
+                                +globalbegin.x()*globalGrid.getSpaceSteps().x();
+               }
+              
+              localbegin=overlap;
+               
+               //vlevo neni prekryv
+               if(left==-1)
+               {
+                   localorigin.x()+=overlap.x()*globalGrid.getSpaceSteps().x();
+                   localbegin.x()=0;
+               }
+               
+               localgridsize=localsize;
+               //add overlaps
+               if(left==-1||right==-1)
+                   localgridsize.x()+=overlap.x();
+               else
+                   localgridsize.x()+=2*overlap.x();
+                         
+           }  
+       } 
+       
+       void SetupGrid( GridType& grid)
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by SetupGrid");
+           grid.setOrigin(localorigin);
+           grid.setDimensions(localgridsize);
+           //compute local proporions by sideefect
+           grid.setSpaceSteps(spaceSteps);
+           grid.SetDistMesh(this);
+       };
+       
+       String printProcessCoords()
+       {
+           return convertToString(rank);
+       };
+
+       String printProcessDistr()
+       {
+           return convertToString(nproc);
+       };       
+
+       bool IsDistributed(void)
+       {
+           return this->isDistributed;
+       };
+       
+       int getLeft()
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by getLeft");
+           return this->left;
+       };
+       
+       int getRight()
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by getRight");
+           return this->right;
+       };
+       
+       CoordinatesType getOverlap()
+       {
+           return this->overlap;
+       };
+
+       //number of elemnts of local sub domain WITHOUT overlap
+       CoordinatesType getLocalSize()
+       {
+           return this->localsize;
+       }
+
+       //number of elements of global grid
+       CoordinatesType getGlobalSize()
+       {
+           return this->globalsize;
+       }
+
+       //coordinates of begin of local subdomain without overlaps in global grid
+       CoordinatesType getGlobalBegin()
+       {
+           return this->globalbegin;
+       }
+
+       //number of elemnts of local sub domain WITH overlap
+       CoordinatesType getLocalGridSize()
+       {
+           return this->localgridsize;
+       }
+       
+       //coordinates of begin of local subdomain without overlaps in local grid       
+       CoordinatesType getLocalBegin()
+       {
+           return this->localbegin;
+       }
+};
+
+
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGrid_2D.h b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_2D.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c0dcf845c899fa744f40678883f6242184548a8
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_2D.h
@@ -0,0 +1,282 @@
+/***************************************************************************
+                          DistributedGrid_2D.h  -  description
+                             -------------------
+    begin                : January 09, 2018
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes {
+
+enum Directions2D { Left = 0 , Right = 1 , Up = 2, Down=3, UpLeft =4, UpRight=5, DownLeft=6, DownRight=7 }; 
+
+template<typename RealType, typename Device, typename Index >     
+class DistributedMesh<Grid< 2, RealType, Device, Index >>
+{
+    public:
+
+    typedef Index IndexType;
+    typedef Grid< 2, RealType, Device, IndexType > GridType;
+    typedef typename GridType::PointType PointType;
+    typedef Containers::StaticVector< 2, IndexType > CoordinatesType;
+    
+    static constexpr int getMeshDimension() { return 2; };
+    
+    private : 
+        
+        PointType spaceSteps;
+        PointType localorigin;
+        CoordinatesType localsize;//velikost gridu zpracovavane danym uzlem bez prekryvu
+        CoordinatesType localbegin;//souradnice zacatku zpracovavane vypoctove oblasi
+        CoordinatesType localgridsize;//velikost lokálního gridu včetně překryvů
+        CoordinatesType overlap;
+        CoordinatesType globalsize;//velikost celé sítě
+        CoordinatesType globalbegin;
+        
+        
+        IndexType Dimensions;        
+        bool isDistributed;
+        
+        int rank;
+        int nproc;
+        
+        int procsdistr[2];
+        int myproccoord[2];
+        int numberoflarger[2];
+        
+        int neighbors[8];
+
+        bool isSet;
+     
+   public:
+       DistributedMesh()
+       {
+            isSet=false;
+       };
+
+       //compute everithing
+       template<typename CommunicatorType>
+       void setGlobalGrid(GridType &globalGrid, CoordinatesType overlap, int *distribution=NULL)
+       {
+           isSet=true;
+
+           this->overlap=overlap;
+           
+           for (int i=0;i<8;i++)
+                neighbors[i]=-1;
+           
+           Dimensions= GridType::getMeshDimension();
+           spaceSteps=globalGrid.getSpaceSteps();
+           //Detect MPI and number of process
+           isDistributed=false;
+           
+           
+           
+           if(CommunicatorType::IsInitialized())
+           {
+               rank=CommunicatorType::GetRank();
+               this->nproc=CommunicatorType::GetSize();
+               //use MPI only if have more than one process
+               if(this->nproc>1)
+               {
+                   isDistributed=true;
+               }
+           }
+           
+           if(!isDistributed)
+           {
+               //Without MPI
+               myproccoord[0]=0;
+               myproccoord[1]=0;
+               procsdistr[0]=1;
+               procsdistr[1]=1;
+               localorigin=globalGrid.getOrigin();
+               localgridsize=globalGrid.getDimensions();
+               localsize=globalGrid.getDimensions();
+               globalsize=globalGrid.getDimensions();
+               globalbegin=CoordinatesType(0);
+               localbegin.x()=0;
+               localbegin.y()=0;
+               
+               return;
+           }
+           else
+           {
+               //With MPI
+               //compute node distribution
+               if(distribution!=NULL)
+               {
+                  procsdistr[0]=distribution[0];
+                  procsdistr[1]=distribution[1];
+               }
+               else
+               {
+                  procsdistr[0]=0;
+                  procsdistr[1]=0;
+               }
+               CommunicatorType::DimsCreate(nproc, 2, procsdistr);
+
+               myproccoord[0]=rank%procsdistr[0];
+               myproccoord[1]=rank/procsdistr[0];        
+
+               //compute local mesh size
+               globalsize=globalGrid.getDimensions();              
+               numberoflarger[0]=globalGrid.getDimensions().x()%procsdistr[0];
+               numberoflarger[1]=globalGrid.getDimensions().y()%procsdistr[1];
+
+               localsize.x()=(globalGrid.getDimensions().x()/procsdistr[0]);
+               localsize.y()=(globalGrid.getDimensions().y()/procsdistr[1]);
+
+               if(numberoflarger[0]>myproccoord[0])
+                    localsize.x()+=1;               
+               if(numberoflarger[1]>myproccoord[1])
+                   localsize.y()+=1;
+
+               if(numberoflarger[0]>myproccoord[0])
+                   globalbegin.x()=myproccoord[0]*localsize.x();
+               else
+                   globalbegin.x()=numberoflarger[0]*(localsize.x()+1)+(myproccoord[0]-numberoflarger[0])*localsize.x();
+
+               if(numberoflarger[1]>myproccoord[1])
+                   globalbegin.y()=myproccoord[1]*localsize.y();
+
+               else
+                   globalbegin.y()=numberoflarger[1]*(localsize.y()+1)+(myproccoord[1]-numberoflarger[1])*localsize.y();
+
+               localorigin=globalGrid.getOrigin()+TNL::Containers::tnlDotProduct(globalGrid.getSpaceSteps(),globalbegin-overlap);
+
+               //nearnodes
+               if(myproccoord[0]>0)
+                   neighbors[Left]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]);
+               if(myproccoord[0]<procsdistr[0]-1)
+                   neighbors[Right]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]);
+               if(myproccoord[1]>0)
+                   neighbors[Up]=getRankOfProcCoord(myproccoord[0],myproccoord[1]-1);
+               if(myproccoord[1]<procsdistr[1]-1)
+                   neighbors[Down]=getRankOfProcCoord(myproccoord[0],myproccoord[1]+1);
+               if(myproccoord[0]>0 && myproccoord[1]>0)
+                   neighbors[UpLeft]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]-1);
+               if(myproccoord[0]>0 && myproccoord[1]<procsdistr[1]-1)
+                   neighbors[DownLeft]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]+1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]>0)
+                   neighbors[UpRight]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]-1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]<procsdistr[1]-1)
+                   neighbors[DownRight]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]+1);
+               
+               localbegin=overlap;
+
+               if(neighbors[Left]==-1)
+               {
+                    localorigin.x()+=overlap.x()*globalGrid.getSpaceSteps().x();
+                    localbegin.x()=0;
+               }
+
+               if(neighbors[Up]==-1)
+               {
+                   localorigin.y()+=overlap.y()*globalGrid.getSpaceSteps().y();
+                   localbegin.y()=0;
+               }
+
+               localgridsize=localsize;
+               //Add Overlaps
+               if(neighbors[Left]!=-1)
+                   localgridsize.x()+=overlap.x();
+               if(neighbors[Right]!=-1)
+                   localgridsize.x()+=overlap.x();
+
+               if(neighbors[Up]!=-1)
+                   localgridsize.y()+=overlap.y();
+               if(neighbors[Down]!=-1)
+                   localgridsize.y()+=overlap.y();
+           }
+                     
+           
+                      
+       }
+       
+       void SetupGrid( GridType& grid)
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by SetupGrid");
+           grid.setOrigin(localorigin);
+           grid.setDimensions(localgridsize);
+           //compute local proporions by sideefect
+           grid.setSpaceSteps(spaceSteps);
+           grid.SetDistMesh(this);
+       };
+       
+       String printProcessCoords()
+       {
+           return convertToString(myproccoord[0])+String("-")+convertToString(myproccoord[1]);
+       };
+
+       String printProcessDistr()
+       {
+           return convertToString(procsdistr[0])+String("-")+convertToString(procsdistr[1]);
+       };  
+       
+       bool IsDistributed(void)
+       {
+           return this->isDistributed;
+       };
+       
+       CoordinatesType getOverlap()
+       {
+           return this->overlap;
+       };
+       
+       int * getNeighbors()
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by getNeighbors");
+           return this->neighbors;
+       }
+       
+       CoordinatesType getLocalSize()
+       {
+           return this->localsize;
+       }
+
+       //number of elements of global grid
+       CoordinatesType getGlobalSize()
+       {
+           return this->globalsize;
+       }
+
+       //coordinates of begin of local subdomain without overlaps in global grid
+       CoordinatesType getGlobalBegin()
+       {
+           return this->globalbegin;
+       }
+
+       CoordinatesType getLocalGridSize()
+       {
+           return this->localgridsize;
+       }
+       
+              
+       CoordinatesType getLocalBegin()
+       {
+           return this->localbegin;
+       }
+       
+       private:
+           
+        int getRankOfProcCoord(int x, int y)
+        {
+            return y*procsdistr[0]+x;
+        }
+
+
+};
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
+
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedGrid_3D.h b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_3D.h
new file mode 100644
index 0000000000000000000000000000000000000000..f12950178a7efcbc3017c0a288024096573e1aa9
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedGrid_3D.h
@@ -0,0 +1,349 @@
+/***************************************************************************
+                          DistributedGrid_3D.h  -  description
+                             -------------------
+    begin                : January 15, 2018
+    copyright            : (C) 2018 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <TNL/Meshes/Grid.h>
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes {
+
+enum Directions3D { West = 0 , East = 1 , Nord = 2, South=3, Top =4, Bottom=5, 
+                  NordWest=6, NordEast=7, SouthWest=8, SouthEast=9,
+                  BottomWest=10,BottomEast=11,BottomNord=12,BottomSouth=13,
+                  TopWest=14,TopEast=15,TopNord=16,TopSouth=17,
+                  BottomNordWest=18,BottomNordEast=19,BottomSouthWest=20,BottomSouthEast=21,
+                  TopNordWest=22,TopNordEast=23,TopSouthWest=24,TopSouthEast=25
+                  };
+
+
+template<typename RealType, typename Device, typename Index >     
+class DistributedMesh<Grid< 3, RealType, Device, Index >>
+{
+
+    public:
+
+    typedef Index IndexType;
+    typedef Grid< 3, RealType, Device, IndexType > GridType;
+    typedef typename GridType::PointType PointType;
+    typedef Containers::StaticVector< 3, IndexType > CoordinatesType;
+    
+    static constexpr int getMeshDimension() { return 3; };    
+
+    private : 
+        
+        PointType spaceSteps;
+        PointType localorigin;
+        CoordinatesType localsize;
+        CoordinatesType localgridsize;
+        CoordinatesType localbegin;
+        CoordinatesType overlap;
+        CoordinatesType globalsize;
+        CoordinatesType globalbegin;
+        
+        IndexType Dimensions;        
+        bool isDistributed;
+        
+        int rank;
+        int nproc;
+        
+        int procsdistr[3];
+        int myproccoord[3];
+        int numberoflarger[3];
+        
+        int neighbors[26];
+
+        bool isSet;
+     
+   public:
+       DistributedMesh()
+       {
+            isSet=false;
+       };
+
+       //compute everithing 
+       template<typename CommunicatorType> 
+       void setGlobalGrid(GridType &globalGrid, CoordinatesType overlap, int *distribution=NULL)
+       {
+
+           isSet=true;           
+
+           this->overlap=overlap;
+           
+           for (int i=0;i<26;i++)
+                neighbors[i]=-1;
+           
+           Dimensions= GridType::getMeshDimension();
+           spaceSteps=globalGrid.getSpaceSteps();
+
+           isDistributed=false;
+           
+           
+           
+           if(CommunicatorType::IsInitialized())
+           {
+               rank=CommunicatorType::GetRank();
+               this->nproc=CommunicatorType::GetSize();
+               //use MPI only if have more than one process
+               if(this->nproc>1)
+               {
+                   isDistributed=true;
+               }
+           }
+           
+           if(!isDistributed)
+           {
+               //Without MPI
+               myproccoord[0]=0;
+               myproccoord[1]=0;
+               myproccoord[2]=0;
+               
+               procsdistr[0]=1;
+               procsdistr[1]=1;
+               procsdistr[2]=1;               
+               
+               localorigin=globalGrid.getOrigin();
+               localsize=globalGrid.getDimensions();
+               globalsize=globalGrid.getDimensions();
+               localgridsize=localsize;
+               globalbegin=CoordinatesType(0);
+               return;
+           }
+           else
+           {
+               //With MPI
+               //compute node distribution
+               if(distribution!=NULL)
+               {
+                  procsdistr[0]=distribution[0];
+                  procsdistr[1]=distribution[1];
+                  procsdistr[2]=distribution[2];
+               }
+               else
+               {
+                  procsdistr[0]=0;
+                  procsdistr[1]=0;
+                  procsdistr[2]=0;
+               }
+               CommunicatorType::DimsCreate(nproc, 3, procsdistr);
+               myproccoord[2]=rank/(procsdistr[0]*procsdistr[1]);
+               myproccoord[1]=(rank%(procsdistr[0]*procsdistr[1]))/procsdistr[0];
+               myproccoord[0]=(rank%(procsdistr[0]*procsdistr[1]))%procsdistr[0];
+
+               //compute local mesh size 
+               globalsize=globalGrid.getDimensions();                
+               numberoflarger[0]=globalGrid.getDimensions().x()%procsdistr[0];
+               numberoflarger[1]=globalGrid.getDimensions().y()%procsdistr[1];
+               numberoflarger[2]=globalGrid.getDimensions().z()%procsdistr[2];
+                 
+               localsize.x()=(globalGrid.getDimensions().x()/procsdistr[0]);
+               localsize.y()=(globalGrid.getDimensions().y()/procsdistr[1]);
+               localsize.z()=(globalGrid.getDimensions().z()/procsdistr[2]);
+               
+               if(numberoflarger[0]>myproccoord[0])
+                    localsize.x()+=1;               
+               if(numberoflarger[1]>myproccoord[1])
+                   localsize.y()+=1;
+               if(numberoflarger[2]>myproccoord[2])
+                   localsize.z()+=1;
+                                  
+               if(numberoflarger[0]>myproccoord[0])
+                   globalbegin.x()=myproccoord[0]*localsize.x();
+               else
+                   globalbegin.x()=numberoflarger[0]*(localsize.x()+1)+(myproccoord[0]-numberoflarger[0])*localsize.x();
+                 
+               if(numberoflarger[1]>myproccoord[1])
+                   globalbegin.y()=myproccoord[1]*localsize.y();
+               else
+                   globalbegin.y()=numberoflarger[1]*(localsize.y()+1)+(myproccoord[1]-numberoflarger[1])*localsize.y();
+ 
+               if(numberoflarger[2]>myproccoord[2])
+                   globalbegin.z()=myproccoord[2]*localsize.z();
+               else
+                   globalbegin.z()=numberoflarger[2]*(localsize.z()+1)+(myproccoord[2]-numberoflarger[2])*localsize.z();
+
+               localorigin=globalGrid.getOrigin()+TNL::Containers::tnlDotProduct(globalGrid.getSpaceSteps(),globalbegin-overlap);
+               
+               //nearnodes
+               //X Y Z
+               if(myproccoord[0]>0)
+                   neighbors[West]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1],myproccoord[2]);               
+               if(myproccoord[0]<procsdistr[0]-1)
+                   neighbors[East]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1],myproccoord[2]);
+               if(myproccoord[1]>0)
+                   neighbors[Nord]=getRankOfProcCoord(myproccoord[0],myproccoord[1]-1,myproccoord[2]);
+               if(myproccoord[1]<procsdistr[1]-1)
+                   neighbors[South]=getRankOfProcCoord(myproccoord[0],myproccoord[1]+1,myproccoord[2]);
+               if(myproccoord[2]>0)
+                   neighbors[Bottom]=getRankOfProcCoord(myproccoord[0],myproccoord[1],myproccoord[2]-1);
+               if(myproccoord[2]<procsdistr[2]-1)
+                   neighbors[Top]=getRankOfProcCoord(myproccoord[0],myproccoord[1],myproccoord[2]+1);
+
+               //XY
+               if(myproccoord[0]>0 && myproccoord[1]>0)
+                   neighbors[NordWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]-1,myproccoord[2]);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]>0)
+                   neighbors[NordEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]-1,myproccoord[2]);
+               if(myproccoord[0]>0 && myproccoord[1]<procsdistr[1]-1)
+                   neighbors[SouthWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]+1,myproccoord[2]);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]<procsdistr[1]-1)
+                   neighbors[SouthEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]+1,myproccoord[2]);             
+               //XZ
+               if(myproccoord[0]>0 && myproccoord[2]>0)
+                   neighbors[BottomWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1],myproccoord[2]-1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[2]>0)
+                   neighbors[BottomEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1],myproccoord[2]-1); 
+               if(myproccoord[0]>0 && myproccoord[2]<procsdistr[2]-1)
+                   neighbors[TopWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1],myproccoord[2]+1);
+              if(myproccoord[0]<procsdistr[0]-1 && myproccoord[2]<procsdistr[2]-1)
+                   neighbors[TopEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1],myproccoord[2]+1);
+               //YZ
+               if(myproccoord[1]>0 && myproccoord[2]>0)
+                   neighbors[BottomNord]=getRankOfProcCoord(myproccoord[0],myproccoord[1]-1,myproccoord[2]-1);
+               if(myproccoord[1]<procsdistr[1]-1 && myproccoord[2]>0)
+                   neighbors[BottomSouth]=getRankOfProcCoord(myproccoord[0],myproccoord[1]+1,myproccoord[2]-1);
+               if(myproccoord[1]>0 && myproccoord[2]<procsdistr[2]-1)
+                   neighbors[TopNord]=getRankOfProcCoord(myproccoord[0],myproccoord[1]-1,myproccoord[2]+1);               
+               if(myproccoord[1]<procsdistr[1]-1 && myproccoord[2]<procsdistr[2]-1)
+                   neighbors[TopSouth]=getRankOfProcCoord(myproccoord[0],myproccoord[1]+1,myproccoord[2]+1);
+               //XYZ
+               if(myproccoord[0]>0 && myproccoord[1]>0 && myproccoord[2]>0 )
+                   neighbors[BottomNordWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]-1,myproccoord[2]-1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]>0 && myproccoord[2]>0 )
+                   neighbors[BottomNordEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]-1,myproccoord[2]-1);
+               if(myproccoord[0]>0 && myproccoord[1]<procsdistr[1]-1 && myproccoord[2]>0 )
+                   neighbors[BottomSouthWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]+1,myproccoord[2]-1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]<procsdistr[1]-1 && myproccoord[2]>0 )
+                   neighbors[BottomSouthEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]+1,myproccoord[2]-1);
+               if(myproccoord[0]>0 && myproccoord[1]>0 && myproccoord[2]<procsdistr[2]-1 )
+                   neighbors[TopNordWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]-1,myproccoord[2]+1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]>0 && myproccoord[2]<procsdistr[2]-1 )
+                   neighbors[TopNordEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]-1,myproccoord[2]+1);
+               if(myproccoord[0]>0 && myproccoord[1]<procsdistr[1]-1 && myproccoord[2]<procsdistr[2]-1 )
+                   neighbors[TopSouthWest]=getRankOfProcCoord(myproccoord[0]-1,myproccoord[1]+1,myproccoord[2]+1);
+               if(myproccoord[0]<procsdistr[0]-1 && myproccoord[1]<procsdistr[1]-1 && myproccoord[2]<procsdistr[2]-1 )
+                   neighbors[TopSouthEast]=getRankOfProcCoord(myproccoord[0]+1,myproccoord[1]+1,myproccoord[2]+1);   
+
+               
+               localbegin=overlap;
+               
+               if(neighbors[West]==-1)
+               {
+                   localorigin.x()+=overlap.x()*globalGrid.getSpaceSteps().x();
+                   localbegin.x()=0;
+               }
+               if(neighbors[Nord]==-1)
+               {
+                   localorigin.y()+=overlap.y()*globalGrid.getSpaceSteps().y();
+                   localbegin.y()=0;
+               }
+               if(neighbors[Bottom]==-1)
+               {
+                   localorigin.z()+=overlap.z()*globalGrid.getSpaceSteps().z();
+                   localbegin.z()=0;
+               }
+               
+               localgridsize=localsize;
+               
+               if(neighbors[West]!=-1)
+                   localgridsize.x()+=overlap.x();
+               if(neighbors[East]!=-1)
+                   localgridsize.x()+=overlap.x();
+
+               if(neighbors[Nord]!=-1)
+                   localgridsize.y()+=overlap.y();
+               if(neighbors[South]!=-1)
+                   localgridsize.y()+=overlap.y();
+               
+               if(neighbors[Bottom]!=-1)
+                   localgridsize.z()+=overlap.z();
+               if(neighbors[Top]!=-1)
+                   localgridsize.z()+=overlap.z();
+               
+           }                     
+       }
+       
+       void SetupGrid( GridType& grid)
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by SetupGrid");
+           grid.setOrigin(localorigin);
+           grid.setDimensions(localgridsize);
+           //compute local proporions by sideefect
+           grid.setSpaceSteps(spaceSteps);
+           grid.SetDistMesh(this);
+       };
+       
+       String printProcessCoords()
+       {
+           return convertToString(myproccoord[0])+String("-")+convertToString(myproccoord[1])+String("-")+convertToString(myproccoord[2]);
+       };
+
+       String printProcessDistr()
+       {
+           return convertToString(procsdistr[0])+String("-")+convertToString(procsdistr[1])+String("-")+convertToString(procsdistr[2]);
+       };  
+
+       bool IsDistributed(void)
+       {
+           return this->isDistributed;
+       };
+       
+       CoordinatesType getOverlap()
+       {
+           return this->overlap;
+       };
+       
+       int * getNeighbors()
+       {
+           TNL_ASSERT_TRUE(isSet,"DistributedGrid is not set, but used by getNeighbors");
+           return this->neighbors;
+       }
+       
+       CoordinatesType getLocalSize()
+       {
+           return this->localsize;
+       }
+       
+       CoordinatesType getLocalGridSize()
+       {
+           return this->localgridsize;
+       }
+       
+       CoordinatesType getLocalBegin()
+       {
+           return this->localbegin;
+       }
+
+       //number of elements of global grid
+       CoordinatesType getGlobalSize()
+       {
+           return this->globalsize;
+       }
+
+       //coordinates of begin of local subdomain without overlaps in global grid
+       CoordinatesType getGlobalBegin()
+       {
+           return this->globalbegin;
+       }
+       
+       private:
+           
+        int getRankOfProcCoord(int x, int y, int z)
+        {
+            return z*procsdistr[0]*procsdistr[1]+y*procsdistr[0]+x;
+        }
+
+
+};
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedMesh.h b/src/TNL/Meshes/DistributedMeshes/DistributedMesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..e03d0975652c41fb4e40a038bc25acf36c67a06c
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedMesh.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+                          DistributedMesh.h  -  description
+                             -------------------
+    begin                : March 17, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes {
+
+template< typename MeshType >    
+class DistributedMesh
+{
+public:
+    bool IsDistributed(void)
+    {
+        return false;
+    };
+};
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/DistributedMeshes/DistributedGrid_1D.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedGrid_2D.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedGrid_3D.h>
diff --git a/src/TNL/Meshes/DistributedMeshes/DistributedMeshSynchronizer.h b/src/TNL/Meshes/DistributedMeshes/DistributedMeshSynchronizer.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef6929e1eedbdb6415667cb718b442dc0cacded2
--- /dev/null
+++ b/src/TNL/Meshes/DistributedMeshes/DistributedMeshSynchronizer.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+                          DistributedMeshSynchronizer.h  -  description
+                             -------------------
+    begin                : January 8, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+namespace TNL {
+namespace Meshes { 
+namespace DistributedMeshes {
+
+template <typename MeshFunctionType>  
+class DistributedMeshSynchronizer
+{
+    public:
+        typedef typename MeshFunctionType::DistributedMeshType DistributedMeshType;
+        void SetDistributedGrid(DistributedMeshType *distrgrid)
+        {
+            TNL_ASSERT_TRUE(false,"Distribution of this type of mesh is NOT implemented");
+        }; 
+
+};
+
+
+} // namespace DistributedMeshes
+} // namespace Meshes
+} // namespace TNL
+
+#include <TNL/Meshes/DistributedMeshes/DistributedGridSynchronizer.h>
diff --git a/src/TNL/Meshes/Grid.h b/src/TNL/Meshes/Grid.h
index 07053991262385c8fd19e72377693c6748fc84de..c196e8b88708bd228707c3b6d059a35a4039a3f8 100644
--- a/src/TNL/Meshes/Grid.h
+++ b/src/TNL/Meshes/Grid.h
@@ -16,7 +16,7 @@
 #include <TNL/Containers/Vector.h>
 
 namespace TNL {
-namespace Meshes {
+namespace Meshes {    
 
 template< int Dimension,
           typename Real = double,
diff --git a/src/TNL/Meshes/GridDetails/Grid1D.h b/src/TNL/Meshes/GridDetails/Grid1D.h
index c8dbd74897d0030efcacd6b6ed2087f5b328bfe1..e2c456c83bd966beb1aef2f34ba81edb34a25828 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D.h
@@ -17,6 +17,7 @@
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter.h>
 #include <TNL/Meshes/GridEntity.h>
 #include <TNL/Meshes/GridEntityConfig.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
 
 namespace TNL {
 namespace Meshes {
@@ -37,6 +38,8 @@ class Grid< 1, Real, Device, Index > : public Object
    typedef Grid< 1, Real, Devices::Cuda, Index > CudaType;
    typedef Grid< 1, Real, Device, Index > ThisType;
 
+   typedef DistributedMeshes::DistributedMesh <ThisType> DistributedMeshType;
+
    // TODO: deprecated and to be removed (GlobalIndexType shall be used instead)
    typedef Index IndexType;
  
@@ -66,10 +69,13 @@ class Grid< 1, Real, Device, Index > : public Object
 
    __cuda_callable__
    const CoordinatesType& getDimensions() const;
+ 
+   void setOrigin( const PointType& origin);
 
    void setDomain( const PointType& origin,
                    const PointType& proportions );
 
+
    __cuda_callable__
    inline const PointType& getOrigin() const;
 
@@ -94,8 +100,12 @@ class Grid< 1, Real, Device, Index > : public Object
    inline Index getEntityIndex( const Entity& entity ) const;
  
    __cuda_callable__
+   
+   inline void setSpaceSteps(const PointType& steps);
+
    inline const PointType& getSpaceSteps() const;
 
+
    template< int xPow >
    __cuda_callable__
    const RealType& getSpaceStepsProducts() const;
@@ -115,6 +125,10 @@ class Grid< 1, Real, Device, Index > : public Object
    typename GridFunction::RealType getDifferenceLpNorm( const GridFunction& f1,
                                                         const GridFunction& f2,
                                                         const typename GridFunction::RealType& p ) const;
+   
+   void SetDistMesh(DistributedMeshType * distMesh);
+   
+   DistributedMeshType * GetDistMesh(void) const;
 
    /****
     *  Method for saving the object to a file as a binary data
@@ -134,6 +148,10 @@ class Grid< 1, Real, Device, Index > : public Object
 
    protected:
 
+   void computeProportions();
+       
+   void computeSpaceStepPowers();
+
    void computeSpaceSteps();
 
    CoordinatesType dimensions;
@@ -145,6 +163,8 @@ class Grid< 1, Real, Device, Index > : public Object
    PointType spaceSteps;
  
    RealType spaceStepsProducts[ 5 ];
+   
+   DistributedMeshType *distGrid;
 };
 
 } // namespace Meshes
diff --git a/src/TNL/Meshes/GridDetails/Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
index e2e9818048c33e39a747cef78cf11b20e2cefae2..47bc02fff4f64e5db49bfb0eef539808cb982e7f 100644
--- a/src/TNL/Meshes/GridDetails/Grid1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid1D_impl.h
@@ -29,7 +29,8 @@ template< typename Real,
           typename Index >
 Grid< 1, Real, Device, Index >::Grid()
 : numberOfCells( 0 ),
-  numberOfVertices( 0 )
+  numberOfVertices( 0 ),
+        distGrid(nullptr)
 {
 }
 
@@ -77,13 +78,39 @@ void Grid< 1, Real, Device, Index >::computeSpaceSteps()
    if( this->getDimensions().x() != 0 )
    {
       this->spaceSteps.x() = this->proportions.x() / ( Real )  this->getDimensions().x();
+      this->computeSpaceStepPowers();
+   }
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 1, Real, Device, Index > ::computeSpaceStepPowers()
+{
       const RealType& hx = this->spaceSteps.x();
       this->spaceStepsProducts[ 0 ] = 1.0 / ( hx * hx );
       this->spaceStepsProducts[ 1 ] = 1.0 / hx;
       this->spaceStepsProducts[ 2 ] = 1.0;
       this->spaceStepsProducts[ 3 ] = hx;
       this->spaceStepsProducts[ 4 ] = hx * hx;
-   }
+   
+}
+
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 1, Real, Device, Index > ::computeProportions()
+{
+    this->proportions.x()=this->dimensions.x()*this->spaceSteps.x();
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 1, Real, Device, Index > :: setOrigin( const PointType& origin)
+{
+   this->origin = origin;
 }
 
 template< typename Real,
@@ -223,6 +250,18 @@ getSpaceSteps() const
    return this->spaceSteps;
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+inline void 
+Grid< 1, Real, Device, Index >::
+setSpaceSteps(const typename Grid< 1, Real, Device, Index >::PointType& steps)
+{
+    this->spaceSteps=steps;
+    computeSpaceStepPowers();
+    computeProportions();
+}
+
 template< typename Real,
           typename Device,
           typename Index >
@@ -302,6 +341,23 @@ Grid< 1, Real, Device, Index >::getDifferenceLpNorm( const GridFunction& f1,
    return ::pow( lpNorm, 1.0 / p );
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 1, Real, Device, Index >:: SetDistMesh(DistributedMeshType * distMesh)
+{
+    this->distGrid=distMesh;
+}
+   
+template< typename Real,
+          typename Device,
+          typename Index >
+DistributedMeshes::DistributedMesh <Grid< 1, Real, Device, Index >> * 
+Grid< 1, Real, Device, Index >:: GetDistMesh(void) const
+{
+    return this->distGrid;
+}
+    
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/GridDetails/Grid2D.h b/src/TNL/Meshes/GridDetails/Grid2D.h
index 0f0c8af4dd6c7f57a802c1a25c5d97b85a7e5368..cc860f4f393bbe81001d511013aedf135d194e5f 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D.h
@@ -15,6 +15,7 @@
 #include <TNL/Meshes/GridDetails/GridEntityTopology.h>
 #include <TNL/Meshes/GridDetails/GridEntityGetter.h>
 #include <TNL/Meshes/GridDetails/NeighborGridEntityGetter.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
 
 namespace TNL {
 namespace Meshes {
@@ -34,6 +35,8 @@ class Grid< 2, Real, Device, Index > : public Object
    typedef Grid< 2, Real, Devices::Host, Index > HostType;
    typedef Grid< 2, Real, Devices::Cuda, Index > CudaType;
    typedef Grid< 2, Real, Device, Index > ThisType;
+
+   typedef DistributedMeshes::DistributedMesh <ThisType> DistributedMeshType;
  
    // TODO: deprecated and to be removed (GlobalIndexType shall be used instead)
    typedef Index IndexType;
@@ -75,6 +78,9 @@ class Grid< 2, Real, Device, Index > : public Object
 
    void setDomain( const PointType& origin,
                    const PointType& proportions );
+
+   void setOrigin( const PointType& origin);
+
    __cuda_callable__
    inline const PointType& getOrigin() const;
 
@@ -99,8 +105,11 @@ class Grid< 2, Real, Device, Index > : public Object
    inline Index getEntityIndex( const Entity& entity ) const;
 
    __cuda_callable__
+
    inline const PointType& getSpaceSteps() const;
 
+   inline void setSpaceSteps(const PointType& steps);
+
    template< int xPow, int yPow >
    __cuda_callable__
    const RealType& getSpaceStepsProducts() const;
@@ -127,6 +136,10 @@ class Grid< 2, Real, Device, Index > : public Object
    typename GridFunction::RealType getDifferenceLpNorm( const GridFunction& f1,
                                                         const GridFunction& f2,
                                                         const typename GridFunction::RealType& p ) const;
+   
+   void SetDistMesh(DistributedMeshType * distGrid);
+   
+   DistributedMeshType * GetDistMesh(void) const;
 
    //! Method for saving the object to a file as a binary data
    bool save( File& file ) const;
@@ -141,6 +154,11 @@ class Grid< 2, Real, Device, Index > : public Object
    void writeProlog( Logger& logger ) const;
 
    protected:
+   
+   void computeProportions();
+       
+   __cuda_callable__
+   void computeSpaceStepPowers();
 
    __cuda_callable__
    void computeSpaceSteps();
@@ -154,6 +172,8 @@ class Grid< 2, Real, Device, Index > : public Object
    PointType spaceSteps;
  
    RealType spaceStepsProducts[ 5 ][ 5 ];
+   
+   DistributedMeshType *distGrid;
  
    template< typename, typename, int >
    friend class GridEntityGetter;
diff --git a/src/TNL/Meshes/GridDetails/Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
index 80c18a3691482b6b41055e0b77d40f19cb78f13e..4ef0717f37158c5fa1e6703849b431ea9bc9ad9e 100644
--- a/src/TNL/Meshes/GridDetails/Grid2D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid2D_impl.h
@@ -32,7 +32,8 @@ Grid< 2, Real, Device, Index > :: Grid()
   numberOfNxFaces( 0 ),
   numberOfNyFaces( 0 ),
   numberOfFaces( 0 ),
-  numberOfVertices( 0 )
+  numberOfVertices( 0 ),
+  distGrid(nullptr)
 {
 }
 
@@ -82,6 +83,16 @@ void Grid< 2, Real, Device, Index > :: computeSpaceSteps()
    {
       this->spaceSteps.x() = this->proportions.x() / ( Real ) this->getDimensions().x();
       this->spaceSteps.y() = this->proportions.y() / ( Real ) this->getDimensions().y();
+      this->computeSpaceStepPowers();
+   }
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+__cuda_callable__
+void Grid< 2, Real, Device, Index > ::computeSpaceStepPowers()
+{
       const RealType& hx = this->spaceSteps.x();
       const RealType& hy = this->spaceSteps.y();
  
@@ -129,7 +140,15 @@ void Grid< 2, Real, Device, Index > :: computeSpaceSteps()
             this->spaceStepsProducts[ i ][ j ] = auxX * auxY;
          }
       }
-   }
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 2, Real, Device, Index > ::computeProportions()
+{
+    this->proportions.x()=this->dimensions.x()*this->spaceSteps.x();
+    this->proportions.y()=this->dimensions.y()*this->spaceSteps.y();
 }
 
 template< typename Real,
@@ -179,6 +198,14 @@ void Grid< 2, Real, Device, Index > :: setDomain( const PointType& origin,
    computeSpaceSteps();
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 2, Real, Device, Index > :: setOrigin( const PointType& origin)
+{
+   this->origin = origin;
+}
+
 template< typename Real,
           typename Device,
           typename Index >
@@ -277,6 +304,18 @@ getSpaceSteps() const
    return this->spaceSteps;
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+inline void 
+Grid< 2, Real, Device, Index >::
+setSpaceSteps(const typename Grid< 2, Real, Device, Index >::PointType& steps)
+{
+    this->spaceSteps=steps;
+    computeSpaceStepPowers();
+    computeProportions();
+}
+
 template< typename Real,
           typename Device,
           typename Index >
@@ -381,6 +420,23 @@ template< typename Real,
    return ::pow( lpNorm, 1.0 / p );
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 2, Real, Device, Index >:: SetDistMesh(DistributedMeshType* distMesh)
+{
+    this->distGrid=distMesh;
+}
+   
+template< typename Real,
+          typename Device,
+          typename Index >
+DistributedMeshes::DistributedMesh <Grid< 2, Real, Device, Index >> * 
+Grid< 2, Real, Device, Index >:: GetDistMesh(void) const
+{
+    return this->distGrid;
+}
+
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/GridDetails/Grid3D.h b/src/TNL/Meshes/GridDetails/Grid3D.h
index 0ff0bf045364d6746c5cb834f0f70f3d278349f2..7056e33f655197d14c4c5a61f7f79240335c5876 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D.h
@@ -34,6 +34,8 @@ class Grid< 3, Real, Device, Index > : public Object
    typedef Grid< 3, Real, Devices::Host, Index > HostType;
    typedef Grid< 3, Real, Devices::Cuda, Index > CudaType;
    typedef Grid< 3, Real, Device, Index > ThisType;
+
+   typedef DistributedMeshes::DistributedMesh <ThisType> DistributedMeshType;
  
    // TODO: deprecated and to be removed (GlobalIndexType shall be used instead)
    typedef Index IndexType;
@@ -68,6 +70,9 @@ class Grid< 3, Real, Device, Index > : public Object
 
    void setDomain( const PointType& origin,
                    const PointType& proportions );
+   
+   void setOrigin( const PointType& origin);
+   
    __cuda_callable__
    inline const PointType& getOrigin() const;
 
@@ -93,7 +98,13 @@ class Grid< 3, Real, Device, Index > : public Object
  
    __cuda_callable__
    inline const PointType& getSpaceSteps() const;
- 
+
+   inline void setSpaceSteps(const PointType& steps);
+   
+   void SetDistMesh(DistributedMeshType * distGrid);
+   
+   DistributedMeshType * GetDistMesh(void) const;
+   
    template< int xPow, int yPow, int zPow >
    __cuda_callable__
    const RealType& getSpaceStepsProducts() const;
@@ -135,6 +146,10 @@ class Grid< 3, Real, Device, Index > : public Object
 
    protected:
 
+   void computeProportions();
+       
+   void computeSpaceStepPowers();    
+       
    void computeSpaceSteps();
 
    CoordinatesType dimensions;
@@ -151,6 +166,8 @@ class Grid< 3, Real, Device, Index > : public Object
    PointType spaceSteps;
  
    RealType spaceStepsProducts[ 5 ][ 5 ][ 5 ];
+   
+   DistributedMeshType *distGrid;
 
    template< typename, typename, int >
    friend class GridEntityGetter;
diff --git a/src/TNL/Meshes/GridDetails/Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
index 9245a74c661329ae5f30511ff50267372507fd65..e2f4f273088780dfac733d050ed547468a88639d 100644
--- a/src/TNL/Meshes/GridDetails/Grid3D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Grid3D_impl.h
@@ -39,7 +39,8 @@ Grid< 3, Real, Device, Index > :: Grid()
   numberOfDzEdges( 0 ),
   numberOfDxAndDyEdges( 0 ),
   numberOfEdges( 0 ),
-  numberOfVertices( 0 )
+  numberOfVertices( 0 ),
+  distGrid(nullptr)
 {
 }
 
@@ -91,6 +92,17 @@ void Grid< 3, Real, Device, Index > :: computeSpaceSteps()
       this->spaceSteps.x() = this->proportions.x() / ( Real ) this->getDimensions().x();
       this->spaceSteps.y() = this->proportions.y() / ( Real ) this->getDimensions().y();
       this->spaceSteps.z() = this->proportions.z() / ( Real ) this->getDimensions().z();
+      
+      this->computeSpaceStepPowers();
+      
+   }
+};
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 3, Real, Device, Index > :: computeSpaceStepPowers()
+{      
       const RealType& hx = this->spaceSteps.x();
       const RealType& hy = this->spaceSteps.y();
       const RealType& hz = this->spaceSteps.z();
@@ -160,9 +172,38 @@ void Grid< 3, Real, Device, Index > :: computeSpaceSteps()
             }
          }
       }
-   }
 }
 
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 3, Real, Device, Index > :: computeProportions()
+{
+    this->proportions.x()=this->dimensions.x()*this->spaceSteps.x();
+    this->proportions.y()=this->dimensions.y()*this->spaceSteps.y();
+    this->proportions.z()=this->dimensions.z()*this->spaceSteps.z();
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 3, Real, Device, Index > :: setOrigin( const PointType& origin)
+{
+    this->origin=origin;
+}
+
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 3, Real, Device, Index > :: setSpaceSteps(const PointType& steps)
+{
+     this->spaceSteps=steps;    
+     computeSpaceStepPowers();
+     computeProportions(); 
+}
+
+
 template< typename Real,
           typename Device,
           typename Index >
@@ -453,6 +494,23 @@ template< typename Real,
    return ::pow( lpNorm, 1.0 / p );
 }
 
+template< typename Real,
+          typename Device,
+          typename Index >
+void Grid< 3, Real, Device, Index >:: SetDistMesh(DistributedMeshType * distMesh)
+{
+    this->distGrid=distMesh;
+}
+   
+template< typename Real,
+          typename Device,
+          typename Index >
+DistributedMeshes::DistributedMesh <Grid< 3, Real, Device, Index >> * 
+Grid< 3, Real, Device, Index >:: GetDistMesh(void) const
+{
+    return this->distGrid;
+}
+
 template< typename Real,
           typename Device,
           typename Index >
diff --git a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h
index 14143220eb451521afb6098e67ebc9889559a68a..b248bd163baa1efa14717bd6ffba465e27c2ff3f 100644
--- a/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/NeighborGridEntityGetter1D_impl.h
@@ -475,4 +475,4 @@ class NeighborGridEntityGetter<
 };
 
 } // namespace Meshes
-} // namespace TNL
\ No newline at end of file
+} // namespace TNL
diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h
index 6e8c1e3b2a6b03dca0bdfc0d4e58dbfe6d7280df..534fbf8e962b826ed5c63812d3bb17a46ca55412 100644
--- a/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Traverser_Grid1D_impl.h
@@ -11,6 +11,8 @@
 #pragma once
 
 #include <TNL/Meshes/GridDetails/GridTraverser.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+
 
 namespace TNL {
 namespace Meshes {
@@ -32,13 +34,39 @@ processBoundaryEntities( const GridPointer& gridPointer,
    /****
     * Boundary cells
     */
-   static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." );
-
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true >(
-      gridPointer,
-      CoordinatesType( 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1 ),
-      userDataPointer );
+   static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimensions." );
+   
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+        GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true >(
+           gridPointer,
+           CoordinatesType( 0 ),
+           gridPointer->getDimensions() - CoordinatesType( 1 ),
+           userDataPointer );
+   }
+   else
+   {
+       //Distributed
+       if(distributedgrid->getLeft()==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+              gridPointer,
+              CoordinatesType( 0 ),
+              CoordinatesType( 0 ),
+              userDataPointer );
+       }
+       
+       if(distributedgrid->getRight()==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+              gridPointer,
+              gridPointer->getDimensions() - CoordinatesType( 1 ),
+              gridPointer->getDimensions() - CoordinatesType( 1 ),
+              userDataPointer );
+       }
+   }
+   
 }
 
 template< typename Real,
@@ -57,11 +85,37 @@ processInteriorEntities( const GridPointer& gridPointer,
     */
    static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." );
 
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
-      gridPointer,
-      CoordinatesType( 1 ),
-      gridPointer->getDimensions() - CoordinatesType( 2 ),
-      userDataPointer );
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+        GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+           gridPointer,
+           CoordinatesType( 1 ),
+           gridPointer->getDimensions() - CoordinatesType( 2 ),
+           userDataPointer );   
+   }
+   else
+   {
+       //Distributed
+       CoordinatesType begin( distributedgrid->getOverlap().x() );
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap().x()-1 );
+       if(distributedgrid->getLeft()==-1)
+       {
+           begin=CoordinatesType( 1 );
+       }
+       
+       if(distributedgrid->getRight()==-1)
+       {
+           end=gridPointer->getDimensions() - CoordinatesType( 2 );
+       }
+       
+       GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+          gridPointer,
+          begin,
+          end,
+          userDataPointer );
+   }
+   
 }
 
 template< typename Real,
@@ -79,13 +133,40 @@ processAllEntities(
    /****
     * All cells
     */
-   static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimension." );
 
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
-      gridPointer,
-      CoordinatesType( 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1 ),
-      userDataPointer );
+   static_assert( GridEntity::getEntityDimension() == 1, "The entity has wrong dimensions." );
+   
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+        GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+           gridPointer,
+           CoordinatesType( 0 ),
+           gridPointer->getDimensions() - CoordinatesType( 1 ),
+           userDataPointer );  
+   }
+   else
+   {
+       //Distributed
+       CoordinatesType begin( distributedgrid->getOverlap().x() );
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap().x()-1 );
+       if(distributedgrid->getLeft()==-1)
+       {
+           begin=CoordinatesType( 0 );
+       }
+       
+       if(distributedgrid->getRight()==-1)
+       {
+           end=gridPointer->getDimensions() - CoordinatesType( 1 );
+       }
+       
+       GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+          gridPointer,
+          begin,
+          end,
+          userDataPointer );
+   }
+
 }
 
 /****
diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h
index 66d03c949733edbc138a9014b5141e7ba84e78ff..cbacdd8a37cfc24e9f13414a5eee7c654a1db0bd 100644
--- a/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Traverser_Grid2D_impl.h
@@ -34,12 +34,60 @@ processBoundaryEntities( const GridPointer& gridPointer,
     */
    static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." );
 
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1 >(
-      gridPointer,
-      CoordinatesType( 0, 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1, 1 ),
-      userDataPointer,
-      0 );
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+    GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1 >(
+       gridPointer,
+       CoordinatesType( 0, 0 ),
+       gridPointer->getDimensions() - CoordinatesType( 1, 1 ),
+       userDataPointer,
+       0 );
+   }
+   else
+   {
+       //Distributed
+       int* neighbors=distributedgrid->getNeighbors(); 
+       if(neighbors[Meshes::DistributedMeshes::Left]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType( 0, 0 ),
+            CoordinatesType(0,gridPointer->getDimensions().y()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Right]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType( gridPointer->getDimensions().x()-1, 0 ),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Up]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType( 0, 0 ),
+            CoordinatesType(gridPointer->getDimensions().x()-1,0),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Down]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType( 0, gridPointer->getDimensions().y()-1 ),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1),
+            userDataPointer,
+            0 );
+       }
+   }
 }
 
 template< typename Real,
@@ -56,7 +104,12 @@ processInteriorEntities( const GridPointer& gridPointer,
    /****
     * Interior cells
     */
-   static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." );
+
+   static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimensions." );
+   
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
 
    GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
       gridPointer,
@@ -64,6 +117,40 @@ processInteriorEntities( const GridPointer& gridPointer,
       gridPointer->getDimensions() - CoordinatesType( 2, 2 ),
       userDataPointer,
       0 );
+   }
+   else
+   {
+       //MPI
+       int* neighbors=distributedgrid->getNeighbors(); 
+       CoordinatesType begin( distributedgrid->getOverlap());
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap()- CoordinatesType(1,1) );
+       if(neighbors[Meshes::DistributedMeshes::Left]==-1)
+       {
+           begin.x()= 1 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Right]==-1)
+       {
+           end.x()=gridPointer->getDimensions().x()-2;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Up]==-1)
+       {
+           begin.y()= 1 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Down]==-1)
+       {
+           end.y()=gridPointer->getDimensions().y()-2;
+       }
+       
+       GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+          gridPointer,
+          begin,
+          end,
+          userDataPointer,
+          0);
+   }
 }
 
 template< typename Real,
@@ -82,12 +169,48 @@ processAllEntities( const GridPointer& gridPointer,
     */
    static_assert( GridEntity::getEntityDimension() == 2, "The entity has wrong dimension." );
  
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
-      gridPointer,
-      CoordinatesType( 0, 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1, 1 ),
-      userDataPointer,
-      0 );
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+    GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+       gridPointer,
+       CoordinatesType( 0, 0 ),
+       gridPointer->getDimensions() - CoordinatesType( 1, 1 ),
+       userDataPointer,
+       0 );
+   }
+   else
+   {
+       int* neighbors=distributedgrid->getNeighbors(); 
+       CoordinatesType begin( distributedgrid->getOverlap());
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap()- CoordinatesType(1,1) );
+       if(neighbors[Meshes::DistributedMeshes::Left]==-1)
+       {
+           begin.x()= 0 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Right]==-1)
+       {
+           end.x()=gridPointer->getDimensions().x()-1;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Up]==-1)
+       {
+           begin.y()= 0 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Down]==-1)
+       {
+           end.y()=gridPointer->getDimensions().y()-1;
+       }
+       
+       GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+          gridPointer,
+          begin,
+          end,
+          userDataPointer,
+          0);   
+   }
 }
 
 /****
diff --git a/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h b/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h
index 84e44ef17c29aca27da6c940e6ab29841fb9aa86..c2ddff5924e89b0ada944f674196f8413fa023e3 100644
--- a/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h
+++ b/src/TNL/Meshes/GridDetails/Traverser_Grid3D_impl.h
@@ -12,6 +12,8 @@
 
 #include <TNL/Meshes/GridDetails/GridTraverser.h>
 
+#include "Traverser_Grid3D.h"
+
 namespace TNL {
 namespace Meshes {
 
@@ -34,12 +36,79 @@ processBoundaryEntities( const GridPointer& gridPointer,
     */
    static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." );
 
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1, 1 >(
-      gridPointer,
-      CoordinatesType( 0, 0, 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1, 1, 1 ),
-      userDataPointer,
-      0 );
+      auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   {
+        GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, true, 1, 1, 1 >(
+          gridPointer,
+          CoordinatesType( 0, 0, 0 ),
+          gridPointer->getDimensions() - CoordinatesType( 1, 1, 1 ),
+          userDataPointer,
+          0 );
+   }
+   else
+   {
+       int* neighbors=distributedgrid->getNeighbors(); 
+       if(neighbors[Meshes::DistributedMeshes::West]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(0,0,0),
+            CoordinatesType(0,gridPointer->getDimensions().y()-1,gridPointer->getDimensions().z()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::East]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(gridPointer->getDimensions().x()-1,0,0),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1,gridPointer->getDimensions().z()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Nord]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(0,0,0),
+            CoordinatesType(gridPointer->getDimensions().x()-1,0,gridPointer->getDimensions().z()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::South]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(0,gridPointer->getDimensions().y()-1,0),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1,gridPointer->getDimensions().z()-1),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Bottom]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(0,0,0),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1,0),
+            userDataPointer,
+            0 );
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Top]==-1)
+       {
+          GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+            gridPointer,
+            CoordinatesType(0,0,gridPointer->getDimensions().z()-1),
+            CoordinatesType(gridPointer->getDimensions().x()-1,gridPointer->getDimensions().y()-1,gridPointer->getDimensions().z()-1),
+            userDataPointer,
+            0 );
+       } 
+   }
 }
 
 template< typename Real,
@@ -57,13 +126,60 @@ processInteriorEntities( const GridPointer& gridPointer,
     * Interior cells
     */
    static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." );
- 
+   
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   { 
    GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
       gridPointer,
       CoordinatesType( 1, 1, 1 ),
       gridPointer->getDimensions() - CoordinatesType( 2, 2, 2 ),
       userDataPointer,
       0 );
+   }
+   else
+   {
+       int* neighbors=distributedgrid->getNeighbors(); 
+       CoordinatesType begin( distributedgrid->getOverlap());
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap()- CoordinatesType(1,1,1) );
+       if(neighbors[Meshes::DistributedMeshes::West]==-1)
+       {
+           begin.x()= 1 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::East]==-1)
+       {
+           end.x()=gridPointer->getDimensions().x()-2;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Nord]==-1)
+       {
+           begin.y()= 1 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::South]==-1)
+       {
+           end.y()=gridPointer->getDimensions().y()-2;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Bottom]==-1)
+       {
+           begin.z()= 1 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Top]==-1)
+       {
+           end.z()=gridPointer->getDimensions().z()-2;
+       }
+
+       GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+          gridPointer,
+          begin,
+          end,
+          userDataPointer,
+          0);      
+   }
+   
 }
 
 template< typename Real,
@@ -82,12 +198,58 @@ processAllEntities( const GridPointer& gridPointer,
     */
    static_assert( GridEntity::getEntityDimension() == 3, "The entity has wrong dimension." );
  
-   GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
-      gridPointer,
-      CoordinatesType( 0, 0, 0 ),
-      gridPointer->getDimensions() - CoordinatesType( 1, 1, 1 ),
-      userDataPointer,
-      0 );
+   auto distributedgrid=gridPointer->GetDistMesh();
+   if(distributedgrid==nullptr||!distributedgrid->IsDistributed())
+   { 
+    GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+       gridPointer,
+       CoordinatesType( 0, 0, 0 ),
+       gridPointer->getDimensions() - CoordinatesType( 1, 1, 1 ),
+       userDataPointer,
+       0 );
+   }
+   else
+   {
+       CoordinatesType begin( distributedgrid->getOverlap());
+       CoordinatesType end( gridPointer->getDimensions() - distributedgrid->getOverlap()- CoordinatesType(1,1,1) );
+       int* neighbors=distributedgrid->getNeighbors(); 
+       if(neighbors[Meshes::DistributedMeshes::West]==-1)
+       {
+           begin.x()= 0 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::East]==-1)
+       {
+           end.x()=gridPointer->getDimensions().x()-1;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Nord]==-1)
+       {
+           begin.y()= 0 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::South]==-1)
+       {
+           end.y()=gridPointer->getDimensions().y()-1;
+       }
+    
+       if(neighbors[Meshes::DistributedMeshes::Bottom]==-1)
+       {
+           begin.z()= 0 ;
+       }
+       
+       if(neighbors[Meshes::DistributedMeshes::Top]==-1)
+       {
+           end.z()=gridPointer->getDimensions().z()-1;
+       }
+    
+        GridTraverser< GridType >::template processEntities< GridEntity, EntitiesProcessor, UserData, false >(
+           gridPointer,
+           begin,
+           end,
+           userDataPointer,
+           0 ); 
+   }
 }
 
 /****
diff --git a/src/TNL/Meshes/Mesh.h b/src/TNL/Meshes/Mesh.h
index 109ccc1043a25588e3bdffeec8b1eecbfdf26314..55c5bca319646a16fb927e0e99c8a74a8dd21817 100644
--- a/src/TNL/Meshes/Mesh.h
+++ b/src/TNL/Meshes/Mesh.h
@@ -26,6 +26,8 @@
 #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 {
 
@@ -170,6 +172,11 @@ class Mesh
 
       void writeProlog( Logger& logger ) const;
 
+      DistributedMeshes::DistributedMesh< Mesh<MeshConfig,Device> >* GetDistMesh(void) const
+      {
+            return NULL;
+      };
+
    protected:
       // Methods for the mesh initializer
       using StorageBaseType::setEntitiesCount;
diff --git a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
index 82767a0f02e2862eba1bf0c0849d3367e5806ace..b6800d7e05e6f0c6a09a87b89c00e9f75f4be5e8 100644
--- a/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
+++ b/src/TNL/Meshes/TypeResolver/TypeResolver_impl.h
@@ -111,10 +111,16 @@ bool resolveMeshType( const String& fileName_,
 }
 
 // TODO: reorganize
-template< typename MeshConfig, typename Device >
+template< typename CommunicatorType, typename MeshConfig, typename Device >
 bool
-loadMesh( const String& fileName_, Mesh< MeshConfig, Device >& mesh )
+loadMesh( const String& fileName_, Mesh< MeshConfig, Device >& mesh, DistributedMeshes::DistributedMesh<Mesh< MeshConfig, Device >> &distributedMesh )
 {
+   if(CommunicatorType::isDistributed())
+   {
+       std::cerr << "Distributed Mesh si not suported yet, only Distributed Grid is supported.";
+       return false;
+   }
+
    std::cout << "Loading mesh from file " << fileName_ << " ..." << std::endl;
    std::string fileName( fileName_.getString() );
    bool status = true;
@@ -145,10 +151,16 @@ loadMesh( const String& fileName_, Mesh< MeshConfig, Device >& mesh )
    return true;
 }
 
-template< typename MeshConfig >
+template<typename CommunicatorType, typename MeshConfig >
 bool
-loadMesh( const String& fileName, Mesh< MeshConfig, Devices::Cuda >& mesh )
+loadMesh( const String& fileName, Mesh< MeshConfig, Devices::Cuda >& mesh, DistributedMeshes::DistributedMesh<Mesh< MeshConfig, Devices::Cuda >> &distributedMesh )
 {
+   if(CommunicatorType::isDistributed())
+   {
+       std::cerr << "Distributed Mesh si not suported yet, only Distributed Grid is supported.";
+       return false;
+   }
+
    Mesh< MeshConfig, Devices::Host > hostMesh;
    if( ! loadMesh( fileName, hostMesh ) )
       return false;
@@ -156,11 +168,46 @@ loadMesh( const String& fileName, Mesh< MeshConfig, Devices::Cuda >& mesh )
    return true;
 }
 
-template< int Dimension, typename Real, typename Device, typename Index >
+template<typename CommunicatorType, int Dimension, typename Real, typename Device, typename Index >
 bool
-loadMesh( const String& fileName, Grid< Dimension, Real, Device, Index >& mesh )
+loadMesh( const String& fileName, Grid< Dimension, Real, Device, Index >& mesh, DistributedMeshes::DistributedMesh<Grid< Dimension, Real, Device, Index >> &distributedMesh)
 {
-   std::cout << "Loading mesh from file " << fileName << " ..." << std::endl;
+
+   if(CommunicatorType::isDistributed())
+   {
+        std::cout << "Loading a global mesh from the file " << fileName << "...";
+        Grid< Dimension, Real, Device, Index > globalGrid;
+        if( ! globalGrid.load( fileName ) )
+        {
+          std::cerr << std::endl;
+          std::cerr << "I am not able to load the global mesh from the file " << fileName << "." << std::endl;
+          return false;
+        }
+        std::cout << " [ OK ] " << std::endl;
+  
+       typename Meshes::DistributedMeshes::DistributedMesh<Grid< Dimension, Real, Device, Index >>::CoordinatesType overlap;
+       overlap.setValue(1);
+       distributedMesh.template setGlobalGrid<CommunicatorType>(globalGrid,overlap);
+       distributedMesh.SetupGrid(mesh);
+       return true;
+   }
+   else
+   {
+       std::cout << "Loading a mesh from the file " << fileName << "...";
+       if( ! mesh.load( fileName ) )
+       {
+          std::cerr << std::endl;
+          std::cerr << "I am not able to load the mesh from the file " << fileName << "." << std::endl;
+          std::cerr << " You may create it with tools like tnl-grid-setup or tnl-mesh-convert." << std::endl;
+          return false;
+       }
+       std::cout << " [ OK ] " << std::endl;
+       return true;
+    }
+
+
+
+  /* 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 << ". "
@@ -168,7 +215,7 @@ loadMesh( const String& fileName, Grid< Dimension, Real, Device, Index >& mesh )
                 << std::endl;
       return false;
    }
-   return true;
+   return true;*/
 }
 
 } // namespace Meshes
diff --git a/src/TNL/Problems/HeatEquationEocProblem.h b/src/TNL/Problems/HeatEquationEocProblem.h
index fd292dde621b9cdbcea3a88b241a0405a728201c..361e4d48f26d08f99693447df7f3805216628e81 100644
--- a/src/TNL/Problems/HeatEquationEocProblem.h
+++ b/src/TNL/Problems/HeatEquationEocProblem.h
@@ -25,13 +25,14 @@ namespace Problems {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator = Operators::LinearDiffusion< Mesh,
                                                               typename BoundaryCondition::RealType > >
-class HeatEquationEocProblem : public HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >
+class HeatEquationEocProblem : public HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >
 {
    public:
       
-      typedef HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator > BaseType;
+      typedef HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator > BaseType;
       
       using typename BaseType::MeshPointer;
 
diff --git a/src/TNL/Problems/HeatEquationEocProblem_impl.h b/src/TNL/Problems/HeatEquationEocProblem_impl.h
index 87eb44d89c2b20a6c6e9f7b36d7fe4f7b7eaaeb3..42b0d61bf6f21bff77caa4bb97d27b3de4067648 100644
--- a/src/TNL/Problems/HeatEquationEocProblem_impl.h
+++ b/src/TNL/Problems/HeatEquationEocProblem_impl.h
@@ -25,9 +25,10 @@ namespace Problems {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-HeatEquationEocProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationEocProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getTypeStatic()
 {
    return String( "heatEquationEocSolver< " ) + Mesh :: getTypeStatic() + " >";
@@ -36,9 +37,10 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationEocProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator  >::
+HeatEquationEocProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator  >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
diff --git a/src/TNL/Problems/HeatEquationProblem.h b/src/TNL/Problems/HeatEquationProblem.h
index a97c681a232ba33b873f4046a590431432a7685f..28ebf2d65898869f9c18e2b0ba4783998e5e7b57 100644
--- a/src/TNL/Problems/HeatEquationProblem.h
+++ b/src/TNL/Problems/HeatEquationProblem.h
@@ -31,6 +31,7 @@ namespace Problems {
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator = Operators::LinearDiffusion< Mesh,
                                                               typename BoundaryCondition::RealType > >
 class HeatEquationProblem : public PDEProblem< Mesh,
@@ -58,6 +59,8 @@ class HeatEquationProblem : public PDEProblem< Mesh,
       using typename BaseType::MeshDependentDataType;
       using typename BaseType::MeshDependentDataPointer;
 
+      typedef CommType CommunicatorType;
+
       static String getTypeStatic();
 
       String getPrologHeader() const;
diff --git a/src/TNL/Problems/HeatEquationProblem_impl.h b/src/TNL/Problems/HeatEquationProblem_impl.h
index 5a27d4da381f7aa25672055ab3933986d62faf80..07040f40001cfe32bd9bf7693dab251859ee236d 100644
--- a/src/TNL/Problems/HeatEquationProblem_impl.h
+++ b/src/TNL/Problems/HeatEquationProblem_impl.h
@@ -24,15 +24,20 @@
 
 #include "HeatEquationProblem.h"
 
+//#define MPIIO
+#include <TNL/Meshes/DistributedMeshes/DistributedGridIO.h>
+
+
 namespace TNL {
 namespace Problems {
 
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getTypeStatic()
 {
    return String( "HeatEquationProblem< " ) + Mesh :: getTypeStatic() + " >";
@@ -41,9 +46,10 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getPrologHeader() const
 {
    return String( "Heat equation" );
@@ -52,9 +58,10 @@ getPrologHeader() const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) const
 {
 }
@@ -62,9 +69,10 @@ writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) cons
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 writeEpilog( Logger& logger )
 {
    return true;
@@ -73,9 +81,10 @@ writeEpilog( Logger& logger )
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
@@ -96,9 +105,10 @@ setup( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
-typename HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::IndexType
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+typename HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::IndexType
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getDofs( const MeshPointer& meshPointer ) const
 {
    /****
@@ -110,9 +120,10 @@ getDofs( const MeshPointer& meshPointer ) const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 bindDofs( const MeshPointer& meshPointer,
           const DofVectorPointer& dofVector )
 {
@@ -123,9 +134,10 @@ bindDofs( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setInitialCondition( const Config::ParameterContainer& parameters,
                      const MeshPointer& meshPointer,
                      DofVectorPointer& dofs,
@@ -133,21 +145,32 @@ setInitialCondition( const Config::ParameterContainer& parameters,
 {
    this->bindDofs( meshPointer, dofs );
    const String& initialConditionFile = parameters.getParameter< String >( "initial-condition" );
-   if( ! this->uPointer->boundLoad( initialConditionFile ) )
-   {
-      std::cerr << "I am not able to load the initial condition from the file " << initialConditionFile << "." << std::endl;
-      return false;
-   }
+   std::cout<<"setInitialCondition" <<std::endl; 
+   if(CommunicatorType::isDistributed())
+    {
+        std::cout<<"Nodes Distribution: " << uPointer->getMesh().GetDistMesh()->printProcessDistr() << std::endl;
+        Meshes::DistributedMeshes::DistributedGridIO<MeshFunctionType,Meshes::DistributedMeshes::LocalCopy> ::load(initialConditionFile, *uPointer );
+        uPointer->template Synchronize<CommunicatorType>();
+    }
+    else
+    {
+       if( ! this->uPointer->boundLoad( initialConditionFile ) )
+       {
+          std::cerr << "I am not able to load the initial condition from the file " << initialConditionFile << "." << std::endl;
+          return false;
+       }
+    }
    return true;
 }
 
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
    template< typename MatrixPointer >          
 bool
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setupLinearSystem( const MeshPointer& meshPointer,
                    MatrixPointer& matrixPointer )
 {
@@ -170,9 +193,10 @@ setupLinearSystem( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 makeSnapshot( const RealType& time,
               const IndexType& step,
               const MeshPointer& meshPointer,
@@ -187,17 +211,28 @@ makeSnapshot( const RealType& time,
    fileName.setFileNameBase( "u-" );
    fileName.setExtension( "tnl" );
    fileName.setIndex( step );
-   if( ! this->uPointer->save( fileName.getFileName() ) )
-      return false;
+
+   std::cout<<"Make snapshot" <<std::endl; 
+
+    if(CommunicatorType::isDistributed())
+    {
+       Meshes::DistributedMeshes::DistributedGridIO<MeshFunctionType,Meshes::DistributedMeshes::LocalCopy> ::save(fileName.getFileName(), *uPointer );
+    }
+    else
+    {
+       if( ! this->uPointer->save( fileName.getFileName() ) )
+          return false;
+    }
    return true;
 }
 
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getExplicitUpdate( const RealType& time,
                 const RealType& tau,
                 const MeshPointer& meshPointer,
@@ -219,16 +254,18 @@ getExplicitUpdate( const RealType& time,
    this->explicitUpdater.setDifferentialOperator( this->differentialOperatorPointer ),
    this->explicitUpdater.setBoundaryConditions( this->boundaryConditionPointer ),
    this->explicitUpdater.setRightHandSide( this->rightHandSidePointer ),
-   this->explicitUpdater.template update< typename Mesh::Cell >( time, tau, meshPointer, this->uPointer, fuPointer );
+   this->explicitUpdater.template update< typename Mesh::Cell, CommType >( time, tau, meshPointer, this->uPointer, fuPointer );
+
 }
 
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
     template< typename MatrixPointer >          
 void
-HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 assemblyLinearSystem( const RealType& time,
                       const RealType& tau,
                       const MeshPointer& meshPointer,
diff --git a/src/TNL/SmartPointersRegister.cpp b/src/TNL/SmartPointersRegister.cpp
index 03d3e058f004c201c61d7c307cce7327d5e106c9..f2910ba36ecfde3fdf0f7c57cfcef61fa3c65a0e 100644
--- a/src/TNL/SmartPointersRegister.cpp
+++ b/src/TNL/SmartPointersRegister.cpp
@@ -30,7 +30,7 @@ void SmartPointersRegister::remove( SmartPointer* pointer, int deviceId )
    try {
       pointersOnDevices.at( deviceId ).erase( pointer );
    }
-   catch( std::out_of_range ) {
+   catch( const std::out_of_range& ) {
       std::cerr << "Given deviceId " << deviceId << " does not have any pointers yet. "
                 << "Requested to remove pointer " << pointer << ". "
                 << "This is most likely a bug in the smart pointer." << std::endl;
@@ -46,7 +46,7 @@ bool SmartPointersRegister::synchronizeDevice( int deviceId )
          ( *it ).synchronize();
       return TNL_CHECK_CUDA_DEVICE;
    }
-   catch( std::out_of_range ) {
+   catch( const std::out_of_range& ) {
       return false;
    }
 }
diff --git a/src/TNL/Solvers/ODE/Euler_impl.h b/src/TNL/Solvers/ODE/Euler_impl.h
index 02c21a6c0bd907bb4843abded43e3a96c4cfa8aa..92cb1e5c974b6a4b19c34b3d116f4fcb6d3ec568 100644
--- a/src/TNL/Solvers/ODE/Euler_impl.h
+++ b/src/TNL/Solvers/ODE/Euler_impl.h
@@ -227,8 +227,15 @@ void Euler< Problem > :: computeNewTimeLevel( DofVectorPointer& u,
     }
 #endif
    }
-   localResidue /= tau * ( RealType ) size;   
-   MPIAllreduce( localResidue, currentResidue, 1, MPI_SUM, this->solver_comm );
+
+   
+   
+   localResidue /= tau * ( RealType ) size;
+#ifdef USE_MPI   
+   TNLMPI::Allreduce( localResidue, currentResidue, 1, MPI_SUM);
+#else
+   currentResidue=localResidue;
+#endif
 
 }
 
diff --git a/src/TNL/Solvers/ODE/ExplicitSolver.h b/src/TNL/Solvers/ODE/ExplicitSolver.h
index 721b472c6e28ef097802dff3c2ea52166d42399f..7ac4f14ecd4bc1eb0ae827a3f67dfd2de4dd1628 100644
--- a/src/TNL/Solvers/ODE/ExplicitSolver.h
+++ b/src/TNL/Solvers/ODE/ExplicitSolver.h
@@ -64,8 +64,6 @@ class ExplicitSolver : public IterativeSolver< typename Problem::RealType,
    void setMaxTau( const RealType& maxTau );
 
    const RealType& getMaxTau() const;
-
-   void setMPIComm( MPI_Comm comm );
  
    void setVerbose( IndexType v );
 
@@ -98,8 +96,6 @@ protected:
 
    RealType maxTau;
 
-   MPI_Comm solver_comm;
-
    IndexType verbosity;
 
    Timer* timer;
diff --git a/src/TNL/Solvers/ODE/ExplicitSolver_impl.h b/src/TNL/Solvers/ODE/ExplicitSolver_impl.h
index 352c5ca2b2fee5a6a93ce641114553e0feb662fa..78f0b0e69dca0ab2e107a17a055cccc12f32dd60 100644
--- a/src/TNL/Solvers/ODE/ExplicitSolver_impl.h
+++ b/src/TNL/Solvers/ODE/ExplicitSolver_impl.h
@@ -21,7 +21,6 @@ ExplicitSolver()
    stopTime( 0.0 ),
    tau( 0.0 ),
    maxTau( DBL_MAX ),
-   solver_comm( MPI_COMM_WORLD ),
    verbosity( 0 ),
    timer( &defaultTimer ),
    testingMode( false ),
@@ -123,14 +122,6 @@ setStopTime( const RealType& stopTime )
     this->stopTime = stopTime;
 }
 
-template< class Problem >
-void
-ExplicitSolver< Problem >::
-setMPIComm( MPI_Comm comm )
-{
-   this->solver_comm = comm;
-};
-
 template< class Problem >
 void
 ExplicitSolver< Problem >::
diff --git a/src/TNL/Solvers/ODE/Merson_impl.h b/src/TNL/Solvers/ODE/Merson_impl.h
index d206087f1cc3d5ba78a888ef916b06f40e76235a..92f754af50aadfafebe8ed67e2afccf3bcb1c61f 100644
--- a/src/TNL/Solvers/ODE/Merson_impl.h
+++ b/src/TNL/Solvers/ODE/Merson_impl.h
@@ -213,7 +213,9 @@ bool Merson< Problem > :: solve( DofVectorPointer& u )
       {
          currentTau *= 0.8 * ::pow( adaptivity / eps, 0.2 );
          currentTau = min( currentTau, this->getMaxTau() );
-         MPIBcast( currentTau, 1, 0, this->solver_comm );
+#ifdef USE_MPI
+         TNLMPI::Bcast( currentTau, 1, 0 );
+#endif        
       }
       if( time + currentTau > this->getStopTime() )
          currentTau = this->getStopTime() - time; //we don't want to keep such tau
@@ -419,7 +421,11 @@ typename Problem :: RealType Merson< Problem > :: computeError( const RealType t
       }
 #endif
    }
-   MPIAllreduce( eps, maxEps, 1, MPI_MAX, this->solver_comm );
+   #ifdef USE_MPI
+        TNLMPI::Allreduce( eps, maxEps, 1, MPI_MAX);
+   #else
+        maxEps=eps;
+   #endif
    return maxEps;
 }
 
@@ -484,8 +490,13 @@ void Merson< Problem >::computeNewTimeLevel( DofVectorPointer& u,
 
 #endif
    }
+
    localResidue /= tau * ( RealType ) size;
-   MPIAllreduce( localResidue, currentResidue, 1, MPI_SUM, this->solver_comm );
+#ifdef USE_MPI
+   TNLMPI::Allreduce( localResidue, currentResidue, 1, MPI_SUM);
+#else
+   currentResidue=localResidue;
+#endif
 
 }
 
diff --git a/src/TNL/Solvers/PDE/ExplicitUpdater.h b/src/TNL/Solvers/PDE/ExplicitUpdater.h
index 264ecef7c0a83a3f6ead920de11a0225fb61cd36..21608dc84e406cc1e54c8a6d3b0ad5cd97374eb6 100644
--- a/src/TNL/Solvers/PDE/ExplicitUpdater.h
+++ b/src/TNL/Solvers/PDE/ExplicitUpdater.h
@@ -19,6 +19,10 @@
 #include <TNL/Meshes/GridDetails/Traverser_Grid3D.h>
 #include <TNL/Solvers/PDE/ExplicitUpdater.h>
 
+#ifdef USE_MPI
+    #include <TNL/Meshes/DistributedGridSynchronizer.h>
+#endif
+
 
 namespace TNL {
 namespace Solvers {
@@ -109,7 +113,8 @@ class ExplicitUpdater
          this->userDataPointer->rightHandSide = &rightHandSidePointer.template getData< DeviceType >();
       }
             
-      template< typename EntityType >
+      template< typename EntityType,
+                typename CommunicatorType >
       void update( const RealType& time,
                    const RealType& tau,
                    const MeshPointer& meshPointer,
@@ -143,7 +148,10 @@ class ExplicitUpdater
                                              TraverserBoundaryEntitiesProcessor >
                                            ( meshPointer,
                                              userDataPointer );
-         
+
+         if(CommunicatorType::isDistributed())
+            fuPointer->template Synchronize<CommunicatorType>();
+
       }
       
          
diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
index af4889ac329fa032bc71bf355e0044327f79c5bb..d0a9cb7c5cba57e940e8e1eafd11064c388e59fb 100644
--- a/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
+++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver.h
@@ -17,6 +17,9 @@
 #include <TNL/Solvers/PDE/PDESolver.h>
 #include <TNL/Solvers/PDE/MeshDependentTimeSteps.h>
 
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+
+
 namespace TNL {
 namespace Solvers {
 namespace PDE {   
@@ -84,6 +87,8 @@ class TimeDependentPDESolver
 
       MeshPointer meshPointer;
 
+      Meshes::DistributedMeshes::DistributedMesh<MeshType> distrMesh;
+
       DofVectorPointer dofsPointer;
 
       MeshDependentDataPointer meshDependentDataPointer;
diff --git a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
index a8a01aa9c506e288cedb2d0f366cbbd3d7de366a..8e5bb166da2b7b708374512a00e3174701560ec9 100644
--- a/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
+++ b/src/TNL/Solvers/PDE/TimeDependentPDESolver_impl.h
@@ -30,6 +30,7 @@ TimeDependentPDESolver()
 {
 }
 
+
 template< typename Problem,
           typename DiscreteSolver,   
           typename TimeStepper >
@@ -62,9 +63,8 @@ setup( const Config::ParameterContainer& parameters,
     * Load the mesh from the mesh file
     */
    const String& meshFile = parameters.getParameter< String >( "mesh" );
-   if( ! Meshes::loadMesh( meshFile, *meshPointer ) )
+   if( ! Meshes::loadMesh<typename Problem::CommunicatorType>( meshFile, *meshPointer, distrMesh ) )
       return false;
-
    /****
     * Setup the problem
     */
diff --git a/src/TNL/Solvers/Solver.h b/src/TNL/Solvers/Solver.h
index 0d5925a1eb80b1fc7a81c94d129c70c5de242545..446569993b0add6b279e690a1ae57f8a9c6351ec 100644
--- a/src/TNL/Solvers/Solver.h
+++ b/src/TNL/Solvers/Solver.h
@@ -15,7 +15,7 @@
 namespace TNL {
 namespace Solvers {   
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           template< typename ConfTag > class ProblemConfig,
           typename ConfigTag = DefaultBuildConfigTag >
 class Solver
diff --git a/src/TNL/Solvers/SolverInitiator.h b/src/TNL/Solvers/SolverInitiator.h
index 40a6d9cddd773c29e58813b996d813373af60b67..31fad1ee81184d585c1476db02665652c17e6685 100644
--- a/src/TNL/Solvers/SolverInitiator.h
+++ b/src/TNL/Solvers/SolverInitiator.h
@@ -17,8 +17,9 @@
 namespace TNL {
 namespace Solvers {   
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter , typename CommunicatorType  > 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 4736e585705f9c785dfe828cb823e8473d66db4b..e940379f5b6d39403c5ea8b2125a3156cd3d6467 100644
--- a/src/TNL/Solvers/SolverInitiator_impl.h
+++ b/src/TNL/Solvers/SolverInitiator_impl.h
@@ -23,23 +23,26 @@
 #include <TNL/Solvers/SolverStarter.h>
 #include <TNL/Meshes/DummyMesh.h>
 
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+
 namespace TNL {
 namespace Solvers {   
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename ConfigTag,
           bool enabled = ConfigTagReal< ConfigTag, Real >::enabled >
 class SolverInitiatorRealResolver {};
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename ConfigTag,
           bool enabled = ConfigTagDevice< ConfigTag, Device >::enabled >
 class SolverInitiatorDeviceResolver {};
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
@@ -47,16 +50,25 @@ template< template< typename Real, typename Device, typename Index, typename Mes
           bool enabled = ConfigTagIndex< ConfigTag, Index >::enabled >
 class SolverInitiatorIndexResolver {};
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename ConfigTag,
+          bool enabled = true  >
+class CommunicatorTypeResolver {};
+
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
           typename ConfigTag,
+          typename CommunicatorType,
           bool enabled = ConfigTagMeshResolve< ConfigTag >::enabled >
 class SolverInitiatorMeshResolver {};
 
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename ConfigTag  >
 bool SolverInitiator< ProblemSetter, ConfigTag > :: run( const Config::ParameterContainer& parameters )
 {
@@ -73,8 +85,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,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename ConfigTag >
 class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, true >
@@ -97,7 +108,7 @@ class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, true >
       }
 };
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename ConfigTag >
 class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, false >
@@ -110,8 +121,7 @@ class SolverInitiatorRealResolver< ProblemSetter, Real, ConfigTag, false >
       }
 };
 
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename ConfigTag >
@@ -134,7 +144,7 @@ class SolverInitiatorDeviceResolver< ProblemSetter, Real, Device, ConfigTag, tru
       }
 };
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename ConfigTag >
@@ -148,8 +158,7 @@ class SolverInitiatorDeviceResolver< ProblemSetter, Real, Device, ConfigTag, fal
       }
 };
 
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
@@ -164,7 +173,7 @@ class SolverInitiatorIndexResolver< ProblemSetter, Real, Device, Index, ConfigTa
       }
 };
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
@@ -174,17 +183,41 @@ class SolverInitiatorIndexResolver< ProblemSetter, Real, Device, Index, ConfigTa
    public:
       static bool run( const Config::ParameterContainer& parameters )
       {
-         return SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag >::run( parameters );
+         return CommunicatorTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >::run( parameters );
       }
 };
 
-
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
           typename ConfigTag >
-class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, false >
+class CommunicatorTypeResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >
+{
+   public:
+      static bool run( const Config::ParameterContainer& parameters )
+      {
+#ifdef HAVE_MPI
+         if(Communicators::MpiCommunicator::isDistributed())
+         {     
+               bool ret=SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, Communicators::MpiCommunicator >::run( parameters );
+               Communicators::MpiCommunicator::Finalize();      
+               return ret;
+         }
+         Communicators::MpiCommunicator::Finalize();
+#endif
+         return SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, Communicators::NoDistrCommunicator >::run( parameters );
+         
+      }
+};
+
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
+          typename Real,
+          typename Device,
+          typename Index,
+          typename ConfigTag,
+          typename CommunicatorType >
+class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, CommunicatorType, false >
 {
    public:
       static bool run( const Config::ParameterContainer& parameters )
@@ -194,20 +227,21 @@ class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag
                                Index,
                                Meshes::DummyMesh< Real, Device, Index >,
                                ConfigTag,
-                               SolverStarter< ConfigTag > >::template run< Real, Device, Index, ConfigTag >( parameters );
+                               SolverStarter< ConfigTag >, CommunicatorType >::template run< Real, Device, Index, ConfigTag >( parameters );
       }
 };
 
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename ConfigTag, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           typename Real,
           typename Device,
           typename Index,
-          typename ConfigTag >
-class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag, true >
+          typename ConfigTag,
+          typename CommunicatorType >
+class SolverInitiatorMeshResolver< ProblemSetter, Real, Device, Index, ConfigTag,CommunicatorType, true >
 {
    // wrapper for MeshTypeResolver
    template< typename MeshType >
-   using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag > >;
+   using ProblemSetterWrapper = ProblemSetter< Real, Device, Index, MeshType, ConfigTag, SolverStarter< ConfigTag >, CommunicatorType >;
 
    public:
       static bool run( const Config::ParameterContainer& parameters )
diff --git a/src/TNL/Solvers/Solver_impl.h b/src/TNL/Solvers/Solver_impl.h
index f7787359bf8b3beea531fa4e65a64e4d73a8a69a..c07d743708fcb7c943b7010f7a23c02f3cf66b28 100644
--- a/src/TNL/Solvers/Solver_impl.h
+++ b/src/TNL/Solvers/Solver_impl.h
@@ -14,11 +14,13 @@
 #include <TNL/Solvers/SolverStarter.h>
 #include <TNL/Solvers/SolverConfig.h>
 #include <TNL/Devices/Cuda.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Communicators/MpiCommunicator.h>
 
 namespace TNL {
 namespace Solvers {
    
-template< template< typename Real, typename Device, typename Index, typename MeshType, typename MeshConfig, typename SolverStarter > class ProblemSetter,
+template< template< typename Real, typename Device, typename Index, typename MeshType, typename MeshConfig, typename SolverStarter, typename CommunicatorType > class ProblemSetter,
           template< typename MeshConfig > class ProblemConfig,
           typename MeshConfig >
 bool
@@ -33,11 +35,19 @@ run( int argc, char* argv[] )
    Devices::Host::configSetup( configDescription );
    Devices::Cuda::configSetup( configDescription );
 
+    //iniicialization needs argc and argc-> needs to be close to main
+       Communicators::NoDistrCommunicator::Init(argc,argv, true);
+#ifdef HAVE_MPI
+       Communicators::MpiCommunicator::Init(argc,argv, true);
+#endif
+
    if( ! parseCommandLine( argc, argv, configDescription, parameters ) )
       return false;
 
    SolverInitiator< ProblemSetter, MeshConfig > solverInitiator;
-   return solverInitiator.run( parameters );
+   bool ret= solverInitiator.run( parameters );
+
+	return ret;
 };
 
 } // namespace Solvers
diff --git a/src/TNL/String.cpp b/src/TNL/String.cpp
index 34c4e3822b940b520861052af809c6665bba6a13..3f733526d935e12f0d6534de22e9d06cdbe91058 100644
--- a/src/TNL/String.cpp
+++ b/src/TNL/String.cpp
@@ -15,7 +15,7 @@
 #include <TNL/Containers/List.h>
 #include <TNL/File.h>
 #include <TNL/Math.h>
-#ifdef HAVE_MPI
+#ifdef USE_MPI
    #include <mpi.h>
 #endif
 
@@ -390,9 +390,9 @@ bool String::load( File& file )
    return true;
 }
 
-void String::MPIBcast( int root, MPI_Comm comm )
+/*void String :: MPIBcast( int root, MPI_Comm comm )
 {
-#ifdef HAVE_MPI
+#ifdef USE_MPI
    dbgFunctionName( "mString", "MPIBcast" );
    int iproc;
    MPI_Comm_rank( MPI_COMM_WORLD, &iproc );
@@ -416,8 +416,8 @@ void String::MPIBcast( int root, MPI_Comm comm )
    dbgExpr( string );
 #endif
 }
-
-bool String::getLine( std::istream& stream )
+*/
+bool String :: getLine( std::istream& stream )
 {
    std::string str;
    getline( stream, str );
diff --git a/src/TNL/String.h b/src/TNL/String.h
index 5c012fca03f5970beab192622bff910fcdcd59a6..0868ac44a46872681367ed48e48f24fdc0a15f59 100644
--- a/src/TNL/String.h
+++ b/src/TNL/String.h
@@ -12,8 +12,6 @@
 
 #include <iostream>
 #include <sstream>
-#include <TNL/mpi-supp.h>
-
 
 namespace TNL {
 
@@ -22,6 +20,8 @@ namespace Containers {
    template< class T > class List;
 }
 
+class String;
+
 template< typename T >
 String convertToString( const T& value );
 
@@ -146,7 +146,7 @@ public:
    bool load( File& file );
 
    //! Broadcast to other nodes in MPI cluster
-   void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD );
+//   void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD );
 
    //! Read one line from given stream.
    bool getLine( std::istream& stream );
diff --git a/src/TNL/mpi-supp.cpp b/src/TNL/mpi-supp.cpp
deleted file mode 100644
index d45bd1da83503f7921c11fea44da71ea6d1aef72..0000000000000000000000000000000000000000
--- a/src/TNL/mpi-supp.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/***************************************************************************
-                          mpi-supp.cpp  -  description
-                             -------------------
-    begin                : 2007/06/21
-    copyright            : (C) 2007 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#include <TNL/mpi-supp.h>
-
-namespace TNL {
-
-void MPIInit( int* argc, char** argv[] )
-{
-#ifdef HAVE_MPI
-   MPI_Init( argc, argv );
-#endif
-}
-
-void MPIFinalize()
-{
-#ifdef HAVE_MPI
-   MPI_Finalize();
-#endif
-}
-
-bool HaveMPI()
-{
-#ifdef HAVE_MPI
-   return true;
-#else
-   return false;
-#endif
-}
-
-int MPIGetRank( MPI_Comm comm )
-{
-#ifdef HAVE_MPI
-   int rank;
-   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
-   return rank;
-#else
-   return 0;
-#endif
-}
-
-int MPIGetSize( MPI_Comm comm )
-{
-#ifdef HAVE_MPI
-   int size;
-   MPI_Comm_size( comm, &size );
-   return size;
-#else
-   return 0;
-#endif
-}
-
-
-void MPIBarrier( MPI_Comm comm )
-{
-#ifdef HAVE_MPI
-   MPI_Barrier( comm );
-#endif
-}
-
-} // namespace TNL
-
diff --git a/src/TNL/mpi-supp.h b/src/TNL/mpi-supp.h
deleted file mode 100644
index 398fe5f793bedee2cce7520091d730131950a61a..0000000000000000000000000000000000000000
--- a/src/TNL/mpi-supp.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/***************************************************************************
-                          mpi-supp.h  -  description
-                             -------------------
-    begin                : 2005/04/23
-    copyright            : (C) 2005 by Tomas Oberhuber
-    email                : tomas.oberhuber@fjfi.cvut.cz
- ***************************************************************************/
-
-/* See Copyright Notice in tnl/Copyright */
-
-#pragma once
-
-#include <iostream>
-#include <cstdlib>
-
-#ifdef HAVE_MPI
-   #include <mpi.h>
-#else
-   typedef int MPI_Comm;
-   typedef int MPI_Op;
-   #define MPI_COMM_WORLD  0
-   #define MPI_MAX 0
-   #define MPI_MIN 0
-   #define MPI_SUM 0
-#endif
-
-namespace TNL {
-   
-class String;
-
-#ifdef HAVE_MPI
-inline MPI_Datatype MPIDataType( const signed char ) { return MPI_CHAR; };
-inline MPI_Datatype MPIDataType( const signed short int ) { return MPI_SHORT; };
-inline MPI_Datatype MPIDataType( const signed int ) { return MPI_INT; };
-inline MPI_Datatype MPIDataType( const signed long int ) { return MPI_LONG; };
-inline MPI_Datatype MPIDataType( const unsigned char ) { return MPI_UNSIGNED_CHAR; };
-inline MPI_Datatype MPIDataType( const unsigned short int ) { return MPI_UNSIGNED_SHORT; };
-inline MPI_Datatype MPIDataType( const unsigned int ) { return MPI_UNSIGNED; };
-inline MPI_Datatype MPIDataType( const unsigned long int ) { return MPI_UNSIGNED_LONG; };
-inline MPI_Datatype MPIDataType( const float& ) { return MPI_FLOAT; };
-inline MPI_Datatype MPIDataType( const double& ) { return MPI_DOUBLE; };
-inline MPI_Datatype MPIDataType( const long double& ) { return MPI_LONG_DOUBLE; };
-#endif
-
-
-void MPIInit( int* argc, char** argv[] );
-
-void MPIFinalize();
-
-bool HaveMPI();
-
-int MPIGetRank( MPI_Comm comm = MPI_COMM_WORLD );
-
-int MPIGetSize( MPI_Comm comm = MPI_COMM_WORLD );
-
-void MPIBarrier( MPI_Comm comm = MPI_COMM_WORLD );
-
-#ifdef HAVE_MPI
-template< class T > void MPISend( const T& data,
-                                  int count,
-                                  int dest,
-                                  MPI_Comm comm = MPI_COMM_WORLD )
-{
-   MPI_Send( &data, count, MPIDataType( data ), dest, 0, comm );
-};
-#else
-template< class T > void MPISend( const T&,
-                                  int,
-                                  int,
-                                  MPI_Comm  )
-{
-};
-#endif
-
-#ifdef HAVE_MPI
-template< class T > void MPIRecv( T& data,
-                                  int count,
-                                  int src,
-                                  MPI_Comm comm = MPI_COMM_WORLD )
-{
-   MPI_Status stat;
-   MPI_Recv( data, count, MPIDataType( data ), src, 0, comm, &stat );
-};
-#else
-template< class T > void MPIRecv( T&,
-                                  int,
-                                  int,
-                                  MPI_Comm = MPI_COMM_WORLD )
-{};
-#endif
-
-#ifdef HAVE_MPI
-template< class T > void MPIBcast( T& data,
-                                   int count,
-                                   int root,
-                                   MPI_Comm comm = MPI_COMM_WORLD )
-{
-   MPI_Bcast( &data, count, MPIDataType( data ), root, comm );
-};
-
-inline void MPIBcast( String& data, intstd::cout, int root, MPI_Comm comm = MPI_COMM_WORLD )
-{
-   std::cerr << "Call method MPIBcast of mString instead of function MPIBcast( mString&, ... ) " << std::endl;
-   abort();
-}
-#else
-template< class T > void MPIBcast( T&,
-                                   int,
-                                   int,
-                                   MPI_Comm = MPI_COMM_WORLD )
-{
-}
-#endif
-
-#ifdef HAVE_MPI
-template< typename T > void MPIReduce( T& data,
-                                       T& reduced_data,
-                                       int count,
-                                       MPI_Op op,
-                                       int root,
-                                       MPI_Comm comm )
-{
-   MPI_Reduce( &data,
-               &reduced_data,
-               count,
-               MPIDataType( data ),
-               op,
-               root,
-               comm );
-};
-#else
-template< typename T > void MPIReduce( T& data,
-                                       T& reduced_data,
-                                       int,
-                                       MPI_Op,
-                                       int,
-                                       MPI_Comm )
-{
-   reduced_data = data;
-};
-#endif
-
-#ifdef HAVE_MPI
-template< typename T > void MPIAllreduce( T& data,
-                                          T& reduced_data,
-                                          int count,
-                                          MPI_Op op,
-                                          MPI_Comm comm )
-{
-   MPI_Allreduce( &data,
-                  &reduced_data,
-                  count,
-                  MPIDataType( data ),
-                  op,
-                  comm );
-};
-#else
-template< typename T > void MPIAllreduce( T& data,
-                                          T& reduced_data,
-                                          int,
-                                          MPI_Op,
-                                          MPI_Comm )
-{
-   reduced_data = data;
-};
-#endif
-
-} // namespace TNL
diff --git a/src/Tools/tnl-init.cpp b/src/Tools/tnl-init.cpp
index f42b9ad3c9aeb02690ef4f7def74acf6c2ce3087..49ee117eae5e262fac28686a445060d32ab1db6d 100644
--- a/src/Tools/tnl-init.cpp
+++ b/src/Tools/tnl-init.cpp
@@ -17,6 +17,10 @@
 #include <TNL/Meshes/DummyMesh.h>
 #include <TNL/Meshes/Grid.h>
 
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+
+
 using namespace TNL;
 
 void setupConfig( Config::ConfigDescription& config )
@@ -43,12 +47,21 @@ void setupConfig( Config::ConfigDescription& config )
    Functions::TestFunction< 1 >::configSetup( config );
 }
 
+
+
 int main( int argc, char* argv[] )
 {
+
    Config::ParameterContainer parameters;
    Config::ConfigDescription conf_desc;
 
    setupConfig( conf_desc );
+
+    //iniicialization needs argc and argc-> needs to be close to main
+       Communicators::NoDistrCommunicator::Init(argc,argv, true);
+#ifdef HAVE_MPI
+       Communicators::MpiCommunicator::Init(argc,argv,true);
+#endif
  
    if( ! parseCommandLine( argc, argv, conf_desc, parameters ) )
       return EXIT_FAILURE;
@@ -69,5 +82,6 @@ int main( int argc, char* argv[] )
    }
    if( ! resolveMeshType( parsedMeshType, parameters ) )
       return EXIT_FAILURE;
+
    return EXIT_SUCCESS;
 }
diff --git a/src/Tools/tnl-init.h b/src/Tools/tnl-init.h
index 355c553f02695d28f45c3994ef80891ead05b4cd..67fbba0a5ec58093dcad37d2805e946cbd95446c 100644
--- a/src/Tools/tnl-init.h
+++ b/src/Tools/tnl-init.h
@@ -19,20 +19,47 @@
 #include <TNL/FileName.h>
 #include <TNL/Functions/MeshFunction.h>
 
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedGridIO.h>
+
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+
 using namespace TNL;
 
 template< typename MeshType,
           typename RealType,
+          typename CommunicatorType,
           int xDiff,
           int yDiff,
           int zDiff >
 bool renderFunction( const Config::ParameterContainer& parameters )
 {
+
+   Meshes::DistributedMeshes::DistributedMesh<MeshType> distributedMesh;
    SharedPointer< MeshType > meshPointer;
-   String meshFile = parameters.getParameter< String >( "mesh" );
-   std::cout << "+ -> Loading mesh from " << meshFile << " ... " << std::endl;
-   if( ! meshPointer->load( meshFile ) )
-      return false;
+   MeshType globalMesh;
+
+   if(CommunicatorType::isDistributed())
+   {
+       //suppose global mesh loaded from single file
+       String meshFile = parameters.getParameter< String >( "mesh" );
+       std::cout << "+ -> Loading mesh from " << meshFile << " ... " << std::endl;
+       if( ! globalMesh.load( meshFile ) )
+          return false;
+   
+       typename Meshes::DistributedMeshes::DistributedMesh<MeshType>::CoordinatesType overlap;
+       overlap.setValue(1);
+       distributedMesh.template setGlobalGrid<CommunicatorType>(globalMesh,overlap); 
+       distributedMesh.SetupGrid(*meshPointer);
+    }
+    else
+    {
+       String meshFile = parameters.getParameter< String >( "mesh" );
+       std::cout << "+ -> Loading mesh from " << meshFile << " ... " << std::endl;
+       if( ! meshPointer->load( meshFile ) )
+            return false;
+    }
 
    typedef Functions::TestFunction< MeshType::getMeshDimension(), RealType > FunctionType;
    typedef SharedPointer< FunctionType, typename MeshType::DeviceType > FunctionPointer;
@@ -87,14 +114,46 @@ bool renderFunction( const Config::ParameterContainer& parameters )
       }
       else
         std::cout << "+ -> Writing the function to " << outputFile << " ... " << std::endl;
-      if( ! meshFunction->save( outputFile) )
+
+      if(CommunicatorType::isDistributed())
+      {
+        Meshes::DistributedMeshes::DistributedGridIO<MeshFunctionType> ::save(outputFile, *meshFunction );
+      }
+      else
+      {
+        if( ! meshFunction->save( outputFile) )
          return false;
+      }
+
       time += tau;
       step ++;
    }
    return true;
 }
 
+template< typename MeshType,
+          typename RealType,
+          int xDiff,
+          int yDiff,
+          int zDiff >
+bool resolvCommunicator( const Config::ParameterContainer& parameters )
+{   
+#ifdef HAVE_MPI
+    if(Communicators::MpiCommunicator::isDistributed())
+    {
+        Communicators::NoDistrCommunicator::Finalize();
+        bool ret=renderFunction<MeshType,RealType, Communicators::MpiCommunicator,xDiff,yDiff,zDiff>(parameters); 
+        Communicators::MpiCommunicator::Finalize();
+        return ret;
+    }
+#endif
+    
+    bool ret=renderFunction<MeshType,RealType, Communicators::NoDistrCommunicator,xDiff,yDiff,zDiff>(parameters);
+    Communicators::NoDistrCommunicator::Finalize();
+    return ret;
+
+}
+
 template< typename MeshType,
           typename RealType >
 bool resolveDerivatives( const Config::ParameterContainer& parameters )
@@ -112,75 +171,75 @@ bool resolveDerivatives( const Config::ParameterContainer& parameters )
       return false;
    }
    if( xDiff == 0 && yDiff == 0 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 0, 0, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 0, 0 >( parameters );
    if( xDiff == 0 && yDiff == 0 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 0, 0, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 0, 1 >( parameters );
    if( xDiff == 0 && yDiff == 0 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 0, 0, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 0, 2 >( parameters );
    if( xDiff == 0 && yDiff == 0 && zDiff == 3 )
-      return renderFunction< MeshType, RealType, 0, 0, 3 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 0, 3 >( parameters );
    if( xDiff == 0 && yDiff == 0 && zDiff == 4 )
-      return renderFunction< MeshType, RealType, 0, 0, 4 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 0, 4 >( parameters );
    if( xDiff == 0 && yDiff == 1 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 0, 1, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 1, 0 >( parameters );
    if( xDiff == 0 && yDiff == 1 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 0, 1, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 1, 1 >( parameters );
    if( xDiff == 0 && yDiff == 1 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 0, 1, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 1, 2 >( parameters );
    if( xDiff == 0 && yDiff == 1 && zDiff == 3 )
-      return renderFunction< MeshType, RealType, 0, 1, 3 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 1, 3 >( parameters );
    if( xDiff == 0 && yDiff == 2 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 0, 2, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 2, 0 >( parameters );
    if( xDiff == 0 && yDiff == 2 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 0, 2, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 2, 1 >( parameters );
    if( xDiff == 0 && yDiff == 2 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 0, 2, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 2, 2 >( parameters );
    if( xDiff == 0 && yDiff == 3 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 0, 3, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 3, 0 >( parameters );
    if( xDiff == 0 && yDiff == 3 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 0, 3, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 3, 1 >( parameters );
    if( xDiff == 0 && yDiff == 4 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 0, 4, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 0, 4, 0 >( parameters );
    if( xDiff == 1 && yDiff == 0 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 1, 0, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 0, 0 >( parameters );
    if( xDiff == 1 && yDiff == 0 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 1, 0, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 0, 1 >( parameters );
    if( xDiff == 1 && yDiff == 0 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 1, 0, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 0, 2 >( parameters );
    if( xDiff == 1 && yDiff == 0 && zDiff == 3 )
-      return renderFunction< MeshType, RealType, 1, 0, 3 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 0, 3 >( parameters );
    if( xDiff == 1 && yDiff == 1 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 1, 1, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 1, 0 >( parameters );
    if( xDiff == 1 && yDiff == 1 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 1, 1, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 1, 1 >( parameters );
    if( xDiff == 1 && yDiff == 1 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 1, 1, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 1, 2 >( parameters );
    if( xDiff == 1 && yDiff == 2 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 1, 2, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 2, 0 >( parameters );
    if( xDiff == 1 && yDiff == 2 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 1, 2, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 2, 1 >( parameters );
    if( xDiff == 1 && yDiff == 3 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 1, 3, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 1, 3, 0 >( parameters );
    if( xDiff == 2 && yDiff == 0 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 2, 0, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 0, 0 >( parameters );
    if( xDiff == 2 && yDiff == 0 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 2, 0, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 0, 1 >( parameters );
    if( xDiff == 2 && yDiff == 0 && zDiff == 2 )
-      return renderFunction< MeshType, RealType, 2, 0, 2 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 0, 2 >( parameters );
    if( xDiff == 2 && yDiff == 1 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 2, 1, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 1, 0 >( parameters );
    if( xDiff == 2 && yDiff == 1 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 2, 1, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 1, 1 >( parameters );
    if( xDiff == 2 && yDiff == 2 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 2, 2, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 2, 2, 0 >( parameters );
    if( xDiff == 3 && yDiff == 0 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 3, 0, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 3, 0, 0 >( parameters );
    if( xDiff == 3 && yDiff == 0 && zDiff == 1 )
-      return renderFunction< MeshType, RealType, 3, 0, 1 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 3, 0, 1 >( parameters );
    if( xDiff == 3 && yDiff == 1 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 3, 1, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 3, 1, 0 >( parameters );
    if( xDiff == 4 && yDiff == 0 && zDiff == 0 )
-      return renderFunction< MeshType, RealType, 4, 0, 0 >( parameters );
+      return resolvCommunicator< MeshType, RealType, 4, 0, 0 >( parameters );
    return false;
 }
 
@@ -264,4 +323,6 @@ bool resolveMeshType( const Containers::List< String >& parsedMeshType,
 
    return false;
 }
+
+
 #endif /* TNL_INIT_H_ */
diff --git a/src/Tools/tnl-mesh-converter.cpp b/src/Tools/tnl-mesh-converter.cpp
index 0bc4e050f9e1e2ec66f88695f08673e3937bbde8..dd7ec0b2049ed7421ff6ec72ad4aeece22ff0e34 100644
--- a/src/Tools/tnl-mesh-converter.cpp
+++ b/src/Tools/tnl-mesh-converter.cpp
@@ -13,6 +13,9 @@
 #include <TNL/Meshes/Writers/VTKWriter.h>
 #include <TNL/Meshes/Writers/NetgenWriter.h>
 
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
+
 using namespace TNL;
 
 struct MeshConverterConfigTag {};
@@ -69,7 +72,8 @@ struct MeshConverter
    static bool run( const String& inputFileName, const String& outputFileName, const String& outputFormat )
    {
       Mesh mesh;
-      if( ! loadMesh( inputFileName, mesh ) ) {
+      Meshes::DistributedMeshes::DistributedMesh<Mesh> distributedMesh;
+      if( ! Meshes::loadMesh<Communicators::NoDistrCommunicator>( inputFileName, mesh, distributedMesh ) ) {
          std::cerr << "Failed to load mesh from file '" << inputFileName << "'." << std::endl;
          return false;
       }
diff --git a/src/Tools/tnl-view.h b/src/Tools/tnl-view.h
index 42f4fd1b300cf7c738efdac37713a77534ce3611..ed81bdf0878f709ee47878b7b4cbfa0add139f7f 100644
--- a/src/Tools/tnl-view.h
+++ b/src/Tools/tnl-view.h
@@ -21,6 +21,9 @@
 #include <TNL/Functions/MeshFunction.h>
 #include <TNL/Functions/VectorField.h>
 
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Meshes/TypeResolver/TypeResolver.h>
+
 using namespace TNL;
 
 bool getOutputFileName( const String& inputFileName,
@@ -424,8 +427,11 @@ struct FilesProcessor
       MeshPointer meshPointer;
       
       if( meshFile != "" )
-         if( ! loadMesh( meshFile, *meshPointer ) )
+      {
+         Meshes::DistributedMeshes::DistributedMesh<Mesh> distributedMesh;
+         if( ! Meshes::loadMesh<Communicators::NoDistrCommunicator>( meshFile, *meshPointer, distributedMesh ) )
             return false;
+      }
 
       bool checkOutputFile = parameters. getParameter< bool >( "check-output-file" );
       Containers::List< String > inputFiles = parameters. getParameter< Containers::List< String > >( "input-files" );
diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt
index fb90e6ee3d41fe06dd4e0724b2356a7f046bddad..3e17aad5d338f543c176d399e1df62b08f2fd1e8 100644
--- a/src/UnitTests/CMakeLists.txt
+++ b/src/UnitTests/CMakeLists.txt
@@ -2,6 +2,7 @@ if( WITH_TESTS STREQUAL "yes" )
 
 ADD_SUBDIRECTORY( Containers )
 ADD_SUBDIRECTORY( Matrices )
+ADD_SUBDIRECTORY( Mpi )
 ADD_SUBDIRECTORY( Meshes )
 
 ADD_EXECUTABLE( UniquePointerTest UniquePointerTest.cpp )
@@ -35,10 +36,16 @@ TARGET_LINK_LIBRARIES( ObjectTest
                            ${GTEST_BOTH_LIBRARIES} 
                            tnl )
 
+ADD_EXECUTABLE( SaveAndLoadMeshfunctionTest SaveAndLoadMeshfunctionTest.cpp )
+TARGET_COMPILE_OPTIONS( SaveAndLoadMeshfunctionTest PRIVATE ${CXX_TESTS_FLAGS} )
+TARGET_LINK_LIBRARIES( SaveAndLoadMeshfunctionTest
+                           ${GTEST_BOTH_LIBRARIES} 
+                           tnl )
 
 ADD_TEST( FileTest ${EXECUTABLE_OUTPUT_PATH}/FileTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( StringTest ${EXECUTABLE_OUTPUT_PATH}/StringTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( ObjectTest ${EXECUTABLE_OUTPUT_PATH}/ObjectTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( UniquePointerTest ${EXECUTABLE_OUTPUT_PATH}/UniquePointerTest${CMAKE_EXECUTABLE_SUFFIX} )
+ADD_TEST( SaveAndLoadMeshfunctionTest ${EXECUTABLE_OUTPUT_PATH}/SaveAndLoadMeshfunctionTest${CMAKE_EXECUTABLE_SUFFIX} )
 
 endif( WITH_TESTS STREQUAL "yes" )
diff --git a/src/UnitTests/Meshes/MeshReaderTest.h b/src/UnitTests/Meshes/MeshReaderTest.h
index 64fe92cc190656001ed066fa46d4a2e917bd4239..17bc6a3178fbd5395a7964150bc67ebf89373516 100644
--- a/src/UnitTests/Meshes/MeshReaderTest.h
+++ b/src/UnitTests/Meshes/MeshReaderTest.h
@@ -2,6 +2,7 @@
 #include <TNL/Meshes/DefaultConfig.h>
 #include <TNL/Meshes/BuildConfigTags.h>
 #include <TNL/Meshes/TypeResolver/TypeResolver.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
 
 #ifdef HAVE_VTK
 #include <TNL/Meshes/Readers/VTKReader_libvtk.h>
@@ -138,7 +139,8 @@ public:
       timer.start();
 
       MeshType mesh;
-      if( ! loadMesh( fileName, mesh ) )
+      Meshes::DistributedMeshes::DistributedMesh<MeshType> distributedMesh;
+      if( ! loadMesh<Communicators::NoDistrCommunicator>( fileName, mesh, distributedMesh ) )
          return false;
 
       timer.stop();
diff --git a/src/UnitTests/Mpi/CMakeLists.txt b/src/UnitTests/Mpi/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5dca444aa40876bd5df0286b3393b7934168149b
--- /dev/null
+++ b/src/UnitTests/Mpi/CMakeLists.txt
@@ -0,0 +1,54 @@
+if( ${CXX_COMPILER_NAME} STREQUAL "mpic++" )
+ADD_EXECUTABLE( DistributedGridTest_1D DistributedGridTest_1D.cpp )
+   TARGET_COMPILE_OPTIONS( DistributedGridTest_1D PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( DistributedGridTest_1D
+                              ${GTEST_BOTH_LIBRARIES}
+                              tnl )
+
+ADD_EXECUTABLE( DistributedGridTest_2D DistributedGridTest_2D.cpp )
+   TARGET_COMPILE_OPTIONS( DistributedGridTest_2D PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( DistributedGridTest_2D
+                              ${GTEST_BOTH_LIBRARIES}
+                              tnl)
+
+ADD_EXECUTABLE( DistributedGridTest_3D DistributedGridTest_3D.cpp )
+   TARGET_COMPILE_OPTIONS( DistributedGridTest_3D PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( DistributedGridTest_3D
+                              ${GTEST_BOTH_LIBRARIES}
+                              tnl )
+
+ADD_EXECUTABLE( CopyEntitesTest CopyEntitiesTest.cpp )
+   TARGET_COMPILE_OPTIONS( CopyEntitesTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( CopyEntitesTest
+                              ${GTEST_BOTH_LIBRARIES}
+                              tnl )
+
+ADD_EXECUTABLE( DistributedGridIOTest DistributedGridIOTest.cpp )
+   TARGET_COMPILE_OPTIONS( DistributedGridIOTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( DistributedGridIOTest
+                              ${GTEST_BOTH_LIBRARIES}
+                              tnl )
+
+ADD_TEST( NAME CopyEntitesTest COMMAND ${EXECUTABLE_OUTPUT_PATH}/CopyEntitesTest${CMAKE_EXECUTABLE_SUFFIX} )
+   
+SET (mpi_test_parameters_1d -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedGridTest_1D${CMAKE_EXECUTABLE_SUFFIX}")
+ADD_TEST( NAME DistributedGridTest_1D COMMAND "mpirun" ${mpi_test_parameters_1d})
+
+SET (mpi_test_parameters_2d -np 9 -H localhost:9 "${EXECUTABLE_OUTPUT_PATH}/DistributedGridTest_2D${CMAKE_EXECUTABLE_SUFFIX}")
+ADD_TEST( NAME DistributedGridTest_2D COMMAND "mpirun" ${mpi_test_parameters_2d})
+
+SET (mpi_test_parameters_3d -np 27 -H localhost:27 "${EXECUTABLE_OUTPUT_PATH}/DistributedGridTest_3D${CMAKE_EXECUTABLE_SUFFIX}")
+ADD_TEST( NAME DistributedGridTest_3D COMMAND "mpirun" ${mpi_test_parameters_3d})
+
+SET (mpi_test_parameters_IO -np 4 "${EXECUTABLE_OUTPUT_PATH}/DistributedGridIOTest${CMAKE_EXECUTABLE_SUFFIX}")
+ADD_TEST( NAME DistributedGridIOTest COMMAND "mpirun" ${mpi_test_parameters_IO})
+
+IF( BUILD_CUDA )
+    CUDA_ADD_EXECUTABLE( GPUDistributedGridIOTest GPUDistributedGridIOTest.cu OPTIONS ${CXX_TESTS_FLAGS})
+    TARGET_LINK_LIBRARIES( GPUDistributedGridIOTest 
+                                    ${GTEST_BOTH_LIBRARIES}
+                                    tnl )   
+ENDIF( BUILD_CUDA )  
+
+endif()
+
diff --git a/src/UnitTests/Mpi/CopyEntitiesTest.cpp b/src/UnitTests/Mpi/CopyEntitiesTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae0be78b99e8c46bb832dbad640c8bcc935a7a80
--- /dev/null
+++ b/src/UnitTests/Mpi/CopyEntitiesTest.cpp
@@ -0,0 +1,237 @@
+/***************************************************************************
+                          CopyEntitiesTest.cpp  -  description
+                             -------------------
+    begin                : Aug 30, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+#include <TNL/Meshes/DistributedMeshes/CopyEntitiesHelper.h>
+#include <TNL/Functions/MeshFunction.h>
+
+
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+#include "Functions.h"
+
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Meshes::DistributedMeshes;
+
+//================================TEST RESULT============================================
+template <typename MeshFunctionType,
+		  int dim=MeshFunctionType::getMeshDimension()>
+class TestMovedMeshfunction
+{
+	public:
+		static void Test(MeshFunctionType &meshFunction)
+		{};
+};
+
+template <typename MeshFunctionType>
+class TestMovedMeshfunction<MeshFunctionType,1>
+{
+	public:
+		static void Test(MeshFunctionType &meshFunction)
+		{
+
+			for(int i=0;i<meshFunction.getData().getSize();i++)
+				EXPECT_EQ( meshFunction.getData()[i], i+1) << "Copy entities Failed for: "<< i;
+		}
+};
+
+template <typename MeshFunctionType>
+class TestMovedMeshfunction<MeshFunctionType,2>
+{
+	public:
+		static void Test(MeshFunctionType &meshFunction)
+		{
+			typename MeshFunctionType::MeshType::Cell entity(meshFunction.getMesh());
+			auto size=meshFunction.getMesh().getDimensions();
+			for(int j=0;j<size.y();j++)
+				for(int i=0;i<size.x();i++)
+				{
+				    entity.getCoordinates().x()=i;
+					entity.getCoordinates().y()=j;			
+				    entity.refresh();
+					EXPECT_EQ( meshFunction.getData()[entity.getIndex()], 10*(j+1)+(i+1)) << "Copy entities Failed for: "<< i;
+				}				
+		};
+};
+
+template <typename MeshFunctionType>
+class TestMovedMeshfunction<MeshFunctionType,3>
+{
+	public:
+		static void Test(MeshFunctionType &meshFunction)
+		{
+			typename MeshFunctionType::MeshType::Cell entity(meshFunction.getMesh());
+			auto size=meshFunction.getMesh().getDimensions();
+			for(int k=0;k<size.z();k++)
+				for(int j=0;j<size.y();j++)
+					for(int i=0;i<size.x();i++)
+					{
+				    	entity.getCoordinates().x()=i;
+						entity.getCoordinates().y()=j;
+						entity.getCoordinates().z()=k;			
+				    	entity.refresh();
+						EXPECT_EQ( meshFunction.getData()[entity.getIndex()], 100*(k+1)+10*(j+1)+(i+1)) << "Copy entities Failed for: "<< i;
+					}				
+		};
+};
+
+//================================SET INPUT============================================
+
+template <typename MeshFunctionType,
+		  int dim=MeshFunctionType::getMeshDimension()>
+class EvalMeshFunction
+{
+	public:
+		static void Eval(MeshFunctionType &meshFunction)
+		{};
+};
+
+template <typename MeshFunctionType>
+class EvalMeshFunction<MeshFunctionType,1>
+{
+	public:
+		static void Eval(MeshFunctionType &meshFunction)
+		{
+			for(int i=0;i<meshFunction.getData().getSize();i++)
+				meshFunction.getData()[i]=i;
+		}
+};
+
+template <typename MeshFunctionType>
+class EvalMeshFunction<MeshFunctionType,2>
+{
+	public:
+		static void Eval(MeshFunctionType &meshFunction)
+		{
+			typename MeshFunctionType::MeshType::Cell entity(meshFunction.getMesh());
+			auto size=meshFunction.getMesh().getDimensions();
+			for(int j=0;j<size.y();j++)
+				for(int i=0;i<size.x();i++)
+				{
+				    entity.getCoordinates().x()=i;
+					entity.getCoordinates().y()=j;			
+				    entity.refresh();
+					meshFunction.getData()[entity.getIndex()]= 10*j+i;
+				}				
+		};
+};
+
+template <typename MeshFunctionType>
+class EvalMeshFunction<MeshFunctionType,3>
+{
+	public:
+		static void Eval(MeshFunctionType &meshFunction)
+		{
+			typename MeshFunctionType::MeshType::Cell entity(meshFunction.getMesh());
+			auto size=meshFunction.getMesh().getDimensions();
+			for(int k=0;k<size.z();k++)
+				for(int j=0;j<size.y();j++)
+					for(int i=0;i<size.x();i++)
+					{
+				    	entity.getCoordinates().x()=i;
+						entity.getCoordinates().y()=j;
+						entity.getCoordinates().z()=k;			
+				    	entity.refresh();
+						meshFunction.getData()[entity.getIndex()]=100*k+10*j+i;
+					}				
+		};
+};
+
+
+//=====================================TEST CLASS==============================================
+
+template <int dim>
+class TestCopyEntities
+{
+	public:
+		static void Test()
+		{
+			typedef Grid<dim,double,Host,int> MeshType;
+			typedef MeshFunction<MeshType> MeshFunctionType;
+			typedef Vector<double,Host,int> DofType;
+
+			typedef typename MeshType::PointType PointType; 
+			typedef typename MeshType::CoordinatesType CoordinatesType;
+			typedef typename MeshType::Cell Cell;
+
+			PointType origin;
+			PointType proportions;
+			SharedPointer<MeshType> gridptr;
+
+			origin.setValue(-0.5);
+			proportions.setValue(10);
+
+			gridptr->setDimensions(proportions);
+			gridptr->setDomain(origin,proportions);
+	
+			DofType inputDof(gridptr-> template getEntitiesCount< Cell >());
+
+			MeshFunctionType inputMeshFunction;
+			inputMeshFunction.bind(gridptr,inputDof); 
+	
+			EvalMeshFunction<MeshFunctionType> :: Eval(inputMeshFunction);
+
+
+			PointType originOut;
+			PointType proportionsOut;
+			SharedPointer<MeshType> gridOutPtr;
+
+			originOut.setValue(0.5);	
+			proportionsOut.setValue(8);		
+			gridOutPtr->setDimensions(proportionsOut);
+			gridOutPtr->setDomain(originOut,proportionsOut);
+			DofType outDof(gridOutPtr-> template getEntitiesCount< Cell >());
+
+			MeshFunctionType outputMeshFunction;
+			outputMeshFunction.bind(gridOutPtr,outDof); 
+
+			CoordinatesType zero;
+			zero.setValue(0);
+			CoordinatesType begin;
+			begin.setValue(1);
+			CoordinatesType size;
+			size.setValue(8);
+
+			CopyEntitiesHelper< MeshFunctionType >::Copy(inputMeshFunction,outputMeshFunction, begin,zero, size);
+
+			TestMovedMeshfunction<MeshFunctionType>::Test(outputMeshFunction);
+		};
+};
+
+TEST( CopyEntitiesTest, 1D )
+{
+	TestCopyEntities<1>::Test();
+}
+
+/*TEST( CopyEntitiesTest, 2D )
+{
+	TestCopyEntities<2>::Test();
+}
+
+TEST( CopyEntitiesTest, 3D )
+{
+	TestCopyEntities<3>::Test();
+}*/
+
+
+#endif
+
+#include "../GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   throw GtestMissingError();
+#endif
+}
+
diff --git a/src/UnitTests/Mpi/DistributedGridIOTest.cpp b/src/UnitTests/Mpi/DistributedGridIOTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b0f51781517e000ee4983b6cefebb4e4e1479f00
--- /dev/null
+++ b/src/UnitTests/Mpi/DistributedGridIOTest.cpp
@@ -0,0 +1,110 @@
+
+#ifdef HAVE_GTEST
+  
+#include <gtest/gtest.h>
+
+#ifdef HAVE_MPI
+
+#include "DistributedGridIOTest.h"
+
+TEST( DistributedGridIO, Save_1D )
+{
+    TestDistributedGridIO<1,Host>::TestSave();
+}
+
+TEST( DistributedGridIO, Save_2D )
+{
+    TestDistributedGridIO<2,Host>::TestSave();
+}
+
+TEST( DistributedGridIO, Save_3D )
+{
+    TestDistributedGridIO<3,Host>::TestSave();
+}
+
+TEST( DistributedGridIO, Load_1D )
+{
+    TestDistributedGridIO<1,Host>::TestLoad();
+}
+
+TEST( DistributedGridIO, Load_2D )
+{
+    TestDistributedGridIO<2,Host>::TestLoad();
+}
+
+TEST( DistributedGridIO, Load_3D )
+{
+    TestDistributedGridIO<3,Host>::TestLoad();
+}
+
+#else
+TEST(NoMPI, NoTest)
+{
+    ASSERT_TRUE(true) << ":-(";
+}
+#endif
+
+#endif
+
+#if (defined(HAVE_GTEST) && defined(HAVE_MPI))
+#include <sstream>
+
+  class MinimalistBuffredPrinter : public ::testing::EmptyTestEventListener {
+      
+  private:
+      std::stringstream sout;
+      
+  public:
+      
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      sout<< test_info.test_case_name() <<"." << test_info.name() << " Start." <<std::endl;
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") 
+              << test_part_result.file_name() << " "
+              << test_part_result.line_number() <<std::endl
+              << test_part_result.summary() <<std::endl;
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) 
+    {
+        int rank=CommunicatorType::GetRank();
+        sout<< test_info.test_case_name() <<"." << test_info.name() << " End." <<std::endl;
+        std::cout << rank << ":" << std::endl << sout.str()<< std::endl;
+        sout.str( std::string() );
+        sout.clear();
+    }
+  };
+#endif
+
+#include "../GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+
+    #ifdef HAVE_MPI
+       ::testing::TestEventListeners& listeners =
+          ::testing::UnitTest::GetInstance()->listeners();
+
+       delete listeners.Release(listeners.default_result_printer());
+       listeners.Append(new MinimalistBuffredPrinter);
+
+       CommunicatorType::Init(argc,argv, false);
+    #endif
+       int result= RUN_ALL_TESTS();
+
+    #ifdef HAVE_MPI
+       CommunicatorType::Finalize();
+    #endif
+       return result;
+#else
+   
+   throw GtestMissingError();
+#endif
+}
diff --git a/src/UnitTests/Mpi/DistributedGridIOTest.h b/src/UnitTests/Mpi/DistributedGridIOTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a2874665eb55bcf29fb67aa863b2b461356b5bc
--- /dev/null
+++ b/src/UnitTests/Mpi/DistributedGridIOTest.h
@@ -0,0 +1,364 @@
+/***************************************************************************
+                          CopyEntitiesTest.cpp  -  description
+                             -------------------
+    begin                : Nov 1, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedGridIO.h>
+
+
+#include "Functions.h"
+
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+using namespace TNL::Meshes::DistributedMeshes;
+
+
+//================Parameters===================================
+template <int dim, typename Device>
+class ParameterProvider
+{
+    public:
+
+    typedef Grid<dim,double,Device,int> MeshType;
+    typedef typename MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshType::PointType PointType;
+
+    PointType getOrigin(int rank)
+    {
+    };
+
+    PointType getProportions(int rank)
+    {
+    };
+
+    int* getDistr(void)
+    {
+        return NULL;
+    };
+};
+
+template<typename Device>
+class ParameterProvider<1,Device>
+{
+    public:
+
+    int distr[1];
+
+    typedef Grid<1,double,Device,int> MeshType;
+    typedef typename MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshType::PointType PointType;
+
+    PointType getOrigin(int rank)
+    {
+        if(rank==0)
+            return PointType(-0.5);
+        if(rank==1)
+            return PointType(4.5);
+        if(rank==2)
+            return PointType(9.5);
+        if(rank==3)
+            return PointType(14.5);
+
+        return PointType(0);
+    };
+
+    PointType getProportions(int rank)
+    {
+        if(rank==0)
+            return PointType(5);
+        if(rank==1)
+            return PointType(5);
+        if(rank==2)
+            return PointType(5);
+        if(rank==3)
+            return PointType(5);
+        return PointType(0);
+    };
+
+    int* getDistr()
+    {
+        distr[0]=4;
+        return distr;
+    };
+};
+
+template<typename Device>
+class ParameterProvider<2,Device>
+{
+    public:
+
+    int distr[2];
+
+    typedef Grid<2,double,Device,int> MeshType;
+    typedef typename MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshType::PointType PointType;
+
+    PointType getOrigin(int rank)
+    {
+        if(rank==0)
+            return PointType(-0.5,-0.5);
+        if(rank==1)
+            return PointType(9.5,-0.5);
+        if(rank==2)
+            return PointType(-0.5,9.5);
+        if(rank==3)
+            return PointType(9.5,9.5);
+
+        return PointType(0,0);
+    };
+
+    PointType getProportions(int rank)
+    {
+        if(rank==0)
+            return PointType(10,10);
+        if(rank==1)
+            return PointType(10,10);
+        if(rank==2)
+            return PointType(10,10);
+        if(rank==3)
+            return PointType(10,10);
+        return PointType(0,0);
+    };
+
+    int* getDistr()
+    {
+        distr[0]=2;
+        distr[1]=2;
+        return distr;
+    };
+};
+
+template<typename Device>
+class ParameterProvider<3,Device>
+{
+    public:
+
+    int distr[3];
+
+    typedef Grid<3,double,Device,int> MeshType;
+    typedef typename MeshType::CoordinatesType CoordinatesType;
+    typedef typename MeshType::PointType PointType;
+
+    PointType getOrigin(int rank)
+    {
+        if(rank==0)
+            return PointType(-0.5,-0.5,-0.5);
+        if(rank==1)
+            return PointType(9.5,-0.5,-0.5);
+        if(rank==2)
+            return PointType(-0.5,9.5,-0.5);
+        if(rank==3)
+            return PointType(9.5,9.5,-0.5);
+
+        return PointType(0,0,0);
+    };
+
+    PointType getProportions(int rank)
+    {
+        if(rank==0)
+            return PointType(10,10,20);
+        if(rank==1)
+            return PointType(10,10,20);
+        if(rank==2)
+            return PointType(10,10,20);
+        if(rank==3)
+            return PointType(10,10,20);
+        return PointType(0,0,0);
+    };
+
+    int* getDistr()
+    {
+        distr[0]=2;
+        distr[1]=2;
+        distr[2]=1;
+        return distr;
+    };
+};
+
+//------------------------------------------------------------------------------
+
+typedef MpiCommunicator CommunicatorType;
+
+template <int dim, typename Device>
+class TestDistributedGridIO{
+    public:
+
+    typedef Grid<dim,double,Device,int> MeshType;
+    typedef MeshFunction<MeshType> MeshFunctionType;
+    typedef Vector<double,Device,int> DofType;
+    typedef typename MeshType::Cell Cell;
+    typedef typename MeshType::IndexType IndexType; 
+    typedef typename MeshType::PointType PointType; 
+    typedef DistributedMesh<MeshType> DistributedGridType;
+
+    typedef typename DistributedGridType::CoordinatesType CoordinatesType;
+    typedef LinearFunction<double,dim> LinearFunctionType;
+
+    static void TestSave()
+    {
+        SharedPointer< LinearFunctionType, Device > linearFunctionPtr;
+        MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;    
+        
+        ParameterProvider<dim,Device> parametry;
+        
+        //save distributed meshfunction into files
+        PointType globalOrigin;
+        globalOrigin.setValue(-0.5);
+
+        PointType globalProportions;
+        globalProportions.setValue(20);
+
+
+        MeshType globalGrid;
+        globalGrid.setDimensions(globalProportions);
+        globalGrid.setDomain(globalOrigin,globalProportions);
+        
+        int *distr=parametry.getDistr();
+
+        CoordinatesType overlap;
+        overlap.setValue(1);
+        DistributedGridType distrgrid;
+        distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap,distr);
+
+        std::cout << distrgrid.printProcessDistr() <<std::endl;
+
+        SharedPointer<MeshType> gridptr;
+        SharedPointer<MeshFunctionType> meshFunctionptr;
+        distrgrid.SetupGrid(*gridptr);
+       
+        DofType dof(gridptr->template getEntitiesCount< Cell >());
+        dof.setValue(0);
+        meshFunctionptr->bind(gridptr,dof);
+            
+        linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);
+ 
+        String FileName=String("/tmp/test-file.tnl");
+        DistributedGridIO<MeshFunctionType> ::save(FileName, *meshFunctionptr );
+
+
+       //create similar local mesh function and evaluate linear function on it
+        PointType localOrigin=parametry.getOrigin(CommunicatorType::GetRank());        
+        PointType localProportions=parametry.getProportions(CommunicatorType::GetRank());;
+            
+        SharedPointer<MeshType>  localGridptr;
+        localGridptr->setDimensions(localProportions);
+        localGridptr->setDomain(localOrigin,localProportions);
+
+        DofType localDof(localGridptr->template getEntitiesCount< Cell >());
+
+        SharedPointer<MeshFunctionType> localMeshFunctionptr;
+        localMeshFunctionptr->bind(localGridptr,localDof);
+        linearFunctionEvaluator.evaluateAllEntities(localMeshFunctionptr , linearFunctionPtr);
+
+        //load other meshfunction on same localgrid from created file
+        SharedPointer<MeshType>  loadGridptr;
+        loadGridptr->setDimensions(localProportions);
+        loadGridptr->setDomain(localOrigin,localProportions);
+
+        DofType loadDof(localGridptr->template getEntitiesCount< Cell >());
+        SharedPointer<MeshFunctionType> loadMeshFunctionptr;
+        loadMeshFunctionptr->bind(loadGridptr,loadDof);
+
+        loadDof.setValue(-1);
+        
+        File file;
+        file.open( FileName+String("-")+distrgrid.printProcessCoords(), IOMode::read );
+        loadMeshFunctionptr->boundLoad(file);
+        file.close();
+
+        for(int i=0;i<localDof.getSize();i++)
+        {
+            EXPECT_EQ( localDof.getElement(i), loadDof.getElement(i)) << "Compare Loaded and evaluated Dof Failed for: "<< i;
+        }
+    }
+    
+    static void TestLoad()
+    {
+        SharedPointer< LinearFunctionType, Device > linearFunctionPtr;
+        MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;    
+        
+        ParameterProvider<dim,Device> parametry;
+
+        //Crete distributed grid            
+        PointType globalOrigin;
+        globalOrigin.setValue(-0.5);
+
+        PointType globalProportions;
+        globalProportions.setValue(20);
+
+        MeshType globalGrid;
+        globalGrid.setDimensions(globalProportions);
+        globalGrid.setDomain(globalOrigin,globalProportions);
+        
+        int *distr=parametry.getDistr();
+
+        CoordinatesType overlap;
+        overlap.setValue(1);
+        DistributedGridType distrgrid;
+        distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap, distr);
+
+        //save files from local mesh        
+        PointType localOrigin=parametry.getOrigin(CommunicatorType::GetRank());        
+        PointType localProportions=parametry.getProportions(CommunicatorType::GetRank());;
+            
+        SharedPointer<MeshType> localGridptr;
+        localGridptr->setDimensions(localProportions);
+        localGridptr->setDomain(localOrigin,localProportions);
+
+        DofType localDof(localGridptr->template getEntitiesCount< Cell >());
+
+        SharedPointer<MeshFunctionType> localMeshFunctionptr;
+        localMeshFunctionptr->bind(localGridptr,localDof);
+        linearFunctionEvaluator.evaluateAllEntities(localMeshFunctionptr , linearFunctionPtr);
+
+
+        String FileName=String("/tmp/test-file.tnl");
+        File file;
+        file.open( FileName+String("-")+distrgrid.printProcessCoords(), IOMode::write );        
+        localMeshFunctionptr->save(file);
+        file.close();
+
+
+
+        //Crete "distributedgrid driven" grid filed by load
+        SharedPointer<MeshType> loadGridptr;
+        SharedPointer<MeshFunctionType> loadMeshFunctionptr;
+        distrgrid.SetupGrid(*loadGridptr);
+        
+        DofType loadDof(loadGridptr->template getEntitiesCount< Cell >());
+        loadDof.setValue(0);
+        loadMeshFunctionptr->bind(loadGridptr,loadDof);
+
+        DistributedGridIO<MeshFunctionType> ::load(FileName, *loadMeshFunctionptr );
+
+        loadMeshFunctionptr->template Synchronize<CommunicatorType>(); //need synchronization for overlaps to be filled corectly in loadDof
+
+
+        //Crete "distributedgrid driven" grid filed by evaluated linear function
+        SharedPointer<MeshType> gridptr;
+        SharedPointer<MeshFunctionType> meshFunctionptr;
+        distrgrid.SetupGrid(*gridptr);
+        
+        DofType dof(gridptr->template getEntitiesCount< Cell >());
+        dof.setValue(-1);
+        meshFunctionptr->bind(gridptr,dof);
+        
+        linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);        
+        meshFunctionptr->template Synchronize<CommunicatorType>();
+
+        for(int i=0;i<dof.getSize();i++)
+        {
+            EXPECT_EQ( dof.getElement(i), loadDof.getElement(i)) << "Compare Loaded and evaluated Dof Failed for: "<< i;
+        }       
+    }
+};
+
diff --git a/src/UnitTests/Mpi/DistributedGridTest_1D.cpp b/src/UnitTests/Mpi/DistributedGridTest_1D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ef560fc0fbe063e940ce976773a949ec0251f1a2
--- /dev/null
+++ b/src/UnitTests/Mpi/DistributedGridTest_1D.cpp
@@ -0,0 +1,301 @@
+/***************************************************************************
+                          DistributedGridTest.cpp  -  description
+                             -------------------
+    begin                : Sep 6, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+
+#ifdef HAVE_GTEST  
+#include <gtest/gtest.h>
+
+#ifdef HAVE_MPI    
+
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+
+#include "Functions.h"
+
+using namespace TNL;
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Meshes::DistributedMeshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+
+
+template<typename DofType>
+void setDof_1D(DofType &dof, typename DofType::RealType value)
+{
+    for(int i=0;i<dof.getSize();i++)
+        dof[i]=value;
+}
+
+template<typename DofType>
+void check_Boundary_1D(int rank, int nproc, DofType dof, typename DofType::RealType expectedValue)
+{
+    if(rank==0)//Left
+    {
+        EXPECT_EQ( dof[0], expectedValue) << "Left boundary test failed";
+        return;
+    }
+    
+    if(rank==(nproc-1))//Right
+    {
+        EXPECT_EQ( dof[dof.getSize()-1], expectedValue) << "Right boundary test failed";
+        return;
+    }
+    
+};
+
+template<typename DofType>
+void check_Overlap_1D(int rank, int nproc, DofType dof, typename DofType::RealType expectedValue)
+{
+    if(rank==0)//Left
+    {
+        EXPECT_EQ( dof[dof.getSize()-1], expectedValue) << "Left boundary node overlap test failed";
+        return;
+    }
+    
+    if(rank==(nproc-1))
+    {
+        EXPECT_EQ( dof[0], expectedValue) << "Right boundary node overlap test failed";
+        return;
+    }
+    
+    EXPECT_EQ( dof[0], expectedValue) << "left overlap test failed";
+    EXPECT_EQ( dof[dof.getSize()-1], expectedValue)<< "right overlap test failed";    
+};
+
+template<typename DofType>
+void check_Inner_1D(int rank, int nproc, DofType dof, typename DofType::RealType expectedValue)
+{
+    for(int i=1;i<(dof.getSize()-2);i++) //buď je vlevo hranice, nebo overlap
+        EXPECT_EQ( dof[i], expectedValue) << " "<< i;
+};
+
+/*
+ * Light check of 1D distriover grid and its synchronization. 
+ * Number of process is not limitated.
+ * Overlap is limitated to 1
+ * Only double is tested as dof Real type -- it may be changed, extend test
+ * Global size is hardcoded as 10 -- it can be changed, extend test
+ */
+
+typedef MpiCommunicator CommunicatorType;
+typedef Grid<1,double,Host,int> MeshType;
+typedef MeshFunction<MeshType> MeshFunctionType;
+typedef Vector<double,Host,int> DofType;
+typedef typename MeshType::Cell Cell;
+typedef typename MeshType::IndexType IndexType; 
+typedef typename MeshType::PointType PointType; 
+typedef DistributedMesh<MeshType> DistributedMeshType;
+     
+class DistributedGirdTest_1D : public ::testing::Test {
+ protected:
+
+    static DistributedMesh<MeshType> *distrgrid;
+    static DofType *dof;
+
+    static SharedPointer<MeshType> gridptr;
+    static SharedPointer<MeshFunctionType> meshFunctionptr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,1> > constFunctionEvaluator;
+    static SharedPointer< ConstFunction<double,1>, Host > constFunctionPtr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,1> > linearFunctionEvaluator;
+    static SharedPointer< LinearFunction<double,1>, Host > linearFunctionPtr;
+
+    static int rank;
+    static int nproc;    
+     
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+      
+    int size=10;
+    rank=CommunicatorType::GetRank();
+    nproc=CommunicatorType::GetSize();
+    
+    PointType globalOrigin;
+    PointType globalProportions;
+    MeshType globalGrid;
+    
+    globalOrigin.x()=-0.5;    
+    globalProportions.x()=size;
+
+        
+    globalGrid.setDimensions(size);
+    globalGrid.setDomain(globalOrigin,globalProportions);
+    
+    typename DistributedMeshType::CoordinatesType overlap;
+    overlap.setValue(1);
+    distrgrid=new DistributedMeshType();
+    distrgrid->template setGlobalGrid<CommunicatorType>(globalGrid,overlap);
+    
+    distrgrid->SetupGrid(*gridptr);
+    dof=new DofType(gridptr->template getEntitiesCount< Cell >());
+    
+    meshFunctionptr->bind(gridptr,*dof);
+    
+    constFunctionPtr->Number=rank;
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+      delete dof;
+      delete distrgrid;
+  }
+};
+
+DistributedMesh<MeshType> *DistributedGirdTest_1D::distrgrid=NULL;
+DofType *DistributedGirdTest_1D::dof=NULL;
+SharedPointer<MeshType> DistributedGirdTest_1D::gridptr;
+SharedPointer<MeshFunctionType> DistributedGirdTest_1D::meshFunctionptr;
+MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,1> > DistributedGirdTest_1D::constFunctionEvaluator;
+SharedPointer< ConstFunction<double,1>, Host > DistributedGirdTest_1D::constFunctionPtr;
+MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,1> > DistributedGirdTest_1D::linearFunctionEvaluator;
+SharedPointer< LinearFunction<double,1>, Host > DistributedGirdTest_1D::linearFunctionPtr;
+int DistributedGirdTest_1D::rank;
+int DistributedGirdTest_1D::nproc;
+
+TEST_F(DistributedGirdTest_1D, evaluateAllEntities)
+{
+    //Check Traversars
+    //All entities, witout overlap
+    setDof_1D(*dof,-1);
+    constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+    //Printer<MeshType,DofType>::print_dof(rank,*gridptr,*dof);
+    check_Boundary_1D(rank, nproc, *dof, rank);
+    check_Overlap_1D(rank, nproc, *dof, -1);
+    check_Inner_1D(rank, nproc, *dof, rank);
+}
+
+TEST_F(DistributedGirdTest_1D, evaluateBoundaryEntities)
+{
+    //Boundary entities, witout overlap
+    setDof_1D(*dof,-1);
+    constFunctionEvaluator.evaluateBoundaryEntities( meshFunctionptr , constFunctionPtr );
+    check_Boundary_1D(rank, nproc, *dof, rank);
+    check_Overlap_1D(rank, nproc, *dof, -1);
+    check_Inner_1D(rank, nproc, *dof, -1);
+}
+
+TEST_F(DistributedGirdTest_1D, evaluateInteriorEntities)
+{
+    //Inner entities, witout overlap
+    setDof_1D(*dof,-1);
+    constFunctionEvaluator.evaluateInteriorEntities( meshFunctionptr , constFunctionPtr );
+    check_Boundary_1D(rank, nproc, *dof, -1);
+    check_Overlap_1D(rank, nproc, *dof, -1);
+    check_Inner_1D(rank, nproc, *dof, rank);
+}    
+
+TEST_F(DistributedGirdTest_1D, LinearFunctionTest)
+{
+    //fill meshfunction with linear function (physical center of cell corresponds with its coordinates in grid) 
+    setDof_1D(*dof,-1);
+    linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr, linearFunctionPtr);
+    meshFunctionptr->template Synchronize<CommunicatorType>();
+
+    auto entite= gridptr->template getEntity< Cell >(0);
+    entite.refresh();
+    EXPECT_EQ(meshFunctionptr->getValue(entite), (*linearFunctionPtr)(entite)) << "Linear function Overlap error on left Edge.";
+
+    auto entite2= gridptr->template getEntity< Cell >((*dof).getSize()-1);
+    entite2.refresh();
+    EXPECT_EQ(meshFunctionptr->getValue(entite), (*linearFunctionPtr)(entite)) << "Linear function Overlap error on right Edge.";
+}
+
+TEST_F(DistributedGirdTest_1D, SynchronizerNeighborTest)
+{
+    setDof_1D(*dof,-1);
+    constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+    meshFunctionptr->template Synchronize<CommunicatorType>();
+
+    if(rank!=0)
+        EXPECT_EQ((*dof)[0],rank-1)<< "Left Overlap was filled by wrong process.";
+    if(rank!=nproc-1)
+        EXPECT_EQ((*dof)[dof->getSize()-1],rank+1)<< "Right Overlap was filled by wrong process.";
+}
+    
+#else
+TEST(NoMPI, NoTest)
+{
+    ASSERT_TRUE(true) << ":-(";
+}
+#endif
+
+#endif
+
+
+#if (defined(HAVE_GTEST) && defined(HAVE_MPI))
+#include <sstream>
+
+  class MinimalistBuffredPrinter : public ::testing::EmptyTestEventListener {
+      
+  private:
+      std::stringstream sout;
+      
+  public:
+      
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      sout<< test_info.test_case_name() <<"." << test_info.name() << " Start." <<std::endl;
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") 
+              << test_part_result.file_name() << " "
+              << test_part_result.line_number() <<std::endl
+              << test_part_result.summary() <<std::endl;
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) 
+    {
+        int rank=MPI::COMM_WORLD.Get_rank();
+        sout<< test_info.test_case_name() <<"." << test_info.name() << " End." <<std::endl;
+        std::cout << rank << ":" << std::endl << sout.str()<< std::endl;
+        sout.str( std::string() );
+        sout.clear();
+    }
+  };
+#endif
+
+#include "../../src/UnitTests/GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+
+    #ifdef HAVE_MPI
+       ::testing::TestEventListeners& listeners =
+          ::testing::UnitTest::GetInstance()->listeners();
+
+       delete listeners.Release(listeners.default_result_printer());
+       listeners.Append(new MinimalistBuffredPrinter);
+
+       CommunicatorType::Init(argc,argv);
+    #endif
+       int result= RUN_ALL_TESTS();
+
+    #ifdef HAVE_MPI
+       CommunicatorType::Finalize();
+    #endif
+       return result;
+#else
+   
+   throw GtestMissingError();
+#endif
+}
+
+
diff --git a/src/UnitTests/Mpi/DistributedGridTest_2D.cpp b/src/UnitTests/Mpi/DistributedGridTest_2D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3657cede1f0e175d91b9a96d45731dd1bfe2be1
--- /dev/null
+++ b/src/UnitTests/Mpi/DistributedGridTest_2D.cpp
@@ -0,0 +1,572 @@
+/***************************************************************************
+                          DistributedGridTest.cpp  -  description
+                             -------------------
+    begin                : Sep 6, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+#ifdef HAVE_MPI    
+
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+
+#include "Functions.h"
+
+using namespace TNL;
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+using namespace TNL::Meshes::DistributedMeshes;
+
+ 
+
+template<typename DofType>
+void setDof_2D(DofType &dof, typename DofType::RealType value)
+{
+    for(int i=0;i<dof.getSize();i++)
+        dof[i]=value;
+}
+
+template<typename DofType,typename GridType>
+void checkLeftEdge(GridType &grid, DofType &dof, bool with_first, bool with_last, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int begin=0;
+    int end=maxy;
+    if(!with_first)
+        begin++;
+    if(!with_last)
+        end--;
+    
+    for(int i=begin;i<end;i++) //posledni je overlap
+            EXPECT_EQ( dof[maxx*i], expectedValue) << "Left Edge test failed " << i<<" " << maxx << " "<< maxy;
+}
+
+template<typename DofType,typename GridType>
+void checkRightEdge(GridType &grid, DofType &dof, bool with_first, bool with_last, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int begin=0;
+    int end=maxy;
+    if(!with_first)
+        begin++;
+    if(!with_last)
+        end--;
+    
+    for(int i=begin;i<end;i++) 
+            EXPECT_EQ( dof[maxx*i+(maxx-1)], expectedValue) << "Right Edge test failed " << i <<" " << maxx << " "<< maxy;
+}
+
+template<typename DofType,typename GridType>
+void checkUpEdge(GridType &grid, DofType &dof, bool with_first, bool with_last, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int begin=0;
+    int end=maxx;
+    if(!with_first)
+        begin++;
+    if(!with_last)
+        end--;
+    
+    for(int i=begin;i<end;i++) //posledni je overlap
+            EXPECT_EQ( dof[i], expectedValue) << "Up Edge test failed " << i<<" " << maxx << " "<< maxy;
+}
+
+template<typename DofType,typename GridType>
+void checkDownEdge(GridType &grid, DofType &dof, bool with_first, bool with_last, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int begin=0;
+    int end=maxx;
+    if(!with_first)
+        begin++;
+    if(!with_last)
+        end--;
+    
+    for(int i=begin;i<end;i++) //posledni je overlap
+            EXPECT_EQ( dof[maxx*(maxy-1)+i], expectedValue) << "Down Edge test failed " << i<<" " << maxx << " "<< maxy;
+}
+
+template<typename DofType,typename GridType>
+void checkConner(GridType &grid, DofType &dof, bool up, bool left, typename DofType::RealType expectedValue )
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    if(up&&left)
+    {
+        EXPECT_EQ( dof[0], expectedValue) << "Up Left Conner test failed ";
+    }
+    if(up && !left)
+    {
+        EXPECT_EQ( dof[maxx-1], expectedValue) << "Up Right Conner test failed ";
+    }
+    if(!up && left)
+    {
+        EXPECT_EQ( dof[(maxy-1)*maxx], expectedValue) << "Down Left Conner test failed ";
+    }
+    if(!up && !left)
+    {
+        EXPECT_EQ( dof[(maxy-1)*maxx+maxx-1], expectedValue) << "Down right Conner test failed ";
+    }
+}
+
+
+/*expect 9 process*/
+template<typename DofType,typename GridType>
+void check_Boundary_2D(int rank, GridType &grid, DofType &dof, typename DofType::RealType expectedValue)
+{    
+
+    if(rank==0)//Up Left
+    {
+        checkUpEdge(grid,dof,true,false,expectedValue);//posledni je overlap
+        checkLeftEdge(grid,dof,true,false, expectedValue);//posledni je overlap
+    }
+    
+    if(rank==1)//Up Center
+    {
+        checkUpEdge(grid,dof,false,false, expectedValue);//prvni a posledni je overlap
+    }
+    
+    if(rank==2)//Up Right
+    {
+        checkUpEdge(grid,dof,false,true,expectedValue);//prvni je overlap
+        checkRightEdge(grid,dof,true,false,expectedValue);//posledni je overlap
+    }
+    
+    if(rank==3)//Center Left
+    {
+        checkLeftEdge(grid,dof,false,false,expectedValue);//prvni a posledni je overlap
+    }
+    
+    if(rank==4)//Center Center
+    {
+        //No boundary
+    }
+    
+    if(rank==5)//Center Right
+    {
+        checkRightEdge(grid,dof,false,false,expectedValue);
+    }
+    
+    if(rank==6)//Down Left
+    {
+        checkDownEdge(grid,dof,true,false,expectedValue);
+        checkLeftEdge(grid,dof,false,true,expectedValue);
+    }
+    
+    if(rank==7) //Down Center
+    {
+        checkDownEdge(grid,dof,false,false,expectedValue);
+    }
+    
+    if(rank==8) //Down Right
+    {
+            checkDownEdge(grid,dof,false,true,expectedValue);
+            checkRightEdge(grid,dof,false,true,expectedValue);
+    }
+};
+
+/*expect 9 process
+ * Known BUG of Traversars: Process boundary is writing over overlap.
+ * it should be true, true, every where, but we dont chcek boundary overalp on boundary
+ * so boundary overlap is not checked (it is filled incorectly by boundary condition).
+ */
+template<typename DofType,typename GridType>
+void check_Overlap_2D(int rank, GridType &grid, DofType &dof, typename DofType::RealType expectedValue)
+{
+    if(rank==0)//Up Left
+    {
+        checkRightEdge(grid,dof,false,true,expectedValue);
+        checkDownEdge(grid,dof,false,true,expectedValue);
+    }
+    
+    if(rank==1)//Up Center
+    {
+        checkDownEdge(grid,dof,true,true,expectedValue);
+        checkLeftEdge(grid,dof,false,true,expectedValue);
+        checkRightEdge(grid,dof,false,true,expectedValue);
+    }
+    
+    if(rank==2)//Up Right
+    {
+        checkDownEdge(grid,dof,true,false,expectedValue);//prvni je overlap
+        checkLeftEdge(grid,dof,false,true,expectedValue);
+    }
+    
+    if(rank==3)//Center Left
+    {
+        checkUpEdge(grid,dof,false,true,expectedValue);
+        checkDownEdge(grid,dof,false,true,expectedValue);
+        checkRightEdge(grid,dof,true,true,expectedValue);
+    }
+    
+    if(rank==4)//Center Center
+    {
+        checkUpEdge(grid,dof,true,true,expectedValue);
+        checkDownEdge(grid,dof,true,true,expectedValue);
+        checkRightEdge(grid,dof,true,true,expectedValue);
+        checkLeftEdge(grid,dof,true,true,expectedValue);
+    }
+    
+    if(rank==5)//Center Right
+    {
+        checkUpEdge(grid,dof,true,false,expectedValue);
+        checkDownEdge(grid,dof,true,false,expectedValue);
+        checkLeftEdge(grid,dof,true,true,expectedValue);
+    }
+    
+    if(rank==6)//Down Left
+    {
+        checkUpEdge(grid,dof,false,true,expectedValue);
+        checkRightEdge(grid,dof,true,false,expectedValue);
+    }
+    
+    if(rank==7) //Down Center
+    {
+        checkUpEdge(grid,dof,true,true,expectedValue);
+        checkLeftEdge(grid,dof,true,false,expectedValue);
+        checkRightEdge(grid,dof,true,false,expectedValue);
+    }
+    
+    if(rank==8) //Down Right
+    {
+        checkUpEdge(grid,dof,true,false,expectedValue);
+        checkLeftEdge(grid,dof,true,false,expectedValue);
+    }
+}
+
+/*Expect 9 process
+ */
+template<typename DofType,typename GridType>
+void checkNeighbor_2D(int rank, GridType &grid, DofType &dof)
+{
+    if(rank==0)//Up Left
+    {
+        checkRightEdge(grid,dof,true,false,1);
+        checkDownEdge(grid,dof,true,false,3);
+        checkConner(grid,dof,false,false,4);
+        
+    }
+    
+    if(rank==1)//Up Center
+    {
+        checkLeftEdge(grid,dof,true,false,0);
+        checkRightEdge(grid,dof,true,false,2);
+        checkConner(grid,dof,false,true,3);
+        checkDownEdge(grid,dof,false,false,4);
+        checkConner(grid,dof,false,false,5);
+    }
+    
+    if(rank==2)//Up Right
+    {
+        checkLeftEdge(grid,dof,true,false,1);
+        checkConner(grid,dof,false,true,4);
+        checkDownEdge(grid,dof,false,true,5);
+    }
+    
+    if(rank==3)//Center Left
+    {
+        checkUpEdge(grid,dof,true,false,0);
+        checkConner(grid,dof,true,false,1);
+        checkRightEdge(grid,dof,false,false,4);
+        checkDownEdge(grid,dof,true,false,6);
+        checkConner(grid,dof,false,false,7);
+    }
+    
+    if(rank==4)//Center Center
+    {
+        checkConner(grid,dof,true,true,0);
+        checkUpEdge(grid,dof,false,false,1);
+        checkConner(grid,dof,true,false,2);
+        checkLeftEdge(grid,dof,false,false,3);
+        checkRightEdge(grid,dof,false,false,5);
+        checkConner(grid,dof,false,true,6);
+        checkDownEdge(grid,dof,false,false,7);
+        checkConner(grid,dof,false,false,8);
+    }
+    
+    if(rank==5)//Center Right
+    {
+        checkConner(grid,dof,true,true,1);
+        checkUpEdge(grid,dof,false,true,2);
+        checkLeftEdge(grid,dof,false,false,4);
+        checkConner(grid,dof,false,true,7);
+        checkDownEdge(grid,dof,false,true,8);
+    }
+    
+    if(rank==6)//Down Left
+    {
+        checkUpEdge(grid,dof,true,false,3);
+        checkConner(grid,dof,true,false,4);
+        checkRightEdge(grid,dof,false,true,7);
+    }
+    
+    if(rank==7) //Down Center
+    {
+        checkConner(grid,dof,true,true,3);
+        checkUpEdge(grid,dof,false,false,4);
+        checkConner(grid,dof,true,false,5);
+        checkLeftEdge(grid,dof,false,true,6);
+        checkRightEdge(grid,dof,false,true,8);
+    }
+    
+    if(rank==8) //Down Right
+    {
+        checkConner(grid,dof,true,true,4);
+        checkUpEdge(grid,dof,false,true,5);
+        checkLeftEdge(grid,dof,false,true,7);
+    }
+}
+
+
+template<typename DofType,typename GridType>
+void check_Inner_2D(int rank, GridType grid, DofType dof, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    for(int j=1;j<maxy-1;j++)//prvni a posledni jsou buď hranice, nebo overlap
+        for(int i=1;i<maxx-1;i++) //buď je vlevo hranice, nebo overlap
+            EXPECT_EQ( dof[j*maxx+i], expectedValue) << " "<< j<<" "<<i << " " << maxx << " " << maxy;
+}
+
+
+
+
+
+/*
+ * Light check of 2D distributed grid and its synchronization. 
+ * expected 9 processors
+ */
+
+typedef MpiCommunicator CommunicatorType;
+typedef Grid<2,double,Host,int> MeshType;
+typedef MeshFunction<MeshType> MeshFunctionType;
+typedef Vector<double,Host,int> DofType;
+typedef typename MeshType::Cell Cell;
+typedef typename MeshType::IndexType IndexType; 
+typedef typename MeshType::PointType PointType; 
+typedef DistributedMesh<MeshType> DistributedGridType;
+
+class DistributedGirdTest_2D : public ::testing::Test {
+ protected:
+
+    static DistributedGridType *distrgrid;
+    static DofType *dof;
+
+    static SharedPointer<MeshType> gridptr;
+    static SharedPointer<MeshFunctionType> meshFunctionptr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,2> > constFunctionEvaluator;
+    static SharedPointer< ConstFunction<double,2>, Host > constFunctionPtr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,2> > linearFunctionEvaluator;
+    static SharedPointer< LinearFunction<double,2>, Host > linearFunctionPtr;
+
+    static int rank;
+    static int nproc;    
+     
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+      
+    int size=10;
+    rank=CommunicatorType::GetRank();
+    nproc=CommunicatorType::GetSize();
+    
+    PointType globalOrigin;
+    PointType globalProportions;
+    MeshType globalGrid;
+    
+    globalOrigin.x()=-0.5;
+    globalOrigin.y()=-0.5;    
+    globalProportions.x()=size;
+    globalProportions.y()=size;
+        
+    globalGrid.setDimensions(size,size);
+    globalGrid.setDomain(globalOrigin,globalProportions);
+    
+    typename DistributedGridType::CoordinatesType overlap;
+    overlap.setValue(1);
+    distrgrid=new DistributedGridType();
+    int distr[2];
+    distr[0]=3;
+    distr[1]=3;
+    distrgrid->template setGlobalGrid<CommunicatorType>(globalGrid,overlap, distr);
+    
+    distrgrid->SetupGrid(*gridptr);
+    dof=new DofType(gridptr->template getEntitiesCount< Cell >());
+    
+    meshFunctionptr->bind(gridptr,*dof);
+    
+    constFunctionPtr->Number=rank;
+    
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+      delete dof;
+      delete distrgrid;
+
+  }
+
+};
+
+DistributedMesh<MeshType> *DistributedGirdTest_2D::distrgrid=NULL;
+DofType *DistributedGirdTest_2D::dof=NULL;
+SharedPointer<MeshType> DistributedGirdTest_2D::gridptr;
+SharedPointer<MeshFunctionType> DistributedGirdTest_2D::meshFunctionptr;
+MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,2> > DistributedGirdTest_2D::constFunctionEvaluator;
+SharedPointer< ConstFunction<double,2>, Host > DistributedGirdTest_2D::constFunctionPtr;
+MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,2> > DistributedGirdTest_2D::linearFunctionEvaluator;
+SharedPointer< LinearFunction<double,2>, Host > DistributedGirdTest_2D::linearFunctionPtr;
+int DistributedGirdTest_2D::rank;
+int DistributedGirdTest_2D::nproc;    
+
+TEST_F(DistributedGirdTest_2D, evaluateAllEntities)
+{
+
+    //Check Traversars
+    //All entities, witout overlap
+    setDof_2D(*dof,-1);
+    constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+    //Printer<MeshType,DofType>::print_dof(rank,*gridptr,*dof);
+    check_Boundary_2D(rank, *gridptr, *dof, rank);
+    check_Overlap_2D(rank, *gridptr, *dof, -1);
+    check_Inner_2D(rank, *gridptr, *dof, rank);
+}
+
+TEST_F(DistributedGirdTest_2D, evaluateBoundaryEntities)
+{
+    //Boundary entities, witout overlap
+    setDof_2D(*dof,-1);
+    constFunctionEvaluator.evaluateBoundaryEntities( meshFunctionptr , constFunctionPtr );
+    //print_dof_2D(rank,*gridptr,dof);
+    check_Boundary_2D(rank, *gridptr, *dof, rank);
+    check_Overlap_2D(rank, *gridptr, *dof, -1);
+    check_Inner_2D(rank, *gridptr, *dof, -1);
+}
+
+TEST_F(DistributedGirdTest_2D, evaluateInteriorEntities)
+{
+    //Inner entities, witout overlap
+    setDof_2D(*dof,-1);
+    constFunctionEvaluator.evaluateInteriorEntities( meshFunctionptr , constFunctionPtr );
+    check_Boundary_2D(rank, *gridptr, *dof, -1);
+    check_Overlap_2D(rank, *gridptr, *dof, -1);
+    check_Inner_2D(rank, *gridptr, *dof, rank);
+}    
+
+TEST_F(DistributedGirdTest_2D, LinearFunctionTest)
+{
+    //fill meshfunction with linear function (physical center of cell corresponds with its coordinates in grid) 
+    setDof_2D(*dof,-1);
+    linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr, linearFunctionPtr);
+    meshFunctionptr->template Synchronize<CommunicatorType>();
+    
+    int count =gridptr->template getEntitiesCount< Cell >();
+    for(int i=0;i<count;i++)
+    {
+            auto entity= gridptr->template getEntity< Cell >(i);
+            entity.refresh();
+            EXPECT_EQ(meshFunctionptr->getValue(entity), (*linearFunctionPtr)(entity)) << "Linear function doesnt fit recievd data. " << entity.getCoordinates().x() << " "<<entity.getCoordinates().y() << " "<< gridptr->getDimensions().x() <<" "<<gridptr->getDimensions().y();
+    }
+}
+
+TEST_F(DistributedGirdTest_2D, SynchronizerNeighborTest)
+{
+    setDof_2D(*dof,-1);
+    constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+    meshFunctionptr->template Synchronize<CommunicatorType>();
+    checkNeighbor_2D(rank, *gridptr, *dof);
+}
+
+
+#else
+TEST(NoMPI, NoTest)
+{
+    ASSERT_TRUE(true) << ":-(";
+}
+#endif
+
+#endif
+
+
+#if (defined(HAVE_GTEST) && defined(HAVE_MPI))
+#include <sstream>
+
+  class MinimalistBuffredPrinter : public ::testing::EmptyTestEventListener {
+      
+  private:
+      std::stringstream sout;
+      
+  public:
+      
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      sout<< test_info.test_case_name() <<"." << test_info.name() << " Start." <<std::endl;
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") 
+              << test_part_result.file_name() << " "
+              << test_part_result.line_number() <<std::endl
+              << test_part_result.summary() <<std::endl;
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) 
+    {
+        int rank=CommunicatorType::GetRank();
+        sout<< test_info.test_case_name() <<"." << test_info.name() << " End." <<std::endl;
+        std::cout << rank << ":" << std::endl << sout.str()<< std::endl;
+        sout.str( std::string() );
+        sout.clear();
+    }
+  };
+#endif
+
+#include "../../src/UnitTests/GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+
+    #ifdef HAVE_MPI
+       ::testing::TestEventListeners& listeners =
+          ::testing::UnitTest::GetInstance()->listeners();
+
+       delete listeners.Release(listeners.default_result_printer());
+       listeners.Append(new MinimalistBuffredPrinter);
+
+       CommunicatorType::Init(argc,argv);
+    #endif
+       int result= RUN_ALL_TESTS();
+
+    #ifdef HAVE_MPI
+       CommunicatorType::Finalize();
+    #endif
+       return result;
+#else
+   
+   throw GtestMissingError();
+#endif
+}
+
+
diff --git a/src/UnitTests/Mpi/DistributedGridTest_3D.cpp b/src/UnitTests/Mpi/DistributedGridTest_3D.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..758c7dcaca984c18963260f73b31a3ce3e8a2330
--- /dev/null
+++ b/src/UnitTests/Mpi/DistributedGridTest_3D.cpp
@@ -0,0 +1,814 @@
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+#ifdef HAVE_MPI    
+
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+
+#include "Functions.h"
+
+using namespace TNL;
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+using namespace TNL::Meshes::DistributedMeshes; 
+
+template<typename DofType>
+void setDof_3D(DofType &dof, typename DofType::RealType value)
+{
+    for(int i=0;i<dof.getSize();i++)
+        dof[i]=value;
+}
+
+template<typename GridType>
+int getAdd(GridType &grid,bool bottom, bool nord, bool west )
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int maxz=grid.getDimensions().z();
+
+    int add=0;
+    if(!west)
+        add+=maxx-1;
+    if(!nord)
+        add+=(maxy-1)*maxx;
+    if(!bottom)
+        add+=(maxz-1)*maxx*maxy;
+
+    return add;
+}
+
+template<typename DofType,typename GridType>
+void checkConner(GridType &grid, DofType &dof,bool bottom, bool nord, bool west, typename DofType::RealType expectedValue )
+{
+    int i=getAdd(grid,bottom,nord,west);
+    EXPECT_EQ( dof[i], expectedValue) << "Conner test failed";
+    
+}
+
+template<typename DofType,typename GridType>
+void checkXDirectionEdge(GridType &grid, DofType &dof, bool bottom, bool nord, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,bottom,nord,true);        
+    for(int i=1;i<grid.getDimensions().x()-1;i++) 
+            EXPECT_EQ( dof[i+add], expectedValue) << "X direction Edge test failed " << i;
+}
+
+
+template<typename DofType,typename GridType>
+void checkYDirectionEdge(GridType &grid, DofType &dof, bool bottom, bool west, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,bottom,true,west);
+    for(int i=1;i<grid.getDimensions().y()-1;i++) 
+            EXPECT_EQ( dof[grid.getDimensions().x()*i+add], expectedValue) << "Y direction Edge test failed " << i;
+}
+
+template<typename DofType,typename GridType>
+void checkZDirectionEdge(GridType &grid, DofType &dof, bool nord, bool west, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,true,nord,west);
+    for(int i=1;i<grid.getDimensions().z()-1;i++) 
+            EXPECT_EQ( dof[grid.getDimensions().y()*grid.getDimensions().x()*i+add], expectedValue) << "Z direction Edge test failed " << i;
+}
+
+template<typename DofType,typename GridType>
+void checkZFace(GridType &grid, DofType &dof, bool bottom, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,bottom,true,true);
+    for(int i=1;i<grid.getDimensions().y()-1;i++)
+        for(int j=1; j<grid.getDimensions().x()-1;j++)
+        {
+            EXPECT_EQ( dof[grid.getDimensions().x()*i+j+add], expectedValue) << "Z Face test failed "<<i<< " " << j;
+        }
+}
+
+template<typename DofType,typename GridType>
+void checkYFace(GridType &grid, DofType &dof, bool nord, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,true,nord,true);
+    for(int i=1;i<grid.getDimensions().z()-1;i++)
+        for(int j=1; j<grid.getDimensions().x()-1;j++)
+        {
+            EXPECT_EQ( dof[grid.getDimensions().y()*grid.getDimensions().x()*i+j+add], expectedValue) << "Y Face test failed "<<i<< " " << j;
+        }
+}
+
+template<typename DofType,typename GridType>
+void checkXFace(GridType &grid, DofType &dof, bool west, typename DofType::RealType expectedValue)
+{
+    int add=getAdd(grid,true,true,west);
+    for(int i=1;i<grid.getDimensions().z()-1;i++)
+        for(int j=1; j<grid.getDimensions().y()-1;j++)
+        {
+            EXPECT_EQ( dof[grid.getDimensions().y()*grid.getDimensions().x()*i+grid.getDimensions().x()*j+add], expectedValue) << "X Face test failed "<<i<< " " << j;
+        }
+}
+
+/*
+Expected 27 process
+*/
+template<typename DofType,typename GridType>
+void check_Boundary_3D(int rank, GridType &grid, DofType &dof, typename DofType::RealType expectedValue)
+{
+    if(rank==0)//Bottom Nord West
+    {
+        checkConner(grid,dof,true, true, true, expectedValue );
+        checkXDirectionEdge(grid,dof,true,true,expectedValue);
+        checkYDirectionEdge(grid,dof,true,true,expectedValue);
+        checkZDirectionEdge(grid,dof,true,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }    
+
+    if(rank==1)//Bottom Nord Center
+    {
+        checkXDirectionEdge(grid,dof,true,true,expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==2)//Bottom Nord East
+    {
+        checkConner(grid,dof,true, true, false, expectedValue );
+        checkXDirectionEdge(grid,dof,true,true,expectedValue);
+        checkYDirectionEdge(grid,dof,true,false,expectedValue);
+        checkZDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==3)//Bottom Center West
+    {
+        checkYDirectionEdge(grid,dof,true,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==4)//Bottom Center Center
+    {
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+
+    if(rank==5)//Bottom Center East
+    {
+        checkYDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==6)//Bottom South West
+    {
+        checkConner(grid,dof,true, false, true, expectedValue );
+        checkXDirectionEdge(grid,dof,true,false,expectedValue);
+        checkYDirectionEdge(grid,dof,true,true,expectedValue);
+        checkZDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==7)//Bottom South Center
+    {
+        checkXDirectionEdge(grid,dof,true,false,expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==8)//Bottom South East
+    {
+        checkConner(grid,dof,true, false, false, expectedValue );
+        checkXDirectionEdge(grid,dof,true,false,expectedValue);
+        checkYDirectionEdge(grid,dof,true,false,expectedValue);
+        checkZDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==9)//Center Nord West
+    {
+        checkZDirectionEdge(grid,dof,true,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+    }    
+
+    if(rank==10)//Center Nord Center
+    {
+        checkYFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==11)//Center Nord East
+    {
+        checkZDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==12)//Center Center West
+    {
+        checkXFace(grid, dof, true, expectedValue);
+    }
+
+    if(rank==13)//Center Center Center
+    {
+        //no Boundary
+    }
+
+
+    if(rank==14)//Center Center East
+    {
+        checkXFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==15)//Center South West
+    {
+        checkZDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==16)//Center South Center
+    {
+        checkYFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==17)//Center South East
+    {
+        checkZDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==18)//Top Nord West
+    {
+        checkConner(grid,dof,false, true, true, expectedValue );
+        checkXDirectionEdge(grid,dof,false,true,expectedValue);
+        checkYDirectionEdge(grid,dof,false,true,expectedValue);
+        checkZDirectionEdge(grid,dof,true,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }    
+
+    if(rank==19)//Top Nord Center
+    {
+        checkXDirectionEdge(grid,dof,false,true,expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==20)//Top Nord East
+    {
+        checkConner(grid,dof,false, true, false, expectedValue );
+        checkXDirectionEdge(grid,dof,false,true,expectedValue);
+        checkYDirectionEdge(grid,dof,false,false,expectedValue);
+        checkZDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==21)//Top Center West
+    {
+        checkYDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==22)//Top Center Center
+    {
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+
+    if(rank==23)//Top Center East
+    {
+        checkYDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==24)//Top South West
+    {
+        checkConner(grid,dof,false, false, true, expectedValue );
+        checkXDirectionEdge(grid,dof,false,false,expectedValue);
+        checkYDirectionEdge(grid,dof,false,true,expectedValue);
+        checkZDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==25)//Top South Center
+    {
+        checkXDirectionEdge(grid,dof,false,false,expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+    if(rank==26)//Top South East
+    {
+        checkConner(grid,dof,false, false, false, expectedValue );
+        checkXDirectionEdge(grid,dof,false,false,expectedValue);
+        checkYDirectionEdge(grid,dof,false,false,expectedValue);
+        checkZDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+    }
+
+}
+
+template<typename DofType,typename GridType>
+void CheckConnerNode_Overlap(GridType &grid, DofType &dof,bool bottom, bool nord, bool west, typename DofType::RealType expectedValue)
+{
+    checkConner(grid,dof,!bottom, !nord, !west, expectedValue );
+    checkXDirectionEdge(grid,dof,!bottom,!nord,expectedValue);
+    checkYDirectionEdge(grid,dof,!bottom,!west,expectedValue);
+    checkZDirectionEdge(grid,dof,!nord,!west,expectedValue);
+    checkXFace(grid, dof, !west, expectedValue);
+    checkYFace(grid, dof, !nord, expectedValue);
+    checkZFace(grid, dof, !bottom, expectedValue);
+}
+
+template<typename DofType,typename GridType>
+void CheckXEdgeNode_Overlap(GridType &grid, DofType &dof,bool bottom, bool nord, typename DofType::RealType expectedValue)
+{
+    checkConner(grid,dof,!bottom, !nord, false, expectedValue );
+    checkConner(grid,dof,!bottom, !nord, true, expectedValue );
+    checkXDirectionEdge(grid,dof,!bottom, !nord,expectedValue);
+    checkYDirectionEdge(grid,dof,!bottom,false,expectedValue);
+    checkYDirectionEdge(grid,dof,!bottom,true,expectedValue);
+    checkZDirectionEdge(grid,dof,!nord,false,expectedValue);
+    checkZDirectionEdge(grid,dof,!nord,true,expectedValue);
+    checkXFace(grid, dof, false, expectedValue);
+    checkXFace(grid, dof, true, expectedValue);
+    checkYFace(grid, dof, !nord, expectedValue);
+    checkZFace(grid, dof, !bottom, expectedValue);
+}
+
+template<typename DofType,typename GridType>
+void CheckYEdgeNode_Overlap(GridType &grid, DofType &dof,bool bottom, bool west, typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof,!bottom, false, !west, expectedValue );
+        checkConner(grid,dof,!bottom, true, !west, expectedValue );
+        checkXDirectionEdge(grid,dof,!bottom,false,expectedValue);
+        checkXDirectionEdge(grid,dof,!bottom,true,expectedValue);
+        checkYDirectionEdge(grid,dof,!bottom,!west,expectedValue);
+        checkZDirectionEdge(grid,dof,false,!west,expectedValue);
+        checkZDirectionEdge(grid,dof,true,!west,expectedValue);
+        checkXFace(grid, dof, !west, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, !bottom, expectedValue);
+}
+
+template<typename DofType,typename GridType>
+void CheckZEdgeNode_Overlap(GridType &grid, DofType &dof,bool nord, bool west, typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof,false, !nord, !west, expectedValue );
+        checkConner(grid,dof,true, !nord, !west, expectedValue );
+        checkXDirectionEdge(grid,dof,false,!nord,expectedValue);
+        checkXDirectionEdge(grid,dof,true,!nord,expectedValue);
+        checkYDirectionEdge(grid,dof,false,!west,expectedValue);
+        checkYDirectionEdge(grid,dof,true,!west,expectedValue);
+        checkZDirectionEdge(grid,dof,!nord,!west,expectedValue);
+        checkXFace(grid, dof, !west, expectedValue);
+        checkYFace(grid, dof, !nord, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);
+}
+
+template<typename DofType,typename GridType>
+void CheckXFaceNode_Overlap(GridType &grid, DofType &dof,bool west, typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof,false, false, !west, expectedValue );
+        checkConner(grid,dof,false, true, !west, expectedValue );
+        checkConner(grid,dof,true, false, !west, expectedValue );
+        checkConner(grid,dof,true, true, !west, expectedValue );
+        checkXDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXDirectionEdge(grid,dof,true,true,expectedValue);
+        checkYDirectionEdge(grid,dof,false,!west,expectedValue);
+        checkYDirectionEdge(grid,dof,true,!west,expectedValue);
+        checkZDirectionEdge(grid,dof,false,!west,expectedValue);
+        checkZDirectionEdge(grid,dof,true,!west,expectedValue);
+        checkXFace(grid, dof, !west, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);    
+        checkZFace(grid, dof, true, expectedValue);        
+}
+
+template<typename DofType,typename GridType>
+void CheckYFaceNode_Overlap(GridType &grid, DofType &dof,bool nord, typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof, false,!nord, false, expectedValue );
+        checkConner(grid,dof, false,!nord, true, expectedValue );
+        checkConner(grid,dof, true, !nord, false, expectedValue );
+        checkConner(grid,dof, true, !nord, true, expectedValue );
+        checkXDirectionEdge(grid,dof,false,!nord,expectedValue);
+        checkXDirectionEdge(grid,dof,true,!nord,expectedValue);
+        checkYDirectionEdge(grid,dof,false,false,expectedValue);
+        checkYDirectionEdge(grid,dof,false,true,expectedValue);
+        checkYDirectionEdge(grid,dof,true,false,expectedValue);
+        checkYDirectionEdge(grid,dof,true,true,expectedValue);
+        checkZDirectionEdge(grid,dof,!nord,false,expectedValue);
+        checkZDirectionEdge(grid,dof,!nord,true,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, !nord, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);    
+}
+
+template<typename DofType,typename GridType>
+void CheckZFaceNode_Overlap(GridType &grid, DofType &dof,bool bottom, typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof,!bottom, false, false, expectedValue );
+        checkConner(grid,dof,!bottom, false, true, expectedValue );
+        checkConner(grid,dof,!bottom, true, false, expectedValue );
+        checkConner(grid,dof,!bottom, true, true, expectedValue );
+        checkXDirectionEdge(grid,dof,!bottom,false,expectedValue);
+        checkXDirectionEdge(grid,dof,!bottom,true,expectedValue);
+        checkYDirectionEdge(grid,dof,!bottom,false,expectedValue);
+        checkYDirectionEdge(grid,dof,!bottom,true,expectedValue);
+        checkZDirectionEdge(grid,dof,false,false,expectedValue);
+        checkZDirectionEdge(grid,dof,false,true,expectedValue);
+        checkZDirectionEdge(grid,dof,true,false,expectedValue);
+        checkZDirectionEdge(grid,dof,true,true,expectedValue);
+        checkXFace(grid, dof, false, expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, !bottom, expectedValue);    
+}
+
+template<typename DofType,typename GridType>
+void CheckCentralNode_Overlap(GridType &grid, DofType &dof,typename DofType::RealType expectedValue)
+{
+        checkConner(grid,dof,false, false, false, expectedValue );
+        checkConner(grid,dof,false, false, true, expectedValue );
+        checkConner(grid,dof,false, true, false, expectedValue );
+        checkConner(grid,dof,false, true, true, expectedValue );
+        checkConner(grid,dof,true, false, false, expectedValue );
+        checkConner(grid,dof,true, false, true, expectedValue );
+        checkConner(grid,dof,true, true, false, expectedValue );
+        checkConner(grid,dof,true, true, true, expectedValue );
+
+        checkXDirectionEdge(grid,dof,false,false,expectedValue);
+        checkXDirectionEdge(grid,dof,false,true,expectedValue);
+        checkXDirectionEdge(grid,dof,true,false,expectedValue);
+        checkXDirectionEdge(grid,dof,true,true,expectedValue);
+        checkYDirectionEdge(grid,dof,false,false,expectedValue);
+        checkYDirectionEdge(grid,dof,false,true,expectedValue);
+        checkYDirectionEdge(grid,dof,true,false,expectedValue);
+        checkYDirectionEdge(grid,dof,true,true,expectedValue);
+        checkZDirectionEdge(grid,dof,false,false,expectedValue);
+        checkZDirectionEdge(grid,dof,false,true,expectedValue);
+        checkZDirectionEdge(grid,dof,true,false,expectedValue);
+        checkZDirectionEdge(grid,dof,true,true,expectedValue);
+
+        checkXFace(grid, dof, false, expectedValue);
+        checkXFace(grid, dof, true, expectedValue);
+        checkYFace(grid, dof, false, expectedValue);
+        checkYFace(grid, dof, true, expectedValue);
+        checkZFace(grid, dof, false, expectedValue);
+        checkZFace(grid, dof, true, expectedValue);    
+}
+
+/*
+* Expected 27 procs. 
+*/
+template<typename DofType,typename GridType>
+void check_Overlap_3D(int rank, GridType &grid, DofType &dof, typename DofType::RealType expectedValue)
+{
+    if(rank==0)
+        CheckConnerNode_Overlap(grid,dof,true,true,true,expectedValue);
+
+    if(rank==1)
+        CheckXEdgeNode_Overlap(grid,dof,true,true,expectedValue);
+
+    if(rank==2)    
+        CheckConnerNode_Overlap(grid,dof,true,true,false,expectedValue);
+    
+    if(rank==3)
+        CheckYEdgeNode_Overlap(grid,dof,true,true,expectedValue);
+
+    if(rank==4)
+        CheckZFaceNode_Overlap(grid,dof,true,expectedValue);
+        
+    if(rank==5)
+        CheckYEdgeNode_Overlap(grid,dof,true,false,expectedValue);
+    
+    if(rank==6)
+        CheckConnerNode_Overlap(grid,dof,true,false,true,expectedValue);
+
+    if(rank==7)
+        CheckXEdgeNode_Overlap(grid,dof,true,false,expectedValue);
+
+    if(rank==8)
+        CheckConnerNode_Overlap(grid,dof,true,false,false,expectedValue);
+
+    if(rank==9)
+        CheckZEdgeNode_Overlap(grid,dof,true,true,expectedValue);
+
+    if(rank==10)
+        CheckYFaceNode_Overlap(grid,dof,true,expectedValue);
+
+    if(rank==11)
+        CheckZEdgeNode_Overlap(grid,dof,true,false,expectedValue);
+
+    if(rank==12)
+        CheckXFaceNode_Overlap(grid,dof,true,expectedValue);
+
+    if(rank==13)
+        CheckCentralNode_Overlap(grid,dof,expectedValue);
+
+    if(rank==14)
+        CheckXFaceNode_Overlap(grid,dof,false,expectedValue);
+
+    if(rank==15)
+        CheckZEdgeNode_Overlap(grid,dof,false,true,expectedValue);
+
+    if(rank==16)
+        CheckYFaceNode_Overlap(grid,dof,false,expectedValue);
+
+    if(rank==17)
+        CheckZEdgeNode_Overlap(grid,dof,false,false,expectedValue);
+    
+    if(rank==18)
+        CheckConnerNode_Overlap(grid,dof,false,true,true,expectedValue);
+
+    if(rank==19)
+        CheckXEdgeNode_Overlap(grid,dof,false,true,expectedValue);
+
+    if(rank==20)    
+        CheckConnerNode_Overlap(grid,dof,false,true,false,expectedValue);
+    
+    if(rank==21)
+        CheckYEdgeNode_Overlap(grid,dof,false,true,expectedValue);
+
+    if(rank==22)
+        CheckZFaceNode_Overlap(grid,dof,false,expectedValue);
+        
+    if(rank==23)
+        CheckYEdgeNode_Overlap(grid,dof,false,false,expectedValue);
+    
+    if(rank==24)
+        CheckConnerNode_Overlap(grid,dof,false,false,true,expectedValue);
+
+    if(rank==25)
+        CheckXEdgeNode_Overlap(grid,dof,false,false,expectedValue);
+
+    if(rank==26)
+        CheckConnerNode_Overlap(grid,dof,false,false,false,expectedValue);
+
+}
+
+template<typename DofType,typename GridType>
+void check_Inner_3D(int rank, GridType grid, DofType dof, typename DofType::RealType expectedValue)
+{
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    int maxz=grid.getDimensions().z();
+    for(int k=1;k<maxz-1;k++)
+        for(int j=1;j<maxy-1;j++)//prvni a posledni jsou buď hranice, nebo overlap
+            for(int i=1;i<maxx-1;i++) //buď je vlevo hranice, nebo overlap
+                EXPECT_EQ( dof[k*maxx*maxy+j*maxx+i], expectedValue) <<" "<<k <<" "<< j<<" "<<i << " " << maxx << " " << maxy<< " " << maxz;
+}
+
+
+/*
+ * Light check of 3D distributed grid and its synchronization. 
+ * expected 27 processors
+ */
+typedef MpiCommunicator CommunicatorType;
+typedef Grid<3,double,Host,int> MeshType;
+typedef MeshFunction<MeshType> MeshFunctionType;
+typedef Vector<double,Host,int> DofType;
+typedef typename MeshType::Cell Cell;
+typedef typename MeshType::IndexType IndexType; 
+typedef typename MeshType::PointType PointType; 
+typedef DistributedMesh<MeshType> DistributedGridType;
+     
+class DistributedGirdTest_3D : public ::testing::Test {
+ protected:
+
+    static DistributedGridType *distrgrid;
+    static DofType *dof;
+
+    static SharedPointer<MeshType> gridptr;
+    static SharedPointer<MeshFunctionType> meshFunctionptr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,3> > constFunctionEvaluator;
+    static SharedPointer< ConstFunction<double,3>, Host > constFunctionPtr;
+
+    static MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,3> > linearFunctionEvaluator;
+    static SharedPointer< LinearFunction<double,3>, Host > linearFunctionPtr;
+
+    static int rank;
+    static int nproc;    
+     
+  // Per-test-case set-up.
+  // Called before the first test in this test case.
+  // Can be omitted if not needed.
+  static void SetUpTestCase() {
+      
+    int size=10;
+    rank=MPI::COMM_WORLD.Get_rank();
+    nproc=MPI::COMM_WORLD.Get_size();
+    
+    PointType globalOrigin;
+    PointType globalProportions;
+    MeshType globalGrid;
+    
+    globalOrigin.x()=-0.5;
+    globalOrigin.y()=-0.5;
+    globalOrigin.z()=-0.5;    
+    globalProportions.x()=size;
+    globalProportions.y()=size;
+    globalProportions.z()=size;
+        
+    globalGrid.setDimensions(size,size,size);
+    globalGrid.setDomain(globalOrigin,globalProportions);
+    
+    typename DistributedGridType::CoordinatesType overlap;
+    overlap.setValue(1);
+    distrgrid=new DistributedGridType();
+    int distr[2];
+    distr[0]=3;
+    distr[1]=3;
+    distr[2]=3;
+    distrgrid->template setGlobalGrid<CommunicatorType>(globalGrid,overlap,distr);
+    
+    distrgrid->SetupGrid(*gridptr);
+    dof=new DofType(gridptr->template getEntitiesCount< Cell >());
+    
+    meshFunctionptr->bind(gridptr,*dof);   
+    constFunctionPtr->Number=rank;
+    
+  }
+
+  // Per-test-case tear-down.
+  // Called after the last test in this test case.
+  // Can be omitted if not needed.
+  static void TearDownTestCase() {
+      delete dof;
+      delete distrgrid;
+
+  }
+
+};
+
+DistributedGridType *DistributedGirdTest_3D::distrgrid=NULL;
+DofType *DistributedGirdTest_3D::dof=NULL;
+SharedPointer<MeshType> DistributedGirdTest_3D::gridptr;
+SharedPointer<MeshFunctionType> DistributedGirdTest_3D::meshFunctionptr;
+MeshFunctionEvaluator< MeshFunctionType, ConstFunction<double,3> > DistributedGirdTest_3D::constFunctionEvaluator;
+SharedPointer< ConstFunction<double,3>, Host > DistributedGirdTest_3D::constFunctionPtr;
+MeshFunctionEvaluator< MeshFunctionType, LinearFunction<double,3> > DistributedGirdTest_3D::linearFunctionEvaluator;
+SharedPointer< LinearFunction<double,3>, Host > DistributedGirdTest_3D::linearFunctionPtr;
+int DistributedGirdTest_3D::rank;
+int DistributedGirdTest_3D::nproc;    
+
+TEST_F(DistributedGirdTest_3D, evaluateAllEntities)
+{
+
+    //Check Traversars
+    //All entities, witout overlap
+    setDof_3D(*dof,-1);
+    constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+    //Printer<MeshType,DofType>::print_dof(rank,*gridptr,*dof);
+    check_Boundary_3D(rank, *gridptr, *dof, rank);
+    check_Overlap_3D(rank, *gridptr, *dof, -1);
+    check_Inner_3D(rank, *gridptr, *dof, rank);
+}
+
+TEST_F(DistributedGirdTest_3D, evaluateBoundaryEntities)
+{
+    //Boundary entities, witout overlap
+    setDof_3D(*dof,-1);
+    constFunctionEvaluator.evaluateBoundaryEntities( meshFunctionptr , constFunctionPtr );
+    check_Boundary_3D(rank, *gridptr, *dof, rank);
+    check_Overlap_3D(rank, *gridptr, *dof, -1);
+    check_Inner_3D(rank, *gridptr, *dof, -1);
+}
+
+TEST_F(DistributedGirdTest_3D, evaluateInteriorEntities)
+{
+    //Inner entities, witout overlap
+    setDof_3D(*dof,-1);
+    constFunctionEvaluator.evaluateInteriorEntities( meshFunctionptr , constFunctionPtr );
+    check_Boundary_3D(rank, *gridptr, *dof, -1);
+    check_Overlap_3D(rank, *gridptr, *dof, -1);
+    check_Inner_3D(rank, *gridptr, *dof, rank);
+}    
+
+TEST_F(DistributedGirdTest_3D, LinearFunctionTest)
+{
+    //fill meshfunction with linear function (physical center of cell corresponds with its coordinates in grid) 
+    setDof_3D(*dof,-1);
+    linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr, linearFunctionPtr);
+    meshFunctionptr->template Synchronize<CommunicatorType>();
+    
+    int count =gridptr->template getEntitiesCount< Cell >();
+    for(int i=0;i<count;i++)
+    {
+            auto entity= gridptr->template getEntity< Cell >(i);
+            entity.refresh();
+            EXPECT_EQ(meshFunctionptr->getValue(entity), (*linearFunctionPtr)(entity)) << "Linear function doesnt fit recievd data. " << entity.getCoordinates().x() << " "<<entity.getCoordinates().y() << " "<< gridptr->getDimensions().x() <<" "<<gridptr->getDimensions().y();
+    }
+}
+
+/* not implemented
+TEST_F(DistributedGirdTest_3D, SynchronizerNeighborTest)
+{
+
+}
+*/
+
+#else
+TEST(NoMPI, NoTest)
+{
+    ASSERT_TRUE(true) << ":-(";
+}
+#endif
+
+#endif
+
+
+#if (defined(HAVE_GTEST) && defined(HAVE_MPI))
+#include <sstream>
+
+  class MinimalistBuffredPrinter : public ::testing::EmptyTestEventListener {
+      
+  private:
+      std::stringstream sout;
+      
+  public:
+      
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      sout<< test_info.test_case_name() <<"." << test_info.name() << " Start." <<std::endl;
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") 
+              << test_part_result.file_name() << " "
+              << test_part_result.line_number() <<std::endl
+              << test_part_result.summary() <<std::endl;
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) 
+    {
+        int rank=CommunicatorType::GetRank();
+        sout<< test_info.test_case_name() <<"." << test_info.name() << " End." <<std::endl;
+        std::cout << rank << ":" << std::endl << sout.str()<< std::endl;
+        sout.str( std::string() );
+        sout.clear();
+    }
+  };
+#endif
+
+#include "../../src/UnitTests/GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+
+    #ifdef HAVE_MPI
+       ::testing::TestEventListeners& listeners =
+          ::testing::UnitTest::GetInstance()->listeners();
+
+       delete listeners.Release(listeners.default_result_printer());
+       listeners.Append(new MinimalistBuffredPrinter);
+
+       CommunicatorType::Init(argc,argv);
+    #endif
+       int result= RUN_ALL_TESTS();
+
+    #ifdef HAVE_MPI
+       CommunicatorType::Finalize();
+    #endif
+       return result;
+#else
+   
+   throw GtestMissingError();
+#endif
+}
+
+
+
+
diff --git a/src/UnitTests/Mpi/Functions.h b/src/UnitTests/Mpi/Functions.h
new file mode 100644
index 0000000000000000000000000000000000000000..59a0335c15af53b880f716318e571688f593d91c
--- /dev/null
+++ b/src/UnitTests/Mpi/Functions.h
@@ -0,0 +1,212 @@
+/***************************************************************************
+                          DistributedGridTest.cpp  -  description
+                             -------------------
+    begin                : Sep 6, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+#pragma once
+
+
+#include <iostream>
+#include <sstream>
+#include <TNL/Functions/MeshFunction.h>
+
+
+using namespace TNL;
+using namespace TNL::Functions;
+
+template <typename Real,
+        int Dim>
+class LinearFunction{};
+
+
+template <typename Real,
+        int Dim>
+class ConstFunction{};
+
+template < typename GridType,
+        typename DofType,
+        int Dim=GridType::getMeshDimension()>
+class Printer
+{};
+
+//=================================1D=====================================================
+template <typename Real>
+class LinearFunction<Real,1> : public Functions::Domain< 1, Functions::MeshDomain >
+{
+   public:
+      typedef Real RealType;
+      LinearFunction( )
+      {};
+
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         return meshEntity.getCenter().x();
+         
+      }
+};
+
+template <typename Real>
+class ConstFunction<Real,1> : public Functions::Domain< 1, Functions::MeshDomain >
+{
+   public:
+      typedef Real RealType;
+          
+          Real Number;
+          
+      ConstFunction( )
+      {};
+
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         return Number;
+         
+      }
+};
+
+template<typename GridType, typename DofType>
+class Printer< GridType,DofType,1>
+{
+    public:
+    void static print_dof(int rank, GridType grid, DofType dof)
+    {
+    std::stringstream sout;
+    for(int i=0;i<dof.getSize();i++) 
+        sout<< dof[i] << " ";
+    
+    std::cout << rank << ":   " << sout.str() << std::endl;
+    };
+};
+
+//=================================2D======================================================
+
+template <typename Real>
+class LinearFunction<Real,2> : public Functions::Domain< 2, Functions::MeshDomain >
+{
+   public:
+      typedef Real RealType;
+      LinearFunction( )
+      {};
+
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         //return meshEntity.getCoordinates().y()*10+meshEntity.getCoordinates().x();
+         return meshEntity.getCenter().y()*100+meshEntity.getCenter().x();
+      }
+};
+
+template <typename Real>
+class ConstFunction<Real,2> : public Functions::Domain< 2, Functions::MeshDomain >
+{
+   public:
+          typedef Real RealType;
+          
+          Real Number;
+      ConstFunction( )
+      {};
+          
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         //return meshEntity.getCoordinates().y()*10+meshEntity.getCoordinates().x();
+         return this->Number;
+         
+      }
+};
+
+template<typename GridType, typename DofType>
+class Printer< GridType,DofType,2>
+{
+    public:
+    void static print_dof(int rank,GridType grid, DofType dof)
+    {
+    int maxx=grid.getDimensions().x();
+    int maxy=grid.getDimensions().y();
+    std::stringstream sout;
+        sout<< rank<<":" <<std::endl;
+    for(int j=0;j<maxy;j++)
+    {
+        for(int i=0;i<maxx;i++)
+            sout<< dof[j*maxx+i] << " ";
+        sout<<std::endl;
+    }
+    std::cout << sout.str() << std::endl<< std::endl;
+    };
+};
+
+//============================3D============================================================
+template <typename Real>
+class LinearFunction<Real,3> : public Functions::Domain< 3, Functions::MeshDomain >
+{
+   public:
+      typedef Real RealType;
+      LinearFunction( )
+      {};
+
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         //return meshEntity.getCoordinates().y()*10+meshEntity.getCoordinates().x();
+         return meshEntity.getCenter().z()*10000+meshEntity.getCenter().y()*100+meshEntity.getCenter().x();
+      }
+};
+
+template <typename Real>
+class ConstFunction<Real,3> : public Functions::Domain< 3, Functions::MeshDomain >
+{
+   public:
+          typedef Real RealType;
+          
+          Real Number;
+      ConstFunction( )
+      {};
+          
+      template< typename EntityType >
+      __cuda_callable__ RealType operator()( const EntityType& meshEntity,
+                                  const RealType& time = 0.0 ) const
+      {
+         //return meshEntity.getCoordinates().y()*10+meshEntity.getCoordinates().x();
+         return this->Number;
+         
+      }
+};
+
+template<typename GridType, typename DofType>
+class Printer< GridType,DofType,3>
+{
+    public:
+    static void print_dof(int rank,GridType grid, DofType dof)
+    {
+      //print local dof
+      int maxx=grid.getDimensions().x();
+      int maxy=grid.getDimensions().y();
+      int maxz=grid.getDimensions().z();
+
+      std::stringstream sout;
+      sout<< rank<<":"  <<std::endl;
+      for(int k=0;k<maxz;k++)
+      {
+            for(int j=0;j<maxy;j++)
+            {
+                    for(int ii=0;ii<k;ii++)
+                            sout<<"  ";
+                    for(int i=0;i<maxx;i++)
+                    {
+                            sout <<dof[k*maxx*maxy+maxx*j+i]<<"  ";
+                    }
+                    sout << std::endl;
+            }
+      }
+      std::cout << sout.str()<< std::endl<<std::endl;
+    };
+};
diff --git a/src/UnitTests/Mpi/GPUDistributedGridIOTest.cu b/src/UnitTests/Mpi/GPUDistributedGridIOTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..dfc57f86cf715d6b9f4d5eb02336388bf58fe897
--- /dev/null
+++ b/src/UnitTests/Mpi/GPUDistributedGridIOTest.cu
@@ -0,0 +1,110 @@
+
+#ifdef HAVE_GTEST
+  
+#include <gtest/gtest.h>
+
+#ifdef HAVE_MPI
+
+#include "DistributedGridIOTest.h"
+
+TEST( DistributedGridIO, Save_1D )
+{
+    TestDistributedGridIO<1,Cuda>::TestSave();
+}
+
+TEST( DistributedGridIO, Save_2D )
+{
+    TestDistributedGridIO<2,Cuda>::TestSave();
+}
+
+TEST( DistributedGridIO, Save_3D )
+{
+    TestDistributedGridIO<3,Cuda>::TestSave();
+}
+
+TEST( DistributedGridIO, Load_1D )
+{
+    TestDistributedGridIO<1,Cuda>::TestLoad();
+}
+
+TEST( DistributedGridIO, Load_2D )
+{
+    TestDistributedGridIO<2,Cuda>::TestLoad();
+}
+
+TEST( DistributedGridIO, Load_3D )
+{
+    TestDistributedGridIO<3,Cuda>::TestLoad();
+}
+
+#else
+TEST(NoMPI, NoTest)
+{
+    ASSERT_TRUE(true) << ":-(";
+}
+#endif
+
+#endif
+
+#if (defined(HAVE_GTEST) && defined(HAVE_MPI))
+#include <sstream>
+
+  class MinimalistBuffredPrinter : public ::testing::EmptyTestEventListener {
+      
+  private:
+      std::stringstream sout;
+      
+  public:
+      
+    // Called before a test starts.
+    virtual void OnTestStart(const ::testing::TestInfo& test_info) {
+      sout<< test_info.test_case_name() <<"." << test_info.name() << " Start." <<std::endl;
+    }
+
+    // Called after a failed assertion or a SUCCEED() invocation.
+    virtual void OnTestPartResult(
+        const ::testing::TestPartResult& test_part_result) {
+      sout << (test_part_result.failed() ? "====Failure=== " : "===Success=== ") 
+              << test_part_result.file_name() << " "
+              << test_part_result.line_number() <<std::endl
+              << test_part_result.summary() <<std::endl;
+    }
+
+    // Called after a test ends.
+    virtual void OnTestEnd(const ::testing::TestInfo& test_info) 
+    {
+        int rank=CommunicatorType::GetRank();
+        sout<< test_info.test_case_name() <<"." << test_info.name() << " End." <<std::endl;
+        std::cout << rank << ":" << std::endl << sout.str()<< std::endl;
+        sout.str( std::string() );
+        sout.clear();
+    }
+  };
+#endif
+
+#include "../GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+
+    #ifdef HAVE_MPI
+       ::testing::TestEventListeners& listeners =
+          ::testing::UnitTest::GetInstance()->listeners();
+
+       delete listeners.Release(listeners.default_result_printer());
+       listeners.Append(new MinimalistBuffredPrinter);
+
+       CommunicatorType::Init(argc,argv);
+    #endif
+       int result= RUN_ALL_TESTS();
+
+    #ifdef HAVE_MPI
+       CommunicatorType::Finalize();
+    #endif
+       return result;
+#else
+   
+   throw GtestMissingError();
+#endif
+}
diff --git a/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77dbc74663330dd2d8d4d7fa32576d99c933c485
--- /dev/null
+++ b/src/UnitTests/SaveAndLoadMeshfunctionTest.cpp
@@ -0,0 +1,125 @@
+/***************************************************************************
+                          SaveAndLoadMeshfunctionTest.cpp  -  description
+                             -------------------
+    begin                : Dec 2, 2017
+    copyright            : (C) 2017 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+#include <TNL/Functions/MeshFunction.h>
+
+#ifdef HAVE_GTEST 
+#include <gtest/gtest.h>
+
+#include "Mpi/Functions.h"
+
+#include <iostream>
+
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+
+
+#define FILENAME "./test-file.tnl"
+
+//=====================================TEST CLASS==============================================
+
+template <int dim>
+class TestSaveAndLoadMeshfunction
+{
+    public:
+        static void Test()
+        {
+
+            typedef Grid<dim,double,Host,int> MeshType;
+            typedef MeshFunction<MeshType> MeshFunctionType;
+            typedef Vector<double,Host,int> DofType;
+            typedef typename MeshType::Cell Cell;
+            typedef typename MeshType::IndexType IndexType; 
+            typedef typename MeshType::PointType PointType; 
+        
+            typedef typename MeshType::CoordinatesType CoordinatesType;
+            typedef LinearFunction<double,dim> LinearFunctionType;
+
+            SharedPointer< LinearFunctionType, Host > linearFunctionPtr;
+            MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;    
+
+
+            PointType localOrigin;
+            localOrigin.setValue(-0.5);
+            PointType localProportions;
+            localProportions.setValue(10);
+            
+            SharedPointer<MeshType>  localGridptr;
+            localGridptr->setDimensions(localProportions);
+            localGridptr->setDomain(localOrigin,localProportions);
+
+            DofType localDof(localGridptr->template getEntitiesCount< Cell >());
+
+            SharedPointer<MeshFunctionType> localMeshFunctionptr;
+            localMeshFunctionptr->bind(localGridptr,localDof);
+            linearFunctionEvaluator.evaluateAllEntities(localMeshFunctionptr , linearFunctionPtr);
+
+            File file;
+            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;
+            loadGridptr->setDimensions(localProportions);
+            loadGridptr->setDomain(localOrigin,localProportions);
+
+            DofType loadDof(loadGridptr->template getEntitiesCount< Cell >());
+            SharedPointer<MeshFunctionType> loadMeshFunctionptr;
+            loadMeshFunctionptr->bind(loadGridptr,loadDof);
+
+            for(int i=0;i<loadDof.getSize();i++)
+            {
+                loadDof[i]=-1;
+            }
+
+            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 );
+
+        };
+};
+
+TEST( CopyEntitiesTest, 1D )
+{
+    TestSaveAndLoadMeshfunction<1>::Test();
+}
+
+TEST( CopyEntitiesTest, 2D )
+{
+    TestSaveAndLoadMeshfunction<2>::Test();
+}
+
+TEST( CopyEntitiesTest, 3D )
+{
+    TestSaveAndLoadMeshfunction<3>::Test();
+}
+
+
+#endif
+
+#include "GtestMissingError.h"
+int main( int argc, char* argv[] )
+{
+#ifdef HAVE_GTEST
+   ::testing::InitGoogleTest( &argc, argv );
+   return RUN_ALL_TESTS();
+#else
+   throw GtestMissingError();
+#endif
+}
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 22266594a9b622be6d0345b3d8ec92a33c979878..21090988a1322a52fdb10006ef413e95db0504a7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -5,5 +5,6 @@ ADD_SUBDIRECTORY( benchmarks )
 #ADD_SUBDIRECTORY( unit-tests )
 ADD_SUBDIRECTORY( long-time-unit-tests )
 ADD_SUBDIRECTORY( mic )
+ADD_SUBDIRECTORY( mpi )
 
-unset( ENABLE_CODECOVERAGE )
\ No newline at end of file
+unset( ENABLE_CODECOVERAGE )
diff --git a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem.h b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem.h
index 25d6eb81ba931c38b222a81ff120b78d3ff07b6d..7eb8c3839cc7b88e06414c2aeba35a95a2594fe7 100644
--- a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem.h
+++ b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem.h
@@ -11,7 +11,8 @@ using namespace TNL::Problems;
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
-           typename DifferentialOperator >
+          typename CommType,
+          typename DifferentialOperator >
 class HeatEquationBenchmarkProblem:
    public PDEProblem< Mesh,
                          typename DifferentialOperator::RealType,
@@ -30,6 +31,7 @@ class HeatEquationBenchmarkProblem:
       typedef SharedPointer< BoundaryCondition > BoundaryConditionPointer;
       typedef SharedPointer< RightHandSide, DeviceType > RightHandSidePointer;
       
+      typedef CommType CommunicatorType;
 
       using typename BaseType::MeshType;
       using typename BaseType::MeshPointer;
diff --git a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem_impl.h b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem_impl.h
index 573eab7885f83c8ffb2f26a6a4438b3129258099..128dd9efd05243e903863e0b38f121ef27dd4676 100644
--- a/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem_impl.h
+++ b/tests/benchmarks/heat-equation-benchmark/HeatEquationBenchmarkProblem_impl.h
@@ -10,9 +10,10 @@
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getTypeStatic()
 {
    return String( "HeatEquationBenchmarkProblem< " ) + Mesh :: getTypeStatic() + " >";
@@ -21,8 +22,9 @@ getTypeStatic()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 HeatEquationBenchmarkProblem()
 : cudaMesh( 0 ),
   cudaBoundaryConditions( 0 ),
@@ -34,9 +36,10 @@ HeatEquationBenchmarkProblem()
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 String
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getPrologHeader() const
 {
    return String( "Heat Equation Benchmark" );
@@ -45,9 +48,10 @@ getPrologHeader() const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) const
 {
    /****
@@ -59,9 +63,10 @@ writeProlog( Logger& logger, const Config::ParameterContainer& parameters ) cons
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setup( const MeshPointer& meshPointer,
        const Config::ParameterContainer& parameters,
        const String& prefix )
@@ -84,9 +89,10 @@ setup( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
-typename HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::IndexType
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+typename HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::IndexType
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getDofs( const MeshPointer& meshPointer ) const
 {
    /****
@@ -99,9 +105,10 @@ getDofs( const MeshPointer& meshPointer ) const
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 bindDofs( const MeshPointer& meshPointer,
           DofVectorPointer& dofsPointer )
 {
@@ -110,9 +117,10 @@ bindDofs( const MeshPointer& meshPointer,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setInitialCondition( const Config::ParameterContainer& parameters,
                      const MeshPointer& meshPointer,
                      DofVectorPointer& dofsPointer,
@@ -131,10 +139,11 @@ setInitialCondition( const Config::ParameterContainer& parameters,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
    template< typename Matrix >
 bool
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 setupLinearSystem( const MeshType& mesh,
                    Matrix& matrix )
 {
@@ -157,9 +166,10 @@ setupLinearSystem( const MeshType& mesh,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 bool
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 makeSnapshot( const RealType& time,
               const IndexType& step,
               const MeshPointer& meshPointer,
@@ -324,6 +334,7 @@ template< typename GridType,
           typename GridEntity,
           typename DifferentialOperator,
           typename RightHandSide,
+          typename CommType,
           typename MeshFunction >
 __global__ void 
 heatEquationTemplatedCompact( const GridType* grid,
@@ -372,9 +383,10 @@ heatEquationTemplatedCompact( const GridType* grid,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
 void
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 getExplicitUpdate( const RealType& time,
                 const RealType& tau,
                 const MeshPointer& mesh,
@@ -528,7 +540,7 @@ getExplicitUpdate( const RealType& time,
          explicitUpdater.setBoundaryConditions( this->boundaryConditionPointer );
          explicitUpdater.setRightHandSide( this->rightHandSidePointer );
          
-         this->explicitUpdater.template update< typename Mesh::Cell >( time, tau, mesh, this->u, this->fu );
+         this->explicitUpdater.template update< typename Mesh::Cell, CommunicatorType >( time, tau, mesh, this->u, this->fu );
       }
    }
 }
@@ -536,10 +548,11 @@ getExplicitUpdate( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
    template< typename MatrixPointer >
 void
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 assemblyLinearSystem( const RealType& time,
                       const RealType& tau,
                       const MeshPointer& mesh,
@@ -569,8 +582,9 @@ assemblyLinearSystem( const RealType& time,
 template< typename Mesh,
           typename BoundaryCondition,
           typename RightHandSide,
+          typename CommType,
           typename DifferentialOperator >
-HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, DifferentialOperator >::
+HeatEquationBenchmarkProblem< Mesh, BoundaryCondition, RightHandSide, CommType, DifferentialOperator >::
 ~HeatEquationBenchmarkProblem()
 {
    if( this->cudaMesh ) Devices::Cuda::freeFromDevice( this->cudaMesh );
diff --git a/tests/benchmarks/heat-equation-benchmark/tnl-benchmark-heat-equation.h b/tests/benchmarks/heat-equation-benchmark/tnl-benchmark-heat-equation.h
index 3db5347a724356c11cf9afe8407ad7cacb5d4300..758003470a0167d52ccfe1b14c3654682a6240dd 100644
--- a/tests/benchmarks/heat-equation-benchmark/tnl-benchmark-heat-equation.h
+++ b/tests/benchmarks/heat-equation-benchmark/tnl-benchmark-heat-equation.h
@@ -48,7 +48,8 @@ template< typename Real,
           typename Index,
           typename MeshType,
           typename ConfigTag,
-          typename SolverStarter >
+          typename SolverStarter,
+          typename CommunicatorType >
 class HeatEquationBenchmarkSetter
 {
    public:
@@ -76,12 +77,12 @@ class HeatEquationBenchmarkSetter
              if( boundaryConditionsType == "dirichlet" )
              {
                 typedef Operators::DirichletBoundaryConditions< MeshType, Constant, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-                typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+                typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
                 SolverStarter solverStarter;
                 return solverStarter.template run< Problem >( parameters );
              }
              typedef Operators::NeumannBoundaryConditions< MeshType, Constant, Real, Index > BoundaryConditions;
-             typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+             typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
              SolverStarter solverStarter;
              return solverStarter.template run< Problem >( parameters );
           }
@@ -89,12 +90,12 @@ class HeatEquationBenchmarkSetter
           if( boundaryConditionsType == "dirichlet" )
           {
              typedef Operators::DirichletBoundaryConditions< MeshType, MeshFunction, MeshType::getMeshDimension(), Real, Index > BoundaryConditions;
-             typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+             typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
              SolverStarter solverStarter;
              return solverStarter.template run< Problem >( parameters );
           }
           typedef Operators::NeumannBoundaryConditions< MeshType, MeshFunction, Real, Index > BoundaryConditions;
-          typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, ApproximateOperator > Problem;
+          typedef HeatEquationBenchmarkProblem< MeshType, BoundaryConditions, RightHandSide, CommunicatorType, ApproximateOperator > Problem;
           SolverStarter solverStarter;
           return solverStarter.template run< Problem >( parameters );
       }
diff --git a/tests/mpi/CMakeLists.txt b/tests/mpi/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0be5708088fcf742181c0ef3c0061484883841e5
--- /dev/null
+++ b/tests/mpi/CMakeLists.txt
@@ -0,0 +1,53 @@
+    ADD_EXECUTABLE( tnlMeshFuncttionEvaluateTest ${headers} MeshFunctionEvauateTest.cpp )   
+    TARGET_LINK_LIBRARIES( tnlMeshFuncttionEvaluateTest ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+    TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTest PUBLIC "-DDIMENSION=2" )
+   	TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTest PUBLIC "-DXDISTR -DYDISTR" )
+
+    ADD_EXECUTABLE( tnlMeshFuncttionEvaluateTestX ${headers} MeshFunctionEvauateTest.cpp )   
+    TARGET_LINK_LIBRARIES( tnlMeshFuncttionEvaluateTestX ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+   	TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestX PUBLIC "-DDIMENSION=2" )
+   	TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestX PUBLIC "-DXDISTR" )
+
+    ADD_EXECUTABLE( tnlMeshFuncttionEvaluateTestY ${headers} MeshFunctionEvauateTest.cpp )   
+    TARGET_LINK_LIBRARIES( tnlMeshFuncttionEvaluateTestY ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+   	TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestY PUBLIC "-DDIMENSION=2" )
+   	TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestY PUBLIC "-DYDISTR" )
+
+
+    ADD_EXECUTABLE( mpiio-save-test ${headers} mpiio-save-test.cpp )   
+    TARGET_LINK_LIBRARIES(  mpiio-save-test ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+
+    ADD_EXECUTABLE( mpiio-save-load-test ${headers} mpiio-save-load-test.cpp )   
+    TARGET_LINK_LIBRARIES(  mpiio-save-load-test ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+
+
+    #ADD_EXECUTABLE( tnlMeshFuncttionEvaluateTestZ ${headers} MeshFunctionEvauateTest.cpp )   
+    #TARGET_LINK_LIBRARIES( tnlMeshFuncttionEvaluateTestZ ${CPPUNIT_LIBRARIES}
+          #                                                  tnl${mpiExt}-0.1 )
+	#TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestZ PUBLIC "-DDIMENSION=3" )
+	#TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestZ PUBLIC "-DZDISTR" )
+
+    #ADD_EXECUTABLE( tnlMeshFuncttionEvaluateTestXY ${headers} MeshFunctionEvauateTest.cpp )   
+    #TARGET_LINK_LIBRARIES( tnlMeshFuncttionEvaluateTestXY ${CPPUNIT_LIBRARIES}
+         #                                                     tnl${mpiExt}-0.1 )
+	#TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestXY PUBLIC "-DDIMENSION=3" )
+	#TARGET_COMPILE_DEFINITIONS( tnlMeshFuncttionEvaluateTestXY PUBLIC "-DXDISTR -DYDISTR" )
+
+IF( BUILD_CUDA )
+    CUDA_ADD_EXECUTABLE( mpi-gpu-test ${headers} mpi-gpu.cu )
+    TARGET_LINK_LIBRARIES( mpi-gpu-test ${CPPUNIT_LIBRARIES}
+                                                   tnl )   
+
+    CUDA_ADD_EXECUTABLE( GPUmeshFunctionEvaluateTest ${headers} GPUmeshFuncitonEvaluateTest.cu )
+    TARGET_LINK_LIBRARIES( GPUmeshFunctionEvaluateTest ${CPPUNIT_LIBRARIES}
+                                           tnl )   
+
+    CUDA_ADD_EXECUTABLE( mpiio-save-test-gpu ${headers} mpiio-save-test.cu )   
+    TARGET_LINK_LIBRARIES(  mpiio-save-test-gpu ${CPPUNIT_LIBRARIES}
+                                                           tnl )
+ENDIF( BUILD_CUDA )    
diff --git a/tests/mpi/GPUmeshFuncitonEvaluateTest.cu b/tests/mpi/GPUmeshFuncitonEvaluateTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..b421dc9c6300074a0dc390be89888341b79fbc5d
--- /dev/null
+++ b/tests/mpi/GPUmeshFuncitonEvaluateTest.cu
@@ -0,0 +1,182 @@
+#include <iostream>
+
+
+#if defined(HAVE_MPI) && defined(HAVE_CUDA)
+
+#include <TNL/Containers/Array.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Functions/MeshFunction.h>
+
+#include <TNL/Timer.h>
+#include  <TNL/SharedPointer.h>
+
+using namespace std;
+
+#define DIMENSION 3
+//#define OUTPUT 
+#define XDISTR
+//#define YDISTR
+//#define ZDISTR
+
+#include "../../src/UnitTests/Mpi/Functions.h"
+
+using namespace TNL;
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Meshes::DistributedMeshes;
+using namespace TNL::Communicators;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+
+ 
+int main ( int argc, char *argv[])
+{
+    
+  Timer all,setup,eval,sync;
+  
+  typedef Cuda Device;  
+  //typedef Host Device;  
+
+  typedef MpiCommunicator CommunicatorType;
+  //typedef NoDistrCommunicator CommType;
+  typedef Grid<DIMENSION, double,Device,int> MeshType;
+  typedef MeshFunction<MeshType> MeshFunctionType;
+  typedef Vector<double,Device,int> DofType;
+  typedef typename MeshType::Cell Cell;
+  typedef typename MeshType::IndexType IndexType; 
+  typedef typename MeshType::PointType PointType; 
+  
+  typedef DistributedMesh<MeshType> DistributedMeshType;
+  
+  typedef LinearFunction<double,DIMENSION> LinearFunctionType;
+  typedef ConstFunction<double,DIMENSION> ConstFunctionType;
+  
+  CommunicatorType::Init(argc,argv);
+
+  int size=10;
+  int cycles=1;
+  if(argc==3)
+  {
+      size=strtol(argv[1],NULL,10);
+      cycles=strtol(argv[2],NULL,10);
+      //cout << "size: "<< size <<"cycles: "<< cycles <<endl;
+  }
+  
+    all.start();
+    setup.start();
+  
+ PointType globalOrigin;
+ globalOrigin.setValue(-0.5);
+ 
+ PointType globalProportions;
+ globalProportions.setValue(size);
+ 
+ 
+ MeshType globalGrid;
+ globalGrid.setDimensions(globalProportions);
+ globalGrid.setDomain(globalOrigin,globalProportions);
+
+ 
+ int distr[DIMENSION];
+ for(int i=0;i<DIMENSION;i++) 
+    distr[i]=1;
+
+ #ifdef XDISTR
+     distr[0]=0;
+ #endif
+
+ #ifdef YDISTR
+    distr[1]=0;
+ #endif
+
+ #ifdef ZDISTR
+     distr[2]=0;
+ #endif
+
+ typename MeshType::CoordinatesType overlap;
+ overlap.setValue(1);
+ DistributedMeshType distrgrid;
+ distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap, distr); 
+   
+ SharedPointer<MeshType> gridptr;
+ SharedPointer<MeshFunctionType> meshFunctionptr;
+ MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;
+ MeshFunctionEvaluator< MeshFunctionType, ConstFunctionType > constFunctionEvaluator;
+ 
+  distrgrid.SetupGrid(*gridptr);
+  
+  DofType dof(gridptr->template getEntitiesCount< Cell >());
+
+  dof.setValue(0);
+  
+  meshFunctionptr->bind(gridptr,dof);  
+  
+  SharedPointer< LinearFunctionType, Device > linearFunctionPtr;
+  SharedPointer< ConstFunctionType, Device > constFunctionPtr; 
+   
+  setup.stop();
+  
+  double sum=0.0;
+
+  constFunctionPtr->Number=CommunicatorType::GetRank();
+  
+  for(int i=0;i<cycles;i++)
+    {    
+        eval.start();
+        
+        constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+        //linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);
+        CommunicatorType::Barrier();
+        eval.stop();
+
+        sync.start();    
+        meshFunctionptr->template Synchronize<CommunicatorType>();
+        CommunicatorType::Barrier();
+        sync.stop();
+
+        ///sum+=dof[gridptr->getDimensions().x()/2]; //dummy acces to array    
+    }
+  all.stop();
+  
+#ifdef OUTPUT    
+  //print local dof
+  Printer<MeshType,DofType>::print_dof(CommunicatorType::GetRank(),*gridptr, dof);
+#endif
+  
+  if(CommunicatorType::GetRank()==0)
+  {
+    cout << sum <<endl<<endl;  
+    
+    cout<<"distr: ";
+    cout << distrgrid.printProcessDistr().getString();
+    cout << endl;
+  
+    cout<<"setup: "<<setup.getRealTime() <<endl;
+    cout<<"evalpercycle: "<<eval.getRealTime()/cycles<<endl;
+    cout<<"syncpercycle: "<<sync.getRealTime()/cycles<<endl;
+    cout <<"eval: "<<eval.getRealTime()<<endl;
+    cout <<"sync: "<<sync.getRealTime()<<endl;
+    cout<<"all: "<<all.getRealTime()<<endl<<endl;
+  }
+  
+
+  CommunicatorType::Finalize();
+
+  return 0;
+
+}
+
+#else
+
+using namespace std;
+
+int main(void)
+{
+    cout << "MPI or Cuda missing...." <<endl;
+}
+#endif
+
+
diff --git a/tests/mpi/MPI-Test.cpp b/tests/mpi/MPI-Test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e6ef254d377921ca8546abb5cd0886e51a7906c9
--- /dev/null
+++ b/tests/mpi/MPI-Test.cpp
@@ -0,0 +1,32 @@
+/*
+* Experimentální test pro implementaci MPI do TNL
+ */
+
+#include <iostream>
+#include <mpi.h>
+
+unsigned int errors=0;
+unsigned int success=0;
+#define TEST_TEST(a) if((a)){cout << __LINE__ <<":\t OK " <<endl;success++;}else{cout << __LINE__<<":\t FAIL" <<endl;errors++;}
+#define TEST_RESULT cout<<"SUCCES: "<<success<<endl<<"ERRRORS: "<<errors<<endl;
+inline void Test_Say( const char * message)
+{
+#ifdef TEST_VERBOSE
+	cout << message <<endl;
+#endif
+}
+
+using namespace std;
+
+int main ( int argc, char *argv[])
+{
+  int rank, size;
+
+  MPI_Init (&argc, &argv);      /* starts MPI */
+  MPI_Comm_rank (MPI_COMM_WORLD, &rank);        /* get current process id */
+  MPI_Comm_size (MPI_COMM_WORLD, &size);        /* get number of processes */
+  cout << "Hello world from process " << rank <<" of " << size << endl;
+  MPI_Finalize();
+  return 0;
+}
+
diff --git a/tests/mpi/MeshFunctionEvauateTest.cpp b/tests/mpi/MeshFunctionEvauateTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8aa6fee8ab142f7e79041405fca4ce517038dacc
--- /dev/null
+++ b/tests/mpi/MeshFunctionEvauateTest.cpp
@@ -0,0 +1,183 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+
+#ifdef HAVE_MPI
+
+#include <TNL/Containers/Array.h>
+#include <TNL/Meshes/Grid.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Communicators/NoDistrCommunicator.h>
+#include <TNL/Functions/MeshFunction.h>
+
+#include <TNL/Timer.h>
+#include  <TNL/SharedPointer.h>
+
+//#define DIMENSION 3
+//#define OUTPUT 
+//#define XDISTR
+//#define YDISTR
+//#define ZDISTR
+
+#include "../../src/UnitTests/Mpi/Functions.h"
+
+using namespace TNL;
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Meshes::DistributedMeshes;
+using namespace TNL::Communicators;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+#endif
+ 
+int main ( int argc, char *argv[])
+{
+    
+#ifdef HAVE_MPI
+  Timer all,setup,eval,sync;
+    
+
+  typedef MpiCommunicator CommunicatorType;
+  //typedef NoDistrCommunicator CommType;
+  typedef Grid<DIMENSION, double,Host,int> MeshType;
+  typedef MeshFunction<MeshType> MeshFunctionType;
+  typedef Vector<double,Host,int> DofType;
+  typedef typename MeshType::Cell Cell;
+  typedef typename MeshType::IndexType IndexType; 
+  typedef typename MeshType::PointType PointType; 
+  
+  typedef DistributedMesh<MeshType> DistributedMeshType;
+  
+  typedef LinearFunction<double,DIMENSION> LinearFunctionType;
+  typedef ConstFunction<double,DIMENSION> ConstFunctionType;
+  
+  CommunicatorType::Init(argc,argv);
+
+  int size=9;
+  int cycles=1;
+  if(argc==3)
+  {
+      size=strtol(argv[1],NULL,10);
+      cycles=strtol(argv[2],NULL,10);
+      //cout << "size: "<< size <<"cycles: "<< cycles <<endl;
+  }
+  
+    all.start();
+    setup.start();
+  
+ PointType globalOrigin;
+ globalOrigin.setValue(-0.5);
+ 
+ PointType globalProportions;
+ globalProportions.setValue(size);
+ 
+ 
+ MeshType globalGrid;
+ globalGrid.setDimensions(globalProportions);
+ globalGrid.setDomain(globalOrigin,globalProportions);
+
+ 
+ int distr[DIMENSION];
+ for(int i=0;i<DIMENSION;i++) 
+    distr[i]=1;
+
+ #ifdef XDISTR
+     distr[0]=0;
+ #endif
+
+ #ifdef YDISTR
+    distr[1]=0;
+ #endif
+
+ #ifdef ZDISTR
+     distr[2]=0;
+ #endif
+
+ typename MeshType::CoordinatesType overlap;
+ overlap.setValue(1);
+ DistributedMeshType distrgrid;
+ distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap, distr); 
+   
+ SharedPointer<MeshType> gridptr;
+ SharedPointer<MeshFunctionType> meshFunctionptr;
+ MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;
+ MeshFunctionEvaluator< MeshFunctionType, ConstFunctionType > constFunctionEvaluator;
+ 
+  distrgrid.SetupGrid(*gridptr);
+  
+  DofType dof(gridptr->template getEntitiesCount< Cell >());
+
+  dof.setValue(0);
+  
+  meshFunctionptr->bind(gridptr,dof);  
+  
+  SharedPointer< LinearFunctionType, Host > linearFunctionPtr;
+  SharedPointer< ConstFunctionType, Host > constFunctionPtr; 
+   
+  
+  
+  setup.stop();
+  
+  double sum=0.0;
+
+  constFunctionPtr->Number=CommunicatorType::GetRank();
+  
+  for(int i=0;i<cycles;i++)
+    {    
+        eval.start();
+        
+        constFunctionEvaluator.evaluateAllEntities( meshFunctionptr , constFunctionPtr );
+        //linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);
+        CommunicatorType::Barrier();
+        eval.stop();
+
+        sync.start();    
+        meshFunctionptr->template Synchronize<CommunicatorType>();
+        CommunicatorType::Barrier();
+        sync.stop();
+
+        sum+=dof[gridptr->getDimensions().x()/2]; //dummy acces to array    
+    }
+  all.stop();
+  
+#ifdef OUTPUT    
+  //print local dof
+  Printer<MeshType,DofType>::print_dof(CommunicatorType::GetRank(),*gridptr, dof);
+#endif
+  
+  if(CommunicatorType::GetRank()==0)
+  {
+    cout << sum <<endl<<endl;  
+    
+    cout<<"distr: ";
+    cout << distrgrid.printProcessDistr().getString();
+    cout << endl;
+  
+    cout<<"setup: "<<setup.getRealTime() <<endl;
+    cout<<"evalpercycle: "<<eval.getRealTime()/cycles<<endl;
+    cout<<"syncpercycle: "<<sync.getRealTime()/cycles<<endl;
+    cout <<"eval: "<<eval.getRealTime()<<endl;
+    cout <<"sync: "<<sync.getRealTime()<<endl;
+    cout<<"all: "<<all.getRealTime()<<endl<<endl;
+  }
+  
+
+  CommunicatorType::Finalize();
+
+
+
+#else
+  std::cout<<"MPI not Supported." << std::endl;
+#endif
+  return 0;
+
+}
diff --git a/tests/mpi/mpi-gpu.cu b/tests/mpi/mpi-gpu.cu
new file mode 100644
index 0000000000000000000000000000000000000000..e136e6bead8350ef8dedb1cab364310f117234cb
--- /dev/null
+++ b/tests/mpi/mpi-gpu.cu
@@ -0,0 +1,79 @@
+#include <iostream>
+
+using namespace std;
+
+
+#if defined(HAVE_MPI) && defined(HAVE_CUDA)
+
+#include <cuda_runtime.h>
+#include <mpi.h>
+ 
+__global__ void SetKernel(float *deviceData, float value)
+{
+    // Just a dummy kernel
+    const int idx = blockIdx.x * blockDim.x + threadIdx.x;
+    deviceData[idx] = value;
+}
+
+double sum(float * data, int count)
+{
+    double sum=0;
+    for(int i=0;i<count;i++)
+        sum+=data[i];
+
+    return sum;
+}
+
+
+int main(int argc, char **argv)
+{
+    MPI_Init(&argc, &argv);
+
+    int rank;
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+    int blockSize = 256; //počet threadů v v bloku
+    int gridSize = 1000; //počet bloků v gridu -> musí být menší než maxGridSize v cudeGetDeviceProperties
+
+    int dataCount=blockSize*gridSize;
+
+    float * deviceData=NULL;
+    cudaMalloc((void **)&deviceData, dataCount * sizeof(float));
+
+    if(rank==0)
+    {
+        cout << rank<<": "<<"Setup GPU alocated array to 1" << endl;
+        SetKernel<<< gridSize,blockSize >>>(deviceData,1.0f);
+        cout << rank<<": "<<" Sending GPU data " <<endl;
+        MPI_Send((void*)deviceData, dataCount, MPI_FLOAT, 1, 1, MPI_COMM_WORLD);
+    }
+    
+    if(rank==1) 
+    {
+        cout << rank<<": "<<" Reciving GPU data " <<endl;
+        MPI_Recv((void*) deviceData, dataCount, MPI_FLOAT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+
+        float *data = new float[dataCount];
+        cout << rank<<": "<<" Copying data from GPU to CPU " <<endl;
+        cudaMemcpy( (void*) data, (void*)deviceData, dataCount*sizeof(float),  cudaMemcpyDeviceToHost);    
+        cout << rank<<": "<<" Computin Sum on CPU " <<endl;
+        cout << rank<<": "<< "sum:" << sum(data,dataCount) << endl;
+        delete [] data;
+    }
+
+    cudaFree(deviceData);
+
+    MPI_Finalize();
+return 0;
+}
+
+#else
+
+int main(void)
+{
+    cout << "CUDA or MPI missing...." <<endl;
+}
+
+#endif
+
+ 
diff --git a/tests/mpi/mpiio-save-load-test.cpp b/tests/mpi/mpiio-save-load-test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f96843d7e26fcf7c64ed8448dd4926a70b4f5ced
--- /dev/null
+++ b/tests/mpi/mpiio-save-load-test.cpp
@@ -0,0 +1,102 @@
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+
+#ifdef HAVE_MPI
+
+#define MPIIO
+#include <TNL/Meshes/DistributedMeshes/DistributedGridIO.h>
+
+
+#include "../../src/UnitTests/Mpi/Functions.h"
+
+#define DIM 1 
+
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+using namespace TNL::Meshes::DistributedMeshes;
+
+
+int main(int argc, char **argv)
+{
+
+        typedef Host Device;
+        typedef MpiCommunicator CommunicatorType;
+
+        typedef Grid<DIM,double,Device,int> MeshType;
+        typedef MeshFunction<MeshType> MeshFunctionType;
+        typedef Vector<double,Device,int> DofType;
+        typedef typename MeshType::Cell Cell;
+        typedef typename MeshType::IndexType IndexType; 
+        typedef typename MeshType::PointType PointType; 
+        typedef DistributedMesh<MeshType> DistributedGridType;
+
+        typedef typename DistributedGridType::CoordinatesType CoordinatesType;
+        typedef LinearFunction<double,DIM> LinearFunctionType;
+
+        CommunicatorType::Init(argc, argv);
+
+        SharedPointer< LinearFunctionType, Device > linearFunctionPtr;
+        MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;    
+                
+        //save distributed meshfunction into files
+        PointType globalOrigin;
+        globalOrigin.setValue(-0.5);
+
+        PointType globalProportions;
+        globalProportions.setValue(10);
+
+
+        MeshType globalGrid;
+        globalGrid.setDimensions(globalProportions);
+        globalGrid.setDomain(globalOrigin,globalProportions);
+        
+        File meshFile;
+        meshFile.open( String("globalGrid.tnl"),IOMode::write);
+        globalGrid.save( meshFile );
+        meshFile.close();
+
+        CoordinatesType overlap;
+        overlap.setValue(1);
+        DistributedGridType distrgrid;
+        distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap);
+
+        SharedPointer<MeshType> gridptr;
+        SharedPointer<MeshFunctionType> meshFunctionptr;
+        distrgrid.SetupGrid(*gridptr);
+       
+        DofType dofsave(gridptr->template getEntitiesCount< Cell >());
+        dofsave.setValue(0);
+        meshFunctionptr->bind(gridptr,dofsave);
+            
+        linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);
+        
+        String fileName=String("./meshFunction.tnl");
+        DistributedGridIO<MeshFunctionType,MpiIO> ::save(fileName, *meshFunctionptr );
+
+        DofType dofload(gridptr->template getEntitiesCount< Cell >());
+        dofload.setValue(0);
+        meshFunctionptr->bind(gridptr,dofload);
+
+        DistributedGridIO<MeshFunctionType,MpiIO> ::load(fileName, *meshFunctionptr );
+
+        for(int i=0;i<dofload.getSize();i++)
+        {
+            if(dofsave[i]!=dofload[i])
+                std::cout<<"Chyba na pozici "<< i << " dofsave: "<< dofsave[i] << " dofload: "<<dofload[i] <<std::endl;
+            else
+                std::cout <<"Ok!"<<std::endl;
+        }
+
+        CommunicatorType::Finalize();
+
+}
+
+#else
+
+main(){}
+#endif
+
diff --git a/tests/mpi/mpiio-save-test.cpp b/tests/mpi/mpiio-save-test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c946a2d637e0e15a4d63a443a12ae055ddfcc6d7
--- /dev/null
+++ b/tests/mpi/mpiio-save-test.cpp
@@ -0,0 +1,3 @@
+#define DEVICE Host
+
+#include "mpiio-save-test.h"
diff --git a/tests/mpi/mpiio-save-test.cu b/tests/mpi/mpiio-save-test.cu
new file mode 100644
index 0000000000000000000000000000000000000000..24f98056dd37fe202f0e5809620d00a1ab323777
--- /dev/null
+++ b/tests/mpi/mpiio-save-test.cu
@@ -0,0 +1,3 @@
+#define DEVICE Cuda
+
+#include "mpiio-save-test.h"
diff --git a/tests/mpi/mpiio-save-test.h b/tests/mpi/mpiio-save-test.h
new file mode 100644
index 0000000000000000000000000000000000000000..4b03e497683f0b8c86de1694f9af6567fc87d890
--- /dev/null
+++ b/tests/mpi/mpiio-save-test.h
@@ -0,0 +1,91 @@
+#include <TNL/Communicators/MpiCommunicator.h>
+#include <TNL/Meshes/DistributedMeshes/DistributedMesh.h>
+#include <TNL/Functions/MeshFunction.h>
+
+#ifdef HAVE_MPI
+
+#define MPIIO
+#include <TNL/Meshes/DistributedMeshes/DistributedGridIO.h>
+
+
+#include "../../src/UnitTests/Mpi/Functions.h"
+
+#define DIM 2
+
+using namespace TNL::Containers;
+using namespace TNL::Meshes;
+using namespace TNL::Functions;
+using namespace TNL::Devices;
+using namespace TNL::Communicators;
+using namespace TNL::Meshes::DistributedMeshes;
+
+
+int main(int argc, char **argv)
+{
+
+        typedef DEVICE Device;
+        typedef MpiCommunicator CommunicatorType;
+
+        typedef Grid<DIM,double,Device,int> MeshType;
+        typedef MeshFunction<MeshType> MeshFunctionType;
+        typedef Vector<double,Device,int> DofType;
+        typedef typename MeshType::Cell Cell;
+        typedef typename MeshType::IndexType IndexType; 
+        typedef typename MeshType::PointType PointType; 
+        typedef DistributedMesh<MeshType> DistributedGridType;
+
+        typedef typename DistributedGridType::CoordinatesType CoordinatesType;
+        typedef LinearFunction<double,DIM> LinearFunctionType;
+
+        CommunicatorType::Init(argc, argv);
+
+        SharedPointer< LinearFunctionType, Device > linearFunctionPtr;
+        MeshFunctionEvaluator< MeshFunctionType, LinearFunctionType > linearFunctionEvaluator;    
+                
+        //save distributed meshfunction into files
+        PointType globalOrigin;
+        globalOrigin.setValue(-0.5);
+
+        PointType globalProportions;
+        //globalProportions.setValue(10);
+        globalProportions.x()=10;   
+        globalProportions.y()=20;   
+        
+
+
+        MeshType globalGrid;
+        globalGrid.setDimensions(globalProportions);
+        globalGrid.setDomain(globalOrigin,globalProportions);
+        
+        File meshFile;
+        meshFile.open( String("globalGrid.tnl"),IOMode::write);
+        globalGrid.save( meshFile );
+        meshFile.close();
+
+        CoordinatesType overlap;
+        overlap.setValue(1);
+        DistributedGridType distrgrid;
+        distrgrid.template setGlobalGrid<CommunicatorType>(globalGrid,overlap);
+
+        SharedPointer<MeshType> gridptr;
+        SharedPointer<MeshFunctionType> meshFunctionptr;
+        distrgrid.SetupGrid(*gridptr);
+       
+        DofType dof(gridptr->template getEntitiesCount< Cell >());
+        dof.setValue(0);
+        meshFunctionptr->bind(gridptr,dof);
+            
+        linearFunctionEvaluator.evaluateAllEntities(meshFunctionptr , linearFunctionPtr);
+        
+        String fileName=String("./meshFunction.tnl");
+        DistributedGridIO<MeshFunctionType,MpiIO> ::save(fileName, *meshFunctionptr );
+
+        CommunicatorType::Finalize();
+
+}
+
+#else
+
+main(){}
+
+#endif
diff --git a/tests/mpi/simple-mpiio.cu b/tests/mpi/simple-mpiio.cu
new file mode 100644
index 0000000000000000000000000000000000000000..1b8de26039b14b230a1b3a5e2d6d43cbc629d062
--- /dev/null
+++ b/tests/mpi/simple-mpiio.cu
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <mpi.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+
+   int localsize = 30;
+   int overlap=1;
+   int globalsize = localsize+2*overlap;
+
+   double * data;
+   //data=(double *)malloc(globalsize*globalsize*sizeof(double));
+   cudaMalloc((void **)&data, globalsize*globalsize*sizeof(double));
+
+   MPI_Init(&argc,&argv);
+
+   int rank;
+   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+   int size;
+   MPI_Comm_size(MPI_COMM_WORLD, &size);
+
+   printf("rank: %d, size %d\n",rank, size);
+
+   int fgsize[2],flsize[2],fstarts[2];
+   fgsize[0]=size*localsize;
+   fgsize[1]=localsize;
+   flsize[0]=localsize;
+   flsize[1]=localsize;
+   fstarts[0]=rank*localsize;
+   fstarts[1]=0;
+
+   MPI_Datatype ftype;
+
+   MPI_Type_create_subarray(2,
+        fgsize,flsize,fstarts,
+        MPI_ORDER_C,MPI_DOUBLE,&ftype);
+
+   MPI_Type_commit(&ftype);
+
+
+   int agsize[2],alsize[2],astarts[2];
+   agsize[0]=globalsize;
+   agsize[1]=globalsize;
+   alsize[0]=localsize;
+   alsize[1]=localsize;
+   astarts[0]=overlap;
+   astarts[1]=overlap;
+
+   MPI_Datatype atype;
+
+   MPI_Type_create_subarray(2,
+        agsize,alsize,astarts,
+        MPI_ORDER_C,MPI_DOUBLE,&atype);
+
+   MPI_Type_commit(&atype);
+
+
+   MPI_File file;
+   MPI_File_open(MPI_COMM_WORLD,"./pokus.file",
+	MPI_MODE_CREATE|MPI_MODE_WRONLY,
+        MPI_INFO_NULL, &file);
+
+   MPI_File_set_view(file,0,MPI_DOUBLE,ftype,"native",MPI_INFO_NULL);
+
+   MPI_Status wstatus;
+   MPI_File_write(file,data,1,atype,&wstatus);
+
+   MPI_File_close(&file);
+
+   MPI_Finalize();
+
+   free(data);
+
+return 0;
+}
+