Index: NEMO/branches/UKMO/NEMO_4.0_mirror_SI3_GPU/src/OCE/lib_fortran.F90
===================================================================
--- NEMO/branches/UKMO/NEMO_4.0_mirror_SI3_GPU/src/OCE/lib_fortran.F90	(revision 13089)
+++ NEMO/branches/UKMO/NEMO_4.0_mirror_SI3_GPU/src/OCE/lib_fortran.F90	(revision 13090)
@@ -69,113 +69,167 @@
    !!----------------------------------------------------------------------
 CONTAINS
-
-#  define GLOBSUM_CODE
-
-#     define DIM_1d
-#     define FUNCTION_GLOBSUM           glob_sum_1d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBSUM
-#     undef DIM_1d
-
-#     define DIM_2d
-#     define OPERATION_GLOBSUM
-#     define FUNCTION_GLOBSUM           glob_sum_2d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBSUM
-#     undef OPERATION_GLOBSUM
-#     define OPERATION_FULL_GLOBSUM
-#     define FUNCTION_GLOBSUM           glob_sum_full_2d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBSUM
-#     undef OPERATION_FULL_GLOBSUM
-#     undef DIM_2d
-
-#     define DIM_3d
-#     define OPERATION_GLOBSUM
-#     define FUNCTION_GLOBSUM           glob_sum_3d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBSUM
-#     undef OPERATION_GLOBSUM
-#     define OPERATION_FULL_GLOBSUM
-#     define FUNCTION_GLOBSUM           glob_sum_full_3d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBSUM
-#     undef OPERATION_FULL_GLOBSUM
-#     undef DIM_3d
-
-#  undef GLOBSUM_CODE
-
-
-#  define GLOBMINMAX_CODE
-
-#     define DIM_2d
-#     define OPERATION_GLOBMIN
-#     define FUNCTION_GLOBMINMAX           glob_min_2d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBMINMAX
-#     undef OPERATION_GLOBMIN
-#     define OPERATION_GLOBMAX
-#     define FUNCTION_GLOBMINMAX           glob_max_2d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBMINMAX
-#     undef OPERATION_GLOBMAX
-#     undef DIM_2d
-
-#     define DIM_3d
-#     define OPERATION_GLOBMIN
-#     define FUNCTION_GLOBMINMAX           glob_min_3d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBMINMAX
-#     undef OPERATION_GLOBMIN
-#     define OPERATION_GLOBMAX
-#     define FUNCTION_GLOBMINMAX           glob_max_3d
-#     include "lib_fortran_generic.h90"
-#     undef FUNCTION_GLOBMINMAX
-#     undef OPERATION_GLOBMAX
-#     undef DIM_3d
-#  undef GLOBMINMAX_CODE
-
-!                          ! FUNCTION local_sum !
-
-   FUNCTION local_sum_2d( ptab )
-      !!----------------------------------------------------------------------
-      REAL(wp),  INTENT(in   ) ::   ptab(:,:) ! array on which operation is applied
-      COMPLEX(wp)              ::  local_sum_2d
-      !
-      !!-----------------------------------------------------------------------
-      !
-      COMPLEX(wp)::   ctmp
-      REAL(wp)   ::   ztmp
-      INTEGER    ::   ji, jj    ! dummy loop indices
-      INTEGER    ::   ipi, ipj  ! dimensions
+!                          ! FUNCTION glob_sum_1d !
+   FUNCTION glob_sum_c1d(ptab, kdim, ldcom, cdname)
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      INTEGER, INTENT(IN) :: kdim
+      COMPLEX(KIND = wp), INTENT(IN), DIMENSION(kdim) :: ptab
+      LOGICAL, INTENT(IN) :: ldcom
+      REAL(KIND = wp) :: glob_sum_c1d
+
+      COMPLEX(KIND = wp) :: ctmp
+      INTEGER :: ji
+
+      ctmp = CMPLX(0.E0, 0.E0, wp)
+
+      DO ji = 1, kdim
+        CALL DDPDD(ptab(ji), ctmp)
+      END DO
+
+      IF (ldcom) CALL mpp_sum(cdname, ctmp)
+
+      glob_sum_c1d = REAL(ctmp, wp)
+
+   END FUNCTION glob_sum_c1d
+
+   FUNCTION glob_sum_1d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_sum_1d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj, jk   ! dummy loop indices
+      INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      !!-----------------------------------------------------------------------
+      !
+      ipi = SIZE(ptab,1)   ! 1st dimension
+      ipj = 1   ! 2nd dimension
+      ipk = 1   ! 3rd dimension
+      !
+      ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
+   
+      DO jk = 1, ipk
+        DO jj = 1, ipj
+          DO ji = 1, ipi
+             ztmp =  ptab(ji) * 1.
+             CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+          END DO
+        END DO
+      END DO
+      CALL mpp_sum( cdname, ctmp )   ! sum over the global domain
+      glob_sum_1d = REAL(ctmp,wp)
+
+   END FUNCTION glob_sum_1d
+
+!
+
+!                          ! FUNCTION glob_sum_2d !
+
+   FUNCTION glob_sum_2d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_sum_2d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj, jk   ! dummy loop indices
+      INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
       !!-----------------------------------------------------------------------
       !
       ipi = SIZE(ptab,1)   ! 1st dimension
       ipj = SIZE(ptab,2)   ! 2nd dimension
