diff --git a/control/descriptor.c b/control/descriptor.c
index b2666d2baa78291a63235a0c60b518ef696749ca..8458fae118c28d6b1fab1bf706038fcd6701f116 100644
--- a/control/descriptor.c
+++ b/control/descriptor.c
@@ -132,7 +132,6 @@ int chameleon_getrankof_2d_diag( const CHAM_desc_t *A, int m, int n )
     return (mm % A->p) * A->q + (mm % A->q);
 }
 
-
 /**
  ******************************************************************************
  *
@@ -1043,3 +1042,134 @@ CHAMELEON_Desc_Print( const CHAM_desc_t *desc )
 {
     chameleon_desc_print( desc, 2 );
 }
+
+/**
+ *****************************************************************************
+ *
+ * @ingroup Descriptor
+ *
+ * @brief Change the data distribution of the given matrix.
+ *
+ ******************************************************************************
+ *
+ * @param[in] uplo
+ *          = ChamUpper: Upper triangle of A is moved; lower part is never referenced.
+ *          = ChamLower: Lower triangle of A is moved; upper part is never referenced.
+ *          = ChamUpperLower: The full matrix A is moved.
+ *
+ * @param[inout] desc The matrix descriptor to move around. On exit, the new
+ *          distribution is registered.
+ *
+ * @param[in] new_get_rankof
+ *          The function that describes the new data distribution.
+ *
+ ******************************************************************************
+ *
+ * @retval CHAMELEON_SUCCESS successful exit.
+ * @retval CHAMELEON_ERR_ILLEGAL_VALUE on error.
+ *
+ */
+int CHAMELEON_Desc_Change_Distribution( cham_uplo_t      uplo,
+                                        CHAM_desc_t     *desc,
+                                        blkrankof_fct_t  new_get_rankof )
+{
+    int                 status;
+    CHAM_context_t     *chamctxt;
+    RUNTIME_sequence_t *sequence = NULL;
+
+    chamctxt = chameleon_context_self();
+    if (chamctxt == NULL) {
+        chameleon_fatal_error("CHAMELEON_Desc_Change_Distribution", "CHAMELEON not initialized");
+        return CHAMELEON_ERR_NOT_INITIALIZED;
+    }
+
+    chameleon_sequence_create( chamctxt, &sequence );
+
+    CHAMELEON_Desc_Change_Distribution_Async( uplo, desc, new_get_rankof, sequence );
+
+    RUNTIME_desc_flush( desc, sequence );
+    chameleon_sequence_wait( chamctxt, sequence );
+    status = sequence->status;
+    chameleon_sequence_destroy( chamctxt, sequence );
+
+    return status;
+}
+
+/**
+ *****************************************************************************
+ *
+ * @ingroup Descriptor
+ *
+ * @brief Change the data distribution of the given matrix.
+ *
+ ******************************************************************************
+ *
+ * @param[in] uplo
+ *          = ChamUpper: Upper triangle of A is moved; lower part is never referenced.
+ *          = ChamLower: Lower triangle of A is moved; upper part is never referenced.
+ *          = ChamUpperLower: The full matrix A is moved.
+ *
+ * @param[inout] desc The matrix descriptor to move around. On exit, the new
+ *          distribution is registered.
+ *
+ * @param[in] new_get_rankof
+ *          The function that describes the new data distribution.
+ *
+ ******************************************************************************
+ *
+ * @retval CHAMELEON_SUCCESS successful exit.
+ * @retval CHAMELEON_ERR_ILLEGAL_VALUE on error.
+ * @retval CHAMELEON_ERR_NOT_INITIALIZED if chameleon is not initialized.
+ * @retval CHAMELEON_ERR_NOT_SUPPORTED if CHAMELEON_USE_MIGRATE is not enabled
+ *
+ */
+int CHAMELEON_Desc_Change_Distribution_Async( cham_uplo_t         uplo,
+                                              CHAM_desc_t        *desc,
+                                              blkrankof_fct_t     new_get_rankof,
+                                              RUNTIME_sequence_t *sequence )
+{
+    CHAM_context_t *chamctxt;
+    int m, n, mmin, mmax;
+
+    chamctxt = chameleon_context_self();
+    if ( chamctxt == NULL ) {
+        chameleon_error("CHAMELEON_Desc_Change_Distribution_Async", "CHAMELEON not initialized");
+        sequence->status = CHAMELEON_ERR_NOT_INITIALIZED;
+        return CHAMELEON_ERR_NOT_INITIALIZED;
+    }
+
+    /* Nothing to do if the new mapping is the same as the original one */
+    if ( ( new_get_rankof == desc->get_rankof ) ||
+         ( RUNTIME_comm_size( chamctxt ) == 1 ) )
+    {
+        return CHAMELEON_SUCCESS;
+    }
+
+    if ( chamctxt->scheduler != RUNTIME_SCHED_STARPU ) {
+        chameleon_error("CHAMELEON_Desc_Change_Distribution_Async", "Distribution change is only supported by StarPU");
+        sequence->status = CHAMELEON_ERR_ILLEGAL_VALUE;
+        return CHAMELEON_ERR_ILLEGAL_VALUE;
+    }
+
+    /* Check that the function is enabled */
+#if !defined(CHAMELEON_USE_MIGRATE)
+    {
+        chameleon_error("CHAMELEON_Desc_Change_Distribution_Async", "Distribution change is only supported by StarPU");
+        sequence->status = CHAMELEON_ERR_NOT_SUPPORTED;
+        return CHAMELEON_ERR_NOT_SUPPORTED;
+    }
+#endif
+
+    for ( n = 0; n < desc->nt; n++ ) {
+        mmin = ( uplo == ChamLower ) ? chameleon_min( n,   desc->mt ) : 0;
+        mmax = ( uplo == ChamUpper ) ? chameleon_min( n+1, desc->mt ) : desc->mt;
+        for ( m = mmin; m < mmax; m++ ) {
+            RUNTIME_data_migrate( sequence, desc, m, n, new_get_rankof( desc, m, n ) );
+        }
+    }
+
+    /* Actually change data location in Chameleon */
+    desc->get_rankof = new_get_rankof;
+
+    return CHAMELEON_SUCCESS;
+}
diff --git a/include/chameleon.h b/include/chameleon.h
index 58cce2ed51d08bf8fe11c4d4f079715dc9216b83..d3f41a16e18a6e62a9fb28f1642dc221e0ea5e82 100644
--- a/include/chameleon.h
+++ b/include/chameleon.h
@@ -145,6 +145,15 @@ int CHAMELEON_Desc_Acquire( const CHAM_desc_t *desc );
 int CHAMELEON_Desc_Release( const CHAM_desc_t *desc );
 int CHAMELEON_Desc_Flush  ( const CHAM_desc_t        *desc,
                             const RUNTIME_sequence_t *sequence );
+
+int CHAMELEON_Desc_Change_Distribution( cham_uplo_t      uplo,
+                                        CHAM_desc_t     *desc,
+                                        blkrankof_fct_t  new_get_rankof );
+int CHAMELEON_Desc_Change_Distribution_Async( cham_uplo_t         uplo,
+                                              CHAM_desc_t        *desc,
+                                              blkrankof_fct_t     new_get_rankof,
+                                              RUNTIME_sequence_t *sequence );
+
 void CHAMELEON_Desc_Print( const CHAM_desc_t *desc );
 
 /* Workspaces */