Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbc_lnk_nc_generic.h90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbc_lnk_nc_generic.h90	(revision 11940)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbc_lnk_nc_generic.h90	(revision 11940)
@@ -0,0 +1,83 @@
+#if defined DIM_2d
+#   define ARRAY_TYPE(i,j,k,l)   REAL(wp), DIMENSION(i,j)
+#   define PTR_TYPE              TYPE(PTR_2D)
+#   define PTR_ptab              pt2d
+#endif
+#if defined DIM_3d
+#   define ARRAY_TYPE(i,j,k,l)   REAL(wp), DIMENSION(i,j,k)
+#   define PTR_TYPE              TYPE(PTR_3D)
+#   define PTR_ptab              pt3d
+#endif
+#if defined DIM_4d
+#   define ARRAY_TYPE(i,j,k,l)   REAL(wp), DIMENSION(i,j,k,l)
+#   define PTR_TYPE              TYPE(PTR_4D)
+#   define PTR_ptab              pt4d
+#endif
+
+   SUBROUTINE ROUTINE_MULTI_NC( cdname                                                                             &
+      &                    , pt1, cdna1, psgn1, pt2 , cdna2 , psgn2 , pt3 , cdna3 , psgn3 , pt4, cdna4, psgn4   &
+      &                    , pt5, cdna5, psgn5, pt6 , cdna6 , psgn6 , pt7 , cdna7 , psgn7 , pt8, cdna8, psgn8   &
+      &                    , pt9, cdna9, psgn9, pt10, cdna10, psgn10, pt11, cdna11, psgn11                      &
+      &                    , kfillmode, pfillval, lsend, lrecv, ihlcom )
+      !!---------------------------------------------------------------------
+      CHARACTER(len=*)   ,                   INTENT(in   ) :: cdname  ! name of the calling subroutine
+      ARRAY_TYPE(:,:,:,:)          , TARGET, INTENT(inout) :: pt1     ! arrays on which the lbc is applied
+      ARRAY_TYPE(:,:,:,:), OPTIONAL, TARGET, INTENT(inout) :: pt2  , pt3  , pt4  , pt5  , pt6  , pt7  , pt8  , pt9  , pt10  , pt11
+      CHARACTER(len=1)                     , INTENT(in   ) :: cdna1   ! nature of pt2D. array grid-points
+      CHARACTER(len=1)   , OPTIONAL        , INTENT(in   ) :: cdna2, cdna3, cdna4, cdna5, cdna6, cdna7, cdna8, cdna9, cdna10, cdna11
+      REAL(wp)                             , INTENT(in   ) :: psgn1   ! sign used across the north fold
+      REAL(wp)           , OPTIONAL        , INTENT(in   ) :: psgn2, psgn3, psgn4, psgn5, psgn6, psgn7, psgn8, psgn9, psgn10, psgn11
+      INTEGER            , OPTIONAL        , INTENT(in   ) :: kfillmode   ! filling method for halo over land (default = constant)
+      REAL(wp)           , OPTIONAL        , INTENT(in   ) :: pfillval    ! background value (used at closed boundaries)
+      LOGICAL, DIMENSION(4), OPTIONAL      , INTENT(in   ) :: lsend, lrecv   ! indicate how communications are to be carried out
+      INTEGER            , OPTIONAL        , INTENT(in   ) :: ihlcom         ! number of ranks and rows to be communicated
+      !!
+      INTEGER                          ::   kfld        ! number of elements that will be attributed
+      PTR_TYPE         , DIMENSION(11) ::   ptab_ptr    ! pointer array
+      CHARACTER(len=1) , DIMENSION(11) ::   cdna_ptr    ! nature of ptab_ptr grid-points
+      REAL(wp)         , DIMENSION(11) ::   psgn_ptr    ! sign used across the north fold boundary
+      !!---------------------------------------------------------------------
+      !
+      kfld = 0          ! initial array of pointer size
+      !
+      !                 ! Load the first array
+      CALL ROUTINE_NC_LOAD( pt1, cdna1, psgn1, ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      !
+      !                 ! Look if more arrays are added
+      IF( PRESENT(psgn2 ) )   CALL ROUTINE_NC_LOAD( pt2 , cdna2 , psgn2 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn3 ) )   CALL ROUTINE_NC_LOAD( pt3 , cdna3 , psgn3 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn4 ) )   CALL ROUTINE_NC_LOAD( pt4 , cdna4 , psgn4 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn5 ) )   CALL ROUTINE_NC_LOAD( pt5 , cdna5 , psgn5 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn6 ) )   CALL ROUTINE_NC_LOAD( pt6 , cdna6 , psgn6 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn7 ) )   CALL ROUTINE_NC_LOAD( pt7 , cdna7 , psgn7 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn8 ) )   CALL ROUTINE_NC_LOAD( pt8 , cdna8 , psgn8 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn9 ) )   CALL ROUTINE_NC_LOAD( pt9 , cdna9 , psgn9 , ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn10) )   CALL ROUTINE_NC_LOAD( pt10, cdna10, psgn10, ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      IF( PRESENT(psgn11) )   CALL ROUTINE_NC_LOAD( pt11, cdna11, psgn11, ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      !
+      CALL lbc_lnk_nc    ( cdname,               ptab_ptr, cdna_ptr, psgn_ptr, kfld, kfillmode, pfillval, lsend, lrecv, ihlcom )
+      !
+   END SUBROUTINE ROUTINE_MULTI_NC
+
+
+   SUBROUTINE ROUTINE_NC_LOAD( ptab, cdna, psgn, ptab_ptr, cdna_ptr, psgn_ptr, kfld )
+      !!---------------------------------------------------------------------
+      ARRAY_TYPE(:,:,:,:)   , TARGET, INTENT(inout) ::   ptab       ! arrays on which the lbc is applied
+      CHARACTER(len=1)              , INTENT(in   ) ::   cdna       ! nature of pt2d array grid-points
+      REAL(wp)                      , INTENT(in   ) ::   psgn       ! sign used across the north fold boundary
+      PTR_TYPE        , DIMENSION(:), INTENT(inout) ::   ptab_ptr   ! array of pointers
+      CHARACTER(len=1), DIMENSION(:), INTENT(inout) ::   cdna_ptr   ! nature of pt2d_array array grid-points
+      REAL(wp)        , DIMENSION(:), INTENT(inout) ::   psgn_ptr   ! sign used across the north fold boundary
+      INTEGER                       , INTENT(inout) ::   kfld       ! number of elements that has been attributed
+      !!---------------------------------------------------------------------
+      !
+      kfld                    =  kfld + 1
+      ptab_ptr(kfld)%PTR_ptab => ptab
+      cdna_ptr(kfld)          =  cdna
+      psgn_ptr(kfld)          =  psgn
+      !
+   END SUBROUTINE ROUTINE_NC_LOAD
+
+#undef ARRAY_TYPE
+#undef PTR_TYPE
+#undef PTR_ptab
Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbclnk.F90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbclnk.F90	(revision 11939)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lbclnk.F90	(revision 11940)
@@ -13,4 +13,6 @@
    !!             -   ! 2017-04  (G. Madec) remove duplicated routines (lbc_lnk_2d_9, lbc_lnk_2d_multiple, lbc_lnk_3d_gather)
    !!             -   ! 2017-05  (G. Madec) create generic.h90 files to generate all lbc and north fold routines
+   !!             -   !  2019  (S. Mocavero, I. Epicoco - CMCC) create generic.h90 files to introduce MPI3 neighbourhood collectives
+
    !!----------------------------------------------------------------------
    !!           define the generic interfaces of lib_mpp routines
@@ -36,4 +38,10 @@
       MODULE PROCEDURE   lbc_lnk_2d_multi, lbc_lnk_3d_multi, lbc_lnk_4d_multi
    END INTERFACE
+   INTERFACE lbc_lnk_nc_multi
+      MODULE PROCEDURE   lbc_lnk_nc_2d, lbc_lnk_nc_3d, lbc_lnk_nc_4d
+   END INTERFACE
+   INTERFACE lbc_lnk_nc
+      MODULE PROCEDURE   mpp_lnk_nc_2d, mpp_lnk_nc_3d, mpp_lnk_nc_4d
+   END INTERFACE
    !
    INTERFACE lbc_lnk_icb
@@ -46,7 +54,8 @@
    END INTERFACE
 
-   PUBLIC   lbc_lnk       ! ocean/ice lateral boundary conditions
-   PUBLIC   lbc_lnk_multi ! modified ocean/ice lateral boundary conditions
-   PUBLIC   lbc_lnk_icb   ! iceberg lateral boundary conditions
+   PUBLIC   lbc_lnk            ! ocean/ice lateral boundary conditions
+   PUBLIC   lbc_lnk_multi      ! modified ocean/ice lateral boundary conditions
+   PUBLIC   lbc_lnk_icb        ! iceberg lateral boundary conditions
+   PUBLIC   lbc_lnk_nc_multi   ! modified ocean/ice lateral boundary conditions
 
 #if   defined key_mpp_mpi
@@ -163,4 +172,84 @@
 #     undef ROUTINE_LNK
 #     undef MULTI
+#  undef DIM_4d
+
+   !!----------------------------------------------------------------------
+   !!                   ***  routine lbc_lnk_nc_(2,3,4)d  ***
+   !!
+   !!   * Argument : dummy argument use in lbc_lnk_nc_... routines
+   !!                ptab   :   array or pointer of arrays on which the boundary
+   !condition is applied
+   !!                cd_nat :   nature of array grid-points
+   !!                psgn   :   sign used across the north fold boundary
+   !!                kfld   :   optional, number of pt3d arrays
+   !!                cd_mpp :   optional, fill the overlap area only
+   !!                pval   :   optional, background value (used at closed
+   !boundaries)
+   !!----------------------------------------------------------------------
+   !
+   !                       !==  2D array and array of 2D pointer  ==!
+   !
+#  define DIM_2d
+#     define ROUTINE_NC_LOAD            load_ptr_nc_2d
+#     define ROUTINE_MULTI_NC           lbc_lnk_nc_2d
+#     include "lbc_lnk_nc_generic.h90"
+#     undef ROUTINE_MULTI_NC
+#     undef ROUTINE_NC_LOAD
+#  undef DIM_2d
+   !
+   !                       !==  3D array and array of 3D pointer  ==!
+   !
+#  define DIM_3d
+#     define ROUTINE_NC_LOAD            load_ptr_nc_3d
+#     define ROUTINE_MULTI_NC           lbc_lnk_nc_3d
+#     include "lbc_lnk_nc_generic.h90"
+#     undef ROUTINE_MULTI_NC
+#     undef ROUTINE_NC_LOAD
+#  undef DIM_3d
+   !
+   !                       !==  4D array and array of 4D pointer  ==!
+   !
+#  define DIM_4d
+#     define ROUTINE_NC_LOAD            load_ptr_nc_4d
+#     define ROUTINE_MULTI_NC           lbc_lnk_nc_4d
+#     include "lbc_lnk_nc_generic.h90"
+#     undef ROUTINE_LOAD
+#     undef ROUTINE_NC_LOAD
+#  undef DIM_4d
+
+   !!----------------------------------------------------------------------
+   !!                   ***  routine mpp_nc_(2,3,4)d  ***
+   !!
+   !!   * Argument : dummy argument use in mpp_nc_... routines
+   !!                ptab   :   array or pointer of arrays on which the boundary condition is applied
+   !!                cd_nat :   nature of array grid-points
+   !!                psgn   :   sign used across the north fold boundary
+   !!                kfld   :   optional, number of pt3d arrays
+   !!                cd_mpp :   optional, fill the overlap area only
+   !!                pval   :   optional, background value (used at closed boundaries)
+   !!----------------------------------------------------------------------
+   !
+   !                       !==  2D array and array of 2D pointer  ==!
+   !
+#  define DIM_2d
+#     define ROUTINE_NC           mpp_lnk_nc_2d
+#     include "mpp_nc_generic.h90"
+#     undef ROUTINE_NC
+#  undef DIM_2d
+   !
+   !                       !==  3D array and array of 3D pointer  ==!
+   !
+#  define DIM_3d
+#     define ROUTINE_NC           mpp_lnk_nc_3d
+#     include "mpp_nc_generic.h90"
+#     undef ROUTINE_NC
+#  undef DIM_3d
+   !
+   !                       !==  4D array and array of 4D pointer  ==!
+   !
+#  define DIM_4d
+#     define ROUTINE_NC           mpp_lnk_nc_4d
+#     include "mpp_nc_generic.h90"
+#     undef ROUTINE_NC
 #  undef DIM_4d
 
Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lib_mpp.F90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lib_mpp.F90	(revision 11939)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/lib_mpp.F90	(revision 11940)
@@ -25,4 +25,5 @@
    !!            4.0  !  2017  (G. Madec) automatique allocation of array argument (use any 3rd dimension)
    !!             -   !  2017  (G. Madec) create generic.h90 files to generate all lbc and north fold routines
+   !!             -   !  2019  (S. Mocavero, I. Epicoco - CMCC) add MPI3 neighbourhood collectives
    !!----------------------------------------------------------------------
 
@@ -50,4 +51,5 @@
    !!   mpp_ini_north : initialisation of north fold
    !!   mpp_lbc_north_icb : alternative to mpp_nfd for extra outer halo with icebergs
+   !!   mpp_ini_nc    : initialisation of MPI3 neighbourhood collectives communicator
    !!----------------------------------------------------------------------
    USE dom_oce        ! ocean space and time domain
@@ -64,4 +66,5 @@
    PUBLIC   mppscatter, mppgather
    PUBLIC   mpp_ini_znl
+   PUBLIC   mpp_ini_nc
    PUBLIC   mppsend, mpprecv                          ! needed by TAM and ICB routines
    PUBLIC   mpp_report
@@ -132,4 +135,8 @@
    INTEGER, PUBLIC ::   north_root        !: number (in the comm_opa) of proc 0 in the northern comm
    INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE, SAVE ::   nrank_north   !: dimension ndim_rank_north
+
+   ! variables used for MPI3 neighbourhood collectives
+   INTEGER, PUBLIC :: mpi_nc_com                   ! MPI3 neighbourhood collectives communicator
+   INTEGER, PUBLIC, DIMENSION(:), ALLOCATABLE :: nranks
 
    ! Communications summary report
@@ -800,4 +807,47 @@
 
    END SUBROUTINE mpp_ini_znl
+
+   SUBROUTINE mpp_ini_nc
+      !!----------------------------------------------------------------------
+      !!               ***  routine mpp_ini_nc  ***
+      !!
+      !! ** Purpose :   Initialize special communicator for MPI3 neighbourhood
+      !!                collectives
+      !!
+      !! ** Method  : - Create a cartesian communicator starting from the
+      !processes   
+      !!                distribution along i and j directions
+      !
+      !! ** output
+      !!         mpi_nc_com = MPI3 neighbourhood collectives communicator
+      !!
+      !!----------------------------------------------------------------------
+      INTEGER, DIMENSION(2) :: ipdims
+      LOGICAL, PARAMETER :: ireord = .FALSE.
+      LOGICAL :: nperiod_nc ( 2 ) = .FALSE.
+      INTEGER :: mpi_nc_com_re, igroup, iprc, ingroup, iii, jjj
+      INTEGER :: ierr
+
+#if defined key_mpp_mpi
+      ipdims(1) = jpni
+      ipdims(2) = jpnj
+      nperiod_nc(1) = .TRUE.
+
+      iprc = jpni*jpnj
+
+      ! Create a group from mpi_comm_oce
+      CALL MPI_Comm_group(mpi_comm_oce, igroup, ierr)
+
+      ! Create a group to reorder MPI rank
+      CALL MPI_Group_incl(igroup, iprc, nranks, ingroup, ierr)
+
+      ! Create reordered communicator
+      CALL MPI_Comm_create(mpi_comm_oce, ingroup, mpi_nc_com_re, ierr)
+
+      ! Create the cartesian communicator
+      CALL MPI_Cart_create(mpi_nc_com_re, 2, ipdims, nperiod_nc, ireord, mpi_nc_com, ierr)
+      DEALLOCATE (nranks)
+#endif
+   END SUBROUTINE mpp_ini_nc
 
 
Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mpp_nc_generic.h90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mpp_nc_generic.h90	(revision 11940)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mpp_nc_generic.h90	(revision 11940)
@@ -0,0 +1,343 @@
+#   define NAT_IN(k)                cd_nat(k)   
+#   define SGN_IN(k)                psgn(k)
+#   define F_SIZE(ptab)             kfld
+#   define OPT_K(k)                 ,ipf
+#   if defined DIM_2d
+#      define ARRAY_TYPE(i,j,k,l,f)    TYPE(PTR_2D)                , INTENT(inout) ::   ptab(f)
+#      define ARRAY_IN(i,j,k,l,f)      ptab(f)%pt2d(i,j)
+#      define K_SIZE(ptab)             1
+#      define L_SIZE(ptab)             1
+#   endif
+#   if defined DIM_3d
+#      define ARRAY_TYPE(i,j,k,l,f)    TYPE(PTR_3D)                , INTENT(inout) ::   ptab(f)
+#      define ARRAY_IN(i,j,k,l,f)      ptab(f)%pt3d(i,j,k)
+#      define K_SIZE(ptab)             SIZE(ptab(1)%pt3d,3)
+#      define L_SIZE(ptab)             1
+#   endif
+#   if defined DIM_4d
+#      define ARRAY_TYPE(i,j,k,l,f)    TYPE(PTR_4D)                , INTENT(inout) ::   ptab(f)
+#      define ARRAY_IN(i,j,k,l,f)      ptab(f)%pt4d(i,j,k,l)
+#      define K_SIZE(ptab)             SIZE(ptab(1)%pt4d,3)
+#      define L_SIZE(ptab)             SIZE(ptab(1)%pt4d,4)
+#   endif
+
+   SUBROUTINE ROUTINE_NC( cdname, ptab, cd_nat, psgn, kfld, kfillmode, pfillval, lsend, lrecv, ihlcom )
+      INTEGER             , INTENT(in   ) ::   kfld        ! number of pt3d arrays
+      ARRAY_TYPE(:,:,:,:,:)                                        ! array or pointer of arrays on which the boundary condition is applied
+      CHARACTER(len=*)              , INTENT(in   ) ::   cdname      ! name of the calling subroutine
+      CHARACTER(len=1)              , INTENT(in   ) ::   NAT_IN(:)   ! nature of array grid-points
+      REAL(wp)                      , INTENT(in   ) ::   SGN_IN(:)   ! sign used across the north fold boundary
+      INTEGER ,             OPTIONAL, INTENT(in   ) ::   kfillmode   ! filling method for halo over land (default = constant)
+      REAL(wp),             OPTIONAL, INTENT(in   ) ::   pfillval    ! background value (used at closed boundaries)
+      LOGICAL, DIMENSION(4),OPTIONAL, INTENT(in   ) ::   lsend, lrecv  ! communication with other 4 proc
+      INTEGER              ,OPTIONAL, INTENT(in   ) ::   ihlcom        ! number of ranks and rows to be communicated
+      !
+      INTEGER  ::   ji,  jj,  jk,  jl,  jf          ! dummy loop indices
+      INTEGER  ::   ipi, ipj, ipk, ipl, ipf         ! dimension of the input array
+      INTEGER  ::   ishift, ishift2, idx            ! local integers
+      INTEGER  ::   ierr
+      INTEGER  ::   ifill_we, ifill_ea, ifill_so, ifill_no
+      INTEGER  ::   ihl                          ! number of ranks and rows to be communicated 
+      REAL(wp) ::   zland
+      INTEGER , DIMENSION(MPI_STATUS_SIZE)        ::   istate          ! for mpi_isend
+      REAL(wp), DIMENSION(:), ALLOCATABLE         ::   zsnd, zrcv      ! halos arrays
+      INTEGER , DIMENSION(4)                      ::   isizes          ! number of elements to be sent/received
+      INTEGER , DIMENSION(4)                      ::   idataty         ! datatype of halos arrays
+      INTEGER (KIND=MPI_ADDRESS_KIND) idispls(4)                       ! displacement in halos arrays
+      LOGICAL  ::   llsend_we, llsend_ea, llsend_no, llsend_so       ! communication send
+      LOGICAL  ::   llrecv_we, llrecv_ea, llrecv_no, llrecv_so       ! communication receive 
+      LOGICAL  ::   lldo_nfd                                     ! do north pole folding
+
+      !!----------------------------------------------------------------------
+      !
+      ! ----------------------------------------- !
+      !     0. local variables initialization     !
+      ! ----------------------------------------- !
+      !
+      ipk = K_SIZE(ptab)   ! 3rd dimension
+      ipl = L_SIZE(ptab)   ! 4th    -
+      ipf = F_SIZE(ptab)   ! 5th    -      use in "multi" case (array of pointers)
+      !
+      IF( PRESENT(ihlcom) ) THEN   ;   ihl = ihlcom
+      ELSE                         ;   ihl = 1
+      END IF
+      !
+      IF( narea == 1 .AND. numcom == -1 ) CALL mpp_report( cdname, ipk, ipl, ipf, ld_lbc = .TRUE. )
+      !
+      IF     ( PRESENT(lsend) .AND. PRESENT(lrecv) ) THEN
+         llsend_we = lsend(1)   ;   llsend_ea = lsend(2)   ;   llsend_so = lsend(3)   ;   llsend_no = lsend(4)
+         llrecv_we = lrecv(1)   ;   llrecv_ea = lrecv(2)   ;   llrecv_so = lrecv(3)   ;   llrecv_no = lrecv(4)
+      ELSE IF( PRESENT(lsend) .OR.  PRESENT(lrecv) ) THEN
+         WRITE(ctmp1,*) ' E R R O R : Routine ', cdname, '  is calling lbc_lnk with only one of the two arguments lsend or lrecv'
+         WRITE(ctmp2,*) ' ========== '
+         CALL ctl_stop( ' ', ctmp1, ctmp2, ' ' )
+      ELSE   ! send and receive with every neighbour
+         llsend_we = nbondi ==  1 .OR. nbondi == 0   ! keep for compatibility, should be defined in mppini
+         llsend_ea = nbondi == -1 .OR. nbondi == 0   ! keep for compatibility, should be defined in mppini
+         llsend_so = nbondj ==  1 .OR. nbondj == 0   ! keep for compatibility, should be defined in mppini
+         llsend_no = nbondj == -1 .OR. nbondj == 0   ! keep for compatibility, should be defined in mppini
+         llrecv_we = llsend_we   ;   llrecv_ea = llsend_ea   ;   llrecv_so = llsend_so   ;   llrecv_no = llsend_no
+      END IF
+         
+         
+      lldo_nfd = npolj /= 0                      ! keep for compatibility, should be defined in mppini
+
+      zland = 0._wp                                     ! land filling value: zero by default
+      IF( PRESENT( pfillval ) )   zland = pfillval      ! set land value
+
+      ! define the method we will use to fill the halos in each direction
+      IF(              llrecv_we ) THEN   ;   ifill_we = jpfillmpi
+      ELSEIF(           l_Iperio ) THEN   ;   ifill_we = jpfillperio
+      ELSEIF( PRESENT(kfillmode) ) THEN   ;   ifill_we = kfillmode
+      ELSE                                ;   ifill_we = jpfillcst
+      END IF
+      !
+      IF(              llrecv_ea ) THEN   ;   ifill_ea = jpfillmpi
+      ELSEIF(           l_Iperio ) THEN   ;   ifill_ea = jpfillperio
+      ELSEIF( PRESENT(kfillmode) ) THEN   ;   ifill_ea = kfillmode
+      ELSE                                ;   ifill_ea = jpfillcst
+      END IF
+      !
+      IF(              llrecv_so ) THEN   ;   ifill_so = jpfillmpi
+      ELSEIF(           l_Jperio ) THEN   ;   ifill_so = jpfillperio
+      ELSEIF( PRESENT(kfillmode) ) THEN   ;   ifill_so = kfillmode
+      ELSE                                ;   ifill_so = jpfillcst
+      END IF
+      !
+      IF(              llrecv_no ) THEN   ;   ifill_no = jpfillmpi
+      ELSEIF(           l_Jperio ) THEN   ;   ifill_no = jpfillperio
+      ELSEIF( PRESENT(kfillmode) ) THEN   ;   ifill_no = kfillmode
+      ELSE                                ;   ifill_no = jpfillcst
+      END IF
+      !
+#if defined PRINT_CAUTION
+      !
+      ! ================================================================================== !
+      ! CAUTION: semi-column notation is often impossible because of the cpp preprocessing !
+      ! ================================================================================== !
+      !
+#endif
+      !
+      ! -------------------------------------------------- !
+      !     1. Do west, east, south and north MPI exchange !
+      ! -------------------------------------------------- !
+      !
+      ! Allocate local temporary arrays to be sent/received. Fill arrays to be sent
+
+      ALLOCATE( zsnd (2 * ipk * ipl * ipf * ihl * ((jpi + jpj - 4*ihl) ) ) )
+      ALLOCATE( zrcv (2 * ipk * ipl * ipf * ihl * ((jpi + jpj - 4*ihl) ) ) )
+
+      zrcv(:)=-1
+      zsnd(:)=-1
+
+      idx = 1
+      DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = ihl + 1, jpj - ihl  ;  DO ji = 1, ihl
+         zsnd(idx) = ARRAY_IN(ihl+ji,jj,jk,jl,jf)
+         idx = idx + 1
+      END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+
+      isizes(1) = ihl * (jpj - 2*ihl) * ipk * ipl * ipf
+      idispls(1) = 0
+
+      ishift = jpi-2*ihl
+
+      DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = ihl + 1, jpj - ihl  ;  DO ji = 1, ihl
+         zsnd(idx) = ARRAY_IN(ishift+ji,jj,jk,jl,jf)
+         idx = idx + 1
+      END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+
+      isizes(2) = ihl * (jpj - 2*ihl) * ipk * ipl * ipf
+      idispls(2) = jpbyt*isizes(1)
+
+      DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1, ihl  ;  DO ji = ihl + 1, jpi - ihl
+         zsnd(idx) = ARRAY_IN(ji,ihl+jj,jk,jl,jf)
+         idx = idx + 1
+      END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+
+      isizes(3) = (jpi - 2*ihl) * ihl * ipk * ipl * ipf
+      idispls(3) = jpbyt*(isizes(1)+isizes(2))
+
+      ishift = jpj-2*ihl
+
+      DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1, ihl  ;  DO ji = ihl + 1, jpi - ihl
+         zsnd(idx) = ARRAY_IN(ji,ishift+jj,jk,jl,jf)
+         idx = idx + 1
+      END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+
+      isizes(4) = (jpi - 2*ihl) * ihl * ipk * ipl * ipf
+      idispls(4) = jpbyt*(isizes(1)+isizes(2)+isizes(3))
+
+      idataty(1) = MPI_DOUBLE_PRECISION
+      idataty(2) = MPI_DOUBLE_PRECISION
+      idataty(3) = MPI_DOUBLE_PRECISION
+      idataty(4) = MPI_DOUBLE_PRECISION
+
+      IF( ln_timing ) CALL tic_tac(.TRUE.)
+
+      CALL mpi_neighbor_alltoallw (zsnd, isizes, idispls, idataty, zrcv, isizes, idispls, idataty, mpi_nc_com, ierr)
+
+      IF( ln_timing ) CALL tic_tac(.FALSE.)
+
+      ! --------------------------------------------------- !
+      !     2. Fill east and west north and south halos     !
+      ! --------------------------------------------------- !
+      !
+      ! 2.1 fill weastern halo
+      ! ----------------------
+      idx = 1
+      SELECT CASE ( ifill_we )
+      CASE ( jpfillnothing )               ! no filling 
+      CASE ( jpfillmpi   )                 ! use data received by MPI 
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ji,jj,jk,jl,jf) = zrcv(idx)   ! 1 -> ihl
+            idx = idx + 1
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+      CASE ( jpfillperio )                 ! use east-weast periodicity
+         ishift2 = jpi - 2 * ihl
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ji,jj,jk,jl,jf) = ARRAY_IN(ishift2+ji,jj,jk,jl,jf)
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcopy  )                 ! filling with inner domain values
+         DO jf = 1, ipf                               ! number of arrays to be treated
+            IF( .NOT. NAT_IN(jf) == 'F' ) THEN        ! do nothing for F point
+               DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+                  ARRAY_IN(ji,jj,jk,jl,jf) = ARRAY_IN(ihl+1,jj,jk,jl,jf)
+               END DO   ;   END DO   ;   END DO   ;   END DO
+            ENDIF
+         END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcst   )                 ! filling with constant value
+         DO jf = 1, ipf                               ! number of arrays to be treated
+            IF( .NOT. NAT_IN(jf) == 'F' ) THEN        ! do nothing for F point
+               DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+                  ARRAY_IN(ji,jj,jk,jl,jf) = zland
+               END DO;   END DO   ;   END DO   ;   END DO
+            ENDIF
+         END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      END SELECT
+      !
+      ! 2.2 fill eastern halo
+      ! ---------------------
+      ishift = jpi - ihl                ! fill halo from ji = jpi-ihl+1 to jpi 
+      SELECT CASE ( ifill_ea )
+      CASE ( jpfillnothing )               ! no filling 
+      CASE ( jpfillmpi   )                 ! use data received by MPI 
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ishift+ji,jj,jk,jl,jf) = zrcv(idx)   ! jpi - ihl + 1 -> jpi
+            idx = idx + 1
+         END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+      CASE ( jpfillperio )                 ! use east-weast periodicity
+         ishift2 = ihl
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ishift+ji,jj,jk,jl,jf) = ARRAY_IN(ishift2+ji,jj,jk,jl,jf)
+         END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcopy  )                 ! filling with inner domain values
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ishift+ji,jj,jk,jl,jf) = ARRAY_IN(ishift,jj,jk,jl,jf)
+         END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcst   )                 ! filling with constant value
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = ihl + 1, jpj - ihl   ;   DO ji = 1, ihl
+            ARRAY_IN(ishift+ji,jj,jk,jl,jf) = zland
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpj-2*ihl)*ihl*ipk*ipl*ipf
+      END SELECT
+      !
+      ! 2.3 fill southern halo
+      ! ----------------------
+      SELECT CASE ( ifill_so )
+      CASE ( jpfillnothing )               ! no filling 
+      CASE ( jpfillmpi   )                 ! use data received by MPI 
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,jj,jk,jl,jf) = zrcv(idx)   ! 1 -> ihl
+            idx = idx + 1
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+      CASE ( jpfillperio )                 ! use north-south periodicity
+         ishift2 = jpj - 2 * ihl
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,jj,jk,jl,jf) = ARRAY_IN(ji,ishift2+jj,jk,jl,jf)
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcopy  )                 ! filling with inner domain values
+         DO jf = 1, ipf                               ! number of arrays to be treated
+            IF( .NOT. NAT_IN(jf) == 'F' ) THEN        ! do nothing for F point
+               DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+                  ARRAY_IN(ji,jj,jk,jl,jf) = ARRAY_IN(ji,ihl+1,jk,jl,jf)
+               END DO   ;   END DO   ;   END DO   ;   END DO
+            ENDIF
+         END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcst   )                 ! filling with constant value
+         DO jf = 1, ipf                               ! number of arrays to be treated
+            IF( .NOT. NAT_IN(jf) == 'F' ) THEN        ! do nothing for F point
+               DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+                  ARRAY_IN(ji,jj,jk,jl,jf) = zland
+               END DO;   END DO   ;   END DO   ;   END DO
+            ENDIF
+         END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      END SELECT
+      !
+      ! 2.4 fill northern halo
+      ! ----------------------
+      ishift = jpj - ihl                ! fill halo from jj = jpj-ihl+1 to jpj 
+      SELECT CASE ( ifill_no )
+      CASE ( jpfillnothing )               ! no filling 
+      CASE ( jpfillmpi   )                 ! use data received by MPI 
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;  DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,ishift+jj,jk,jl,jf) = zrcv(idx)   ! jpj-ihl+1 -> jpj
+            idx = idx + 1
+         END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
+      CASE ( jpfillperio )                 ! use north-south periodicity
+         ishift2 = ihl
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,ishift+jj,jk,jl,jf) = ARRAY_IN(ji,ishift2+jj,jk,jl,jf)
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcopy  )                 ! filling with inner domain values
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,ishift+jj,jk,jl,jf) = ARRAY_IN(ji,ishift,jk,jl,jf)
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      CASE ( jpfillcst   )                 ! filling with constant value
+         DO jf = 1, ipf   ;   DO jl = 1, ipl   ;   DO jk = 1, ipk   ;   DO jj = 1, ihl   ;   DO ji = ihl + 1, jpi - ihl
+            ARRAY_IN(ji,ishift+jj,jk,jl,jf) = zland
+         END DO;   END DO   ;   END DO   ;   END DO   ;   END DO
+         idx = idx + (jpi-2*ihl)*ihl*ipk*ipl*ipf
+      END SELECT
+      !
+      ! -------------------------------------------- !
+      !     3. deallocate local temporary arrays     !
+      ! -------------------------------------------- !
+      !
+      DEALLOCATE( zsnd )
+      DEALLOCATE( zrcv )
+      !
+      ! ------------------------------- !
+      !     4. north fold treatment     !
+      ! ------------------------------- !
+      !
+      IF( lldo_nfd .AND. ifill_no /= jpfillnothing ) THEN
+         !
+         SELECT CASE ( jpni )
+         CASE ( 1 )     ;   CALL lbc_nfd( ptab, NAT_IN(:), SGN_IN(:) OPT_K(:) )   ! only 1 northern proc, no mpp
+         CASE DEFAULT   ;   CALL mpp_nfd( ptab, NAT_IN(:), SGN_IN(:) OPT_K(:) )   ! for all northern procs.
+         END SELECT
+         !
+         ifill_no = jpfillnothing  ! force to do nothing for the northern halo as we just done the north pole folding
+         !
+      ENDIF
+
+   END SUBROUTINE ROUTINE_NC
+
+#undef ARRAY_TYPE
+#undef NAT_IN
+#undef SGN_IN
+#undef ARRAY_IN
+#undef K_SIZE
+#undef L_SIZE
+#undef F_SIZE
+#undef OPT_K
Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mppini.F90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mppini.F90	(revision 11939)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/LBC/mppini.F90	(revision 11940)
@@ -38,5 +38,5 @@
    INTEGER :: numbot = -1  ! 'bottom_level' local logical unit
    INTEGER :: numbdy = -1  ! 'bdy_msk'      local logical unit