-      !
-      ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
-
-      DO jj = 1, ipj
-         DO ji = 1, ipi
-            ztmp =  ptab(ji,jj) * tmask_i(ji,jj)
-            CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
-         END DO
-      END DO
-      !
-      local_sum_2d = ctmp
-       
-   END FUNCTION local_sum_2d
-
-   FUNCTION local_sum_3d( ptab )
-      !!----------------------------------------------------------------------
-      REAL(wp),  INTENT(in   ) ::   ptab(:,:,:) ! array on which operation is applied
-      COMPLEX(wp)              ::  local_sum_3d
-      !
-      !!-----------------------------------------------------------------------
-      !
+      ipk = 1   ! 3rd dimension
+      
+      ALLOCATE(hsum(ipj))
+   
+      DO jk = 1, ipk
+        DO jj = 1, ipj
+          ctmp = CMPLX( 0.e0, 0.e0, wp )
+          DO ji = 1, ipi
+             ztmp =  ptab(ji,jj) * tmask_i(ji,jj)
+             CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+          END DO
+          hsum(jj) = ctmp
+        END DO
+      END DO
+
+      glob_sum_2d = glob_sum_c1d(hsum, ipj, .TRUE..AND.lk_mpp, cdname)
+
+      DEALLOCATE(hsum)
+
+   END FUNCTION glob_sum_2d
+
+!
+!                          ! FUNCTION glob_sum_full_2d !
+
+   FUNCTION glob_sum_full_2d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_sum_full_2d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
       COMPLEX(wp)::   ctmp
       REAL(wp)   ::   ztmp
       INTEGER    ::   ji, jj, jk   ! dummy loop indices
       INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
+      !!-----------------------------------------------------------------------
+      !
+      ipi = SIZE(ptab,1)   ! 1st dimension
+      ipj = SIZE(ptab,2)   ! 2nd dimension
+      ipk = 1   ! 3rd dimension
+      ALLOCATE(hsum(ipj))
+      !
+      DO jk = 1, ipk
+        DO jj = 1, ipj
+          ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
+          DO ji = 1, ipi
+             ztmp =  ptab(ji,jj) * tmask_h(ji,jj)
+             CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+          END DO
+          hsum(jj) = ctmp
+        END DO
+      END DO
+
+      glob_sum_full_2d = glob_sum_c1d(hsum, ipj, .TRUE..AND.lk_mpp, cdname)
+
+      DEALLOCATE(hsum)
+
+   END FUNCTION glob_sum_full_2d
+
+!
+
+!                          ! FUNCTION glob_sum_3d !
+
+   FUNCTION glob_sum_3d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_sum_3d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj, jk   ! dummy loop indices
+      INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
       !!-----------------------------------------------------------------------
       !
