diff --git a/tutorials/poisson_overlap/CMakeLists.txt b/tutorials/poisson_overlap/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3ed63f13623e9d7ed45010b2a7ffd418461a2b0c
--- /dev/null
+++ b/tutorials/poisson_overlap/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/poisson_overlap/README.md b/tutorials/poisson_overlap/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cc49cc5f69f2ef2c94642fb22c58c033bb24a62c
--- /dev/null
+++ b/tutorials/poisson_overlap/README.md
@@ -0,0 +1,6 @@
+# Poisson Equation with overlap and Dirichlet 
+
+We solve a homogeneous Poisson (i.e. Laplace) equation with domain decomposition.
+The domain is a 2 by one rectangle, with boundary conditions $`u(0, y) = 0, u(2, y) = 2`$ and homogeneous von Neumann conditions on the other edges. The analytical solution is $`u(x,y) = x`$.
+
+This tutorial illustrates overlapping DDM. The first domain solves the equation for $`x`$ ranging from 0 to 1.2, and the other domain from 0.8 to 2. They exchange data over the center of the domain (0.8 to 1.2), which provide the boundary conditions on the inner boundaries.
\ No newline at end of file
diff --git a/tutorials/poisson_overlap/domain.geo b/tutorials/poisson_overlap/domain.geo
new file mode 100644
index 0000000000000000000000000000000000000000..283f0836ac1f517266a36dcff7cd5df9525c1fca
--- /dev/null
+++ b/tutorials/poisson_overlap/domain.geo
@@ -0,0 +1,64 @@
+// Gmsh project created on Thu Oct  6 12:29:07 2022
+//SetFactory("OpenCASCADE");
+//+
+Point(1) = {0, 0, 0, 0.05};
+//+
+Point(2) = {0.8, 0, 0, 0.05};
+//+
+Point(3) = {1.2, 0, 0, 0.05};
+//+
+Point(4) = {2.0, 0, 0, 0.05};
+//+
+Point(5) = {2, 1, 0, 0.05};
+//+
+Point(6) = {1.2, 1, 0, 0.05};
+//+
+Point(7) = {0.8, 1, 0, 0.05};
+//+
+Point(8) = {0.0, 1, 0, 0.05};
+//+
+Line(1) = {1, 2};
+//+
+Line(2) = {2, 7};
+//+
+Line(3) = {7, 8};
+//+
+Line(4) = {8, 1};
+//+
+Line(5) = {3, 2};
+//+
+Line(6) = {6, 3};
+//+
+Line(7) = {6, 7};
+//+
+Line(8) = {3, 4};
+//+
+Line(9) = {4, 5};
+//+
+Line(10) = {5, 6};
+//+
+Curve Loop(1) = {4, 1, 2, 3};
+//+
+Plane Surface(1) = {1};
+//+
+Curve Loop(2) = {7, -2, -5, -6};
+//+
+Plane Surface(2) = {2};
+//+
+Curve Loop(3) = {10, 6, 8, 9};
+//+
+Plane Surface(3) = {3};
+//+
+Physical Surface("left", 11) = {1};
+//+
+Physical Surface("center", 12) = {2};
+//+
+Physical Surface("right", 13) = {3};
+//+
+Physical Curve("gammaLeft", 14) = {4};
+//+
+Physical Curve("gammaRight", 15) = {9};
+//+
+Physical Curve("interface1", 16) = {2};
+//+
+Physical Curve("interface2", 17) = {6};
diff --git a/tutorials/poisson_overlap/main.cpp b/tutorials/poisson_overlap/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..405d84fe9c4bc7b52b18938bde2b10b9b02c948c
--- /dev/null
+++ b/tutorials/poisson_overlap/main.cpp
@@ -0,0 +1,116 @@
+#include "gmsh.h"
+
+#include <gmshddm/Formulation.h>
+#include <gmshddm/GmshDdm.h>
+#include <gmshddm/MPIInterface.h>
+#include <gmshfem/Message.h>
+
+
+using namespace gmshddm;
+using namespace gmshddm::common;
+using namespace gmshddm::domain;
+using namespace gmshddm::problem;
+using namespace gmshddm::field;
+using namespace gmshddm::mpi;
+
+using namespace gmshfem;
+using namespace gmshfem::domain;
+using namespace gmshfem::equation;
+using namespace gmshfem::problem;
+using namespace gmshfem::field;
+using namespace gmshfem::function;
+using namespace gmshfem::post;
+
+
+int main(int argc, char **argv)
+{
+  GmshDdm gmshDdm(argc, argv);
+
+  unsigned int nDom = 2;
+  int order = 1;
+  double lc = 0.05;
+  std::string gauss = "Gauss10";
+
+  gmshDdm.userDefinedParameter(nDom, "nDom");
+  gmshDdm.userDefinedParameter(order, "order");
+  gmshDdm.userDefinedParameter(lc, "lc");
+  gmshDdm.userDefinedParameter(gauss, "gauss");
+
+  gmsh::open("../domain.geo"); // Assume we run from the "build" subfolder
+  gmsh::model::mesh::generate();
+
+  // Domains are partitions of the x-axis.
+  Domain left("left"); // 0 to 1.2
+  Domain center("center"); // 0.8 to 1.2
+  Domain right("right"); // 0.8 to 2
+
+  Domain gammaLeft("gammaLeft"); // 0
+  Domain interface1("interface1"); // 0.8
+  Domain interface2("interface2"); // 1.2
+  Domain gammaRight("gammaRight"); // 2.0
+
+  Subdomain omega(nDom);
+  Interface sigma(nDom);
+  omega(0) = gammaLeft | left | interface1 | center;
+  omega(1) = gammaRight | center | interface2 | right;
+
+  sigma(0, 1) = interface1 | interface2;
+  sigma(1, 0) = interface2 | interface1;
+
+  std::vector< std::vector< unsigned int > > topology(nDom);
+  topology[0] = {1};
+  topology[1] = {0};
+
+  // Create DDM formulation
+  // And BCs on the subdomain problems
+  gmshddm::problem::Formulation< std::complex< double > > formulation("Laplace", topology);
+  SubdomainField< std::complex< double >, Form::Form0 > u("u", omega,  FunctionSpaceTypeForm0::HierarchicalH1, order);
+
+  // Toy problem with solution u(x,y) = x
+  u(0).addConstraint(gammaLeft, 0);
+  u(1).addConstraint(gammaRight, 2);
+  auto trueSolution = x<std::complex< double >>();
+
+
+  InterfaceField< std::complex< double >, Form::Form0 > g("g", sigma, FunctionSpaceTypeForm0::HierarchicalH1, order);
+  formulation.addInterfaceField(g);
+
+  // First domain
+  // Laplacian(u) = 0 on the domain, and u matches g(1,0) on the interface
+  formulation(0).integral(grad(dof(u(0))), grad(tf(u(0))), omega(0), gauss);
+  formulation(0).integral((-g(1, 0)), tf(u(0)), interface2, gauss);
+  formulation(0).integral(dof(u(0)), tf(u(0)), interface2, gauss);
+  
+  // First interface (What 0 sends to 1)
+  // Compute g(0,1) such that g(0,1) + g(1,0) = 2 u(0)
+  formulation(0, 1).integral(-dof(g(0, 1)), tf(g(0, 1)), sigma(0, 1), gauss);
+  formulation(0, 1).integral(-(g(1, 0)), tf(g(0, 1)), sigma(0, 1), gauss);
+  formulation(0, 1).integral((2*u(0)), tf(g(0, 1)), sigma(0, 1), gauss);
+
+  // Second domain
+  formulation(1).integral(grad(dof(u(1))), grad(tf(u(1))), omega(1), gauss);
+  formulation(1).integral((-g(0, 1)), tf(u(1)), interface1, gauss);
+  formulation(1).integral(dof(u(1)), tf(u(1)), interface1, gauss);
+
+  // Second interface
+  formulation(1, 0).integral(-dof(g(1, 0)), tf(g(1, 0)), sigma(1, 0), gauss);
+  formulation(1, 0).integral(-(g(0, 1)), tf(g(1, 0)), sigma(1, 0), gauss);
+  formulation(1, 0).integral((2*u(1)), tf(g(1, 0)), sigma(1, 0), gauss);
+
+
+  formulation.pre();
+  int iterMax = 1000;
+  gmshDdm.userDefinedParameter(iterMax, "iter");
+  formulation.solve("jacobi", 1e-10, iterMax);
+
+
+  for(unsigned int i = 0; i < nDom; ++i) {
+    if(isItMySubdomain(i)) {
+      save(u(i), omega(i), "u_" + std::to_string(i));
+      save(u(i) - trueSolution, omega(i), "err_" + std::to_string(i));
+    }
+  }
+
+
+  return 0;
+}