diff --git a/runtime/domain/domain_partitioning.hpp b/runtime/domain/domain_partitioning.hpp
index 9d22df20e1fef1a6961ed3f5b8894b834878f5b2..5e628f867cd3de109ca70397e44fbbbb6e1c7a69 100644
--- a/runtime/domain/domain_partitioning.hpp
+++ b/runtime/domain/domain_partitioning.hpp
@@ -6,10 +6,12 @@ typedef double real_t;
 
 namespace pairs {
 
-template<int ndims>
-class DomainPartitioner {
+template<int ndims> class Regular6DStencil;
+
+template<int ndims> class DomainPartitioner {
+    friend class Regular6DStencil<ndims>;
+
 protected:
-    int world_size, rank;
     real_t grid_min[ndims];
     real_t grid_max[ndims];
     
@@ -28,87 +30,16 @@ public:
         grid_max[2] = zmax;
     }
 
-    virtual void initialize();
-    virtual void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]);
-    virtual void communicateSizes(int dim, const int *nsend, int *nrecv);
+    virtual void initialize(int *argc, char ***argv) = 0;
+    virtual void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]) = 0;
+    virtual void communicateSizes(int dim, const int *nsend, int *nrecv) = 0;
     virtual void communicateData(
         int dim, int elem_size,
         const real_t *send_buf, const int *send_offsets, const int *nsend,
-        real_t *recv_buf, const int *recv_offsets, const int *nrecv);
-    virtual void finalize();
-    inline int getRank() { return rank; }
+        real_t *recv_buf, const int *recv_offsets, const int *nrecv) = 0;
+    virtual void finalize() = 0;
 };
 