@@ -184,7 +238,8 @@
       ipk = SIZE(ptab,3)   ! 3rd dimension
       !
-      ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
-
+      ALLOCATE(hsum(ipk))
+   
       DO jk = 1, ipk
+        ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
         DO jj = 1, ipj
           DO ji = 1, ipi
@@ -193,8 +248,257 @@
           END DO
         END DO
-      END DO
-      !
-      local_sum_3d = ctmp
+        hsum(jk) = ctmp
+      END DO
+
+      glob_sum_3d = glob_sum_c1d(hsum, ipk, .TRUE..AND.lk_mpp, cdname)
+
+      DEALLOCATE(hsum)
+
+   END FUNCTION glob_sum_3d
+
+!
+!                          ! FUNCTION glob_sum_full_3d !
+
+   FUNCTION glob_sum_full_3d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_sum_full_3d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj, jk   ! dummy loop indices
+      INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
+      !!-----------------------------------------------------------------------
+      !
+      ipi = SIZE(ptab,1)   ! 1st dimension
+      ipj = SIZE(ptab,2)   ! 2nd dimension
+      ipk = SIZE(ptab,3)   ! 3rd dimension
+      !
+      ALLOCATE(hsum(ipk))
+   
+      DO jk = 1, ipk
+        ctmp = CMPLX( 0.e0, 0.e0, wp )
+        DO jj = 1, ipj
+          DO ji = 1, ipi
+             ztmp =  ptab(ji,jj,jk) * tmask_h(ji,jj)
+             CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+          END DO
+        END DO
+        hsum(jk) = ctmp
+      END DO
+
+      glob_sum_full_3d = glob_sum_c1d(hsum, ipk, .TRUE..AND.lk_mpp, cdname)
+
+      DEALLOCATE(hsum)
+
+   END FUNCTION glob_sum_full_3d
+
+!
+
+
+
+
+!                          ! FUNCTION glob_min_2d !
+
+   FUNCTION glob_min_2d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_min_2d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   jk       ! dummy loop indices
+      INTEGER    ::   ipk      ! dimensions
+      !!-----------------------------------------------------------------------
+      !
+      ipk = 1   ! 3rd dimension
+      !
+      ztmp = minval( ptab(:,:)*tmask_i(:,:) )
+
+      CALL mpp_min( cdname, ztmp)
+
+      glob_min_2d = ztmp
+
+
+   END FUNCTION glob_min_2d
+
+!                          ! FUNCTION glob_max_2d !
+
+   FUNCTION glob_max_2d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_max_2d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   jk       ! dummy loop indices
+      INTEGER    ::   ipk      ! dimensions
+      !!-----------------------------------------------------------------------
+      !
+      ipk = 1   ! 3rd dimension
+      !
+      ztmp = maxval( ptab(:,:)*tmask_i(:,:) )
+
+      CALL mpp_max( cdname, ztmp)
+
+      glob_max_2d = ztmp
+
+
+   END FUNCTION glob_max_2d
+
+
+!                          ! FUNCTION glob_min_3d !
+
+   FUNCTION glob_min_3d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_min_3d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   jk       ! dummy loop indices
+      INTEGER    ::   ipk      ! dimensions
+      !!-----------------------------------------------------------------------
+      !
+      ipk = SIZE(ptab,3)   ! 3rd dimension
+      !
+      ztmp = minval( ptab(:,:,1)*tmask_i(:,:) )
+      DO jk = 2, ipk
+         ztmp = min(ztmp, minval( ptab(:,:,jk)*tmask_i(:,:) ))
+      ENDDO
+
+      CALL mpp_min( cdname, ztmp)
+
+      glob_min_3d = ztmp
+
+
+   END FUNCTION glob_min_3d
+
+!                          ! FUNCTION glob_max_3d !
+
+   FUNCTION glob_max_3d( cdname, ptab )
+      !!----------------------------------------------------------------------
+      CHARACTER(len=*),  INTENT(in   ) ::   cdname  ! name of the calling subroutine
+      REAL(wp)                 , INTENT(in   ) ::   ptab(:,:,:)                             ! array on which operation is applied
+      REAL(wp)   ::  glob_max_3d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      REAL(wp)                              ::   FUNCTION_GLOB_OP   ! global sum
+      !!
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   jk       ! dummy loop indices
+      INTEGER    ::   ipk      ! dimensions
+      !!-----------------------------------------------------------------------
+      !
+      ipk = SIZE(ptab,3)   ! 3rd dimension
+      !
+      ztmp = maxval( ptab(:,:,1)*tmask_i(:,:) )
+      DO jk = 2, ipk
+         ztmp = max(ztmp, maxval( ptab(:,:,jk)*tmask_i(:,:) ))
+      ENDDO
+
+      CALL mpp_max( cdname, ztmp)
+
+      glob_max_3d = ztmp
+
+
+   END FUNCTION glob_max_3d
+
+
+!                          ! FUNCTION local_sum !
+
+   FUNCTION local_sum_2d( ptab )
+      !!----------------------------------------------------------------------
+      REAL(wp),  INTENT(in   ) ::   ptab(:,:) ! array on which operation is applied
+      COMPLEX(wp)              ::  local_sum_2d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj    ! dummy loop indices
+      INTEGER    ::   ipi, ipj  ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
+      !!-----------------------------------------------------------------------
+      !
+      ipi = SIZE(ptab,1)   ! 1st dimension
+      ipj = SIZE(ptab,2)   ! 2nd dimension
+      !
+      ALLOCATE(hsum(ipj))
+
+      DO jj = 1, ipj
+         ctmp = CMPLX( 0.e0, 0.e0, wp )
+         DO ji = 1, ipi
+            ztmp =  ptab(ji,jj) * tmask_i(ji,jj)
+            CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+         END DO
+         hsum(jj) = ctmp
+      END DO
+      !
+      local_sum_2d = glob_sum_c1d(hsum, ipj, .FALSE., 'NONE')  
+
+      DEALLOCATE(hsum)
        