-   
+
    !!----------------------------------------------------------------------
    !! NEMO/OCE 4.0 , NEMO Consortium (2018)
@@ -464,4 +464,14 @@
       END DO
       nfipproc(:,:) = ipproc(:,:)
+
+      ! compute rank for MPI3 neighbourhood colectives
+      ALLOCATE(nranks(jpni*jpnj))
+      icont = 1
+      DO ji = 1, jpni
+         DO jj = 1, jpnj
+            nranks(icont) = ipproc(ji,jj)
+            icont = icont + 1
+         END DO
+      END DO
 
       ! neighbour treatment: change ibondi, ibondj if next to a land zone
@@ -694,4 +704,6 @@
          ENDIF
       ENDIF
+
+      CALL mpp_ini_nc
       !
       CALL mpp_init_ioipsl       ! Prepare NetCDF output file (if necessary)
Index: /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/TRA/traadv_fct.F90
===================================================================
--- /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/TRA/traadv_fct.F90	(revision 11939)
+++ /NEMO/branches/2019/dev_r11470_HPC_12_mpi3/src/OCE/TRA/traadv_fct.F90	(revision 11940)
@@ -89,4 +89,5 @@
       REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::   zwinf, zwdia, zwsup
       LOGICAL  ::   ll_zAimp                                 ! flag to apply adaptive implicit vertical advection
