From 68f63eed0d0c63aeab58bd161340496ac9cdb16f Mon Sep 17 00:00:00 2001
From: "raphael.bach" <raphael.bach@etu.hesge.ch>
Date: Mon, 18 Jul 2022 22:18:57 +0200
Subject: [PATCH] Add `fmpi_halo_exchange_2d()`

---
 include/fmpi_domain.h |  7 +++++++
 src/fmpi_domain.c     | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/include/fmpi_domain.h b/include/fmpi_domain.h
index 8512564..6699ac9 100644
--- a/include/fmpi_domain.h
+++ b/include/fmpi_domain.h
@@ -46,6 +46,7 @@ typedef struct fmpi_domain {
     const struct fmpi_data * data; //!< Data composing the domain.
     struct fmpi_data inner;
     struct fmpi_data halo;
+    struct fmpi_stencil stencil;
     size_t part_cnt;          //!< Number of partitions.
 } fmpi_domain;
 /*==============================================================================
@@ -71,6 +72,12 @@ void fmpi_domain_set_inner(
 int fmpi_halo_exchange_1d(
     const struct fmpi_ctx * ctx, const struct fmpi_domain * domain
 );
+/*------------------------------------------------------------------------------
+    fmpi_halo_exchange_2d()
+------------------------------------------------------------------------------*/
+int fmpi_halo_exchange_2d(
+    const struct fmpi_ctx * ctx, const struct fmpi_domain * domain
+);
 /*==============================================================================
     GUARD
 ==============================================================================*/
diff --git a/src/fmpi_domain.c b/src/fmpi_domain.c
index 8e70be5..d5f25c9 100644
--- a/src/fmpi_domain.c
+++ b/src/fmpi_domain.c
@@ -25,6 +25,7 @@
 #include "fmpi_domain.h"
 // C Standard Library
 #include <assert.h>
+#include <limits.h> // INT_MAX
 #include <stdlib.h> // size_t, NULL, malloc(), free()
 #include <string.h> // memcpy()
 // Internal
@@ -80,6 +81,7 @@ struct fmpi_domain fmpi_new_domain(
     const size_t proc_cnt = (size_t)ctx->mpi->size;
     struct fmpi_domain domain = {
         .data = data,
+        .stencil = stencil,
         .part_cnt = proc_cnt
     };
     domain.inner = fmpi_partition_block_1d(ctx, data);
@@ -135,6 +137,39 @@ int fmpi_halo_exchange_1d(
     );
     return FMPI_SUCCESS;
 }
+/*------------------------------------------------------------------------------
+    fmpi_halo_exchange_2d()
+------------------------------------------------------------------------------*/
+int fmpi_halo_exchange_2d(
+    const struct fmpi_ctx * const ctx, const struct fmpi_domain * const domain
+){
+    assert(ctx != NULL);
+    assert(domain != NULL);
+
+    const size_t type_size = domain->inner.type.size;
+          void * const halo_top     = domain->halo.raw;
+    const void * const inner_top    = (const char *)halo_top  + (domain->halo.dim_len[0] * domain->stencil.length       * type_size);
+    const void * const inner_bottom = (const char *)inner_top + (domain->halo.dim_len[0] * (domain->inner.dim_len[1]-1) * type_size);
+          void * const halo_bottom  = (char *)halo_top        + (domain->halo.dim_len[0] * (domain->halo.dim_len [1]-1) * type_size);
+
+    const int rank = ctx->mpi->rank;
+    const int above = (rank != 0) ? (rank - 1) : MPI_PROC_NULL;
+    const int under = (rank != (ctx->mpi->size-1)) ? (rank + 1) : MPI_PROC_NULL;
+    assert(domain->inner.dim_len[0] <= INT_MAX);
+    const int cnt = (int)domain->halo.dim_len[0];
+    MPI_Datatype type = fmpi_mpi_type(domain->halo.type.base);
+    MPI_Sendrecv(
+        inner_top  , cnt, type, above, 0,
+        halo_bottom, cnt, type, under, 0,
+        ctx->mpi->world, MPI_STATUS_IGNORE
+    );
+    MPI_Sendrecv(
+        inner_bottom, cnt, type, under, 1,
+        halo_top    , cnt, type, above, 1,
+        ctx->mpi->world, MPI_STATUS_IGNORE
+    );
+    return FMPI_SUCCESS;
+}
 /*==============================================================================
     PRIVATE FUNCTION DEFINITION
 ==============================================================================*/
-- 
GitLab