diff --git a/tutorials/mpi_rhs/CMakeLists.txt b/tutorials/mpi_rhs/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3ed63f13623e9d7ed45010b2a7ffd418461a2b0c
--- /dev/null
+++ b/tutorials/mpi_rhs/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
+
+project(tuto CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../tutorial.cmake)
+
+add_executable(tuto main.cpp ${EXTRA_INCS})
+target_link_libraries(tuto ${EXTRA_LIBS})
diff --git a/tutorials/mpi_rhs/main.cpp b/tutorials/mpi_rhs/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..992a14e51177f9ced27118e645d294481e351775
--- /dev/null
+++ b/tutorials/mpi_rhs/main.cpp
@@ -0,0 +1,122 @@
+
+#include <gmsh.h>
+#include <gmshfem/Formulation.h>
+#include <gmshfem/GmshFem.h>
+#include <gmshfem/DistributedField.h>
+
+using namespace gmshfem;
+using namespace gmshfem::common;
+using namespace gmshfem::problem;
+using namespace gmshfem::domain;
+using namespace gmshfem::field;
+using namespace gmshfem::function;
+using namespace gmshfem::post;
+using namespace gmshfem::equation;
+
+int main(int argc, char **argv)
+{
+  GmshFem gmshFem(argc, argv);
+
+  double lc = 0.05;
+  gmshFem.userDefinedParameter(lc, "lc");
+  /****
+   * Gmsh part
+   ****/
+
+  gmsh::model::add("poissonDirichlet");
+  gmshfem::function::ScalarFunction<std::complex<double>> sol = x<double>() + 2*y<double>() + 0.5 * pow(x<double>(), 2) + x<double>()*y<double>() + 0.5 * pow(y<double>(), 2);
+
+
+  // small circle
+  gmsh::model::geo::addPoint(0., 0., 0., lc, 1);
+  gmsh::model::geo::addPoint(1, 0., 0., lc, 2);
+  gmsh::model::geo::addPoint(1, 1., 0., lc, 3);
+  gmsh::model::geo::addPoint(0, 1., 0., lc, 4);
+
+  gmsh::model::geo::addLine(1, 2, 1);
+  gmsh::model::geo::addLine(2, 3, 2);
+  gmsh::model::geo::addLine(3, 4, 3);
+  gmsh::model::geo::addLine(4, 1, 4);
+
+  gmsh::model::geo::addCurveLoop({1, 2, 3, 4}, 2);
+
+  // surface
+  gmsh::model::geo::addPlaneSurface({2}, 2);
+  gmsh::model::geo::synchronize();
+
+  // physicals
+  gmsh::model::addPhysicalGroup(2, {2}, 1);
+  gmsh::model::setPhysicalName(2, 1, "omega");
+  gmsh::model::addPhysicalGroup(1, {1, 2, 3, 4}, 1);
+  gmsh::model::setPhysicalName(1, 1, "gammaSmall");
+
+  gmsh::model::geo::synchronize();
+  gmsh::model::mesh::generate();
+  gmsh::model::mesh::createEdges();
+
+  /****
+   * GmshFem part
+   *****/
+
+  if(gmshFem.getMPISize() != 2) {
+    gmshfem::msg::error << "This example needs 2 MPI ranks" << gmshfem::msg::endl;
+    return 1;
+  }
+
+  gmsh::model::mesh::partition(2);
+  gmsh::model::mesh::generateOverlapForEntity(2, 2);
+  std::vector<int> tagsOvlp, tagsOvlpBnd, tagsBndOvlp;
+  auto rank = gmshFem.getMPIRank();
+  gmsh::model::mesh::findOverlapEntities(2, 2, rank + 1, tagsOvlp);
+
+  gmsh::vectorpair entities;
+  gmshfem::domain::Domain omegaOvlp, omegaLoc;
+  gmsh::model::getEntities(entities, 2);
+  for (auto entity: entities) {
+    std::vector<int> parts;
+    gmsh::model::getPartitions(entity.first, entity.second, parts);
+    if (std::find(parts.begin(), parts.end(), rank + 1) != parts.end()) {
+      omegaLoc.addEntity(entity.first, entity.second);
+    } 
+  }
+  
+  omegaOvlp.addEntity(2, tagsOvlp[0]);
+
+  auto computeError = [&omegaOvlp, &omegaLoc, &sol](bool useSum, bool addTermOnOverlap) {
+    Formulation< std::complex< double > > formulation("poissonDirichlet");
+
+    DistributedField< std::complex< double >, Form::Form0 > v("v", omegaLoc, omegaOvlp, FunctionSpaceTypeForm0::HierarchicalH1, 2);
+
+
+    formulation.integral(-dof(v), (tf(v)), omegaLoc | omegaOvlp, "Gauss6");
+    formulation.integral(sol, tf(v), omegaLoc, "Gauss6");
+    if (addTermOnOverlap)
+      formulation.integral(sol, tf(v), omegaOvlp, "Gauss6");
+    formulation.pre();
+    formulation.preDistributed();
+
+    // Pro
+    formulation.assemble();
+    formulation.setSumDistributedRHS(useSum);
+    formulation.solveDistributed(gmshfem::system::DISTRIBUTED_SOLVE_TYPE::DIRECT);
+
+    auto err = sol - v;
+    auto errL2 = gmshfem::post::integrate(err * conj(err), omegaLoc, "Gauss6");
+    auto sumErr = gmshfem::common::GmshFem::currentInstance()->reductionSum(real(errL2));
+    return std::sqrt(sumErr);
+  };
+
+  auto classic = computeError(false, true);
+  auto distributed = computeError(true, false);
+  auto tooMuch = computeError(true, true);
+  auto notEnough = computeError(false, false);
+  if(rank == 0) {
+    gmshfem::msg::info << "Classic: " << classic << gmshfem::msg::endl;
+    gmshfem::msg::info << "Distributed: " << distributed << gmshfem::msg::endl;
+    gmshfem::msg::info << "Sum and term on ovlp: " << tooMuch << gmshfem::msg::endl;
+    gmshfem::msg::info << "No sum and no term on ovlp: " << notEnough << gmshfem::msg::endl;
+  }
+
+
+  return 0;
+}