+
       !!----------------------------------------------------------------------
       !
@@ -254,5 +255,10 @@
                END DO
             END DO
-            CALL lbc_lnk_multi( 'traadv_fct', zltu, 'T', 1. , zltv, 'T', 1. )   ! Lateral boundary cond. (unchanged sgn)
+
+            IF(jpnij .eq. jpni*jpnj) THEN
+               CALL lbc_lnk_nc_multi( 'traadv_fct', zltu, 'T', 1. , zltv, 'T', 1. )   ! Lateral boundary cond. (unchanged sgn)
+            ELSE
+               CALL lbc_lnk_multi( 'traadv_fct', zltu, 'T', 1. , zltv, 'T', 1. )   ! Lateral boundary cond. (unchanged sgn)
+            END IF
             !
             DO jk = 1, jpkm1                 ! Horizontal advective fluxes
@@ -279,5 +285,10 @@
                END DO
             END DO
-            CALL lbc_lnk_multi( 'traadv_fct', ztu, 'U', -1. , ztv, 'V', -1. )   ! Lateral boundary cond. (unchanged sgn)
+
+            IF(jpnij .eq. jpni*jpnj) THEN
+               CALL lbc_lnk_nc_multi( 'traadv_fct', ztu, 'U', -1. , ztv, 'V', -1. )   ! Lateral boundary cond. (unchanged sgn)
+            ELSE
+               CALL lbc_lnk_multi( 'traadv_fct', ztu, 'U', -1. , ztv, 'V', -1. )   ! Lateral boundary cond. (unchanged sgn)
+            END IF
             !
             DO jk = 1, jpkm1                 ! Horizontal advective fluxes
