diff --git a/src/Makefile.am b/src/Makefile.am
index 0fdc51571424e2a9ad91d1d7c714d91446702161..c71cbbbbd1b1463a61e8b138fb85525d74ebbe03 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -41,7 +41,7 @@ include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \
 AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \
     serial_io.c timers.c debug.c scheduler.c proxy.c parallel_io.c \
     units.c common_io.c single_io.c multipole.c version.c map.c \
-    kernel.c tools.c
+    kernel.c tools.c part.c
 
 # Include files for distribution, not installation.
 noinst_HEADERS = atomic.h cycle.h error.h inline.h kernel.h vector.h \
diff --git a/src/engine.c b/src/engine.c
index 2f242f2ec3a27e143e7e4f08a3abdf3af8619dfe..c9a1de94cf8ddc2accc7049fd0ca232e5c650ebf 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -47,6 +47,7 @@
 #include "cycle.h"
 #include "debug.h"
 #include "error.h"
+#include "part.h"
 #include "timers.h"
 
 #ifdef LEGACY_GADGET2_SPH
@@ -215,28 +216,24 @@ void engine_redistribute(struct engine *e) {
         offset_send += counts[ind_send];
         offset_recv += counts[ind_recv];
       } else {
-        if (MPI_Isend(&s->parts[offset_send],
-                      sizeof(struct part) * counts[ind_send], MPI_BYTE, k,
-                      2 * ind_send + 0, MPI_COMM_WORLD,
+        if (MPI_Isend(&s->parts[offset_send], counts[ind_send],
+                      *(e->part_mpi_type), k, 2 * ind_send + 0, MPI_COMM_WORLD,
                       &reqs[4 * k]) != MPI_SUCCESS)
           error("Failed to isend parts to node %i.", k);
-        if (MPI_Isend(&s->xparts[offset_send],
-                      sizeof(struct xpart) * counts[ind_send], MPI_BYTE, k,
-                      2 * ind_send + 1, MPI_COMM_WORLD,
+        if (MPI_Isend(&s->xparts[offset_send], counts[ind_send],
+                      *(e->xpart_mpi_type), k, 2 * ind_send + 1, MPI_COMM_WORLD,
                       &reqs[4 * k + 1]) != MPI_SUCCESS)
           error("Failed to isend xparts to node %i.", k);
         offset_send += counts[ind_send];
       }
     }
     if (k != nodeID && counts[ind_recv] > 0) {
-      if (MPI_Irecv(&parts_new[offset_recv],
-                    sizeof(struct part) * counts[ind_recv], MPI_BYTE, k,
-                    2 * ind_recv + 0, MPI_COMM_WORLD,
+      if (MPI_Irecv(&parts_new[offset_recv], counts[ind_recv],
+                    *(e->part_mpi_type), k, 2 * ind_recv + 0, MPI_COMM_WORLD,
                     &reqs[4 * k + 2]) != MPI_SUCCESS)
         error("Failed to emit irecv of parts from node %i.", k);
-      if (MPI_Irecv(&xparts_new[offset_recv],
-                    sizeof(struct xpart) * counts[ind_recv], MPI_BYTE, k,
-                    2 * ind_recv + 1, MPI_COMM_WORLD,
+      if (MPI_Irecv(&xparts_new[offset_recv], counts[ind_recv],
+                    *(e->xpart_mpi_type), k, 2 * ind_recv + 1, MPI_COMM_WORLD,
                     &reqs[4 * k + 3]) != MPI_SUCCESS)
         error("Failed to emit irecv of parts from node %i.", k);
       offset_recv += counts[ind_recv];
@@ -2202,6 +2199,12 @@ void engine_init(struct engine *e, struct space *s, float dt, int nr_threads,
 #endif
   }
 
+/* Construct types for MPI communications */
+#ifdef WITH_MPI
+  part_create_mpi_type(e->part_mpi_type);
+  xpart_create_mpi_type(e->xpart_mpi_type);
+#endif
+
   /* First of all, init the barrier and lock it. */
   if (pthread_mutex_init(&e->barrier_mutex, NULL) != 0)
     error("Failed to initialize barrier mutex.");
diff --git a/src/engine.h b/src/engine.h
index 4da743f3151704b2d32a6086352957e4d947bfc6..4ab86288a04fc18b6236a6c44a048a01314a088d 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -19,6 +19,14 @@
 #ifndef SWIFT_ENGINE_H
 #define SWIFT_ENGINE_H
 
+/* Config parameters. */
+#include "../config.h"
+
+/* MPI headers. */
+#ifdef WITH_MPI
+#include <mpi.h>
+#endif
+
 /* Some standard headers. */
 #include <pthread.h>
 
@@ -125,6 +133,10 @@ struct engine {
   /* Linked list for cell-task association. */
   struct link *links;
   int nr_links, size_links;
+
+  /* MPI data type for the particle transfers */
+  MPI_Datatype *part_mpi_type;
+  MPI_Datatype *xpart_mpi_type;
 };
 
 /* Function prototypes. */
diff --git a/src/part.c b/src/part.c
new file mode 100644
index 0000000000000000000000000000000000000000..1923e3f0443153fff97227f6005762d51cb33f78
--- /dev/null
+++ b/src/part.c
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * This file is part of SWIFT.
+ * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ ******************************************************************************/
+
+/* Config parameters. */
+#include "../config.h"
+
+/* MPI headers. */
+#ifdef WITH_MPI
+#include <mpi.h>
+#endif
+
+/* This object's header. */
+#include "part.h"
+
+#ifdef WITH_MPI
+/**
+ * @brief Registers and returns an MPI type for the particles
+ *
+ */
+void part_create_mpi_type(MPI_Datatype* part_type) {
+
+  /* This is not the recommended way of doing this. */
+  /* One should define the structure field by field */
+  /* But as long as we don't do serialization via MPI-IO */
+  /* we don't really care. */
+  MPI_Type_contiguous(sizeof(struct part) / sizeof(unsigned char), MPI_BYTE,
+                      part_type);
+  MPI_Type_commit(part_type);
+}
+
+/**
+ * @brief Registers and returns an MPI type for the xparticles
+ *
+ */
+void xpart_create_mpi_type(MPI_Datatype* xpart_type) {
+
+  /* This is not the recommended way of doing this. */
+  /* One should define the structure field by field */
+  /* But as long as we don't do serialization via MPI-IO */
+  /* we don't really care. */
+  MPI_Type_contiguous(sizeof(struct xpart) / sizeof(unsigned char), MPI_BYTE,
+                      xpart_type);
+  MPI_Type_commit(xpart_type);
+}
+
+#endif
diff --git a/src/part.h b/src/part.h
index 1ad62888b3accd38c6c3f5e13f49988d2c6d69d1..e2940e29c1b008b55efbb7dfa178bae80c134add 100644
--- a/src/part.h
+++ b/src/part.h
@@ -19,6 +19,18 @@
 #ifndef SWIFT_PART_H
 #define SWIFT_PART_H
 
+/* Config parameters. */
+#include "../config.h"
+
+/* Some standard headers. */
+#include <stdlib.h>
+
+/* MPI headers. */
+#ifdef WITH_MPI
+#include <mpi.h>
+#endif
+
+/* Local headers. */
 #include "const.h"
 
 /* Some constants. */
@@ -72,7 +84,7 @@ struct gpart {
     size_t id;
 
     /* Pointer to corresponding SPH part. */
-    struct part *part;
+    struct part* part;
   };
 
 } __attribute__((aligned(part_align)));
@@ -162,8 +174,13 @@ struct part {
   unsigned long long id;
 
   /* Associated gravitas. */
-  struct gpart *gpart;
+  struct gpart* gpart;
 
 } __attribute__((aligned(part_align)));
 
+#ifdef WITH_MPI
+void part_create_mpi_type(MPI_Datatype* part_type);
+void xpart_create_mpi_type(MPI_Datatype* xpart_type);
+#endif
+
 #endif /* SWIFT_PART_H */