New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
lib_mpp.F90 in branches/2011/dev_r2855_NOCS_mppsca/NEMOGCM/NEMO/OPA_SRC/LBC – NEMO

source: branches/2011/dev_r2855_NOCS_mppsca/NEMOGCM/NEMO/OPA_SRC/LBC/lib_mpp.F90 @ 2883

Last change on this file since 2883 was 2883, checked in by acc, 13 years ago

Branch 2011/dev_r2855_NOCS_mppsca. Correction to comments and removal of unwanted debugging options

  • Property svn:keywords set to Id
File size: 128.9 KB
Line 
1MODULE lib_mpp
2   !!======================================================================
3   !!                       ***  MODULE  lib_mpp  ***
4   !! Ocean numerics:  massively parallel processing library
5   !!=====================================================================
6   !! History :  OPA  !  1994  (M. Guyon, J. Escobar, M. Imbard)  Original code
7   !!            7.0  !  1997  (A.M. Treguier)  SHMEM additions
8   !!            8.0  !  1998  (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
9   !!                 !  1998  (J.M. Molines) Open boundary conditions
10   !!   NEMO     1.0  !  2003  (J.-M. Molines, G. Madec)  F90, free form
11   !!                 !  2003  (J.M. Molines) add mpp_ini_north(_3d,_2d)
12   !!             -   !  2004  (R. Bourdalle Badie)  isend option in mpi
13   !!                 !  2004  (J.M. Molines) minloc, maxloc
14   !!             -   !  2005  (G. Madec, S. Masson)  npolj=5,6 F-point & ice cases
15   !!             -   !  2005  (R. Redler) Replacement of MPI_COMM_WORLD except for MPI_Abort
16   !!             -   !  2005  (R. Benshila, G. Madec)  add extra halo case
17   !!             -   !  2008  (R. Benshila) add mpp_ini_ice
18   !!            3.2  !  2009  (R. Benshila) SHMEM suppression, north fold in lbc_nfd
19   !!            3.2  !  2009  (O. Marti)    add mpp_ini_znl
20   !!            4.0  !  2011  (G. Madec)  move ctl_ routines from in_out_manager
21   !!----------------------------------------------------------------------
22
23   !!----------------------------------------------------------------------
24   !!   ctl_stop   : update momentum and tracer Kz from a tke scheme
25   !!   ctl_warn   : initialization, namelist read, and parameters control
26   !!   ctl_opn    : Open file and check if required file is available.
27   !!   get_unit    : give the index of an unused logical unit
28   !!----------------------------------------------------------------------
29#if   defined key_mpp_mpi 
30   !!----------------------------------------------------------------------
31   !!   'key_mpp_mpi'             MPI massively parallel processing library
32   !!----------------------------------------------------------------------
33   !!   lib_mpp_alloc : allocate mpp arrays
34   !!   mynode        : indentify the processor unit
35   !!   mpp_lnk       : interface (defined in lbclnk) for message passing of 2d or 3d arrays (mpp_lnk_2d, mpp_lnk_3d)
36   !!   mpp_lnk_3d_gather :  Message passing manadgement for two 3D arrays
37   !!   mpp_lnk_e     : interface (defined in lbclnk) for message passing of 2d array with extra halo (mpp_lnk_2d_e)
38   !!   mpprecv         :
39   !!   mppsend       :   SUBROUTINE mpp_ini_znl
40   !!   mppscatter    :
41   !!   mppgather     :
42   !!   mpp_min       : generic interface for mppmin_int , mppmin_a_int , mppmin_real, mppmin_a_real
43   !!   mpp_max       : generic interface for mppmax_int , mppmax_a_int , mppmax_real, mppmax_a_real
44   !!   mpp_sum       : generic interface for mppsum_int , mppsum_a_int , mppsum_real, mppsum_a_real
45   !!   mpp_minloc    :
46   !!   mpp_maxloc    :
47   !!   mppsync       :
48   !!   mppstop       :
49   !!   mppobc        : variant of mpp_lnk for open boundary condition
50   !!   mpp_ini_north : initialisation of north fold
51   !!   mpp_lbc_north : north fold processors gathering
52   !!   mpp_lbc_north_e : variant of mpp_lbc_north for extra outer halo
53   !!----------------------------------------------------------------------
54   USE dom_oce        ! ocean space and time domain
55   USE lbcnfd         ! north fold treatment
56   USE in_out_manager ! I/O manager
57
58   IMPLICIT NONE
59   PRIVATE
60   
61   PUBLIC   ctl_stop, ctl_warn, get_unit, ctl_opn
62   PUBLIC   mynode, mppstop, mppsync, mpp_comm_free
63   PUBLIC   mpp_ini_north, mpp_lbc_north, mpp_lbc_north_e
64   PUBLIC   mpp_min, mpp_max, mpp_sum, mpp_minloc, mpp_maxloc
65   PUBLIC   mpp_lnk_3d, mpp_lnk_3d_gather, mpp_lnk_2d, mpp_lnk_2d_e
66   PUBLIC   mppobc, mpp_ini_ice, mpp_ini_znl
67   PUBLIC   mppsize
68   PUBLIC   lib_mpp_alloc   ! Called in nemogcm.F90
69
70   !! * Interfaces
71   !! define generic interface for these routine as they are called sometimes
72   !! with scalar arguments instead of array arguments, which causes problems
73   !! for the compilation on AIX system as well as NEC and SGI. Ok on COMPACQ
74   INTERFACE mpp_min
75      MODULE PROCEDURE mppmin_a_int, mppmin_int, mppmin_a_real, mppmin_real
76   END INTERFACE
77   INTERFACE mpp_max
78      MODULE PROCEDURE mppmax_a_int, mppmax_int, mppmax_a_real, mppmax_real
79   END INTERFACE
80   INTERFACE mpp_sum
81# if defined key_mpp_rep
82      MODULE PROCEDURE mppsum_a_int, mppsum_int, mppsum_a_real, mppsum_real, &
83                       mppsum_realdd, mppsum_a_realdd
84# else
85      MODULE PROCEDURE mppsum_a_int, mppsum_int, mppsum_a_real, mppsum_real
86# endif
87   END INTERFACE
88   INTERFACE mpp_lbc_north
89      MODULE PROCEDURE mpp_lbc_north_3d, mpp_lbc_north_2d 
90   END INTERFACE
91   INTERFACE mpp_minloc
92      MODULE PROCEDURE mpp_minloc2d ,mpp_minloc3d
93   END INTERFACE
94   INTERFACE mpp_maxloc
95      MODULE PROCEDURE mpp_maxloc2d ,mpp_maxloc3d
96   END INTERFACE
97   
98   !! ========================= !!
99   !!  MPI  variable definition !!
100   !! ========================= !!
101!$AGRIF_DO_NOT_TREAT
102   INCLUDE 'mpif.h'
103!$AGRIF_END_DO_NOT_TREAT
104   
105   LOGICAL, PUBLIC, PARAMETER ::   lk_mpp = .TRUE.    !: mpp flag
106
107   INTEGER, PARAMETER         ::   nprocmax = 2**10   ! maximun dimension (required to be a power of 2)
108   
109   INTEGER ::   mppsize        ! number of process
110   INTEGER ::   mpprank        ! process number  [ 0 - size-1 ]
111!$AGRIF_DO_NOT_TREAT
112   INTEGER, PUBLIC ::   mpi_comm_opa   ! opa local communicator
113!$AGRIF_END_DO_NOT_TREAT
114
115# if defined key_mpp_rep
116   INTEGER :: MPI_SUMDD
117# endif
118
119   ! variables used in case of sea-ice
120   INTEGER, PUBLIC ::   ncomm_ice       !: communicator made by the processors with sea-ice
121   INTEGER ::   ngrp_ice        !  group ID for the ice processors (for rheology)
122   INTEGER ::   ndim_rank_ice   !  number of 'ice' processors
123   INTEGER ::   n_ice_root      !  number (in the comm_ice) of proc 0 in the ice comm
124   INTEGER, DIMENSION(:), ALLOCATABLE, SAVE ::   nrank_ice     ! dimension ndim_rank_ice
125
126   ! variables used for zonal integration
127   INTEGER, PUBLIC ::   ncomm_znl       !: communicator made by the processors on the same zonal average
128   LOGICAL, PUBLIC ::   l_znl_root      ! True on the 'left'most processor on the same row
129   INTEGER ::   ngrp_znl        ! group ID for the znl processors
130   INTEGER ::   ndim_rank_znl   ! number of processors on the same zonal average
131   INTEGER, DIMENSION(:), ALLOCATABLE, SAVE ::   nrank_znl  ! dimension ndim_rank_znl, number of the procs into the same znl domain
132   
133   ! North fold condition in mpp_mpi with jpni > 1
134   INTEGER ::   ngrp_world        ! group ID for the world processors
135   INTEGER ::   ngrp_opa          ! group ID for the opa processors
136   INTEGER ::   ngrp_north        ! group ID for the northern processors (to be fold)
137   INTEGER ::   ncomm_north       ! communicator made by the processors belonging to ngrp_north
138   INTEGER ::   ndim_rank_north   ! number of 'sea' processor in the northern line (can be /= jpni !)
139   INTEGER ::   njmppmax          ! value of njmpp for the processors of the northern line
140   INTEGER ::   north_root        ! number (in the comm_opa) of proc 0 in the northern comm
141   INTEGER, DIMENSION(:), ALLOCATABLE, SAVE ::   nrank_north   ! dimension ndim_rank_north
142
143   ! Type of send : standard, buffered, immediate
144   CHARACTER(len=1) ::   cn_mpi_send = 'S'    ! type od mpi send/recieve (S=standard, B=bsend, I=isend)
145   LOGICAL          ::   l_isend = .FALSE.   ! isend use indicator (T if cn_mpi_send='I')
146   INTEGER          ::   nn_buffer = 0       ! size of the buffer in case of mpi_bsend
147     
148   REAL(wp), DIMENSION(:), ALLOCATABLE, SAVE :: tampon  ! buffer in case of bsend
149
150   ! message passing arrays
151   REAL(wp), DIMENSION(:,:,:,:,:), ALLOCATABLE, SAVE ::   t4ns, t4sn   ! 2 x 3d for north-south & south-north
152   REAL(wp), DIMENSION(:,:,:,:,:), ALLOCATABLE, SAVE ::   t4ew, t4we   ! 2 x 3d for east-west & west-east
153   REAL(wp), DIMENSION(:,:,:,:,:), ALLOCATABLE, SAVE ::   t4p1, t4p2   ! 2 x 3d for north fold
154   REAL(wp), DIMENSION(:,:,:,:)  , ALLOCATABLE, SAVE ::   t3ns, t3sn   ! 3d for north-south & south-north
155   REAL(wp), DIMENSION(:,:,:,:)  , ALLOCATABLE, SAVE ::   t3ew, t3we   ! 3d for east-west & west-east
156   REAL(wp), DIMENSION(:,:,:,:)  , ALLOCATABLE, SAVE ::   t3p1, t3p2   ! 3d for north fold
157   REAL(wp), DIMENSION(:,:,:)    , ALLOCATABLE, SAVE ::   t2ns, t2sn   ! 2d for north-south & south-north
158   REAL(wp), DIMENSION(:,:,:)    , ALLOCATABLE, SAVE ::   t2ew, t2we   ! 2d for east-west & west-east
159   REAL(wp), DIMENSION(:,:,:)    , ALLOCATABLE, SAVE ::   t2p1, t2p2   ! 2d for north fold
160   REAL(wp), DIMENSION(:,:,:)    , ALLOCATABLE, SAVE ::   tr2ns, tr2sn ! 2d for north-south & south-north + extra outer halo
161   REAL(wp), DIMENSION(:,:,:)    , ALLOCATABLE, SAVE ::   tr2ew, tr2we ! 2d for east-west   & west-east   + extra outer halo
162
163   ! Arrays used in mpp_lbc_north_3d()
164   REAL(wp), DIMENSION(:,:,:)  , ALLOCATABLE, SAVE   ::   ztab, znorthloc
165   REAL(wp), DIMENSION(:,:,:,:), ALLOCATABLE, SAVE   ::   znorthgloio
166   REAL(wp), DIMENSION(:,:,:)  , ALLOCATABLE, SAVE   ::   zfoldwk      ! Workspace for message transfers avoiding mpi_allgather
167
168   ! Arrays used in mpp_lbc_north_2d()
169   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, SAVE    ::   ztab_2d, znorthloc_2d
170   REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, SAVE    ::   znorthgloio_2d
171   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, SAVE    ::   zfoldwk_2d    ! Workspace for message transfers avoiding mpi_allgather
172
173   ! Arrays used in mpp_lbc_north_e()
174   REAL(wp), DIMENSION(:,:)  , ALLOCATABLE, SAVE    ::   ztab_e, znorthloc_e
175   REAL(wp), DIMENSION(:,:,:), ALLOCATABLE, SAVE    ::   znorthgloio_e
176
177   ! North fold arrays used to minimise the use of allgather operations. Set in nemo_northcomms (nemogcm) so need to be public
178   INTEGER, PUBLIC,  PARAMETER :: jpmaxngh = 8                 ! Assumed maximum number of active neighbours
179   INTEGER, PUBLIC,  PARAMETER :: jptyps   = 5                 ! Number of different neighbour lists to be used for northfold exchanges
180   INTEGER, PUBLIC,  DIMENSION (jpmaxngh,jptyps)    ::   isendto
181   INTEGER, PUBLIC,  DIMENSION (jptyps)             ::   nsndto
182   LOGICAL, PUBLIC                                  ::   ln_nnogather     = .FALSE.  ! namelist control of northfold comms
183   LOGICAL, PUBLIC                                  ::   l_north_nogather = .FALSE.  ! internal control of northfold comms
184   INTEGER, PUBLIC                                  ::   ityp
185   !!----------------------------------------------------------------------
186   !! NEMO/OPA 3.3 , NEMO Consortium (2010)
187   !! $Id$
188   !! Software governed by the CeCILL licence     (NEMOGCM/NEMO_CeCILL.txt)
189   !!----------------------------------------------------------------------
190CONTAINS
191
192   INTEGER FUNCTION lib_mpp_alloc( kumout )
193      !!----------------------------------------------------------------------
194      !!              ***  routine lib_mpp_alloc  ***
195      !!----------------------------------------------------------------------
196      INTEGER, INTENT(in) ::   kumout   ! ocean.output logical unit
197      !!----------------------------------------------------------------------
198      !
199      ALLOCATE( t4ns(jpi,jprecj,jpk,2,2) , t4sn(jpi,jprecj,jpk,2,2) ,                                            &
200         &      t4ew(jpj,jpreci,jpk,2,2) , t4we(jpj,jpreci,jpk,2,2) ,                                            &
201         &      t4p1(jpi,jprecj,jpk,2,2) , t4p2(jpi,jprecj,jpk,2,2) ,                                            &
202         &      t3ns(jpi,jprecj,jpk,2)   , t3sn(jpi,jprecj,jpk,2)   ,                                            &
203         &      t3ew(jpj,jpreci,jpk,2)   , t3we(jpj,jpreci,jpk,2)   ,                                            &
204         &      t3p1(jpi,jprecj,jpk,2)   , t3p2(jpi,jprecj,jpk,2)   ,                                            &
205         &      t2ns(jpi,jprecj    ,2)   , t2sn(jpi,jprecj    ,2)   ,                                            &
206         &      t2ew(jpj,jpreci    ,2)   , t2we(jpj,jpreci    ,2)   ,                                            &
207         &      t2p1(jpi,jprecj    ,2)   , t2p2(jpi,jprecj    ,2)   ,                                            &
208         !
209         &      tr2ns(1-jpr2di:jpi+jpr2di,jprecj+jpr2dj,2) ,                                                     &
210         &      tr2sn(1-jpr2di:jpi+jpr2di,jprecj+jpr2dj,2) ,                                                     &
211         &      tr2ew(1-jpr2dj:jpj+jpr2dj,jpreci+jpr2di,2) ,                                                     &
212         &      tr2we(1-jpr2dj:jpj+jpr2dj,jpreci+jpr2di,2) ,                                                     &
213         !
214         &      ztab(jpiglo,4,jpk) , znorthloc(jpi,4,jpk) , znorthgloio(jpi,4,jpk,jpni) ,                        &
215         &      zfoldwk(jpi,4,jpk) ,                                                                             &
216         !
217         &      ztab_2d(jpiglo,4)  , znorthloc_2d(jpi,4)  , znorthgloio_2d(jpi,4,jpni)  ,                        &
218         &      zfoldwk_2d(jpi,4)  ,                                                                             &
219         !
220         &      ztab_e(jpiglo,4+2*jpr2dj) , znorthloc_e(jpi,4+2*jpr2dj) , znorthgloio_e(jpi,4+2*jpr2dj,jpni) ,   &
221         !
222         &      STAT=lib_mpp_alloc )
223         !
224      IF( lib_mpp_alloc /= 0 ) THEN
225         WRITE(kumout,cform_war)
226         WRITE(kumout,*) 'lib_mpp_alloc : failed to allocate arrays'
227      ENDIF
228      !
229   END FUNCTION lib_mpp_alloc
230
231
232   FUNCTION mynode( ldtxt, kumnam, kstop, localComm )
233      !!----------------------------------------------------------------------
234      !!                  ***  routine mynode  ***
235      !!                   
236      !! ** Purpose :   Find processor unit
237      !!----------------------------------------------------------------------
238      CHARACTER(len=*),DIMENSION(:), INTENT(  out) ::   ldtxt 
239      INTEGER                      , INTENT(in   ) ::   kumnam       ! namelist logical unit
240      INTEGER                      , INTENT(inout) ::   kstop        ! stop indicator
241      INTEGER, OPTIONAL            , INTENT(in   ) ::   localComm
242      !
243      INTEGER ::   mynode, ierr, code, ji, ii
244      LOGICAL ::   mpi_was_called
245      !
246      NAMELIST/nammpp/ cn_mpi_send, nn_buffer, jpni, jpnj, jpnij, ln_nnogather
247      !!----------------------------------------------------------------------
248      !
249      ii = 1
250      WRITE(ldtxt(ii),*)                                                                          ;   ii = ii + 1
251      WRITE(ldtxt(ii),*) 'mynode : mpi initialisation'                                            ;   ii = ii + 1
252      WRITE(ldtxt(ii),*) '~~~~~~ '                                                                ;   ii = ii + 1
253      !
254      jpni = -1; jpnj = -1; jpnij = -1
255      REWIND( kumnam )               ! Namelist namrun : parameters of the run
256      READ  ( kumnam, nammpp )
257      !                              ! control print
258      WRITE(ldtxt(ii),*) '   Namelist nammpp'                                                     ;   ii = ii + 1
259      WRITE(ldtxt(ii),*) '      mpi send type                      cn_mpi_send = ', cn_mpi_send   ;   ii = ii + 1
260      WRITE(ldtxt(ii),*) '      size in bytes of exported buffer   nn_buffer   = ', nn_buffer     ;   ii = ii + 1
261
262#if defined key_agrif
263      IF( .NOT. Agrif_Root() ) THEN
264         jpni  = Agrif_Parent(jpni ) 
265         jpnj  = Agrif_Parent(jpnj )
266         jpnij = Agrif_Parent(jpnij)
267      ENDIF
268#endif
269
270      IF(jpnij < 1)THEN
271         ! If jpnij is not specified in namelist then we calculate it - this
272         ! means there will be no land cutting out.
273         jpnij = jpni * jpnj
274      END IF
275
276      IF( (jpni < 1) .OR. (jpnj < 1) )THEN
277         WRITE(ldtxt(ii),*) '      jpni, jpnj and jpnij will be calculated automatically'; ii = ii + 1
278      ELSE
279         WRITE(ldtxt(ii),*) '      processor grid extent in i         jpni = ',jpni; ii = ii + 1
280         WRITE(ldtxt(ii),*) '      processor grid extent in j         jpnj = ',jpnj; ii = ii + 1
281         WRITE(ldtxt(ii),*) '      number of local domains           jpnij = ',jpnij; ii = ii +1
282      END IF
283
284      WRITE(ldtxt(ii),*) '      avoid use of mpi_allgather at the north fold  ln_nnogather = ', ln_nnogather  ; ii = ii + 1
285
286      CALL mpi_initialized ( mpi_was_called, code )
287      IF( code /= MPI_SUCCESS ) THEN
288         DO ji = 1, SIZE(ldtxt) 
289            IF( TRIM(ldtxt(ji)) /= '' )   WRITE(*,*) ldtxt(ji)      ! control print of mynode
290         END DO         
291         WRITE(*, cform_err)
292         WRITE(*, *) 'lib_mpp: Error in routine mpi_initialized'
293         CALL mpi_abort( mpi_comm_world, code, ierr )
294      ENDIF
295
296      IF( mpi_was_called ) THEN
297         !
298         SELECT CASE ( cn_mpi_send )
299         CASE ( 'S' )                ! Standard mpi send (blocking)
300            WRITE(ldtxt(ii),*) '           Standard blocking mpi send (send)'                     ;   ii = ii + 1
301         CASE ( 'B' )                ! Buffer mpi send (blocking)
302            WRITE(ldtxt(ii),*) '           Buffer blocking mpi send (bsend)'                      ;   ii = ii + 1
303            IF( Agrif_Root() )   CALL mpi_init_opa( ldtxt, ii, ierr ) 
304         CASE ( 'I' )                ! Immediate mpi send (non-blocking send)
305            WRITE(ldtxt(ii),*) '           Immediate non-blocking send (isend)'                   ;   ii = ii + 1
306            l_isend = .TRUE.
307         CASE DEFAULT
308            WRITE(ldtxt(ii),cform_err)                                                            ;   ii = ii + 1
309            WRITE(ldtxt(ii),*) '           bad value for cn_mpi_send = ', cn_mpi_send             ;   ii = ii + 1
310            kstop = kstop + 1
311         END SELECT
312      ELSE IF ( PRESENT(localComm) .and. .not. mpi_was_called ) THEN
313         WRITE(ldtxt(ii),*) ' lib_mpp: You cannot provide a local communicator '                  ;   ii = ii + 1
314         WRITE(ldtxt(ii),*) '          without calling MPI_Init before ! '                        ;   ii = ii + 1
315         kstop = kstop + 1
316      ELSE
317         SELECT CASE ( cn_mpi_send )
318         CASE ( 'S' )                ! Standard mpi send (blocking)
319            WRITE(ldtxt(ii),*) '           Standard blocking mpi send (send)'                     ;   ii = ii + 1
320            CALL mpi_init( ierr )
321         CASE ( 'B' )                ! Buffer mpi send (blocking)
322            WRITE(ldtxt(ii),*) '           Buffer blocking mpi send (bsend)'                      ;   ii = ii + 1
323            IF( Agrif_Root() )   CALL mpi_init_opa( ldtxt, ii, ierr )
324         CASE ( 'I' )                ! Immediate mpi send (non-blocking send)
325            WRITE(ldtxt(ii),*) '           Immediate non-blocking send (isend)'                   ;   ii = ii + 1
326            l_isend = .TRUE.
327            CALL mpi_init( ierr )
328         CASE DEFAULT
329            WRITE(ldtxt(ii),cform_err)                                                            ;   ii = ii + 1
330            WRITE(ldtxt(ii),*) '           bad value for cn_mpi_send = ', cn_mpi_send             ;   ii = ii + 1
331            kstop = kstop + 1
332         END SELECT
333         !
334      ENDIF
335
336      IF( PRESENT(localComm) ) THEN
337         IF( Agrif_Root() ) THEN
338            mpi_comm_opa = localComm
339         ENDIF
340      ELSE
341         CALL mpi_comm_dup( mpi_comm_world, mpi_comm_opa, code)
342         IF( code /= MPI_SUCCESS ) THEN
343            DO ji = 1, SIZE(ldtxt) 
344               IF( TRIM(ldtxt(ji)) /= '' )   WRITE(*,*) ldtxt(ji)      ! control print of mynode
345            END DO
346            WRITE(*, cform_err)
347            WRITE(*, *) ' lib_mpp: Error in routine mpi_comm_dup'
348            CALL mpi_abort( mpi_comm_world, code, ierr )
349         ENDIF
350      ENDIF
351
352      CALL mpi_comm_rank( mpi_comm_opa, mpprank, ierr )
353      CALL mpi_comm_size( mpi_comm_opa, mppsize, ierr )
354      mynode = mpprank
355      !
356#if defined key_mpp_rep
357      CALL MPI_OP_CREATE(DDPDD_MPI, .TRUE., MPI_SUMDD, ierr)
358#endif
359      !
360   END FUNCTION mynode
361
362
363   SUBROUTINE mpp_lnk_3d( ptab, cd_type, psgn, cd_mpp, pval )
364      !!----------------------------------------------------------------------
365      !!                  ***  routine mpp_lnk_3d  ***
366      !!
367      !! ** Purpose :   Message passing manadgement
368      !!
369      !! ** Method  :   Use mppsend and mpprecv function for passing mask
370      !!      between processors following neighboring subdomains.
371      !!            domain parameters
372      !!                    nlci   : first dimension of the local subdomain
373      !!                    nlcj   : second dimension of the local subdomain
374      !!                    nbondi : mark for "east-west local boundary"
375      !!                    nbondj : mark for "north-south local boundary"
376      !!                    noea   : number for local neighboring processors
377      !!                    nowe   : number for local neighboring processors
378      !!                    noso   : number for local neighboring processors
379      !!                    nono   : number for local neighboring processors
380      !!
381      !! ** Action  :   ptab with update value at its periphery
382      !!
383      !!----------------------------------------------------------------------
384      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab     ! 3D array on which the boundary condition is applied
385      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type  ! define the nature of ptab array grid-points
386      !                                                             ! = T , U , V , F , W points
387      REAL(wp)                        , INTENT(in   ) ::   psgn     ! =-1 the sign change across the north fold boundary
388      !                                                             ! =  1. , the sign is kept
389      CHARACTER(len=3), OPTIONAL      , INTENT(in   ) ::   cd_mpp   ! fill the overlap area only
390      REAL(wp)        , OPTIONAL      , INTENT(in   ) ::   pval     ! background value (used at closed boundaries)
391      !!
392      INTEGER  ::   ji, jj, jk, jl             ! dummy loop indices
393      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
394      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
395      REAL(wp) ::   zland
396      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
397      !!----------------------------------------------------------------------
398
399      IF( PRESENT( pval ) ) THEN   ;   zland = pval      ! set land value
400      ELSE                         ;   zland = 0.e0      ! zero by default
401      ENDIF
402
403      ! 1. standard boundary treatment
404      ! ------------------------------
405      IF( PRESENT( cd_mpp ) ) THEN      ! only fill added line/raw with existing values
406         !
407         ! WARNING ptab is defined only between nld and nle
408         DO jk = 1, jpk
409            DO jj = nlcj+1, jpj                 ! added line(s)   (inner only)
410               ptab(nldi  :nlei  , jj          ,jk) = ptab(nldi:nlei,     nlej,jk)   
411               ptab(1     :nldi-1, jj          ,jk) = ptab(nldi     ,     nlej,jk)
412               ptab(nlei+1:nlci  , jj          ,jk) = ptab(     nlei,     nlej,jk)
413            END DO
414            DO ji = nlci+1, jpi                 ! added column(s) (full)
415               ptab(ji           ,nldj  :nlej  ,jk) = ptab(     nlei,nldj:nlej,jk)
416               ptab(ji           ,1     :nldj-1,jk) = ptab(     nlei,nldj     ,jk)
417               ptab(ji           ,nlej+1:jpj   ,jk) = ptab(     nlei,     nlej,jk)
418            END DO
419         END DO
420         !
421      ELSE                              ! standard close or cyclic treatment
422         !
423         !                                   ! East-West boundaries
424         !                                        !* Cyclic east-west
425         IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
426            ptab( 1 ,:,:) = ptab(jpim1,:,:)
427            ptab(jpi,:,:) = ptab(  2  ,:,:)
428         ELSE                                     !* closed
429            IF( .NOT. cd_type == 'F' )   ptab(     1       :jpreci,:,:) = zland    ! south except F-point
430                                         ptab(nlci-jpreci+1:jpi   ,:,:) = zland    ! north
431         ENDIF
432         !                                   ! North-South boundaries (always closed)
433         IF( .NOT. cd_type == 'F' )   ptab(:,     1       :jprecj,:) = zland       ! south except F-point
434                                      ptab(:,nlcj-jprecj+1:jpj   ,:) = zland       ! north
435         !
436      ENDIF
437
438      ! 2. East and west directions exchange
439      ! ------------------------------------
440      ! we play with the neigbours AND the row number because of the periodicity
441      !
442      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
443      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
444         iihom = nlci-nreci
445         DO jl = 1, jpreci
446            t3ew(:,jl,:,1) = ptab(jpreci+jl,:,:)
447            t3we(:,jl,:,1) = ptab(iihom +jl,:,:)
448         END DO
449      END SELECT 
450      !
451      !                           ! Migrations
452      imigr = jpreci * jpj * jpk
453      !
454      SELECT CASE ( nbondi ) 
455      CASE ( -1 )
456         CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req1 )
457         CALL mpprecv( 1, t3ew(1,1,1,2), imigr, noea )
458         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
459      CASE ( 0 )
460         CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
461         CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req2 )
462         CALL mpprecv( 1, t3ew(1,1,1,2), imigr, noea )
463         CALL mpprecv( 2, t3we(1,1,1,2), imigr, nowe )
464         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
465         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
466      CASE ( 1 )
467         CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
468         CALL mpprecv( 2, t3we(1,1,1,2), imigr, nowe )
469         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
470      END SELECT
471      !
472      !                           ! Write Dirichlet lateral conditions
473      iihom = nlci-jpreci
474      !
475      SELECT CASE ( nbondi )
476      CASE ( -1 )
477         DO jl = 1, jpreci
478            ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
479         END DO
480      CASE ( 0 ) 
481         DO jl = 1, jpreci
482            ptab(jl      ,:,:) = t3we(:,jl,:,2)
483            ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
484         END DO
485      CASE ( 1 )
486         DO jl = 1, jpreci
487            ptab(jl      ,:,:) = t3we(:,jl,:,2)
488         END DO
489      END SELECT
490
491
492      ! 3. North and south directions
493      ! -----------------------------
494      ! always closed : we play only with the neigbours
495      !
496      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
497         ijhom = nlcj-nrecj
498         DO jl = 1, jprecj
499            t3sn(:,jl,:,1) = ptab(:,ijhom +jl,:)
500            t3ns(:,jl,:,1) = ptab(:,jprecj+jl,:)
501         END DO
502      ENDIF
503      !
504      !                           ! Migrations
505      imigr = jprecj * jpi * jpk
506      !
507      SELECT CASE ( nbondj )     
508      CASE ( -1 )
509         CALL mppsend( 4, t3sn(1,1,1,1), imigr, nono, ml_req1 )
510         CALL mpprecv( 3, t3ns(1,1,1,2), imigr, nono )
511         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
512      CASE ( 0 )
513         CALL mppsend( 3, t3ns(1,1,1,1), imigr, noso, ml_req1 )
514         CALL mppsend( 4, t3sn(1,1,1,1), imigr, nono, ml_req2 )
515         CALL mpprecv( 3, t3ns(1,1,1,2), imigr, nono )
516         CALL mpprecv( 4, t3sn(1,1,1,2), imigr, noso )
517         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
518         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
519      CASE ( 1 ) 
520         CALL mppsend( 3, t3ns(1,1,1,1), imigr, noso, ml_req1 )
521         CALL mpprecv( 4, t3sn(1,1,1,2), imigr, noso )
522         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
523      END SELECT
524      !
525      !                           ! Write Dirichlet lateral conditions
526      ijhom = nlcj-jprecj
527      !
528      SELECT CASE ( nbondj )
529      CASE ( -1 )
530         DO jl = 1, jprecj
531            ptab(:,ijhom+jl,:) = t3ns(:,jl,:,2)
532         END DO
533      CASE ( 0 ) 
534         DO jl = 1, jprecj
535            ptab(:,jl      ,:) = t3sn(:,jl,:,2)
536            ptab(:,ijhom+jl,:) = t3ns(:,jl,:,2)
537         END DO
538      CASE ( 1 )
539         DO jl = 1, jprecj
540            ptab(:,jl,:) = t3sn(:,jl,:,2)
541         END DO
542      END SELECT
543
544
545      ! 4. north fold treatment
546      ! -----------------------
547      !
548      IF( npolj /= 0 .AND. .NOT. PRESENT(cd_mpp) ) THEN
549         !
550         SELECT CASE ( jpni )
551         CASE ( 1 )     ;   CALL lbc_nfd      ( ptab, cd_type, psgn )   ! only 1 northern proc, no mpp
552         CASE DEFAULT   ;   CALL mpp_lbc_north( ptab, cd_type, psgn )   ! for all northern procs.
553         END SELECT
554         !
555      ENDIF
556      !
557   END SUBROUTINE mpp_lnk_3d
558
559
560   SUBROUTINE mpp_lnk_2d( pt2d, cd_type, psgn, cd_mpp, pval )
561      !!----------------------------------------------------------------------
562      !!                  ***  routine mpp_lnk_2d  ***
563      !!                 
564      !! ** Purpose :   Message passing manadgement for 2d array
565      !!
566      !! ** Method  :   Use mppsend and mpprecv function for passing mask
567      !!      between processors following neighboring subdomains.
568      !!            domain parameters
569      !!                    nlci   : first dimension of the local subdomain
570      !!                    nlcj   : second dimension of the local subdomain
571      !!                    nbondi : mark for "east-west local boundary"
572      !!                    nbondj : mark for "north-south local boundary"
573      !!                    noea   : number for local neighboring processors
574      !!                    nowe   : number for local neighboring processors
575      !!                    noso   : number for local neighboring processors
576      !!                    nono   : number for local neighboring processors
577      !!
578      !!----------------------------------------------------------------------
579      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) ::   pt2d     ! 2D array on which the boundary condition is applied
580      CHARACTER(len=1)            , INTENT(in   ) ::   cd_type  ! define the nature of ptab array grid-points
581      !                                                         ! = T , U , V , F , W and I points
582      REAL(wp)                    , INTENT(in   ) ::   psgn     ! =-1 the sign change across the north fold boundary
583      !                                                         ! =  1. , the sign is kept
584      CHARACTER(len=3), OPTIONAL  , INTENT(in   ) ::   cd_mpp   ! fill the overlap area only
585      REAL(wp)        , OPTIONAL  , INTENT(in   ) ::   pval     ! background value (used at closed boundaries)
586      !!
587      INTEGER  ::   ji, jj, jl   ! dummy loop indices
588      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
589      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
590      REAL(wp) ::   zland
591      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
592      !!----------------------------------------------------------------------
593
594      IF( PRESENT( pval ) ) THEN   ;   zland = pval      ! set land value
595      ELSE                         ;   zland = 0.e0      ! zero by default
596      ENDIF
597
598      ! 1. standard boundary treatment
599      ! ------------------------------
600      !
601      IF( PRESENT( cd_mpp ) ) THEN      ! only fill added line/raw with existing values
602         !
603         ! WARNING pt2d is defined only between nld and nle
604         DO jj = nlcj+1, jpj                 ! added line(s)   (inner only)
605            pt2d(nldi  :nlei  , jj          ) = pt2d(nldi:nlei,     nlej)   
606            pt2d(1     :nldi-1, jj          ) = pt2d(nldi     ,     nlej)
607            pt2d(nlei+1:nlci  , jj          ) = pt2d(     nlei,     nlej)
608         END DO
609         DO ji = nlci+1, jpi                 ! added column(s) (full)
610            pt2d(ji           ,nldj  :nlej  ) = pt2d(     nlei,nldj:nlej)
611            pt2d(ji           ,1     :nldj-1) = pt2d(     nlei,nldj     )
612            pt2d(ji           ,nlej+1:jpj   ) = pt2d(     nlei,     nlej)
613         END DO
614         !
615      ELSE                              ! standard close or cyclic treatment
616         !
617         !                                   ! East-West boundaries
618         IF( nbondi == 2 .AND.   &                ! Cyclic east-west
619            &    (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
620            pt2d( 1 ,:) = pt2d(jpim1,:)                                    ! west
621            pt2d(jpi,:) = pt2d(  2  ,:)                                    ! east
622         ELSE                                     ! closed
623            IF( .NOT. cd_type == 'F' )   pt2d(     1       :jpreci,:) = zland    ! south except F-point
624                                         pt2d(nlci-jpreci+1:jpi   ,:) = zland    ! north
625         ENDIF
626         !                                   ! North-South boundaries (always closed)
627            IF( .NOT. cd_type == 'F' )   pt2d(:,     1       :jprecj) = zland    !south except F-point
628                                         pt2d(:,nlcj-jprecj+1:jpj   ) = zland    ! north
629         !
630      ENDIF
631
632      ! 2. East and west directions exchange
633      ! ------------------------------------
634      ! we play with the neigbours AND the row number because of the periodicity
635      !
636      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
637      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
638         iihom = nlci-nreci
639         DO jl = 1, jpreci
640            t2ew(:,jl,1) = pt2d(jpreci+jl,:)
641            t2we(:,jl,1) = pt2d(iihom +jl,:)
642         END DO
643      END SELECT
644      !
645      !                           ! Migrations
646      imigr = jpreci * jpj
647      !
648      SELECT CASE ( nbondi )
649      CASE ( -1 )
650         CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req1 )
651         CALL mpprecv( 1, t2ew(1,1,2), imigr, noea )
652         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
653      CASE ( 0 )
654         CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
655         CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req2 )
656         CALL mpprecv( 1, t2ew(1,1,2), imigr, noea )
657         CALL mpprecv( 2, t2we(1,1,2), imigr, nowe )
658         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
659         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
660      CASE ( 1 )
661         CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
662         CALL mpprecv( 2, t2we(1,1,2), imigr, nowe )
663         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
664      END SELECT
665      !
666      !                           ! Write Dirichlet lateral conditions
667      iihom = nlci - jpreci
668      !
669      SELECT CASE ( nbondi )
670      CASE ( -1 )
671         DO jl = 1, jpreci
672            pt2d(iihom+jl,:) = t2ew(:,jl,2)
673         END DO
674      CASE ( 0 )
675         DO jl = 1, jpreci
676            pt2d(jl      ,:) = t2we(:,jl,2)
677            pt2d(iihom+jl,:) = t2ew(:,jl,2)
678         END DO
679      CASE ( 1 )
680         DO jl = 1, jpreci
681            pt2d(jl      ,:) = t2we(:,jl,2)
682         END DO
683      END SELECT
684
685
686      ! 3. North and south directions
687      ! -----------------------------
688      ! always closed : we play only with the neigbours
689      !
690      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
691         ijhom = nlcj-nrecj
692         DO jl = 1, jprecj
693            t2sn(:,jl,1) = pt2d(:,ijhom +jl)
694            t2ns(:,jl,1) = pt2d(:,jprecj+jl)
695         END DO
696      ENDIF
697      !
698      !                           ! Migrations
699      imigr = jprecj * jpi
700      !
701      SELECT CASE ( nbondj )
702      CASE ( -1 )
703         CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req1 )
704         CALL mpprecv( 3, t2ns(1,1,2), imigr, nono )
705         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
706      CASE ( 0 )
707         CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
708         CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req2 )
709         CALL mpprecv( 3, t2ns(1,1,2), imigr, nono )
710         CALL mpprecv( 4, t2sn(1,1,2), imigr, noso )
711         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
712         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
713      CASE ( 1 )
714         CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
715         CALL mpprecv( 4, t2sn(1,1,2), imigr, noso )
716         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
717      END SELECT
718      !
719      !                           ! Write Dirichlet lateral conditions
720      ijhom = nlcj - jprecj
721      !
722      SELECT CASE ( nbondj )
723      CASE ( -1 )
724         DO jl = 1, jprecj
725            pt2d(:,ijhom+jl) = t2ns(:,jl,2)
726         END DO
727      CASE ( 0 )
728         DO jl = 1, jprecj
729            pt2d(:,jl      ) = t2sn(:,jl,2)
730            pt2d(:,ijhom+jl) = t2ns(:,jl,2)
731         END DO
732      CASE ( 1 ) 
733         DO jl = 1, jprecj
734            pt2d(:,jl      ) = t2sn(:,jl,2)
735         END DO
736      END SELECT
737
738
739      ! 4. north fold treatment
740      ! -----------------------
741      !
742      IF( npolj /= 0 .AND. .NOT. PRESENT(cd_mpp) ) THEN
743         !
744         SELECT CASE ( jpni )
745         CASE ( 1 )     ;   CALL lbc_nfd      ( pt2d, cd_type, psgn )   ! only 1 northern proc, no mpp
746         CASE DEFAULT   ;   CALL mpp_lbc_north( pt2d, cd_type, psgn )   ! for all northern procs.
747         END SELECT
748         !
749      ENDIF
750      !
751   END SUBROUTINE mpp_lnk_2d
752
753
754   SUBROUTINE mpp_lnk_3d_gather( ptab1, cd_type1, ptab2, cd_type2, psgn )
755      !!----------------------------------------------------------------------
756      !!                  ***  routine mpp_lnk_3d_gather  ***
757      !!
758      !! ** Purpose :   Message passing manadgement for two 3D arrays
759      !!
760      !! ** Method  :   Use mppsend and mpprecv function for passing mask
761      !!      between processors following neighboring subdomains.
762      !!            domain parameters
763      !!                    nlci   : first dimension of the local subdomain
764      !!                    nlcj   : second dimension of the local subdomain
765      !!                    nbondi : mark for "east-west local boundary"
766      !!                    nbondj : mark for "north-south local boundary"
767      !!                    noea   : number for local neighboring processors
768      !!                    nowe   : number for local neighboring processors
769      !!                    noso   : number for local neighboring processors
770      !!                    nono   : number for local neighboring processors
771      !!
772      !! ** Action  :   ptab1 and ptab2  with update value at its periphery
773      !!
774      !!----------------------------------------------------------------------
775      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab1     ! first and second 3D array on which
776      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab2     ! the boundary condition is applied
777      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type1  ! nature of ptab1 and ptab2 arrays
778      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type2  ! i.e. grid-points = T , U , V , F or W points
779      REAL(wp)                        , INTENT(in   ) ::   psgn      ! =-1 the sign change across the north fold boundary
780      !!                                                             ! =  1. , the sign is kept
781      INTEGER  ::   jl   ! dummy loop indices
782      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
783      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
784      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
785      !!----------------------------------------------------------------------
786
787      ! 1. standard boundary treatment
788      ! ------------------------------
789      !                                      ! East-West boundaries
790      !                                           !* Cyclic east-west
791      IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
792         ptab1( 1 ,:,:) = ptab1(jpim1,:,:)
793         ptab1(jpi,:,:) = ptab1(  2  ,:,:)
794         ptab2( 1 ,:,:) = ptab2(jpim1,:,:)
795         ptab2(jpi,:,:) = ptab2(  2  ,:,:)
796      ELSE                                        !* closed
797         IF( .NOT. cd_type1 == 'F' )   ptab1(     1       :jpreci,:,:) = 0.e0    ! south except at F-point
798         IF( .NOT. cd_type2 == 'F' )   ptab2(     1       :jpreci,:,:) = 0.e0
799                                       ptab1(nlci-jpreci+1:jpi   ,:,:) = 0.e0    ! north
800                                       ptab2(nlci-jpreci+1:jpi   ,:,:) = 0.e0
801      ENDIF
802
803     
804      !                                      ! North-South boundaries
805      IF( .NOT. cd_type1 == 'F' )   ptab1(:,     1       :jprecj,:) = 0.e0    ! south except at F-point
806      IF( .NOT. cd_type2 == 'F' )   ptab2(:,     1       :jprecj,:) = 0.e0
807                                    ptab1(:,nlcj-jprecj+1:jpj   ,:) = 0.e0    ! north
808                                    ptab2(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
809
810
811      ! 2. East and west directions exchange
812      ! ------------------------------------
813      ! we play with the neigbours AND the row number because of the periodicity
814      !
815      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
816      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
817         iihom = nlci-nreci
818         DO jl = 1, jpreci
819            t4ew(:,jl,:,1,1) = ptab1(jpreci+jl,:,:)
820            t4we(:,jl,:,1,1) = ptab1(iihom +jl,:,:)
821            t4ew(:,jl,:,2,1) = ptab2(jpreci+jl,:,:)
822            t4we(:,jl,:,2,1) = ptab2(iihom +jl,:,:)
823         END DO
824      END SELECT
825      !
826      !                           ! Migrations
827      imigr = jpreci * jpj * jpk *2
828      !
829      SELECT CASE ( nbondi ) 
830      CASE ( -1 )
831         CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req1 )
832         CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr, noea )
833         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
834      CASE ( 0 )
835         CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
836         CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req2 )
837         CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr, noea )
838         CALL mpprecv( 2, t4we(1,1,1,1,2), imigr, nowe )
839         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
840         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
841      CASE ( 1 )
842         CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
843         CALL mpprecv( 2, t4we(1,1,1,1,2), imigr, nowe )
844         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
845      END SELECT
846      !
847      !                           ! Write Dirichlet lateral conditions
848      iihom = nlci - jpreci
849      !
850      SELECT CASE ( nbondi )
851      CASE ( -1 )
852         DO jl = 1, jpreci
853            ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
854            ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
855         END DO
856      CASE ( 0 ) 
857         DO jl = 1, jpreci
858            ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
859            ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
860            ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
861            ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
862         END DO
863      CASE ( 1 )
864         DO jl = 1, jpreci
865            ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
866            ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
867         END DO
868      END SELECT
869
870
871      ! 3. North and south directions
872      ! -----------------------------
873      ! always closed : we play only with the neigbours
874      !
875      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
876         ijhom = nlcj - nrecj
877         DO jl = 1, jprecj
878            t4sn(:,jl,:,1,1) = ptab1(:,ijhom +jl,:)
879            t4ns(:,jl,:,1,1) = ptab1(:,jprecj+jl,:)
880            t4sn(:,jl,:,2,1) = ptab2(:,ijhom +jl,:)
881            t4ns(:,jl,:,2,1) = ptab2(:,jprecj+jl,:)
882         END DO
883      ENDIF
884      !
885      !                           ! Migrations
886      imigr = jprecj * jpi * jpk * 2
887      !
888      SELECT CASE ( nbondj )     
889      CASE ( -1 )
890         CALL mppsend( 4, t4sn(1,1,1,1,1), imigr, nono, ml_req1 )
891         CALL mpprecv( 3, t4ns(1,1,1,1,2), imigr, nono )
892         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
893      CASE ( 0 )
894         CALL mppsend( 3, t4ns(1,1,1,1,1), imigr, noso, ml_req1 )
895         CALL mppsend( 4, t4sn(1,1,1,1,1), imigr, nono, ml_req2 )
896         CALL mpprecv( 3, t4ns(1,1,1,1,2), imigr, nono )
897         CALL mpprecv( 4, t4sn(1,1,1,1,2), imigr, noso )
898         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
899         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
900      CASE ( 1 ) 
901         CALL mppsend( 3, t4ns(1,1,1,1,1), imigr, noso, ml_req1 )
902         CALL mpprecv( 4, t4sn(1,1,1,1,2), imigr, noso )
903         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
904      END SELECT
905      !
906      !                           ! Write Dirichlet lateral conditions
907      ijhom = nlcj - jprecj
908      !
909      SELECT CASE ( nbondj )
910      CASE ( -1 )
911         DO jl = 1, jprecj
912            ptab1(:,ijhom+jl,:) = t4ns(:,jl,:,1,2)
913            ptab2(:,ijhom+jl,:) = t4ns(:,jl,:,2,2)
914         END DO
915      CASE ( 0 ) 
916         DO jl = 1, jprecj
917            ptab1(:,jl      ,:) = t4sn(:,jl,:,1,2)
918            ptab1(:,ijhom+jl,:) = t4ns(:,jl,:,1,2)
919            ptab2(:,jl      ,:) = t4sn(:,jl,:,2,2)
920            ptab2(:,ijhom+jl,:) = t4ns(:,jl,:,2,2)
921         END DO
922      CASE ( 1 )
923         DO jl = 1, jprecj
924            ptab1(:,jl,:) = t4sn(:,jl,:,1,2)
925            ptab2(:,jl,:) = t4sn(:,jl,:,2,2)
926         END DO
927      END SELECT
928
929
930      ! 4. north fold treatment
931      ! -----------------------
932      IF( npolj /= 0 ) THEN
933         !
934         SELECT CASE ( jpni )
935         CASE ( 1 )                                           
936            CALL lbc_nfd      ( ptab1, cd_type1, psgn )   ! only for northern procs.
937            CALL lbc_nfd      ( ptab2, cd_type2, psgn )
938         CASE DEFAULT
939            CALL mpp_lbc_north( ptab1, cd_type1, psgn )   ! for all northern procs.
940            CALL mpp_lbc_north (ptab2, cd_type2, psgn)
941         END SELECT 
942         !
943      ENDIF
944      !
945   END SUBROUTINE mpp_lnk_3d_gather
946
947
948   SUBROUTINE mpp_lnk_2d_e( pt2d, cd_type, psgn )
949      !!----------------------------------------------------------------------
950      !!                  ***  routine mpp_lnk_2d_e  ***
951      !!                 
952      !! ** Purpose :   Message passing manadgement for 2d array (with halo)
953      !!
954      !! ** Method  :   Use mppsend and mpprecv function for passing mask
955      !!      between processors following neighboring subdomains.
956      !!            domain parameters
957      !!                    nlci   : first dimension of the local subdomain
958      !!                    nlcj   : second dimension of the local subdomain
959      !!                    jpr2di : number of rows for extra outer halo
960      !!                    jpr2dj : number of columns for extra outer halo
961      !!                    nbondi : mark for "east-west local boundary"
962      !!                    nbondj : mark for "north-south local boundary"
963      !!                    noea   : number for local neighboring processors
964      !!                    nowe   : number for local neighboring processors
965      !!                    noso   : number for local neighboring processors
966      !!                    nono   : number for local neighboring processors
967      !!
968      !!----------------------------------------------------------------------
969      REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT(inout) ::   pt2d     ! 2D array with extra halo
970      CHARACTER(len=1)                                            , INTENT(in   ) ::   cd_type  ! nature of ptab array grid-points
971      !                                                                                         ! = T , U , V , F , W and I points
972      REAL(wp)                                                    , INTENT(in   ) ::   psgn     ! =-1 the sign change across the
973      !!                                                                                        ! north boundary, =  1. otherwise
974      INTEGER  ::   jl   ! dummy loop indices
975      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
976      INTEGER  ::   ipreci, iprecj             ! temporary integers
977      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
978      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
979      !!----------------------------------------------------------------------
980
981      ipreci = jpreci + jpr2di      ! take into account outer extra 2D overlap area
982      iprecj = jprecj + jpr2dj
983
984
985      ! 1. standard boundary treatment
986      ! ------------------------------
987      ! Order matters Here !!!!
988      !
989      !                                      !* North-South boundaries (always colsed)
990      IF( .NOT. cd_type == 'F' )   pt2d(:,  1-jpr2dj   :  jprecj  ) = 0.e0    ! south except at F-point
991                                   pt2d(:,nlcj-jprecj+1:jpj+jpr2dj) = 0.e0    ! north
992                               
993      !                                      ! East-West boundaries
994      !                                           !* Cyclic east-west
995      IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
996         pt2d(1-jpr2di:     1    ,:) = pt2d(jpim1-jpr2di:  jpim1 ,:)       ! east
997         pt2d(   jpi  :jpi+jpr2di,:) = pt2d(     2      :2+jpr2di,:)       ! west
998         !
999      ELSE                                        !* closed
1000         IF( .NOT. cd_type == 'F' )   pt2d(  1-jpr2di   :jpreci    ,:) = 0.e0    ! south except at F-point
1001                                      pt2d(nlci-jpreci+1:jpi+jpr2di,:) = 0.e0    ! north
1002      ENDIF
1003      !
1004
1005      ! north fold treatment
1006      ! -----------------------
1007      IF( npolj /= 0 ) THEN
1008         !
1009         SELECT CASE ( jpni )
1010         CASE ( 1 )     ;   CALL lbc_nfd        ( pt2d(1:jpi,1:jpj+jpr2dj), cd_type, psgn, pr2dj=jpr2dj )
1011         CASE DEFAULT   ;   CALL mpp_lbc_north_e( pt2d                    , cd_type, psgn               )
1012         END SELECT 
1013         !
1014      ENDIF
1015
1016      ! 2. East and west directions exchange
1017      ! ------------------------------------
1018      ! we play with the neigbours AND the row number because of the periodicity
1019      !
1020      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
1021      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
1022         iihom = nlci-nreci-jpr2di
1023         DO jl = 1, ipreci
1024            tr2ew(:,jl,1) = pt2d(jpreci+jl,:)
1025            tr2we(:,jl,1) = pt2d(iihom +jl,:)
1026         END DO
1027      END SELECT
1028      !
1029      !                           ! Migrations
1030      imigr = ipreci * ( jpj + 2*jpr2dj)
1031      !
1032      SELECT CASE ( nbondi )
1033      CASE ( -1 )
1034         CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req1 )
1035         CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr, noea )
1036         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1037      CASE ( 0 )
1038         CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
1039         CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req2 )
1040         CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr, noea )
1041         CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr, nowe )
1042         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1043         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1044      CASE ( 1 )
1045         CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
1046         CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr, nowe )
1047         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1048      END SELECT
1049      !
1050      !                           ! Write Dirichlet lateral conditions
1051      iihom = nlci - jpreci
1052      !
1053      SELECT CASE ( nbondi )
1054      CASE ( -1 )
1055         DO jl = 1, ipreci
1056            pt2d(iihom+jl,:) = tr2ew(:,jl,2)
1057         END DO
1058      CASE ( 0 )
1059         DO jl = 1, ipreci
1060            pt2d(jl-jpr2di,:) = tr2we(:,jl,2)
1061            pt2d( iihom+jl,:) = tr2ew(:,jl,2)
1062         END DO
1063      CASE ( 1 )
1064         DO jl = 1, ipreci
1065            pt2d(jl-jpr2di,:) = tr2we(:,jl,2)
1066         END DO
1067      END SELECT
1068
1069
1070      ! 3. North and south directions
1071      ! -----------------------------
1072      ! always closed : we play only with the neigbours
1073      !
1074      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
1075         ijhom = nlcj-nrecj-jpr2dj
1076         DO jl = 1, iprecj
1077            tr2sn(:,jl,1) = pt2d(:,ijhom +jl)
1078            tr2ns(:,jl,1) = pt2d(:,jprecj+jl)
1079         END DO
1080      ENDIF
1081      !
1082      !                           ! Migrations
1083      imigr = iprecj * ( jpi + 2*jpr2di )
1084      !
1085      SELECT CASE ( nbondj )
1086      CASE ( -1 )
1087         CALL mppsend( 4, tr2sn(1-jpr2di,1,1), imigr, nono, ml_req1 )
1088         CALL mpprecv( 3, tr2ns(1-jpr2di,1,2), imigr, nono )
1089         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1090      CASE ( 0 )
1091         CALL mppsend( 3, tr2ns(1-jpr2di,1,1), imigr, noso, ml_req1 )
1092         CALL mppsend( 4, tr2sn(1-jpr2di,1,1), imigr, nono, ml_req2 )
1093         CALL mpprecv( 3, tr2ns(1-jpr2di,1,2), imigr, nono )
1094         CALL mpprecv( 4, tr2sn(1-jpr2di,1,2), imigr, noso )
1095         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1096         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1097      CASE ( 1 )
1098         CALL mppsend( 3, tr2ns(1-jpr2di,1,1), imigr, noso, ml_req1 )
1099         CALL mpprecv( 4, tr2sn(1-jpr2di,1,2), imigr, noso )
1100         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1101      END SELECT
1102      !
1103      !                           ! Write Dirichlet lateral conditions
1104      ijhom = nlcj - jprecj 
1105      !
1106      SELECT CASE ( nbondj )
1107      CASE ( -1 )
1108         DO jl = 1, iprecj
1109            pt2d(:,ijhom+jl) = tr2ns(:,jl,2)
1110         END DO
1111      CASE ( 0 )
1112         DO jl = 1, iprecj
1113            pt2d(:,jl-jpr2dj) = tr2sn(:,jl,2)
1114            pt2d(:,ijhom+jl ) = tr2ns(:,jl,2)
1115         END DO
1116      CASE ( 1 ) 
1117         DO jl = 1, iprecj
1118            pt2d(:,jl-jpr2dj) = tr2sn(:,jl,2)
1119         END DO
1120      END SELECT
1121
1122   END SUBROUTINE mpp_lnk_2d_e
1123
1124
1125   SUBROUTINE mppsend( ktyp, pmess, kbytes, kdest, md_req )
1126      !!----------------------------------------------------------------------
1127      !!                  ***  routine mppsend  ***
1128      !!                   
1129      !! ** Purpose :   Send messag passing array
1130      !!
1131      !!----------------------------------------------------------------------
1132      REAL(wp), INTENT(inout) ::   pmess(*)   ! array of real
1133      INTEGER , INTENT(in   ) ::   kbytes     ! size of the array pmess
1134      INTEGER , INTENT(in   ) ::   kdest      ! receive process number
1135      INTEGER , INTENT(in   ) ::   ktyp       ! tag of the message
1136      INTEGER , INTENT(in   ) ::   md_req     ! argument for isend
1137      !!
1138      INTEGER ::   iflag
1139      !!----------------------------------------------------------------------
1140      !
1141      SELECT CASE ( cn_mpi_send )
1142      CASE ( 'S' )                ! Standard mpi send (blocking)
1143         CALL mpi_send ( pmess, kbytes, mpi_double_precision, kdest , ktyp, mpi_comm_opa        , iflag )
1144      CASE ( 'B' )                ! Buffer mpi send (blocking)
1145         CALL mpi_bsend( pmess, kbytes, mpi_double_precision, kdest , ktyp, mpi_comm_opa        , iflag )
1146      CASE ( 'I' )                ! Immediate mpi send (non-blocking send)
1147         ! be carefull, one more argument here : the mpi request identifier..
1148         CALL mpi_isend( pmess, kbytes, mpi_double_precision, kdest , ktyp, mpi_comm_opa, md_req, iflag )
1149      END SELECT
1150      !
1151   END SUBROUTINE mppsend
1152
1153
1154   SUBROUTINE mpprecv( ktyp, pmess, kbytes, ksource )
1155      !!----------------------------------------------------------------------
1156      !!                  ***  routine mpprecv  ***
1157      !!
1158      !! ** Purpose :   Receive messag passing array
1159      !!
1160      !!----------------------------------------------------------------------
1161      REAL(wp), INTENT(inout) ::   pmess(*)   ! array of real
1162      INTEGER , INTENT(in   ) ::   kbytes     ! suze of the array pmess
1163      INTEGER , INTENT(in   ) ::   ktyp       ! Tag of the recevied message
1164      INTEGER, OPTIONAL, INTENT(in) :: ksource    ! source process number
1165      !!
1166      INTEGER :: istatus(mpi_status_size)
1167      INTEGER :: iflag
1168      INTEGER :: use_source
1169      !!----------------------------------------------------------------------
1170      !
1171
1172      ! If a specific process number has been passed to the receive call,
1173      ! use that one. Default is to use mpi_any_source
1174      use_source=mpi_any_source
1175      if(present(ksource)) then
1176         use_source=ksource
1177      end if
1178
1179      CALL mpi_recv( pmess, kbytes, mpi_double_precision, use_source, ktyp, mpi_comm_opa, istatus, iflag )
1180      !
1181   END SUBROUTINE mpprecv
1182
1183
1184   SUBROUTINE mppgather( ptab, kp, pio )
1185      !!----------------------------------------------------------------------
1186      !!                   ***  routine mppgather  ***
1187      !!                   
1188      !! ** Purpose :   Transfert between a local subdomain array and a work
1189      !!     array which is distributed following the vertical level.
1190      !!
1191      !!----------------------------------------------------------------------
1192      REAL(wp), DIMENSION(jpi,jpj),       INTENT(in   ) ::   ptab   ! subdomain input array
1193      INTEGER ,                           INTENT(in   ) ::   kp     ! record length
1194      REAL(wp), DIMENSION(jpi,jpj,jpnij), INTENT(  out) ::   pio    ! subdomain input array
1195      !!
1196      INTEGER :: itaille, ierror   ! temporary integer
1197      !!---------------------------------------------------------------------
1198      !
1199      itaille = jpi * jpj
1200      CALL mpi_gather( ptab, itaille, mpi_double_precision, pio, itaille     ,   &
1201         &                            mpi_double_precision, kp , mpi_comm_opa, ierror ) 
1202      !
1203   END SUBROUTINE mppgather
1204
1205
1206   SUBROUTINE mppscatter( pio, kp, ptab )
1207      !!----------------------------------------------------------------------
1208      !!                  ***  routine mppscatter  ***
1209      !!
1210      !! ** Purpose :   Transfert between awork array which is distributed
1211      !!      following the vertical level and the local subdomain array.
1212      !!
1213      !!----------------------------------------------------------------------
1214      REAL(wp), DIMENSION(jpi,jpj,jpnij)  ::  pio        ! output array
1215      INTEGER                             ::   kp        ! Tag (not used with MPI
1216      REAL(wp), DIMENSION(jpi,jpj)        ::  ptab       ! subdomain array input
1217      !!
1218      INTEGER :: itaille, ierror   ! temporary integer
1219      !!---------------------------------------------------------------------
1220      !
1221      itaille=jpi*jpj
1222      !
1223      CALL mpi_scatter( pio, itaille, mpi_double_precision, ptab, itaille     ,   &
1224         &                            mpi_double_precision, kp  , mpi_comm_opa, ierror )
1225      !
1226   END SUBROUTINE mppscatter
1227
1228
1229   SUBROUTINE mppmax_a_int( ktab, kdim, kcom )
1230      !!----------------------------------------------------------------------
1231      !!                  ***  routine mppmax_a_int  ***
1232      !!
1233      !! ** Purpose :   Find maximum value in an integer layout array
1234      !!
1235      !!----------------------------------------------------------------------
1236      INTEGER , INTENT(in   )                  ::   kdim   ! size of array
1237      INTEGER , INTENT(inout), DIMENSION(kdim) ::   ktab   ! input array
1238      INTEGER , INTENT(in   ), OPTIONAL        ::   kcom   !
1239      !!
1240      INTEGER :: ierror, localcomm   ! temporary integer
1241      INTEGER, DIMENSION(kdim) ::   iwork
1242      !!----------------------------------------------------------------------
1243      !
1244      localcomm = mpi_comm_opa
1245      IF( PRESENT(kcom) )   localcomm = kcom
1246      !
1247      CALL mpi_allreduce( ktab, iwork, kdim, mpi_integer, mpi_max, localcomm, ierror )
1248      !
1249      ktab(:) = iwork(:)
1250      !
1251   END SUBROUTINE mppmax_a_int
1252
1253
1254   SUBROUTINE mppmax_int( ktab, kcom )
1255      !!----------------------------------------------------------------------
1256      !!                  ***  routine mppmax_int  ***
1257      !!
1258      !! ** Purpose :   Find maximum value in an integer layout array
1259      !!
1260      !!----------------------------------------------------------------------
1261      INTEGER, INTENT(inout)           ::   ktab      ! ???
1262      INTEGER, INTENT(in   ), OPTIONAL ::   kcom      ! ???
1263      !!
1264      INTEGER ::   ierror, iwork, localcomm   ! temporary integer
1265      !!----------------------------------------------------------------------
1266      !
1267      localcomm = mpi_comm_opa 
1268      IF( PRESENT(kcom) )   localcomm = kcom
1269      !
1270      CALL mpi_allreduce( ktab, iwork, 1, mpi_integer, mpi_max, localcomm, ierror)
1271      !
1272      ktab = iwork
1273      !
1274   END SUBROUTINE mppmax_int
1275
1276
1277   SUBROUTINE mppmin_a_int( ktab, kdim, kcom )
1278      !!----------------------------------------------------------------------
1279      !!                  ***  routine mppmin_a_int  ***
1280      !!
1281      !! ** Purpose :   Find minimum value in an integer layout array
1282      !!
1283      !!----------------------------------------------------------------------
1284      INTEGER , INTENT( in  )                  ::   kdim        ! size of array
1285      INTEGER , INTENT(inout), DIMENSION(kdim) ::   ktab        ! input array
1286      INTEGER , INTENT( in  ), OPTIONAL        ::   kcom        ! input array
1287      !!
1288      INTEGER ::   ierror, localcomm   ! temporary integer
1289      INTEGER, DIMENSION(kdim) ::   iwork
1290      !!----------------------------------------------------------------------
1291      !
1292      localcomm = mpi_comm_opa
1293      IF( PRESENT(kcom) )   localcomm = kcom
1294      !
1295      CALL mpi_allreduce( ktab, iwork, kdim, mpi_integer, mpi_min, localcomm, ierror )
1296      !
1297      ktab(:) = iwork(:)
1298      !
1299   END SUBROUTINE mppmin_a_int
1300
1301
1302   SUBROUTINE mppmin_int( ktab, kcom )
1303      !!----------------------------------------------------------------------
1304      !!                  ***  routine mppmin_int  ***
1305      !!
1306      !! ** Purpose :   Find minimum value in an integer layout array
1307      !!
1308      !!----------------------------------------------------------------------
1309      INTEGER, INTENT(inout) ::   ktab      ! ???
1310      INTEGER , INTENT( in  ), OPTIONAL        ::   kcom        ! input array
1311      !!
1312      INTEGER ::  ierror, iwork, localcomm
1313      !!----------------------------------------------------------------------
1314      !
1315      localcomm = mpi_comm_opa
1316      IF( PRESENT(kcom) )   localcomm = kcom
1317      !
1318     CALL mpi_allreduce( ktab, iwork, 1, mpi_integer, mpi_min, localcomm, ierror )
1319      !
1320      ktab = iwork
1321      !
1322   END SUBROUTINE mppmin_int
1323
1324
1325   SUBROUTINE mppsum_a_int( ktab, kdim )
1326      !!----------------------------------------------------------------------
1327      !!                  ***  routine mppsum_a_int  ***
1328      !!                   
1329      !! ** Purpose :   Global integer sum, 1D array case
1330      !!
1331      !!----------------------------------------------------------------------
1332      INTEGER, INTENT(in   )                   ::   kdim      ! ???
1333      INTEGER, INTENT(inout), DIMENSION (kdim) ::   ktab      ! ???
1334      !!
1335      INTEGER :: ierror
1336      INTEGER, DIMENSION (kdim) ::  iwork
1337      !!----------------------------------------------------------------------
1338      !
1339      CALL mpi_allreduce( ktab, iwork, kdim, mpi_integer, mpi_sum, mpi_comm_opa, ierror )
1340      !
1341      ktab(:) = iwork(:)
1342      !
1343   END SUBROUTINE mppsum_a_int
1344
1345
1346   SUBROUTINE mppsum_int( ktab )
1347      !!----------------------------------------------------------------------
1348      !!                 ***  routine mppsum_int  ***
1349      !!                 
1350      !! ** Purpose :   Global integer sum
1351      !!
1352      !!----------------------------------------------------------------------
1353      INTEGER, INTENT(inout) ::   ktab
1354      !!
1355      INTEGER :: ierror, iwork
1356      !!----------------------------------------------------------------------
1357      !
1358      CALL mpi_allreduce( ktab, iwork, 1, mpi_integer, mpi_sum, mpi_comm_opa, ierror )
1359      !
1360      ktab = iwork
1361      !
1362   END SUBROUTINE mppsum_int
1363
1364
1365   SUBROUTINE mppmax_a_real( ptab, kdim, kcom )
1366      !!----------------------------------------------------------------------
1367      !!                 ***  routine mppmax_a_real  ***
1368      !!                 
1369      !! ** Purpose :   Maximum
1370      !!
1371      !!----------------------------------------------------------------------
1372      INTEGER , INTENT(in   )                  ::   kdim
1373      REAL(wp), INTENT(inout), DIMENSION(kdim) ::   ptab
1374      INTEGER , INTENT(in   ), OPTIONAL        ::   kcom
1375      !!
1376      INTEGER :: ierror, localcomm
1377      REAL(wp), DIMENSION(kdim) ::  zwork
1378      !!----------------------------------------------------------------------
1379      !
1380      localcomm = mpi_comm_opa
1381      IF( PRESENT(kcom) ) localcomm = kcom
1382      !
1383      CALL mpi_allreduce( ptab, zwork, kdim, mpi_double_precision, mpi_max, localcomm, ierror )
1384      ptab(:) = zwork(:)
1385      !
1386   END SUBROUTINE mppmax_a_real
1387
1388
1389   SUBROUTINE mppmax_real( ptab, kcom )
1390      !!----------------------------------------------------------------------
1391      !!                  ***  routine mppmax_real  ***
1392      !!                   
1393      !! ** Purpose :   Maximum
1394      !!
1395      !!----------------------------------------------------------------------
1396      REAL(wp), INTENT(inout)           ::   ptab   ! ???
1397      INTEGER , INTENT(in   ), OPTIONAL ::   kcom   ! ???
1398      !!
1399      INTEGER  ::   ierror, localcomm
1400      REAL(wp) ::   zwork
1401      !!----------------------------------------------------------------------
1402      !
1403      localcomm = mpi_comm_opa 
1404      IF( PRESENT(kcom) )   localcomm = kcom
1405      !
1406      CALL mpi_allreduce( ptab, zwork, 1, mpi_double_precision, mpi_max, localcomm, ierror )
1407      ptab = zwork
1408      !
1409   END SUBROUTINE mppmax_real
1410
1411
1412   SUBROUTINE mppmin_a_real( ptab, kdim, kcom )
1413      !!----------------------------------------------------------------------
1414      !!                 ***  routine mppmin_a_real  ***
1415      !!                 
1416      !! ** Purpose :   Minimum of REAL, array case
1417      !!
1418      !!-----------------------------------------------------------------------
1419      INTEGER , INTENT(in   )                  ::   kdim
1420      REAL(wp), INTENT(inout), DIMENSION(kdim) ::   ptab
1421      INTEGER , INTENT(in   ), OPTIONAL        ::   kcom
1422      !!
1423      INTEGER :: ierror, localcomm
1424      REAL(wp), DIMENSION(kdim) ::   zwork
1425      !!-----------------------------------------------------------------------
1426      !
1427      localcomm = mpi_comm_opa 
1428      IF( PRESENT(kcom) ) localcomm = kcom
1429      !
1430      CALL mpi_allreduce( ptab, zwork, kdim, mpi_double_precision, mpi_min, localcomm, ierror )
1431      ptab(:) = zwork(:)
1432      !
1433   END SUBROUTINE mppmin_a_real
1434
1435
1436   SUBROUTINE mppmin_real( ptab, kcom )
1437      !!----------------------------------------------------------------------
1438      !!                  ***  routine mppmin_real  ***
1439      !!
1440      !! ** Purpose :   minimum of REAL, scalar case
1441      !!
1442      !!-----------------------------------------------------------------------
1443      REAL(wp), INTENT(inout)           ::   ptab        !
1444      INTEGER , INTENT(in   ), OPTIONAL :: kcom
1445      !!
1446      INTEGER  ::   ierror
1447      REAL(wp) ::   zwork
1448      INTEGER :: localcomm
1449      !!-----------------------------------------------------------------------
1450      !
1451      localcomm = mpi_comm_opa 
1452      IF( PRESENT(kcom) )   localcomm = kcom
1453      !
1454      CALL mpi_allreduce( ptab, zwork, 1, mpi_double_precision, mpi_min, localcomm, ierror )
1455      ptab = zwork
1456      !
1457   END SUBROUTINE mppmin_real
1458
1459
1460   SUBROUTINE mppsum_a_real( ptab, kdim, kcom )
1461      !!----------------------------------------------------------------------
1462      !!                  ***  routine mppsum_a_real  ***
1463      !!
1464      !! ** Purpose :   global sum, REAL ARRAY argument case
1465      !!
1466      !!-----------------------------------------------------------------------
1467      INTEGER , INTENT( in )                     ::   kdim      ! size of ptab
1468      REAL(wp), DIMENSION(kdim), INTENT( inout ) ::   ptab      ! input array
1469      INTEGER , INTENT( in ), OPTIONAL           :: kcom
1470      !!
1471      INTEGER                   ::   ierror    ! temporary integer
1472      INTEGER                   ::   localcomm 
1473      REAL(wp), DIMENSION(kdim) ::   zwork     ! temporary workspace
1474      !!-----------------------------------------------------------------------
1475      !
1476      localcomm = mpi_comm_opa 
1477      IF( PRESENT(kcom) )   localcomm = kcom
1478      !
1479      CALL mpi_allreduce( ptab, zwork, kdim, mpi_double_precision, mpi_sum, localcomm, ierror )
1480      ptab(:) = zwork(:)
1481      !
1482   END SUBROUTINE mppsum_a_real
1483
1484
1485   SUBROUTINE mppsum_real( ptab, kcom )
1486      !!----------------------------------------------------------------------
1487      !!                  ***  routine mppsum_real  ***
1488      !!             
1489      !! ** Purpose :   global sum, SCALAR argument case
1490      !!
1491      !!-----------------------------------------------------------------------
1492      REAL(wp), INTENT(inout)           ::   ptab   ! input scalar
1493      INTEGER , INTENT(in   ), OPTIONAL ::   kcom
1494      !!
1495      INTEGER  ::   ierror, localcomm 
1496      REAL(wp) ::   zwork
1497      !!-----------------------------------------------------------------------
1498      !
1499      localcomm = mpi_comm_opa 
1500      IF( PRESENT(kcom) ) localcomm = kcom
1501      !
1502      CALL mpi_allreduce( ptab, zwork, 1, mpi_double_precision, mpi_sum, localcomm, ierror )
1503      ptab = zwork
1504      !
1505   END SUBROUTINE mppsum_real
1506
1507# if defined key_mpp_rep
1508   SUBROUTINE mppsum_realdd( ytab, kcom )
1509      !!----------------------------------------------------------------------
1510      !!                  ***  routine mppsum_realdd ***
1511      !!
1512      !! ** Purpose :   global sum in Massively Parallel Processing
1513      !!                SCALAR argument case for double-double precision
1514      !!
1515      !!-----------------------------------------------------------------------
1516      COMPLEX(wp), INTENT(inout)         :: ytab    ! input scalar
1517      INTEGER , INTENT( in  ), OPTIONAL :: kcom
1518
1519      !! * Local variables   (MPI version)
1520      INTEGER  ::    ierror
1521      INTEGER  ::   localcomm
1522      COMPLEX(wp) :: zwork
1523
1524      localcomm = mpi_comm_opa
1525      IF( PRESENT(kcom) ) localcomm = kcom
1526
1527      ! reduce local sums into global sum
1528      CALL MPI_ALLREDUCE (ytab, zwork, 1, MPI_DOUBLE_COMPLEX, &
1529                       MPI_SUMDD,localcomm,ierror)
1530      ytab = zwork
1531
1532   END SUBROUTINE mppsum_realdd
1533 
1534 
1535   SUBROUTINE mppsum_a_realdd( ytab, kdim, kcom )
1536      !!----------------------------------------------------------------------
1537      !!                  ***  routine mppsum_a_realdd  ***
1538      !!
1539      !! ** Purpose :   global sum in Massively Parallel Processing
1540      !!                COMPLEX ARRAY case for double-double precision
1541      !!
1542      !!-----------------------------------------------------------------------
1543      INTEGER , INTENT( in )                        ::   kdim      ! size of ytab
1544      COMPLEX(wp), DIMENSION(kdim), INTENT( inout ) ::   ytab      ! input array
1545      INTEGER , INTENT( in  ), OPTIONAL :: kcom
1546
1547      !! * Local variables   (MPI version)
1548      INTEGER                      :: ierror    ! temporary integer
1549      INTEGER                      ::   localcomm
1550      COMPLEX(wp), DIMENSION(kdim) :: zwork     ! temporary workspace
1551
1552      localcomm = mpi_comm_opa
1553      IF( PRESENT(kcom) ) localcomm = kcom
1554
1555      CALL MPI_ALLREDUCE (ytab, zwork, kdim, MPI_DOUBLE_COMPLEX, &
1556                       MPI_SUMDD,localcomm,ierror)
1557      ytab(:) = zwork(:)
1558
1559   END SUBROUTINE mppsum_a_realdd
1560# endif   
1561   
1562   SUBROUTINE mpp_minloc2d( ptab, pmask, pmin, ki,kj )
1563      !!------------------------------------------------------------------------
1564      !!             ***  routine mpp_minloc  ***
1565      !!
1566      !! ** Purpose :   Compute the global minimum of an array ptab
1567      !!              and also give its global position
1568      !!
1569      !! ** Method  :   Use MPI_ALLREDUCE with MPI_MINLOC
1570      !!
1571      !!--------------------------------------------------------------------------
1572      REAL(wp), DIMENSION (jpi,jpj), INTENT(in   ) ::   ptab    ! Local 2D array
1573      REAL(wp), DIMENSION (jpi,jpj), INTENT(in   ) ::   pmask   ! Local mask
1574      REAL(wp)                     , INTENT(  out) ::   pmin    ! Global minimum of ptab
1575      INTEGER                      , INTENT(  out) ::   ki, kj   ! index of minimum in global frame
1576      !!
1577      INTEGER , DIMENSION(2)   ::   ilocs
1578      INTEGER :: ierror
1579      REAL(wp) ::   zmin   ! local minimum
1580      REAL(wp), DIMENSION(2,1) ::   zain, zaout
1581      !!-----------------------------------------------------------------------
1582      !
1583      zmin  = MINVAL( ptab(:,:) , mask= pmask == 1.e0 )
1584      ilocs = MINLOC( ptab(:,:) , mask= pmask == 1.e0 )
1585      !
1586      ki = ilocs(1) + nimpp - 1
1587      kj = ilocs(2) + njmpp - 1
1588      !
1589      zain(1,:)=zmin
1590      zain(2,:)=ki+10000.*kj
1591      !
1592      CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MINLOC,MPI_COMM_OPA,ierror)
1593      !
1594      pmin = zaout(1,1)
1595      kj = INT(zaout(2,1)/10000.)
1596      ki = INT(zaout(2,1) - 10000.*kj )
1597      !
1598   END SUBROUTINE mpp_minloc2d
1599
1600
1601   SUBROUTINE mpp_minloc3d( ptab, pmask, pmin, ki, kj ,kk)
1602      !!------------------------------------------------------------------------
1603      !!             ***  routine mpp_minloc  ***
1604      !!
1605      !! ** Purpose :   Compute the global minimum of an array ptab
1606      !!              and also give its global position
1607      !!
1608      !! ** Method  :   Use MPI_ALLREDUCE with MPI_MINLOC
1609      !!
1610      !!--------------------------------------------------------------------------
1611      REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT(in   ) ::   ptab         ! Local 2D array
1612      REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT(in   ) ::   pmask        ! Local mask
1613      REAL(wp)                         , INTENT(  out) ::   pmin         ! Global minimum of ptab
1614      INTEGER                          , INTENT(  out) ::   ki, kj, kk   ! index of minimum in global frame
1615      !!
1616      INTEGER  ::   ierror
1617      REAL(wp) ::   zmin     ! local minimum
1618      INTEGER , DIMENSION(3)   ::   ilocs
1619      REAL(wp), DIMENSION(2,1) ::   zain, zaout
1620      !!-----------------------------------------------------------------------
1621      !
1622      zmin  = MINVAL( ptab(:,:,:) , mask= pmask == 1.e0 )
1623      ilocs = MINLOC( ptab(:,:,:) , mask= pmask == 1.e0 )
1624      !
1625      ki = ilocs(1) + nimpp - 1
1626      kj = ilocs(2) + njmpp - 1
1627      kk = ilocs(3)
1628      !
1629      zain(1,:)=zmin
1630      zain(2,:)=ki+10000.*kj+100000000.*kk
1631      !
1632      CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MINLOC,MPI_COMM_OPA,ierror)
1633      !
1634      pmin = zaout(1,1)
1635      kk   = INT( zaout(2,1) / 100000000. )
1636      kj   = INT( zaout(2,1) - kk * 100000000. ) / 10000
1637      ki   = INT( zaout(2,1) - kk * 100000000. -kj * 10000. )
1638      !
1639   END SUBROUTINE mpp_minloc3d
1640
1641
1642   SUBROUTINE mpp_maxloc2d( ptab, pmask, pmax, ki, kj )
1643      !!------------------------------------------------------------------------
1644      !!             ***  routine mpp_maxloc  ***
1645      !!
1646      !! ** Purpose :   Compute the global maximum of an array ptab
1647      !!              and also give its global position
1648      !!
1649      !! ** Method  :   Use MPI_ALLREDUCE with MPI_MINLOC
1650      !!
1651      !!--------------------------------------------------------------------------
1652      REAL(wp), DIMENSION (jpi,jpj), INTENT(in   ) ::   ptab     ! Local 2D array
1653      REAL(wp), DIMENSION (jpi,jpj), INTENT(in   ) ::   pmask    ! Local mask
1654      REAL(wp)                     , INTENT(  out) ::   pmax     ! Global maximum of ptab
1655      INTEGER                      , INTENT(  out) ::   ki, kj   ! index of maximum in global frame
1656      !! 
1657      INTEGER  :: ierror
1658      INTEGER, DIMENSION (2)   ::   ilocs
1659      REAL(wp) :: zmax   ! local maximum
1660      REAL(wp), DIMENSION(2,1) ::   zain, zaout
1661      !!-----------------------------------------------------------------------
1662      !
1663      zmax  = MAXVAL( ptab(:,:) , mask= pmask == 1.e0 )
1664      ilocs = MAXLOC( ptab(:,:) , mask= pmask == 1.e0 )
1665      !
1666      ki = ilocs(1) + nimpp - 1
1667      kj = ilocs(2) + njmpp - 1
1668      !
1669      zain(1,:) = zmax
1670      zain(2,:) = ki + 10000. * kj
1671      !
1672      CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MAXLOC,MPI_COMM_OPA,ierror)
1673      !
1674      pmax = zaout(1,1)
1675      kj   = INT( zaout(2,1) / 10000.     )
1676      ki   = INT( zaout(2,1) - 10000.* kj )
1677      !
1678   END SUBROUTINE mpp_maxloc2d
1679
1680
1681   SUBROUTINE mpp_maxloc3d( ptab, pmask, pmax, ki, kj, kk )
1682      !!------------------------------------------------------------------------
1683      !!             ***  routine mpp_maxloc  ***
1684      !!
1685      !! ** Purpose :  Compute the global maximum of an array ptab
1686      !!              and also give its global position
1687      !!
1688      !! ** Method : Use MPI_ALLREDUCE with MPI_MINLOC
1689      !!
1690      !!--------------------------------------------------------------------------
1691      REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT(in   ) ::   ptab         ! Local 2D array
1692      REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT(in   ) ::   pmask        ! Local mask
1693      REAL(wp)                         , INTENT(  out) ::   pmax         ! Global maximum of ptab
1694      INTEGER                          , INTENT(  out) ::   ki, kj, kk   ! index of maximum in global frame
1695      !!   
1696      REAL(wp) :: zmax   ! local maximum
1697      REAL(wp), DIMENSION(2,1) ::   zain, zaout
1698      INTEGER , DIMENSION(3)   ::   ilocs
1699      INTEGER :: ierror
1700      !!-----------------------------------------------------------------------
1701      !
1702      zmax  = MAXVAL( ptab(:,:,:) , mask= pmask == 1.e0 )
1703      ilocs = MAXLOC( ptab(:,:,:) , mask= pmask == 1.e0 )
1704      !
1705      ki = ilocs(1) + nimpp - 1
1706      kj = ilocs(2) + njmpp - 1
1707      kk = ilocs(3)
1708      !
1709      zain(1,:)=zmax
1710      zain(2,:)=ki+10000.*kj+100000000.*kk
1711      !
1712      CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MAXLOC,MPI_COMM_OPA,ierror)
1713      !
1714      pmax = zaout(1,1)
1715      kk   = INT( zaout(2,1) / 100000000. )
1716      kj   = INT( zaout(2,1) - kk * 100000000. ) / 10000
1717      ki   = INT( zaout(2,1) - kk * 100000000. -kj * 10000. )
1718      !
1719   END SUBROUTINE mpp_maxloc3d
1720
1721
1722   SUBROUTINE mppsync()
1723      !!----------------------------------------------------------------------
1724      !!                  ***  routine mppsync  ***
1725      !!                   
1726      !! ** Purpose :   Massively parallel processors, synchroneous
1727      !!
1728      !!-----------------------------------------------------------------------
1729      INTEGER :: ierror
1730      !!-----------------------------------------------------------------------
1731      !
1732      CALL mpi_barrier( mpi_comm_opa, ierror )
1733      !
1734   END SUBROUTINE mppsync
1735
1736
1737   SUBROUTINE mppstop
1738      !!----------------------------------------------------------------------
1739      !!                  ***  routine mppstop  ***
1740      !!                   
1741      !! ** purpose :   Stop massilively parallel processors method
1742      !!
1743      !!----------------------------------------------------------------------
1744      INTEGER ::   info
1745      !!----------------------------------------------------------------------
1746      !
1747      CALL mppsync
1748      CALL mpi_finalize( info )
1749      !
1750   END SUBROUTINE mppstop
1751
1752
1753   SUBROUTINE mppobc( ptab, kd1, kd2, kl, kk, ktype, kij , kumout)
1754      !!----------------------------------------------------------------------
1755      !!                  ***  routine mppobc  ***
1756      !!
1757      !! ** Purpose :   Message passing manadgement for open boundary
1758      !!     conditions array
1759      !!
1760      !! ** Method  :   Use mppsend and mpprecv function for passing mask
1761      !!       between processors following neighboring subdomains.
1762      !!       domain parameters
1763      !!                    nlci   : first dimension of the local subdomain
1764      !!                    nlcj   : second dimension of the local subdomain
1765      !!                    nbondi : mark for "east-west local boundary"
1766      !!                    nbondj : mark for "north-south local boundary"
1767      !!                    noea   : number for local neighboring processors
1768      !!                    nowe   : number for local neighboring processors
1769      !!                    noso   : number for local neighboring processors
1770      !!                    nono   : number for local neighboring processors
1771      !!
1772      !!----------------------------------------------------------------------
1773      USE wrk_nemo, ONLY:   wrk_in_use, wrk_not_released
1774      USE wrk_nemo, ONLY:   ztab => wrk_2d_1
1775      !
1776      INTEGER , INTENT(in   )                     ::   kd1, kd2   ! starting and ending indices
1777      INTEGER , INTENT(in   )                     ::   kl         ! index of open boundary
1778      INTEGER , INTENT(in   )                     ::   kk         ! vertical dimension
1779      INTEGER , INTENT(in   )                     ::   ktype      ! define north/south or east/west cdt
1780      !                                                           !  = 1  north/south  ;  = 2  east/west
1781      INTEGER , INTENT(in   )                     ::   kij        ! horizontal dimension
1782      INTEGER , INTENT(in   )                     ::   kumout     ! ocean.output logical unit
1783      REAL(wp), INTENT(inout), DIMENSION(kij,kk)  ::   ptab       ! variable array
1784      !
1785      INTEGER ::   ji, jj, jk, jl        ! dummy loop indices
1786      INTEGER ::   iipt0, iipt1, ilpt1   ! local integers
1787      INTEGER ::   ijpt0, ijpt1          !   -       -
1788      INTEGER ::   imigr, iihom, ijhom   !   -       -
1789      INTEGER ::   ml_req1, ml_req2, ml_err    ! for key_mpi_isend
1790      INTEGER ::   ml_stat(MPI_STATUS_SIZE)    ! for key_mpi_isend
1791      !!----------------------------------------------------------------------
1792
1793      IF( wrk_in_use(2, 1) ) THEN
1794         WRITE(kumout, cform_err)
1795         WRITE(kumout,*) 'mppobc : requested workspace array unavailable'
1796         CALL mppstop
1797      ENDIF
1798
1799      ! boundary condition initialization
1800      ! ---------------------------------
1801      ztab(:,:) = 0.e0
1802      !
1803      IF( ktype==1 ) THEN                                  ! north/south boundaries
1804         iipt0 = MAX( 1, MIN(kd1 - nimpp+1, nlci     ) )
1805         iipt1 = MAX( 0, MIN(kd2 - nimpp+1, nlci - 1 ) )
1806         ilpt1 = MAX( 1, MIN(kd2 - nimpp+1, nlci     ) )
1807         ijpt0 = MAX( 1, MIN(kl  - njmpp+1, nlcj     ) )
1808         ijpt1 = MAX( 0, MIN(kl  - njmpp+1, nlcj - 1 ) )
1809      ELSEIF( ktype==2 ) THEN                              ! east/west boundaries
1810         iipt0 = MAX( 1, MIN(kl  - nimpp+1, nlci     ) )
1811         iipt1 = MAX( 0, MIN(kl  - nimpp+1, nlci - 1 ) )
1812         ijpt0 = MAX( 1, MIN(kd1 - njmpp+1, nlcj     ) )
1813         ijpt1 = MAX( 0, MIN(kd2 - njmpp+1, nlcj - 1 ) )
1814         ilpt1 = MAX( 1, MIN(kd2 - njmpp+1, nlcj     ) )
1815      ELSE
1816         WRITE(kumout, cform_err)
1817         WRITE(kumout,*) 'mppobc : bad ktype'
1818         CALL mppstop
1819      ENDIF
1820     
1821      ! Communication level by level
1822      ! ----------------------------
1823!!gm Remark : this is very time consumming!!!
1824      !                                         ! ------------------------ !
1825      DO jk = 1, kk                             !   Loop over the levels   !
1826         !                                      ! ------------------------ !
1827         !
1828         IF( ktype == 1 ) THEN                               ! north/south boundaries
1829            DO jj = ijpt0, ijpt1
1830               DO ji = iipt0, iipt1
1831                  ztab(ji,jj) = ptab(ji,jk)
1832               END DO
1833            END DO
1834         ELSEIF( ktype == 2 ) THEN                           ! east/west boundaries
1835            DO jj = ijpt0, ijpt1
1836               DO ji = iipt0, iipt1
1837                  ztab(ji,jj) = ptab(jj,jk)
1838               END DO
1839            END DO
1840         ENDIF
1841
1842
1843         ! 1. East and west directions
1844         ! ---------------------------
1845         !
1846         IF( nbondi /= 2 ) THEN         ! Read Dirichlet lateral conditions
1847            iihom = nlci-nreci
1848            DO jl = 1, jpreci
1849               t2ew(:,jl,1) = ztab(jpreci+jl,:)
1850               t2we(:,jl,1) = ztab(iihom +jl,:)
1851            END DO
1852         ENDIF
1853         !
1854         !                              ! Migrations
1855         imigr=jpreci*jpj
1856         !
1857         IF( nbondi == -1 ) THEN
1858            CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req1 )
1859            CALL mpprecv( 1, t2ew(1,1,2), imigr, noea )
1860            IF(l_isend)   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1861         ELSEIF( nbondi == 0 ) THEN
1862            CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1863            CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req2 )
1864            CALL mpprecv( 1, t2ew(1,1,2), imigr, noea )
1865            CALL mpprecv( 2, t2we(1,1,2), imigr, nowe )
1866            IF(l_isend)   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1867            IF(l_isend)   CALL mpi_wait( ml_req2, ml_stat, ml_err )
1868         ELSEIF( nbondi == 1 ) THEN
1869            CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1870            CALL mpprecv( 2, t2we(1,1,2), imigr, nowe )
1871            IF(l_isend) CALL mpi_wait( ml_req1, ml_stat, ml_err )
1872         ENDIF
1873         !
1874         !                              ! Write Dirichlet lateral conditions
1875         iihom = nlci-jpreci
1876         !
1877         IF( nbondi == 0 .OR. nbondi == 1 ) THEN
1878            DO jl = 1, jpreci
1879               ztab(jl,:) = t2we(:,jl,2)
1880            END DO
1881         ENDIF
1882         IF( nbondi == -1 .OR. nbondi == 0 ) THEN
1883            DO jl = 1, jpreci
1884               ztab(iihom+jl,:) = t2ew(:,jl,2)
1885            END DO
1886         ENDIF
1887
1888
1889         ! 2. North and south directions
1890         ! -----------------------------
1891         !
1892         IF( nbondj /= 2 ) THEN         ! Read Dirichlet lateral conditions
1893            ijhom = nlcj-nrecj
1894            DO jl = 1, jprecj
1895               t2sn(:,jl,1) = ztab(:,ijhom +jl)
1896               t2ns(:,jl,1) = ztab(:,jprecj+jl)
1897            END DO
1898         ENDIF
1899         !
1900         !                              ! Migrations
1901         imigr = jprecj * jpi
1902         !
1903         IF( nbondj == -1 ) THEN
1904            CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req1 )
1905            CALL mpprecv( 3, t2ns(1,1,2), imigr, nono )
1906            IF(l_isend) CALL mpi_wait( ml_req1, ml_stat, ml_err )
1907         ELSEIF( nbondj == 0 ) THEN
1908            CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
1909            CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req2 )
1910            CALL mpprecv( 3, t2ns(1,1,2), imigr, nono )
1911            CALL mpprecv( 4, t2sn(1,1,2), imigr, noso )
1912            IF( l_isend )   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1913            IF( l_isend )   CALL mpi_wait( ml_req2, ml_stat, ml_err )
1914         ELSEIF( nbondj == 1 ) THEN
1915            CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
1916            CALL mpprecv( 4, t2sn(1,1,2), imigr, noso)
1917            IF( l_isend )   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1918         ENDIF
1919         !
1920         !                              ! Write Dirichlet lateral conditions
1921         ijhom = nlcj - jprecj
1922         IF( nbondj == 0 .OR. nbondj == 1 ) THEN
1923            DO jl = 1, jprecj
1924               ztab(:,jl) = t2sn(:,jl,2)
1925            END DO
1926         ENDIF
1927         IF( nbondj == 0 .OR. nbondj == -1 ) THEN
1928            DO jl = 1, jprecj
1929               ztab(:,ijhom+jl) = t2ns(:,jl,2)
1930            END DO
1931         ENDIF
1932         IF( ktype==1 .AND. kd1 <= jpi+nimpp-1 .AND. nimpp <= kd2 ) THEN
1933            DO jj = ijpt0, ijpt1            ! north/south boundaries
1934               DO ji = iipt0,ilpt1
1935                  ptab(ji,jk) = ztab(ji,jj) 
1936               END DO
1937            END DO
1938         ELSEIF( ktype==2 .AND. kd1 <= jpj+njmpp-1 .AND. njmpp <= kd2 ) THEN
1939            DO jj = ijpt0, ilpt1            ! east/west boundaries
1940               DO ji = iipt0,iipt1
1941                  ptab(jj,jk) = ztab(ji,jj) 
1942               END DO
1943            END DO
1944         ENDIF
1945         !
1946      END DO
1947      !
1948      IF( wrk_not_released(2, 1) ) THEN
1949         WRITE(kumout, cform_err)
1950         WRITE(kumout,*) 'mppobc : failed to release workspace array'
1951         CALL mppstop
1952      ENDIF
1953      !
1954   END SUBROUTINE mppobc
1955   
1956
1957   SUBROUTINE mpp_comm_free( kcom )
1958      !!----------------------------------------------------------------------
1959      !!----------------------------------------------------------------------
1960      INTEGER, INTENT(in) ::   kcom
1961      !!
1962      INTEGER :: ierr
1963      !!----------------------------------------------------------------------
1964      !
1965      CALL MPI_COMM_FREE(kcom, ierr)
1966      !
1967   END SUBROUTINE mpp_comm_free
1968
1969
1970   SUBROUTINE mpp_ini_ice( pindic, kumout )
1971      !!----------------------------------------------------------------------
1972      !!               ***  routine mpp_ini_ice  ***
1973      !!
1974      !! ** Purpose :   Initialize special communicator for ice areas
1975      !!      condition together with global variables needed in the ddmpp folding
1976      !!
1977      !! ** Method  : - Look for ice processors in ice routines
1978      !!              - Put their number in nrank_ice
1979      !!              - Create groups for the world processors and the ice processors
1980      !!              - Create a communicator for ice processors
1981      !!
1982      !! ** output
1983      !!      njmppmax = njmpp for northern procs
1984      !!      ndim_rank_ice = number of processors with ice
1985      !!      nrank_ice (ndim_rank_ice) = ice processors
1986      !!      ngrp_world = group ID for the world processors
1987      !!      ngrp_ice = group ID for the ice processors
1988      !!      ncomm_ice = communicator for the ice procs.
1989      !!      n_ice_root = number (in the world) of proc 0 in the ice comm.
1990      !!
1991      !!----------------------------------------------------------------------
1992      INTEGER, INTENT(in) ::   pindic
1993      INTEGER, INTENT(in) ::   kumout   ! ocean.output logical unit
1994      !!
1995      INTEGER :: jjproc
1996      INTEGER :: ii, ierr
1997      INTEGER, ALLOCATABLE, DIMENSION(:) ::   kice
1998      INTEGER, ALLOCATABLE, DIMENSION(:) ::   zwork
1999      !!----------------------------------------------------------------------
2000      !
2001      ! Since this is just an init routine and these arrays are of length jpnij
2002      ! then don't use wrk_nemo module - just allocate and deallocate.
2003      ALLOCATE( kice(jpnij), zwork(jpnij), STAT=ierr )
2004      IF( ierr /= 0 ) THEN
2005         WRITE(kumout, cform_err)
2006         WRITE(kumout,*) 'mpp_ini_ice : failed to allocate 2, 1D arrays (jpnij in length)'
2007         CALL mppstop
2008      ENDIF
2009
2010      ! Look for how many procs with sea-ice
2011      !
2012      kice = 0
2013      DO jjproc = 1, jpnij
2014         IF( jjproc == narea .AND. pindic .GT. 0 )   kice(jjproc) = 1   
2015      END DO
2016      !
2017      zwork = 0
2018      CALL MPI_ALLREDUCE( kice, zwork, jpnij, mpi_integer, mpi_sum, mpi_comm_opa, ierr )
2019      ndim_rank_ice = SUM( zwork )         
2020
2021      ! Allocate the right size to nrank_north
2022      IF( ALLOCATED ( nrank_ice ) )   DEALLOCATE( nrank_ice )
2023      ALLOCATE( nrank_ice(ndim_rank_ice) )
2024      !
2025      ii = 0     
2026      nrank_ice = 0
2027      DO jjproc = 1, jpnij
2028         IF( zwork(jjproc) == 1) THEN
2029            ii = ii + 1
2030            nrank_ice(ii) = jjproc -1 
2031         ENDIF
2032      END DO
2033
2034      ! Create the world group
2035      CALL MPI_COMM_GROUP( mpi_comm_opa, ngrp_world, ierr )
2036
2037      ! Create the ice group from the world group
2038      CALL MPI_GROUP_INCL( ngrp_world, ndim_rank_ice, nrank_ice, ngrp_ice, ierr )
2039
2040      ! Create the ice communicator , ie the pool of procs with sea-ice
2041      CALL MPI_COMM_CREATE( mpi_comm_opa, ngrp_ice, ncomm_ice, ierr )
2042
2043      ! Find proc number in the world of proc 0 in the north
2044      ! The following line seems to be useless, we just comment & keep it as reminder
2045      ! CALL MPI_GROUP_TRANSLATE_RANKS(ngrp_ice,1,0,ngrp_world,n_ice_root,ierr)
2046      !
2047      DEALLOCATE(kice, zwork)
2048      !
2049   END SUBROUTINE mpp_ini_ice
2050
2051
2052   SUBROUTINE mpp_ini_znl( kumout )
2053      !!----------------------------------------------------------------------
2054      !!               ***  routine mpp_ini_znl  ***
2055      !!
2056      !! ** Purpose :   Initialize special communicator for computing zonal sum
2057      !!
2058      !! ** Method  : - Look for processors in the same row
2059      !!              - Put their number in nrank_znl
2060      !!              - Create group for the znl processors
2061      !!              - Create a communicator for znl processors
2062      !!              - Determine if processor should write znl files
2063      !!
2064      !! ** output
2065      !!      ndim_rank_znl = number of processors on the same row
2066      !!      ngrp_znl = group ID for the znl processors
2067      !!      ncomm_znl = communicator for the ice procs.
2068      !!      n_znl_root = number (in the world) of proc 0 in the ice comm.
2069      !!
2070      !!----------------------------------------------------------------------
2071      INTEGER, INTENT(in) ::   kumout   ! ocean.output logical units
2072      !
2073      INTEGER :: jproc      ! dummy loop integer
2074      INTEGER :: ierr, ii   ! local integer
2075      INTEGER, ALLOCATABLE, DIMENSION(:) ::   kwork
2076      !!----------------------------------------------------------------------
2077      !-$$     WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - ngrp_world     : ', ngrp_world
2078      !-$$     WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - mpi_comm_world : ', mpi_comm_world
2079      !-$$     WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - mpi_comm_opa   : ', mpi_comm_opa
2080      !
2081      ALLOCATE( kwork(jpnij), STAT=ierr )
2082      IF( ierr /= 0 ) THEN
2083         WRITE(kumout, cform_err)
2084         WRITE(kumout,*) 'mpp_ini_znl : failed to allocate 1D array of length jpnij'
2085         CALL mppstop
2086      ENDIF
2087
2088      IF( jpnj == 1 ) THEN
2089         ngrp_znl  = ngrp_world
2090         ncomm_znl = mpi_comm_opa
2091      ELSE
2092         !
2093         CALL MPI_ALLGATHER ( njmpp, 1, mpi_integer, kwork, 1, mpi_integer, mpi_comm_opa, ierr )
2094         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - kwork pour njmpp : ', kwork
2095         !-$$        CALL flush(numout)
2096         !
2097         ! Count number of processors on the same row
2098         ndim_rank_znl = 0
2099         DO jproc=1,jpnij
2100            IF ( kwork(jproc) == njmpp ) THEN
2101               ndim_rank_znl = ndim_rank_znl + 1
2102            ENDIF
2103         END DO
2104         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - ndim_rank_znl : ', ndim_rank_znl
2105         !-$$        CALL flush(numout)
2106         ! Allocate the right size to nrank_znl
2107         IF (ALLOCATED (nrank_znl)) DEALLOCATE(nrank_znl)
2108         ALLOCATE(nrank_znl(ndim_rank_znl))
2109         ii = 0     
2110         nrank_znl (:) = 0
2111         DO jproc=1,jpnij
2112            IF ( kwork(jproc) == njmpp) THEN
2113               ii = ii + 1
2114               nrank_znl(ii) = jproc -1 
2115            ENDIF
2116         END DO
2117         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - nrank_znl : ', nrank_znl
2118         !-$$        CALL flush(numout)
2119
2120         ! Create the opa group
2121         CALL MPI_COMM_GROUP(mpi_comm_opa,ngrp_opa,ierr)
2122         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - ngrp_opa : ', ngrp_opa
2123         !-$$        CALL flush(numout)
2124
2125         ! Create the znl group from the opa group
2126         CALL MPI_GROUP_INCL  ( ngrp_opa, ndim_rank_znl, nrank_znl, ngrp_znl, ierr )
2127         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - ngrp_znl ', ngrp_znl
2128         !-$$        CALL flush(numout)
2129
2130         ! Create the znl communicator from the opa communicator, ie the pool of procs in the same row
2131         CALL MPI_COMM_CREATE ( mpi_comm_opa, ngrp_znl, ncomm_znl, ierr )
2132         !-$$        WRITE (numout,*) 'mpp_ini_znl ', nproc, ' - ncomm_znl ', ncomm_znl
2133         !-$$        CALL flush(numout)
2134         !
2135      END IF
2136
2137      ! Determines if processor if the first (starting from i=1) on the row
2138      IF ( jpni == 1 ) THEN
2139         l_znl_root = .TRUE.
2140      ELSE
2141         l_znl_root = .FALSE.
2142         kwork (1) = nimpp
2143         CALL mpp_min ( kwork(1), kcom = ncomm_znl)
2144         IF ( nimpp == kwork(1)) l_znl_root = .TRUE.
2145      END IF
2146
2147      DEALLOCATE(kwork)
2148
2149   END SUBROUTINE mpp_ini_znl
2150
2151
2152   SUBROUTINE mpp_ini_north
2153      !!----------------------------------------------------------------------
2154      !!               ***  routine mpp_ini_north  ***
2155      !!
2156      !! ** Purpose :   Initialize special communicator for north folding
2157      !!      condition together with global variables needed in the mpp folding
2158      !!
2159      !! ** Method  : - Look for northern processors
2160      !!              - Put their number in nrank_north
2161      !!              - Create groups for the world processors and the north processors
2162      !!              - Create a communicator for northern processors
2163      !!
2164      !! ** output
2165      !!      njmppmax = njmpp for northern procs
2166      !!      ndim_rank_north = number of processors in the northern line
2167      !!      nrank_north (ndim_rank_north) = number  of the northern procs.
2168      !!      ngrp_world = group ID for the world processors
2169      !!      ngrp_north = group ID for the northern processors
2170      !!      ncomm_north = communicator for the northern procs.
2171      !!      north_root = number (in the world) of proc 0 in the northern comm.
2172      !!
2173      !!----------------------------------------------------------------------
2174      INTEGER ::   ierr
2175      INTEGER ::   jjproc
2176      INTEGER ::   ii, ji
2177      !!----------------------------------------------------------------------
2178      !
2179      njmppmax = MAXVAL( njmppt )
2180      !
2181      ! Look for how many procs on the northern boundary
2182      ndim_rank_north = 0
2183      DO jjproc = 1, jpnij
2184         IF( njmppt(jjproc) == njmppmax )   ndim_rank_north = ndim_rank_north + 1
2185      END DO
2186      !
2187      ! Allocate the right size to nrank_north
2188      IF (ALLOCATED (nrank_north)) DEALLOCATE(nrank_north)
2189      ALLOCATE( nrank_north(ndim_rank_north) )
2190
2191      ! Fill the nrank_north array with proc. number of northern procs.
2192      ! Note : the rank start at 0 in MPI
2193      ii = 0
2194      DO ji = 1, jpnij
2195         IF ( njmppt(ji) == njmppmax   ) THEN
2196            ii=ii+1
2197            nrank_north(ii)=ji-1
2198         END IF
2199      END DO
2200      !
2201      ! create the world group
2202      CALL MPI_COMM_GROUP( mpi_comm_opa, ngrp_world, ierr )
2203      !
2204      ! Create the North group from the world group
2205      CALL MPI_GROUP_INCL( ngrp_world, ndim_rank_north, nrank_north, ngrp_north, ierr )
2206      !
2207      ! Create the North communicator , ie the pool of procs in the north group
2208      CALL MPI_COMM_CREATE( mpi_comm_opa, ngrp_north, ncomm_north, ierr )
2209      !
2210   END SUBROUTINE mpp_ini_north
2211
2212
2213   SUBROUTINE mpp_lbc_north_3d( pt3d, cd_type, psgn )
2214      !!---------------------------------------------------------------------
2215      !!                   ***  routine mpp_lbc_north_3d  ***
2216      !!
2217      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
2218      !!              in mpp configuration in case of jpn1 > 1
2219      !!
2220      !! ** Method  :   North fold condition and mpp with more than one proc
2221      !!              in i-direction require a specific treatment. We gather
2222      !!              the 4 northern lines of the global domain on 1 processor
2223      !!              and apply lbc north-fold on this sub array. Then we
2224      !!              scatter the north fold array back to the processors.
2225      !!
2226      !!----------------------------------------------------------------------
2227      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   pt3d      ! 3D array on which the b.c. is applied
2228      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type   ! nature of pt3d grid-points
2229      !                                                              !   = T ,  U , V , F or W  gridpoints
2230      REAL(wp)                        , INTENT(in   ) ::   psgn      ! = -1. the sign change across the north fold
2231      !!                                                             ! =  1. , the sign is kept
2232      INTEGER ::   ji, jj, jr
2233      INTEGER ::   ierr, itaille, ildi, ilei, iilb
2234      INTEGER ::   ijpj, ijpjm1, ij, iproc
2235      INTEGER, DIMENSION (jpmaxngh)          ::   ml_req5            ! for mpi_isend when avoiding mpi_allgather
2236      INTEGER                                ::   ml_err             ! for mpi_isend when avoiding mpi_allgather
2237      INTEGER, DIMENSION(MPI_STATUS_SIZE)    ::   ml_stat            ! for mpi_isend when avoiding mpi_allgather
2238      !!----------------------------------------------------------------------
2239      !   
2240      ijpj   = 4
2241      ityp = -1
2242      ijpjm1 = 3
2243      ztab(:,:,:) = 0.e0
2244      !
2245      DO jj = nlcj - ijpj +1, nlcj          ! put in znorthloc the last 4 jlines of pt3d
2246         ij = jj - nlcj + ijpj
2247         znorthloc(:,ij,:) = pt3d(:,jj,:)
2248      END DO
2249      !
2250      !                                     ! Build in procs of ncomm_north the znorthgloio
2251      itaille = jpi * jpk * ijpj
2252      IF ( l_north_nogather ) THEN
2253!
2254! Avoid the use of mpi_allgather by exchanging only with the processes already identified (in nemo_northcomms)
2255! as being  involved in this process' northern boundary exchange
2256!
2257! First put local values into the global arraay
2258         DO jj = nlcj-ijpj+1, nlcj
2259           ij = jj - nlcj + ijpj
2260           DO ji = 1, nlci
2261             ztab(ji+nimpp-1,ij,:) = pt3d(ji,jj,:)
2262           END DO
2263         END DO
2264
2265!
2266! Set the exchange type in order to access the correct list of active neighbours
2267!
2268         SELECT CASE ( cd_type )
2269            CASE ( 'T' , 'W' )
2270             ityp = 1
2271            CASE ( 'U' )
2272             ityp = 2
2273            CASE ( 'V' )
2274             ityp = 3
2275            CASE ( 'F' )
2276             ityp = 4
2277            CASE ( 'I' )
2278             ityp = 5
2279            CASE DEFAULT
2280!
2281! Set a default value for unsupported types which will cause a fallback to
2282! the mpi_allgather method
2283!
2284             ityp = -1
2285          END SELECT
2286          IF ( ityp .gt. 0 ) THEN
2287
2288           DO jr = 1,nsndto(ityp)
2289            CALL mppsend(5, znorthloc, itaille, isendto(jr,ityp), ml_req5(jr) )
2290           END DO
2291           DO jr = 1,nsndto(ityp)
2292            CALL mpprecv(5, zfoldwk, itaille, isendto(jr,ityp))
2293            iproc = isendto(jr,ityp) + 1
2294            ildi=nldit (iproc)
2295            ilei=nleit (iproc)
2296            iilb=nimppt(iproc)
2297            DO jj = 1, 4
2298               DO ji = ildi, ilei
2299                  ztab(ji+iilb-1,jj,:) = zfoldwk(ji,jj,:)
2300               END DO
2301            END DO
2302           END DO
2303           IF(l_isend) THEN
2304              DO jr = 1,nsndto(ityp)
2305                CALL mpi_wait(ml_req5(jr), ml_stat, ml_err)
2306              END DO
2307           ENDIF
2308
2309          ENDIF
2310
2311      ENDIF
2312
2313      IF ( ityp .lt. 0 ) THEN
2314         CALL MPI_ALLGATHER( znorthloc  , itaille, MPI_DOUBLE_PRECISION,                &
2315            &                znorthgloio, itaille, MPI_DOUBLE_PRECISION, ncomm_north, ierr )
2316      !
2317      !                                     ! recover the global north array
2318         DO jr = 1, ndim_rank_north
2319            iproc = nrank_north(jr) + 1
2320            ildi  = nldit (iproc)
2321            ilei  = nleit (iproc)
2322            iilb  = nimppt(iproc)
2323            DO jj = 1, 4
2324               DO ji = ildi, ilei
2325                  ztab(ji+iilb-1,jj,:) = znorthgloio(ji,jj,:,jr)
2326               END DO
2327            END DO
2328         END DO
2329      ENDIF
2330      !
2331      ! The ztab array has been either:
2332      !  a. Fully populated by the mpi_allgather operation or
2333      !  b. Had the active points for this domain and northern neighbours populated
2334      !     by peer to peer exchanges
2335      ! Either way the array may be folded by lbc_nfd and the result for the span of
2336      ! this domain will be identical.
2337      !
2338      CALL lbc_nfd( ztab, cd_type, psgn )   ! North fold boundary condition
2339      !
2340      DO jj = nlcj-ijpj+1, nlcj             ! Scatter back to pt3d
2341         ij = jj - nlcj + ijpj
2342         DO ji= 1, nlci
2343            pt3d(ji,jj,:) = ztab(ji+nimpp-1,ij,:)
2344         END DO
2345      END DO
2346      !
2347   END SUBROUTINE mpp_lbc_north_3d
2348
2349
2350   SUBROUTINE mpp_lbc_north_2d( pt2d, cd_type, psgn)
2351      !!---------------------------------------------------------------------
2352      !!                   ***  routine mpp_lbc_north_2d  ***
2353      !!
2354      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
2355      !!              in mpp configuration in case of jpn1 > 1 (for 2d array )
2356      !!
2357      !! ** Method  :   North fold condition and mpp with more than one proc
2358      !!              in i-direction require a specific treatment. We gather
2359      !!              the 4 northern lines of the global domain on 1 processor
2360      !!              and apply lbc north-fold on this sub array. Then we
2361      !!              scatter the north fold array back to the processors.
2362      !!
2363      !!----------------------------------------------------------------------
2364      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) ::   pt2d      ! 3D array on which the b.c. is applied
2365      CHARACTER(len=1)            , INTENT(in   ) ::   cd_type   ! nature of pt3d grid-points
2366      !                                                          !   = T ,  U , V , F or W  gridpoints
2367      REAL(wp)                    , INTENT(in   ) ::   psgn      ! = -1. the sign change across the north fold
2368      !!                                                             ! =  1. , the sign is kept
2369      INTEGER ::   ji, jj, jr
2370      INTEGER ::   ierr, itaille, ildi, ilei, iilb
2371      INTEGER ::   ijpj, ijpjm1, ij, iproc
2372      INTEGER, DIMENSION (jpmaxngh)      ::   ml_req5            ! for mpi_isend when avoiding mpi_allgather
2373      INTEGER                            ::   ml_err             ! for mpi_isend when avoiding mpi_allgather
2374      INTEGER, DIMENSION(MPI_STATUS_SIZE)::   ml_stat            ! for mpi_isend when avoiding mpi_allgather
2375      !!----------------------------------------------------------------------
2376      !
2377      ijpj   = 4
2378      ityp = -1
2379      ijpjm1 = 3
2380      ztab_2d(:,:) = 0.e0
2381      !
2382      DO jj = nlcj-ijpj+1, nlcj             ! put in znorthloc_2d the last 4 jlines of pt2d
2383         ij = jj - nlcj + ijpj
2384         znorthloc_2d(:,ij) = pt2d(:,jj)
2385      END DO
2386
2387      !                                     ! Build in procs of ncomm_north the znorthgloio_2d
2388      itaille = jpi * ijpj
2389      IF ( l_north_nogather ) THEN
2390!
2391! Avoid the use of mpi_allgather by exchanging only with the processes already identified (in nemo_northcomms)
2392! as being  involved in this process' northern boundary exchange
2393!
2394! First put local values into the global array
2395!
2396         DO jj = nlcj-ijpj+1, nlcj
2397           ij = jj - nlcj + ijpj
2398           DO ji = 1, nlci
2399             ztab_2d(ji+nimpp-1,ij) = pt2d(ji,jj)
2400           END DO
2401         END DO
2402
2403!
2404! Set the exchange type in order to access the correct list of active neighbours
2405!
2406         SELECT CASE ( cd_type )
2407            CASE ( 'T' , 'W' )
2408             ityp = 1
2409            CASE ( 'U' )
2410             ityp = 2
2411            CASE ( 'V' )
2412             ityp = 3
2413            CASE ( 'F' )
2414             ityp = 4
2415            CASE ( 'I' )
2416             ityp = 5
2417            CASE DEFAULT
2418!
2419! Set a default value for unsupported types which will cause a fallback to
2420! the mpi_allgather method
2421!
2422             ityp = -1
2423          END SELECT
2424
2425          IF ( ityp .gt. 0 ) THEN
2426
2427           DO jr = 1,nsndto(ityp)
2428            CALL mppsend(5, znorthloc_2d, itaille, isendto(jr,ityp), ml_req5(jr) )
2429           END DO
2430           DO jr = 1,nsndto(ityp)
2431            CALL mpprecv(5, zfoldwk_2d, itaille, isendto(jr,ityp))
2432            iproc = isendto(jr,ityp) + 1
2433            ildi=nldit (iproc)
2434            ilei=nleit (iproc)
2435            iilb=nimppt(iproc)
2436            DO jj = 1, 4
2437               DO ji = ildi, ilei
2438                  ztab_2d(ji+iilb-1,jj) = zfoldwk_2d(ji,jj)
2439               END DO
2440            END DO
2441           END DO
2442           IF(l_isend) THEN
2443              DO jr = 1,nsndto(ityp)
2444                CALL mpi_wait(ml_req5(jr), ml_stat, ml_err)
2445              END DO
2446           ENDIF
2447
2448          ENDIF
2449
2450      ENDIF
2451
2452      IF ( ityp .lt. 0 ) THEN
2453       CALL MPI_ALLGATHER( znorthloc_2d  , itaille, MPI_DOUBLE_PRECISION,        &
2454          &                znorthgloio_2d, itaille, MPI_DOUBLE_PRECISION, ncomm_north, ierr )
2455      !
2456       DO jr = 1, ndim_rank_north            ! recover the global north array
2457          iproc = nrank_north(jr) + 1
2458          ildi=nldit (iproc)
2459          ilei=nleit (iproc)
2460          iilb=nimppt(iproc)
2461          DO jj = 1, 4
2462             DO ji = ildi, ilei
2463                ztab_2d(ji+iilb-1,jj) = znorthgloio_2d(ji,jj,jr)
2464             END DO
2465          END DO
2466       END DO
2467      ENDIF
2468      !
2469      ! The ztab array has been either:
2470      !  a. Fully populated by the mpi_allgather operation or
2471      !  b. Had the active points for this domain and northern neighbours populated
2472      !     by peer to peer exchanges
2473      ! Either way the array may be folded by lbc_nfd and the result for the span of
2474      ! this domain will be identical.
2475      !
2476      CALL lbc_nfd( ztab_2d, cd_type, psgn )   ! North fold boundary condition
2477      !
2478      !
2479      DO jj = nlcj-ijpj+1, nlcj             ! Scatter back to pt2d
2480         ij = jj - nlcj + ijpj
2481         DO ji = 1, nlci
2482            pt2d(ji,jj) = ztab_2d(ji+nimpp-1,ij)
2483         END DO
2484      END DO
2485      !
2486   END SUBROUTINE mpp_lbc_north_2d
2487
2488
2489   SUBROUTINE mpp_lbc_north_e( pt2d, cd_type, psgn)
2490      !!---------------------------------------------------------------------
2491      !!                   ***  routine mpp_lbc_north_2d  ***
2492      !!
2493      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
2494      !!              in mpp configuration in case of jpn1 > 1 and for 2d
2495      !!              array with outer extra halo
2496      !!
2497      !! ** Method  :   North fold condition and mpp with more than one proc
2498      !!              in i-direction require a specific treatment. We gather
2499      !!              the 4+2*jpr2dj northern lines of the global domain on 1
2500      !!              processor and apply lbc north-fold on this sub array.
2501      !!              Then we scatter the north fold array back to the processors.
2502      !!
2503      !!----------------------------------------------------------------------
2504      REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT(inout) ::   pt2d     ! 2D array with extra halo
2505      CHARACTER(len=1)                                            , INTENT(in   ) ::   cd_type  ! nature of pt3d grid-points
2506      !                                                                                         !   = T ,  U , V , F or W -points
2507      REAL(wp)                                                    , INTENT(in   ) ::   psgn     ! = -1. the sign change across the 
2508      !!                                                                                        ! north fold, =  1. otherwise
2509      INTEGER ::   ji, jj, jr
2510      INTEGER ::   ierr, itaille, ildi, ilei, iilb
2511      INTEGER ::   ijpj, ij, iproc
2512      !!----------------------------------------------------------------------
2513      !
2514      ijpj=4
2515      ztab_e(:,:) = 0.e0
2516
2517      ij=0
2518      ! put in znorthloc_e the last 4 jlines of pt2d
2519      DO jj = nlcj - ijpj + 1 - jpr2dj, nlcj +jpr2dj
2520         ij = ij + 1
2521         DO ji = 1, jpi
2522            znorthloc_e(ji,ij)=pt2d(ji,jj)
2523         END DO
2524      END DO
2525      !
2526      itaille = jpi * ( ijpj + 2 * jpr2dj )
2527      CALL MPI_ALLGATHER( znorthloc_e(1,1)  , itaille, MPI_DOUBLE_PRECISION,    &
2528         &                znorthgloio_e(1,1,1), itaille, MPI_DOUBLE_PRECISION, ncomm_north, ierr )
2529      !
2530      DO jr = 1, ndim_rank_north            ! recover the global north array
2531         iproc = nrank_north(jr) + 1
2532         ildi = nldit (iproc)
2533         ilei = nleit (iproc)
2534         iilb = nimppt(iproc)
2535         DO jj = 1, ijpj+2*jpr2dj
2536            DO ji = ildi, ilei
2537               ztab_e(ji+iilb-1,jj) = znorthgloio_e(ji,jj,jr)
2538            END DO
2539         END DO
2540      END DO
2541
2542
2543      ! 2. North-Fold boundary conditions
2544      ! ----------------------------------
2545      CALL lbc_nfd( ztab_e(:,:), cd_type, psgn, pr2dj = jpr2dj )
2546
2547      ij = jpr2dj
2548      !! Scatter back to pt2d
2549      DO jj = nlcj - ijpj + 1 , nlcj +jpr2dj
2550      ij  = ij +1 
2551         DO ji= 1, nlci
2552            pt2d(ji,jj) = ztab_e(ji+nimpp-1,ij)
2553         END DO
2554      END DO
2555      !
2556   END SUBROUTINE mpp_lbc_north_e
2557
2558
2559   SUBROUTINE mpi_init_opa( ldtxt, ksft, code )
2560      !!---------------------------------------------------------------------
2561      !!                   ***  routine mpp_init.opa  ***
2562      !!
2563      !! ** Purpose :: export and attach a MPI buffer for bsend
2564      !!
2565      !! ** Method  :: define buffer size in namelist, if 0 no buffer attachment
2566      !!            but classical mpi_init
2567      !!
2568      !! History :: 01/11 :: IDRIS initial version for IBM only 
2569      !!            08/04 :: R. Benshila, generalisation
2570      !!---------------------------------------------------------------------
2571      CHARACTER(len=*),DIMENSION(:), INTENT(  out) ::   ldtxt 
2572      INTEGER                      , INTENT(inout) ::   ksft
2573      INTEGER                      , INTENT(  out) ::   code
2574      INTEGER                                      ::   ierr, ji
2575      LOGICAL                                      ::   mpi_was_called
2576      !!---------------------------------------------------------------------
2577      !
2578      CALL mpi_initialized( mpi_was_called, code )      ! MPI initialization
2579      IF ( code /= MPI_SUCCESS ) THEN
2580         DO ji = 1, SIZE(ldtxt) 
2581            IF( TRIM(ldtxt(ji)) /= '' )   WRITE(*,*) ldtxt(ji)      ! control print of mynode
2582         END DO         
2583         WRITE(*, cform_err)
2584         WRITE(*, *) ' lib_mpp: Error in routine mpi_initialized'
2585         CALL mpi_abort( mpi_comm_world, code, ierr )
2586      ENDIF
2587      !
2588      IF( .NOT. mpi_was_called ) THEN
2589         CALL mpi_init( code )
2590         CALL mpi_comm_dup( mpi_comm_world, mpi_comm_opa, code )
2591         IF ( code /= MPI_SUCCESS ) THEN
2592            DO ji = 1, SIZE(ldtxt) 
2593               IF( TRIM(ldtxt(ji)) /= '' )   WRITE(*,*) ldtxt(ji)      ! control print of mynode
2594            END DO
2595            WRITE(*, cform_err)
2596            WRITE(*, *) ' lib_mpp: Error in routine mpi_comm_dup'
2597            CALL mpi_abort( mpi_comm_world, code, ierr )
2598         ENDIF
2599      ENDIF
2600      !
2601      IF( nn_buffer > 0 ) THEN
2602         WRITE(ldtxt(ksft),*) 'mpi_bsend, buffer allocation of  : ', nn_buffer   ;   ksft = ksft + 1
2603         ! Buffer allocation and attachment
2604         ALLOCATE( tampon(nn_buffer), stat = ierr )
2605         IF( ierr /= 0 ) THEN
2606            DO ji = 1, SIZE(ldtxt) 
2607               IF( TRIM(ldtxt(ji)) /= '' )   WRITE(*,*) ldtxt(ji)      ! control print of mynode
2608            END DO
2609            WRITE(*, cform_err)
2610            WRITE(*, *) ' lib_mpp: Error in ALLOCATE', ierr
2611            CALL mpi_abort( mpi_comm_world, code, ierr )
2612         END IF
2613         CALL mpi_buffer_attach( tampon, nn_buffer, code )
2614      ENDIF
2615      !
2616   END SUBROUTINE mpi_init_opa
2617
2618#if defined key_mpp_rep
2619   SUBROUTINE DDPDD_MPI (ydda, yddb, ilen, itype)
2620      !!---------------------------------------------------------------------
2621      !!   Routine DDPDD_MPI: used by reduction operator MPI_SUMDD
2622      !!
2623      !!   Modification of original codes written by David H. Bailey
2624      !!   This subroutine computes yddb(i) = ydda(i)+yddb(i)
2625      !!---------------------------------------------------------------------
2626      INTEGER, INTENT(in)                         :: ilen, itype
2627      COMPLEX(wp), DIMENSION(ilen), INTENT(in)     :: ydda
2628      COMPLEX(wp), DIMENSION(ilen), INTENT(inout)  :: yddb
2629      !
2630      REAL(wp) :: zerr, zt1, zt2    ! local work variables
2631      INTEGER :: ji, ztmp           ! local scalar
2632
2633      ztmp = itype   ! avoid compilation warning
2634
2635      DO ji=1,ilen
2636      ! Compute ydda + yddb using Knuth's trick.
2637         zt1  = real(ydda(ji)) + real(yddb(ji))
2638         zerr = zt1 - real(ydda(ji))
2639         zt2  = ((real(yddb(ji)) - zerr) + (real(ydda(ji)) - (zt1 - zerr))) &
2640                + aimag(ydda(ji)) + aimag(yddb(ji))
2641
2642         ! The result is zt1 + zt2, after normalization.
2643         yddb(ji) = cmplx ( zt1 + zt2, zt2 - ((zt1 + zt2) - zt1),wp )
2644      END DO
2645
2646   END SUBROUTINE DDPDD_MPI
2647#endif
2648
2649#else
2650   !!----------------------------------------------------------------------
2651   !!   Default case:            Dummy module        share memory computing
2652   !!----------------------------------------------------------------------
2653   USE in_out_manager
2654
2655   INTERFACE mpp_sum
2656      MODULE PROCEDURE mpp_sum_a2s, mpp_sum_as, mpp_sum_ai, mpp_sum_s, mpp_sum_i
2657   END INTERFACE
2658   INTERFACE mpp_max
2659      MODULE PROCEDURE mppmax_a_int, mppmax_int, mppmax_a_real, mppmax_real
2660   END INTERFACE
2661   INTERFACE mpp_min
2662      MODULE PROCEDURE mppmin_a_int, mppmin_int, mppmin_a_real, mppmin_real
2663   END INTERFACE
2664   INTERFACE mppobc
2665      MODULE PROCEDURE mppobc_1d, mppobc_2d, mppobc_3d, mppobc_4d
2666   END INTERFACE
2667   INTERFACE mpp_minloc
2668      MODULE PROCEDURE mpp_minloc2d ,mpp_minloc3d
2669   END INTERFACE
2670   INTERFACE mpp_maxloc
2671      MODULE PROCEDURE mpp_maxloc2d ,mpp_maxloc3d
2672   END INTERFACE
2673
2674   LOGICAL, PUBLIC, PARAMETER ::   lk_mpp = .FALSE.      !: mpp flag
2675   INTEGER :: ncomm_ice
2676   !!----------------------------------------------------------------------
2677CONTAINS
2678
2679   INTEGER FUNCTION lib_mpp_alloc(kumout)          ! Dummy function
2680      INTEGER, INTENT(in) ::   kumout
2681      lib_mpp_alloc = 0
2682   END FUNCTION lib_mpp_alloc
2683
2684   FUNCTION mynode( ldtxt, kumnam, kstop, localComm ) RESULT (function_value)
2685      INTEGER, OPTIONAL            , INTENT(in   ) ::   localComm
2686      CHARACTER(len=*),DIMENSION(:) ::   ldtxt 
2687      INTEGER ::   kumnam, kstop
2688      IF( PRESENT( localComm ) .OR. .NOT.PRESENT( localComm ) )   function_value = 0
2689      IF( .FALSE. )   ldtxt(:) = 'never done'
2690   END FUNCTION mynode
2691
2692   SUBROUTINE mppsync                       ! Dummy routine
2693   END SUBROUTINE mppsync
2694
2695   SUBROUTINE mpp_sum_as( parr, kdim, kcom )      ! Dummy routine
2696      REAL   , DIMENSION(:) :: parr
2697      INTEGER               :: kdim
2698      INTEGER, OPTIONAL     :: kcom 
2699      WRITE(*,*) 'mpp_sum_as: You should not have seen this print! error?', kdim, parr(1), kcom
2700   END SUBROUTINE mpp_sum_as
2701
2702   SUBROUTINE mpp_sum_a2s( parr, kdim, kcom )      ! Dummy routine
2703      REAL   , DIMENSION(:,:) :: parr
2704      INTEGER               :: kdim
2705      INTEGER, OPTIONAL     :: kcom 
2706      WRITE(*,*) 'mpp_sum_a2s: You should not have seen this print! error?', kdim, parr(1,1), kcom
2707   END SUBROUTINE mpp_sum_a2s
2708
2709   SUBROUTINE mpp_sum_ai( karr, kdim, kcom )      ! Dummy routine
2710      INTEGER, DIMENSION(:) :: karr
2711      INTEGER               :: kdim
2712      INTEGER, OPTIONAL     :: kcom 
2713      WRITE(*,*) 'mpp_sum_ai: You should not have seen this print! error?', kdim, karr(1), kcom
2714   END SUBROUTINE mpp_sum_ai
2715
2716   SUBROUTINE mpp_sum_s( psca, kcom )            ! Dummy routine
2717      REAL                  :: psca
2718      INTEGER, OPTIONAL     :: kcom 
2719      WRITE(*,*) 'mpp_sum_s: You should not have seen this print! error?', psca, kcom
2720   END SUBROUTINE mpp_sum_s
2721
2722   SUBROUTINE mpp_sum_i( kint, kcom )            ! Dummy routine
2723      integer               :: kint
2724      INTEGER, OPTIONAL     :: kcom 
2725      WRITE(*,*) 'mpp_sum_i: You should not have seen this print! error?', kint, kcom
2726   END SUBROUTINE mpp_sum_i
2727
2728   SUBROUTINE mppmax_a_real( parr, kdim, kcom )
2729      REAL   , DIMENSION(:) :: parr
2730      INTEGER               :: kdim
2731      INTEGER, OPTIONAL     :: kcom 
2732      WRITE(*,*) 'mppmax_a_real: You should not have seen this print! error?', kdim, parr(1), kcom
2733   END SUBROUTINE mppmax_a_real
2734
2735   SUBROUTINE mppmax_real( psca, kcom )
2736      REAL                  :: psca
2737      INTEGER, OPTIONAL     :: kcom 
2738      WRITE(*,*) 'mppmax_real: You should not have seen this print! error?', psca, kcom
2739   END SUBROUTINE mppmax_real
2740
2741   SUBROUTINE mppmin_a_real( parr, kdim, kcom )
2742      REAL   , DIMENSION(:) :: parr
2743      INTEGER               :: kdim
2744      INTEGER, OPTIONAL     :: kcom 
2745      WRITE(*,*) 'mppmin_a_real: You should not have seen this print! error?', kdim, parr(1), kcom
2746   END SUBROUTINE mppmin_a_real
2747
2748   SUBROUTINE mppmin_real( psca, kcom )
2749      REAL                  :: psca
2750      INTEGER, OPTIONAL     :: kcom 
2751      WRITE(*,*) 'mppmin_real: You should not have seen this print! error?', psca, kcom
2752   END SUBROUTINE mppmin_real
2753
2754   SUBROUTINE mppmax_a_int( karr, kdim ,kcom)
2755      INTEGER, DIMENSION(:) :: karr
2756      INTEGER               :: kdim
2757      INTEGER, OPTIONAL     :: kcom 
2758      WRITE(*,*) 'mppmax_a_int: You should not have seen this print! error?', kdim, karr(1), kcom
2759   END SUBROUTINE mppmax_a_int
2760
2761   SUBROUTINE mppmax_int( kint, kcom)
2762      INTEGER               :: kint
2763      INTEGER, OPTIONAL     :: kcom 
2764      WRITE(*,*) 'mppmax_int: You should not have seen this print! error?', kint, kcom
2765   END SUBROUTINE mppmax_int
2766
2767   SUBROUTINE mppmin_a_int( karr, kdim, kcom )
2768      INTEGER, DIMENSION(:) :: karr
2769      INTEGER               :: kdim
2770      INTEGER, OPTIONAL     :: kcom 
2771      WRITE(*,*) 'mppmin_a_int: You should not have seen this print! error?', kdim, karr(1), kcom
2772   END SUBROUTINE mppmin_a_int
2773
2774   SUBROUTINE mppmin_int( kint, kcom )
2775      INTEGER               :: kint
2776      INTEGER, OPTIONAL     :: kcom 
2777      WRITE(*,*) 'mppmin_int: You should not have seen this print! error?', kint, kcom
2778   END SUBROUTINE mppmin_int
2779
2780   SUBROUTINE mppobc_1d( parr, kd1, kd2, kl, kk, ktype, kij, knum )
2781      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij, knum
2782      REAL, DIMENSION(:) ::   parr           ! variable array
2783      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1), kd1, kd2, kl, kk, ktype, kij, knum
2784   END SUBROUTINE mppobc_1d
2785
2786   SUBROUTINE mppobc_2d( parr, kd1, kd2, kl, kk, ktype, kij, knum )
2787      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij, knum
2788      REAL, DIMENSION(:,:) ::   parr           ! variable array
2789      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1), kd1, kd2, kl, kk, ktype, kij, knum
2790   END SUBROUTINE mppobc_2d
2791
2792   SUBROUTINE mppobc_3d( parr, kd1, kd2, kl, kk, ktype, kij, knum )
2793      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij, knum
2794      REAL, DIMENSION(:,:,:) ::   parr           ! variable array
2795      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1,1), kd1, kd2, kl, kk, ktype, kij, knum
2796   END SUBROUTINE mppobc_3d
2797
2798   SUBROUTINE mppobc_4d( parr, kd1, kd2, kl, kk, ktype, kij, knum )
2799      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij, knum
2800      REAL, DIMENSION(:,:,:,:) ::   parr           ! variable array
2801      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1,1,1), kd1, kd2, kl, kk, ktype, kij, knum
2802   END SUBROUTINE mppobc_4d
2803
2804   SUBROUTINE mpp_minloc2d( ptab, pmask, pmin, ki, kj )
2805      REAL                   :: pmin
2806      REAL , DIMENSION (:,:) :: ptab, pmask
2807      INTEGER :: ki, kj
2808      WRITE(*,*) 'mpp_minloc2d: You should not have seen this print! error?', pmin, ki, kj, ptab(1,1), pmask(1,1)
2809   END SUBROUTINE mpp_minloc2d
2810
2811   SUBROUTINE mpp_minloc3d( ptab, pmask, pmin, ki, kj, kk )
2812      REAL                     :: pmin
2813      REAL , DIMENSION (:,:,:) :: ptab, pmask
2814      INTEGER :: ki, kj, kk
2815      WRITE(*,*) 'mpp_minloc3d: You should not have seen this print! error?', pmin, ki, kj, kk, ptab(1,1,1), pmask(1,1,1)
2816   END SUBROUTINE mpp_minloc3d
2817
2818   SUBROUTINE mpp_maxloc2d( ptab, pmask, pmax, ki, kj )
2819      REAL                   :: pmax
2820      REAL , DIMENSION (:,:) :: ptab, pmask
2821      INTEGER :: ki, kj
2822      WRITE(*,*) 'mpp_maxloc2d: You should not have seen this print! error?', pmax, ki, kj, ptab(1,1), pmask(1,1)
2823   END SUBROUTINE mpp_maxloc2d
2824
2825   SUBROUTINE mpp_maxloc3d( ptab, pmask, pmax, ki, kj, kk )
2826      REAL                     :: pmax
2827      REAL , DIMENSION (:,:,:) :: ptab, pmask
2828      INTEGER :: ki, kj, kk
2829      WRITE(*,*) 'mpp_maxloc3d: You should not have seen this print! error?', pmax, ki, kj, kk, ptab(1,1,1), pmask(1,1,1)
2830   END SUBROUTINE mpp_maxloc3d
2831
2832   SUBROUTINE mppstop
2833      WRITE(*,*) 'mppstop: You should not have seen this print! error?'
2834   END SUBROUTINE mppstop
2835
2836   SUBROUTINE mpp_ini_ice( kcom, knum )
2837      INTEGER :: kcom, knum
2838      WRITE(*,*) 'mpp_ini_ice: You should not have seen this print! error?', kcom, knum
2839   END SUBROUTINE mpp_ini_ice
2840
2841   SUBROUTINE mpp_ini_znl( knum )
2842      INTEGER :: knum
2843      WRITE(*,*) 'mpp_ini_znl: You should not have seen this print! error?', knum
2844   END SUBROUTINE mpp_ini_znl
2845
2846   SUBROUTINE mpp_comm_free( kcom )
2847      INTEGER :: kcom
2848      WRITE(*,*) 'mpp_comm_free: You should not have seen this print! error?', kcom
2849   END SUBROUTINE mpp_comm_free
2850#endif
2851
2852   !!----------------------------------------------------------------------
2853   !!   All cases:         ctl_stop, ctl_warn, get_unit, ctl_opn   routines
2854   !!----------------------------------------------------------------------
2855
2856   SUBROUTINE ctl_stop( cd1, cd2, cd3, cd4, cd5 ,   &
2857      &                 cd6, cd7, cd8, cd9, cd10 )
2858      !!----------------------------------------------------------------------
2859      !!                  ***  ROUTINE  stop_opa  ***
2860      !!
2861      !! ** Purpose :   print in ocean.outpput file a error message and
2862      !!                increment the error number (nstop) by one.
2863      !!----------------------------------------------------------------------
2864      CHARACTER(len=*), INTENT(in), OPTIONAL ::  cd1, cd2, cd3, cd4, cd5
2865      CHARACTER(len=*), INTENT(in), OPTIONAL ::  cd6, cd7, cd8, cd9, cd10
2866      !!----------------------------------------------------------------------
2867      !
2868      nstop = nstop + 1 
2869      IF(lwp) THEN
2870         WRITE(numout,cform_err)
2871         IF( PRESENT(cd1 ) )   WRITE(numout,*) cd1
2872         IF( PRESENT(cd2 ) )   WRITE(numout,*) cd2
2873         IF( PRESENT(cd3 ) )   WRITE(numout,*) cd3
2874         IF( PRESENT(cd4 ) )   WRITE(numout,*) cd4
2875         IF( PRESENT(cd5 ) )   WRITE(numout,*) cd5
2876         IF( PRESENT(cd6 ) )   WRITE(numout,*) cd6
2877         IF( PRESENT(cd7 ) )   WRITE(numout,*) cd7
2878         IF( PRESENT(cd8 ) )   WRITE(numout,*) cd8
2879         IF( PRESENT(cd9 ) )   WRITE(numout,*) cd9
2880         IF( PRESENT(cd10) )   WRITE(numout,*) cd10
2881      ENDIF
2882                               CALL FLUSH(numout    )
2883      IF( numstp     /= -1 )   CALL FLUSH(numstp    )
2884      IF( numsol     /= -1 )   CALL FLUSH(numsol    )
2885      IF( numevo_ice /= -1 )   CALL FLUSH(numevo_ice)
2886      !
2887      IF( cd1 == 'STOP' ) THEN
2888         IF(lwp) WRITE(numout,*)  'huge E-R-R-O-R : immediate stop'
2889         CALL mppstop()
2890      ENDIF
2891      !
2892   END SUBROUTINE ctl_stop
2893
2894
2895   SUBROUTINE ctl_warn( cd1, cd2, cd3, cd4, cd5,   &
2896      &                 cd6, cd7, cd8, cd9, cd10 )
2897      !!----------------------------------------------------------------------
2898      !!                  ***  ROUTINE  stop_warn  ***
2899      !!
2900      !! ** Purpose :   print in ocean.outpput file a error message and
2901      !!                increment the warning number (nwarn) by one.
2902      !!----------------------------------------------------------------------
2903      CHARACTER(len=*), INTENT(in), OPTIONAL ::  cd1, cd2, cd3, cd4, cd5
2904      CHARACTER(len=*), INTENT(in), OPTIONAL ::  cd6, cd7, cd8, cd9, cd10
2905      !!----------------------------------------------------------------------
2906      !
2907      nwarn = nwarn + 1 
2908      IF(lwp) THEN
2909         WRITE(numout,cform_war)
2910         IF( PRESENT(cd1 ) ) WRITE(numout,*) cd1
2911         IF( PRESENT(cd2 ) ) WRITE(numout,*) cd2
2912         IF( PRESENT(cd3 ) ) WRITE(numout,*) cd3
2913         IF( PRESENT(cd4 ) ) WRITE(numout,*) cd4
2914         IF( PRESENT(cd5 ) ) WRITE(numout,*) cd5
2915         IF( PRESENT(cd6 ) ) WRITE(numout,*) cd6
2916         IF( PRESENT(cd7 ) ) WRITE(numout,*) cd7
2917         IF( PRESENT(cd8 ) ) WRITE(numout,*) cd8
2918         IF( PRESENT(cd9 ) ) WRITE(numout,*) cd9
2919         IF( PRESENT(cd10) ) WRITE(numout,*) cd10
2920      ENDIF
2921      CALL FLUSH(numout)
2922      !
2923   END SUBROUTINE ctl_warn
2924
2925
2926   SUBROUTINE ctl_opn( knum, cdfile, cdstat, cdform, cdacce, klengh, kout, ldwp, karea )
2927      !!----------------------------------------------------------------------
2928      !!                  ***  ROUTINE ctl_opn  ***
2929      !!
2930      !! ** Purpose :   Open file and check if required file is available.
2931      !!
2932      !! ** Method  :   Fortan open
2933      !!----------------------------------------------------------------------
2934      INTEGER          , INTENT(  out) ::   knum      ! logical unit to open
2935      CHARACTER(len=*) , INTENT(in   ) ::   cdfile    ! file name to open
2936      CHARACTER(len=*) , INTENT(in   ) ::   cdstat    ! disposition specifier
2937      CHARACTER(len=*) , INTENT(in   ) ::   cdform    ! formatting specifier
2938      CHARACTER(len=*) , INTENT(in   ) ::   cdacce    ! access specifier
2939      INTEGER          , INTENT(in   ) ::   klengh    ! record length
2940      INTEGER          , INTENT(in   ) ::   kout      ! number of logical units for write
2941      LOGICAL          , INTENT(in   ) ::   ldwp      ! boolean term for print
2942      INTEGER, OPTIONAL, INTENT(in   ) ::   karea     ! proc number
2943      !!
2944      CHARACTER(len=80) ::   clfile
2945      INTEGER           ::   iost
2946      !!----------------------------------------------------------------------
2947
2948      ! adapt filename
2949      ! ----------------
2950      clfile = TRIM(cdfile)
2951      IF( PRESENT( karea ) ) THEN
2952         IF( karea > 1 )   WRITE(clfile, "(a,'_',i4.4)") TRIM(clfile), karea-1
2953      ENDIF
2954#if defined key_agrif
2955      IF( .NOT. Agrif_Root() )   clfile = TRIM(Agrif_CFixed())//'_'//TRIM(clfile)
2956      knum=Agrif_Get_Unit()
2957#else
2958      knum=get_unit()
2959#endif
2960
2961      iost=0
2962      IF( cdacce(1:6) == 'DIRECT' )  THEN
2963         OPEN( UNIT=knum, FILE=clfile, FORM=cdform, ACCESS=cdacce, STATUS=cdstat, RECL=klengh, ERR=100, IOSTAT=iost )
2964      ELSE
2965         OPEN( UNIT=knum, FILE=clfile, FORM=cdform, ACCESS=cdacce, STATUS=cdstat             , ERR=100, IOSTAT=iost )
2966      ENDIF
2967      IF( iost == 0 ) THEN
2968         IF(ldwp) THEN
2969            WRITE(kout,*) '     file   : ', clfile,' open ok'
2970            WRITE(kout,*) '     unit   = ', knum
2971            WRITE(kout,*) '     status = ', cdstat
2972            WRITE(kout,*) '     form   = ', cdform
2973            WRITE(kout,*) '     access = ', cdacce
2974            WRITE(kout,*)
2975         ENDIF
2976      ENDIF
2977100   CONTINUE
2978      IF( iost /= 0 ) THEN
2979         IF(ldwp) THEN
2980            WRITE(kout,*)
2981            WRITE(kout,*) ' ===>>>> : bad opening file: ', clfile
2982            WRITE(kout,*) ' =======   ===  '
2983            WRITE(kout,*) '           unit   = ', knum
2984            WRITE(kout,*) '           status = ', cdstat
2985            WRITE(kout,*) '           form   = ', cdform
2986            WRITE(kout,*) '           access = ', cdacce
2987            WRITE(kout,*) '           iostat = ', iost
2988            WRITE(kout,*) '           we stop. verify the file '
2989            WRITE(kout,*)
2990         ENDIF
2991         STOP 'ctl_opn bad opening'
2992      ENDIF
2993     
2994   END SUBROUTINE ctl_opn
2995
2996
2997   INTEGER FUNCTION get_unit()
2998      !!----------------------------------------------------------------------
2999      !!                  ***  FUNCTION  get_unit  ***
3000      !!
3001      !! ** Purpose :   return the index of an unused logical unit
3002      !!----------------------------------------------------------------------
3003      LOGICAL :: llopn 
3004      !!----------------------------------------------------------------------
3005      !
3006      get_unit = 15   ! choose a unit that is big enough then it is not already used in NEMO
3007      llopn = .TRUE.
3008      DO WHILE( (get_unit < 998) .AND. llopn )
3009         get_unit = get_unit + 1
3010         INQUIRE( unit = get_unit, opened = llopn )
3011      END DO
3012      IF( (get_unit == 999) .AND. llopn ) THEN
3013         CALL ctl_stop( 'get_unit: All logical units until 999 are used...' )
3014         get_unit = -1
3015      ENDIF
3016      !
3017   END FUNCTION get_unit
3018
3019   !!----------------------------------------------------------------------
3020END MODULE lib_mpp
Note: See TracBrowser for help on using the repository browser.