@@ -351,5 +362,9 @@
          END IF
          !
-         CALL lbc_lnk_multi( 'traadv_fct', zwi, 'T', 1., zwx, 'U', -1. , zwy, 'V', -1.,  zwz, 'W',  1. )
+         IF(jpnij .eq. jpni*jpnj) THEN
+            CALL lbc_lnk_nc_multi( 'traadv_fct', zwi, 'T', 1., zwx, 'U', -1. , zwy, 'V', -1.,  zwz, 'W',  1. )
+         ELSE
+            CALL lbc_lnk_multi( 'traadv_fct', zwi, 'T', 1., zwx, 'U', -1. , zwy, 'V', -1.,  zwz, 'W',  1. )
+         END IF
          !
          !        !==  monotonicity algorithm  ==!
@@ -413,4 +428,5 @@
          ENDIF
          !
+
       END DO                     ! end of tracer loop
       !
@@ -426,5 +442,4 @@
       !
    END SUBROUTINE tra_adv_fct
-
 
    SUBROUTINE nonosc( pbef, paa, pbb, pcc, paft, p2dt )
@@ -498,6 +513,9 @@
          END DO
       END DO
-      CALL lbc_lnk_multi( 'traadv_fct', zbetup, 'T', 1. , zbetdo, 'T', 1. )   ! lateral boundary cond. (unchanged sign)
-
+      IF(jpnij .eq. jpni*jpnj) THEN
+         CALL lbc_lnk_nc_multi( 'traadv_fct', zbetup, 'T', 1. , zbetdo, 'T', 1. )   ! lateral boundary cond. (unchanged sign)
+      ELSE
+         CALL lbc_lnk_multi( 'traadv_fct', zbetup, 'T', 1. , zbetdo, 'T', 1. )   ! lateral boundary cond. (unchanged sign)
+      END IF
       ! 3. monotonic flux in the i & j direction (paa & pbb)
       ! ----------------------------------------
@@ -524,5 +542,9 @@
          END DO
       END DO
-      CALL lbc_lnk_multi( 'traadv_fct', paa, 'U', -1. , pbb, 'V', -1. )   ! lateral boundary condition (changed sign)
+      IF(jpnij .eq. jpni*jpnj) THEN
+         CALL lbc_lnk_nc_multi( 'traadv_fct', paa, 'U', -1. , pbb, 'V', -1. )   ! lateral boundary condition (changed sign)
+      ELSE
+         CALL lbc_lnk_multi( 'traadv_fct', paa, 'U', -1. , pbb, 'V', -1. )   ! lateral boundary condition (changed sign)
+      END IF
       !
    END SUBROUTINE nonosc