-template<int ndims>
-class DimensionRanges : public DomainPartitioner<ndims> {
-protected:
-    int nranks[ndims];
-    int prev[ndims];
-    int next[ndims];
-    int pbc_prev[ndims];
-    int pbc_next[ndims];
-    real_t subdom_min[ndims];
-    real_t subdom_max[ndims];
-
-public:
-    DimensionRanges(real_t xmin, real_t xmax, real_t ymin, real_t ymax, real_t zmin, real_t zmax) :
-        DomainPartitioner<ndims>(xmin, xmax, ymin, ymax, zmin, zmax) {}
-
-    void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]) {
-        for(int d = 0; d < ndims; d++) {
-            neighbor_ranks[d * 2 + 0] = this->prev[d];
-            neighbor_ranks[d * 2 + 1] = this->next[d];
-            pbc[d * 2 + 0] = this->pbc_prev[d];
-            pbc[d * 2 + 1] = this->pbc_next[d];
-            subdom[d * 2 + 0] = this->subdom_min[d];
-            subdom[d * 2 + 1] = this->subdom_max[d];
-        }
-    }
-
-    void communicateSizes(int dim, const int *send_sizes, int *recv_sizes) {
-        if(prev[dim] != this->getRank()) {
-            MPI_Send(&send_sizes[dim * 2 + 0], 1, MPI_INT, prev[dim], 0, MPI_COMM_WORLD);
-            MPI_Recv(&recv_sizes[dim * 2 + 0], 1, MPI_INT, next[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-        } else {
-            recv_sizes[dim * 2 + 0] = send_sizes[dim * 2 + 0];
-        }
-
-        if(next[dim] != this->getRank()) {
-            MPI_Send(&send_sizes[dim * 2 + 1], 1, MPI_INT, next[dim], 0, MPI_COMM_WORLD);
-            MPI_Recv(&recv_sizes[dim * 2 + 1], 1, MPI_INT, prev[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-        } else {
-            recv_sizes[dim * 2 + 1] = send_sizes[dim * 2 + 1];
-        }
-    }
-
-    void communicateData(
-        int dim, int elem_size,
-        const real_t *send_buf, const int *send_offsets, const int *nsend,
-        real_t *recv_buf, const int *recv_offsets, const int *nrecv) {
-
-        if(prev[dim] != this->getRank()) {
-            MPI_Send(&send_buf[send_offsets[dim * 2 + 0]], nsend[dim * 2 + 0] * elem_size, MPI_DOUBLE, prev[dim], 0, MPI_COMM_WORLD);
-            MPI_Recv(&recv_buf[recv_offsets[dim * 2 + 0]], nrecv[dim * 2 + 0] * elem_size, MPI_DOUBLE, next[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-        } else {
-            for(int i = 0; i < nsend[dim * 2 + 0] * elem_size; i++) {
-                recv_buf[recv_offsets[dim * 2 + 0] + i] = send_buf[send_offsets[dim * 2 + 0] + i];
-            }
-        }
-
-        if(next[dim] != this->getRank()) {
-            MPI_Send(&send_buf[send_offsets[dim * 2 + 1]], nsend[dim * 2 + 1] * elem_size, MPI_DOUBLE, next[dim], 0, MPI_COMM_WORLD);
-            MPI_Recv(&recv_buf[recv_offsets[dim * 2 + 1]], nrecv[dim * 2 + 1] * elem_size, MPI_DOUBLE, prev[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
-        } else {
-            for(int i = 0; i < nsend[dim * 2 + 1] * elem_size; i++) {
-                recv_buf[recv_offsets[dim * 2 + 1] + i] = send_buf[send_offsets[dim * 2 + 1] + i];
-            }
-        }
-    }
-};
-
-template<int ndims>
-class ListOfBoxes : public DomainPartitioner<ndims> {};
-
-class DomainPartitioner<3>;
+//class DomainPartitioner<3>;
 
 }
diff --git a/runtime/domain/no_partition.hpp b/runtime/domain/no_partition.hpp
index db9561f3ccf8e672816c3979f5a31aa09a9714d6..51eaa2f3737424a91932216d41c8c213f1db0e0c 100644
--- a/runtime/domain/no_partition.hpp
+++ b/runtime/domain/no_partition.hpp
@@ -10,9 +10,6 @@ template <int ndims>
 class NoPartitioning : DimensionRanges<ndims> {
 public:
     void initialize(int *argc, const char **argv) {
-        this->world_size = 1;
-        this->rank = 0;
-
         for(int d = 0; d < ndims; d++) {
             this->nranks[d] = 1;
             this->prev[d] = 0;
@@ -25,6 +22,36 @@ public:
     }
 
     void finalize() {}
+
+    void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]) {
+        for(int d = 0; d < ndims; d++) {
+            neighbor_ranks[d * 2 + 0] = this->prev[d];
+            neighbor_ranks[d * 2 + 1] = this->next[d];
+            pbc[d * 2 + 0] = this->pbc_prev[d];
+            pbc[d * 2 + 1] = this->pbc_next[d];
+            subdom[d * 2 + 0] = this->subdom_min[d];
+            subdom[d * 2 + 1] = this->subdom_max[d];
+        }
+    }
+
+    void communicateSizes(int dim, const int *send_sizes, int *recv_sizes) {
+        recv_sizes[dim * 2 + 0] = send_sizes[dim * 2 + 0];
+        recv_sizes[dim * 2 + 1] = send_sizes[dim * 2 + 1];
+    }
+
+    void communicateData(
+        int dim, int elem_size,
+        const real_t *send_buf, const int *send_offsets, const int *nsend,
+        real_t *recv_buf, const int *recv_offsets, const int *nrecv) {
+
+        for(int i = 0; i < nsend[dim * 2 + 0] * elem_size; i++) {
+            recv_buf[recv_offsets[dim * 2 + 0] + i] = send_buf[send_offsets[dim * 2 + 0] + i];
+        }
+
+        for(int i = 0; i < nsend[dim * 2 + 1] * elem_size; i++) {
+            recv_buf[recv_offsets[dim * 2 + 1] + i] = send_buf[send_offsets[dim * 2 + 1] + i];
+        }
+    }
 };
 
 }
diff --git a/runtime/domain/regular_6d_stencil.hpp b/runtime/domain/regular_6d_stencil.hpp
index 6ec03eec6721168cc230e830ccb457d967b3b5e3..289123221f43b246db756e36997244f4110925d0 100644
--- a/runtime/domain/regular_6d_stencil.hpp
+++ b/runtime/domain/regular_6d_stencil.hpp
@@ -7,10 +7,20 @@ typedef double real_t;
 namespace pairs {
 
 template <int ndims>
-class Regular6DStencil : public DimensionRanges<ndims> {
+class Regular6DStencil : public DomainPartitioner<ndims> {
+private:
+    int world_size, rank;
+    int nranks[ndims];
+    int prev[ndims];
+    int next[ndims];
+    int pbc_prev[ndims];
+    int pbc_next[ndims];
+    real_t subdom_min[ndims];
+    real_t subdom_max[ndims];
+
 public:
     Regular6DStencil(real_t xmin, real_t xmax, real_t ymin, real_t ymax, real_t zmin, real_t zmax) :
-        DimensionRanges<ndims>(xmin, xmax, ymin, ymax, zmin, zmax) {}
+        DomainPartitioner<ndims>(xmin, xmax, ymin, ymax, zmin, zmax) {}
 
     void setConfig() {
         static_assert(ndims == 3, "setConfig() only implemented for three dimensions!");
@@ -69,8 +79,8 @@ public:
 
     void initialize(int *argc, char ***argv) {
         MPI_Init(argc, argv);
-        MPI_Comm_size(MPI_COMM_WORLD, &(this->world_size));
-        MPI_Comm_rank(MPI_COMM_WORLD, &(this->rank));
+        MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
         this->setConfig();
         this->setBoundingBox();
     }
@@ -78,6 +88,57 @@ public:
     void finalize() {
         MPI_Finalize();
     }
+
+    void fillArrays(int neighbor_ranks[], int pbc[], real_t subdom[]) {
+        for(int d = 0; d < ndims; d++) {
+            neighbor_ranks[d * 2 + 0] = this->prev[d];
+            neighbor_ranks[d * 2 + 1] = this->next[d];
+            pbc[d * 2 + 0] = this->pbc_prev[d];
+            pbc[d * 2 + 1] = this->pbc_next[d];
+            subdom[d * 2 + 0] = this->subdom_min[d];
+            subdom[d * 2 + 1] = this->subdom_max[d];
+        }
+    }
+
+    void communicateSizes(int dim, const int *send_sizes, int *recv_sizes) {
+        if(prev[dim] != rank) {
+            MPI_Send(&send_sizes[dim * 2 + 0], 1, MPI_INT, prev[dim], 0, MPI_COMM_WORLD);
+            MPI_Recv(&recv_sizes[dim * 2 + 0], 1, MPI_INT, next[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+        } else {
+            recv_sizes[dim * 2 + 0] = send_sizes[dim * 2 + 0];
+        }
+
+        if(next[dim] != rank) {
+            MPI_Send(&send_sizes[dim * 2 + 1], 1, MPI_INT, next[dim], 0, MPI_COMM_WORLD);
+            MPI_Recv(&recv_sizes[dim * 2 + 1], 1, MPI_INT, prev[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+        } else {
+            recv_sizes[dim * 2 + 1] = send_sizes[dim * 2 + 1];
+        }
+    }
+
+    void communicateData(
+        int dim, int elem_size,
+        const real_t *send_buf, const int *send_offsets, const int *nsend,
+        real_t *recv_buf, const int *recv_offsets, const int *nrecv) {
+
+        if(prev[dim] != rank) {
+            MPI_Send(&send_buf[send_offsets[dim * 2 + 0]], nsend[dim * 2 + 0] * elem_size, MPI_DOUBLE, prev[dim], 0, MPI_COMM_WORLD);
+            MPI_Recv(&recv_buf[recv_offsets[dim * 2 + 0]], nrecv[dim * 2 + 0] * elem_size, MPI_DOUBLE, next[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+        } else {
+            for(int i = 0; i < nsend[dim * 2 + 0] * elem_size; i++) {
+                recv_buf[recv_offsets[dim * 2 + 0] + i] = send_buf[send_offsets[dim * 2 + 0] + i];
+            }
+        }
+
+        if(next[dim] != rank) {
+            MPI_Send(&send_buf[send_offsets[dim * 2 + 1]], nsend[dim * 2 + 1] * elem_size, MPI_DOUBLE, next[dim], 0, MPI_COMM_WORLD);
+            MPI_Recv(&recv_buf[recv_offsets[dim * 2 + 1]], nrecv[dim * 2 + 1] * elem_size, MPI_DOUBLE, prev[dim], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
+        } else {
+            for(int i = 0; i < nsend[dim * 2 + 1] * elem_size; i++) {
+                recv_buf[recv_offsets[dim * 2 + 1] + i] = send_buf[send_offsets[dim * 2 + 1] + i];
+            }
+        }
+    }
 };
 
 }
diff --git a/runtime/pairs.hpp b/runtime/pairs.hpp
index 05aed09a9d69a7d01d471003af3bd49965b0d86d..91ca0ae690ee333d484c06fc180b9c376865f640 100644
--- a/runtime/pairs.hpp
+++ b/runtime/pairs.hpp
@@ -285,7 +285,7 @@ public:
         dom_part->initialize(argc, argv);
     }
 
-    DomainPartitioner<ndims> *getDomainPartitioner() { return dom_part; }
+    Regular6DStencil<ndims> *getDomainPartitioner() { return dom_part; }
 
     template<typename T_ptr>
     void addArray(array_t id, std::string name, T_ptr **h_ptr, std::nullptr_t, size_t size) {