+   END FUNCTION local_sum_2d
+
+   FUNCTION local_sum_3d( ptab )
+      !!----------------------------------------------------------------------
+      REAL(wp),  INTENT(in   ) ::   ptab(:,:,:) ! array on which operation is applied
+      COMPLEX(wp)              ::  local_sum_3d
+      !
+      !!-----------------------------------------------------------------------
+      !
+      COMPLEX(wp)::   ctmp
+      REAL(wp)   ::   ztmp
+      INTEGER    ::   ji, jj, jk   ! dummy loop indices
+      INTEGER    ::   ipi, ipj, ipk    ! dimensions
+      COMPLEX(KIND = wp), allocatable :: hsum(:)
+      !!-----------------------------------------------------------------------
+      !
+      ipi = SIZE(ptab,1)   ! 1st dimension
+      ipj = SIZE(ptab,2)   ! 2nd dimension
+      ipk = SIZE(ptab,3)   ! 3rd dimension
+      !
+      ALLOCATE(hsum(ipk))
+      ctmp = CMPLX( 0.e0, 0.e0, wp )   ! warning ctmp is cumulated
+
+      DO jk = 1, ipk
+        ctmp = CMPLX( 0.e0, 0.e0, wp )
+        DO jj = 1, ipj
+          DO ji = 1, ipi
+             ztmp =  ptab(ji,jj,jk) * tmask_i(ji,jj)
+             CALL DDPDD( CMPLX( ztmp, 0.e0, wp ), ctmp )
+          END DO
+        END DO
+        hsum(jk) = ctmp
+      END DO
+      !
+      local_sum_3d = glob_sum_c1d(hsum, ipk, .FALSE., 'NONE')
+      
+      DEALLOCATE(hsum) 
+
    END FUNCTION local_sum_3d
 
