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 trunk/NEMO/OFF_SRC – NEMO

source: trunk/NEMO/OFF_SRC/lib_mpp.F90 @ 1152

Last change on this file since 1152 was 1152, checked in by rblod, 16 years ago

Convert cvs header to svn Id, step II

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 173.5 KB
Line 
1MODULE lib_mpp
2   !!======================================================================
3   !!                       ***  MODULE  lib_mpp  ***
4   !! Ocean numerics:  massively parallel processing librairy
5   !!=====================================================================
6#if   defined key_mpp_mpi   ||   defined key_mpp_shmem
7   !!----------------------------------------------------------------------
8   !!   'key_mpp_mpi'     OR      MPI massively parallel processing library
9   !!   'key_mpp_shmem'         SHMEM massively parallel processing library
10   !!----------------------------------------------------------------------
11   !!   mynode
12   !!   mpparent
13   !!   mppshmem
14   !!   mpp_lnk     : generic interface (defined in lbclnk) for :
15   !!                 mpp_lnk_2d, mpp_lnk_3d
16   !!   mpp_lnk_3d_gather :  Message passing manadgement for two 3D arrays
17   !!   mpp_lnk_e   : interface defined in lbclnk
18   !!   mpplnks
19   !!   mpprecv
20   !!   mppsend
21   !!   mppscatter
22   !!   mppgather
23   !!   mpp_isl    : generic inteface  for :
24   !!                mppisl_int , mppisl_a_int , mppisl_real, mppisl_a_real
25   !!   mpp_min    : generic interface for :
26   !!                mppmin_int , mppmin_a_int , mppmin_real, mppmin_a_real
27   !!   mpp_max    : generic interface for :
28   !!                mppmax_real, mppmax_a_real
29   !!   mpp_sum    : generic interface for :
30   !!                mppsum_int , mppsum_a_int , mppsum_real, mppsum_a_real
31   !!   mpp_minloc
32   !!   mpp_maxloc
33   !!   mppsync
34   !!   mppstop
35   !!   mppobc     : variant of mpp_lnk for open boundaries
36   !!   mpp_ini_north
37   !!   mpp_lbc_north
38   !!   mpp_lbc_north_e : variant of mpp_lbc_north for extra outer halo (nsolv=4)
39   !!----------------------------------------------------------------------
40   !! History :
41   !!        !  94 (M. Guyon, J. Escobar, M. Imbard)  Original code
42   !!        !  97  (A.M. Treguier)  SHMEM additions
43   !!        !  98  (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
44   !!   9.0  !  03  (J.-M. Molines, G. Madec)  F90, free form
45   !!        !  04  (R. Bourdalle Badie)  isend option in mpi
46   !!        !  05  (G. Madec, S. Masson)  npolj=5,6 F-point & ice cases
47   !!----------------------------------------------------------------------
48   !!  OPA 9.0 , LOCEAN-IPSL (2005)
49   !! $Id$
50   !! This software is governed by the CeCILL licence see modipsl/doc/NEMO_CeCILL.txt
51   !!---------------------------------------------------------------------
52   !! * Modules used
53   USE dom_oce                    ! ocean space and time domain
54   USE in_out_manager             ! I/O manager
55
56   IMPLICIT NONE
57
58   PRIVATE
59   PUBLIC  mynode, mpparent, mpp_isl, mpp_min, mpp_max, mpp_sum,  mpp_lbc_north
60   PUBLIC  mpp_lbc_north_e, mpp_minloc, mpp_maxloc, mpp_lnk_3d, mpp_lnk_2d, mpp_lnk_3d_gather, mpp_lnk_2d_e, mpplnks
61   PUBLIC  mpprecv, mppsend, mppscatter, mppgather, mppobc, mpp_ini_north, mppstop, mppsync
62
63   !! * Interfaces
64   !! define generic interface for these routine as they are called sometimes
65   !!        with scalar arguments instead of array arguments, which causes problems
66   !!        for the compilation on AIX system as well as NEC and SGI. Ok on COMPACQ
67
68   INTERFACE mpp_isl
69      MODULE PROCEDURE mppisl_a_int, mppisl_int, mppisl_a_real, mppisl_real
70   END INTERFACE
71   INTERFACE mpp_min
72      MODULE PROCEDURE mppmin_a_int, mppmin_int, mppmin_a_real, mppmin_real
73   END INTERFACE
74   INTERFACE mpp_max
75      MODULE PROCEDURE mppmax_a_real, mppmax_real
76   END INTERFACE
77   INTERFACE mpp_sum
78      MODULE PROCEDURE mppsum_a_int, mppsum_int, mppsum_a_real, mppsum_real
79   END INTERFACE
80   INTERFACE mpp_lbc_north
81      MODULE PROCEDURE mpp_lbc_north_3d, mpp_lbc_north_2d 
82   END INTERFACE
83  INTERFACE mpp_minloc
84     MODULE PROCEDURE mpp_minloc2d ,mpp_minloc3d
85  END INTERFACE
86  INTERFACE mpp_maxloc
87     MODULE PROCEDURE mpp_maxloc2d ,mpp_maxloc3d
88  END INTERFACE
89
90
91   !! * Share module variables
92   LOGICAL, PUBLIC, PARAMETER ::   lk_mpp = .TRUE.       !: mpp flag
93
94   !! The processor number is a required power of two : 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,...
95   INTEGER, PARAMETER ::   &
96      nprocmax = 2**10,    &  ! maximun dimension
97      ndim_mpp = jpnij        ! dimension for this simulation
98
99#if defined key_mpp_mpi
100   !! ========================= !!
101   !!  MPI  variable definition !!
102   !! ========================= !!
103!$AGRIF_DO_NOT_TREAT
104#  include <mpif.h>
105!$AGRIF_END_DO_NOT_TREAT
106
107   INTEGER ::   &
108      size,     &  ! number of process
109      rank         ! process number  [ 0 - size-1 ]
110
111   ! variables used in case of north fold condition in mpp_mpi with jpni > 1
112   INTEGER ::      &       !
113      ngrp_world,  &       ! group ID for the world processors
114      ngrp_north,  &       ! group ID for the northern processors (to be fold)
115      ncomm_north, &       ! communicator made by the processors belonging to ngrp_north
116      ndim_rank_north, &   ! number of 'sea' processor in the northern line (can be /= jpni !)
117      njmppmax             ! value of njmpp for the processors of the northern line
118   INTEGER ::      &       !
119      north_root           ! number (in the comm_world) of proc 0 in the northern comm
120   INTEGER, DIMENSION(:), ALLOCATABLE ::   &
121      nrank_north          ! dimension ndim_rank_north, number of the procs belonging to ncomm_north
122   CHARACTER (len=1) ::  &
123      c_mpi_send = 'S'     ! type od mpi send/recieve (S=standard, B=bsend, I=isend)
124   LOGICAL  ::           &
125      l_isend = .FALSE.    ! isend use indicator (T if c_mpi_send='I')
126
127
128#elif defined key_mpp_shmem
129   !! ========================= !!
130   !! SHMEM variable definition !!
131   !! ========================= !!
132#  include  <fpvm3.h>
133#  include <mpp/shmem.fh>
134
135   CHARACTER (len=80), PARAMETER ::   simfile    = 'pvm3_ndim'   ! file name
136   CHARACTER (len=47), PARAMETER ::   executable = 'opa'         ! executable name
137   CHARACTER, PARAMETER ::            opaall     = ""            ! group name (old def opaall*(*))
138
139   INTEGER, PARAMETER ::   & !! SHMEM control print
140      mynode_print   = 0,  &  ! flag for print, mynode   routine
141      mpprecv_print  = 0,  &  ! flag for print, mpprecv  routine
142      mppsend_print  = 0,  &  ! flag for print, mppsend  routine
143      mppsync_print  = 0,  &  ! flag for print, mppsync  routine
144      mppsum_print   = 0,  &  ! flag for print, mpp_sum  routine
145      mppisl_print   = 0,  &  ! flag for print, mpp_isl  routine
146      mppmin_print   = 0,  &  ! flag for print, mpp_min  routine
147      mppmax_print   = 0,  &  ! flag for print, mpp_max  routine
148      mpparent_print = 0      ! flag for print, mpparent routine
149
150   INTEGER, PARAMETER ::   & !! Variable definition
151      jpvmint = 21            ! ???
152
153   INTEGER, PARAMETER ::   & !! Maximum  dimension of array to sum on the processors
154      jpmsec   = 50000,    &  ! ???
155      jpmpplat =    30,    &  ! ???
156      jpmppsum = MAX( jpisl*jpisl, jpmpplat*jpk, jpmsec )   ! ???
157
158   INTEGER ::   &
159      npvm_ipas ,  &  ! pvm initialization flag
160      npvm_mytid,  &  ! pvm tid
161      npvm_me   ,  &  ! node number [ 0 - nproc-1 ]
162      npvm_nproc,  &  ! real number of nodes
163      npvm_inum       ! ???
164   INTEGER, DIMENSION(0:nprocmax-1) ::   &
165      npvm_tids       ! tids array [ 0 - nproc-1 ]
166
167   INTEGER ::   &
168      nt3d_ipas ,  &  ! pvm initialization flag
169      nt3d_mytid,  &  ! pvm tid
170      nt3d_me   ,  &  ! node number [ 0 - nproc-1 ]
171      nt3d_nproc      ! real number of nodes
172   INTEGER, DIMENSION(0:nprocmax-1) ::   &
173      nt3d_tids       ! tids array [ 0 - nproc-1 ]
174
175   !! real sum reduction
176   INTEGER, DIMENSION(SHMEM_REDUCE_SYNC_SIZE) ::   &
177       nrs1sync_shmem,   &  !
178       nrs2sync_shmem
179   REAL(wp), DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
180       wrs1wrk_shmem,    &  !
181       wrs2wrk_shmem        !
182   REAL(wp), DIMENSION(jpmppsum) ::   &
183       wrstab_shmem         !
184
185   !! minimum and maximum reduction
186   INTEGER, DIMENSION(SHMEM_REDUCE_SYNC_SIZE) ::   &
187       ni1sync_shmem,    &  !
188       ni2sync_shmem        !
189   REAL(wp), DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
190       wi1wrk_shmem,     &  !
191       wi2wrk_shmem
192   REAL(wp), DIMENSION(jpmppsum) ::   &
193       wintab_shmem,     &  !
194       wi1tab_shmem,     &  !
195       wi2tab_shmem         !
196       
197       !! value not equal zero for barotropic stream function around islands
198   INTEGER, DIMENSION(SHMEM_REDUCE_SYNC_SIZE) ::   &
199       ni11sync_shmem,   &  !
200       ni12sync_shmem,   &  !
201       ni21sync_shmem,   &  !
202       ni22sync_shmem       !
203   REAL(wp), DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
204       wi11wrk_shmem,    &  !
205       wi12wrk_shmem,    &  !
206       wi21wrk_shmem,    &  !
207       wi22wrk_shmem        !
208   REAL(wp), DIMENSION(jpmppsum) ::   &
209       wiltab_shmem ,    &  !
210       wi11tab_shmem,    &  !
211       wi12tab_shmem,    &  !
212       wi21tab_shmem,    &  !
213       wi22tab_shmem
214
215   INTEGER, DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
216       ni11wrk_shmem,    &  !
217       ni12wrk_shmem,    &  !
218       ni21wrk_shmem,    &  !
219       ni22wrk_shmem        !
220   INTEGER, DIMENSION(jpmppsum) ::   &
221       niitab_shmem ,    &  !
222       ni11tab_shmem,    &  !
223       ni12tab_shmem        !
224   INTEGER, DIMENSION(SHMEM_REDUCE_SYNC_SIZE) ::   &
225       nis1sync_shmem,   &  !
226       nis2sync_shmem       !
227   INTEGER, DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
228       nis1wrk_shmem,    &  !
229       nis2wrk_shmem        !
230   INTEGER, DIMENSION(jpmppsum) ::   &
231       nistab_shmem
232
233   !! integer sum reduction
234   INTEGER, DIMENSION(SHMEM_REDUCE_SYNC_SIZE) ::   &
235       nil1sync_shmem,   &  !
236       nil2sync_shmem       !
237   INTEGER, DIMENSION( MAX( SHMEM_REDUCE_MIN_WRKDATA_SIZE, jpmppsum/2+1 ) ) ::   &
238       nil1wrk_shmem,    &  !
239       nil2wrk_shmem        !
240   INTEGER, DIMENSION(jpmppsum) ::   &
241       niltab_shmem
242#endif
243
244   REAL(wp), DIMENSION(jpi,jprecj,jpk,2,2) ::   &
245       t4ns, t4sn  ! 3d message passing arrays north-south & south-north
246   REAL(wp), DIMENSION(jpj,jpreci,jpk,2,2) ::   &
247       t4ew, t4we  ! 3d message passing arrays east-west & west-east
248   REAL(wp), DIMENSION(jpi,jprecj,jpk,2,2) ::   &
249       t4p1, t4p2  ! 3d message passing arrays north fold
250   REAL(wp), DIMENSION(jpi,jprecj,jpk,2) ::   &
251       t3ns, t3sn  ! 3d message passing arrays north-south & south-north
252   REAL(wp), DIMENSION(jpj,jpreci,jpk,2) ::   &
253       t3ew, t3we  ! 3d message passing arrays east-west & west-east
254   REAL(wp), DIMENSION(jpi,jprecj,jpk,2) ::   &
255       t3p1, t3p2  ! 3d message passing arrays north fold
256   REAL(wp), DIMENSION(jpi,jprecj,2) ::   &
257       t2ns, t2sn  ! 2d message passing arrays north-south & south-north
258   REAL(wp), DIMENSION(jpj,jpreci,2) ::   &
259       t2ew, t2we  ! 2d message passing arrays east-west & west-east
260   REAL(wp), DIMENSION(jpi,jprecj,2) ::   &
261       t2p1, t2p2  ! 2d message passing arrays north fold
262   REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,jprecj+jpr2dj,2) ::   &
263       tr2ns, tr2sn  ! 2d message passing arrays north-south & south-north including extra outer halo
264   REAL(wp), DIMENSION(1-jpr2dj:jpj+jpr2dj,jpreci+jpr2di,2) ::   &
265       tr2ew, tr2we  ! 2d message passing arrays east-west & west-east including extra outer halo
266   !!----------------------------------------------------------------------
267   !!  OPA 9.0 , LOCEAN-IPSL (2005)
268   !! $Id$
269   !! This software is governed by the CeCILL licence see modipsl/doc/NEMO_CeCILL.txt
270   !!---------------------------------------------------------------------
271
272CONTAINS
273
274   FUNCTION mynode()
275      !!----------------------------------------------------------------------
276      !!                  ***  routine mynode  ***
277      !!                   
278      !! ** Purpose :   Find processor unit
279      !!
280      !!----------------------------------------------------------------------
281#if defined key_mpp_mpi
282      !! * Local variables   (MPI version)
283      INTEGER ::   mynode, ierr
284      NAMELIST/nammpp/ c_mpi_send
285      !!----------------------------------------------------------------------
286
287      WRITE(numout,*)
288      WRITE(numout,*) 'mynode : mpi initialisation'
289      WRITE(numout,*) '~~~~~~ '
290      WRITE(numout,*)
291
292      ! Namelist namrun : parameters of the run
293      REWIND( numnam )
294      READ  ( numnam, nammpp )
295
296      WRITE(numout,*) '        Namelist nammpp'
297      WRITE(numout,*) '           mpi send type            c_mpi_send = ', c_mpi_send
298
299#if defined key_agrif
300      IF( Agrif_Root() ) THEN
301#endif
302         SELECT CASE ( c_mpi_send )
303         CASE ( 'S' )                ! Standard mpi send (blocking)
304            WRITE(numout,*) '           Standard blocking mpi send (send)'
305            CALL mpi_init( ierr )
306         CASE ( 'B' )                ! Buffer mpi send (blocking)
307            WRITE(numout,*) '           Buffer blocking mpi send (bsend)'
308            CALL mpi_init_opa( ierr )
309         CASE ( 'I' )                ! Immediate mpi send (non-blocking send)
310            WRITE(numout,*) '           Immediate non-blocking send (isend)'
311            l_isend = .TRUE.
312            CALL mpi_init( ierr )
313         CASE DEFAULT
314            WRITE(ctmp1,*) '           bad value for c_mpi_send = ', c_mpi_send
315            CALL ctl_stop( ctmp1 )
316         END SELECT
317
318#if defined key_agrif
319      ENDIF
320#endif
321
322      CALL mpi_comm_rank( mpi_comm_world, rank, ierr )
323      CALL mpi_comm_size( mpi_comm_world, size, ierr )
324      mynode = rank
325#else
326      !! * Local variables   (SHMEM version)
327      INTEGER ::   mynode
328      INTEGER ::   &
329           imypid, imyhost, ji, info, iparent_tid
330      !!----------------------------------------------------------------------
331
332      IF( npvm_ipas /= nprocmax ) THEN
333         !         ---   first passage in mynode
334         !         -------------
335         !         enroll in pvm
336         !         -------------
337         CALL pvmfmytid( npvm_mytid )
338         IF( mynode_print /= 0 ) THEN
339            WRITE(numout,*) 'mynode, npvm_ipas =', npvm_ipas, ' nprocmax=', nprocmax
340            WRITE(numout,*) 'mynode, npvm_mytid=', npvm_mytid, ' after pvmfmytid'
341         ENDIF
342
343         !         ---------------------------------------------------------------
344         !         find out IF i am parent or child spawned processes have parents
345         !         ---------------------------------------------------------------
346         CALL mpparent( iparent_tid )
347         IF( mynode_print /= 0 ) THEN
348            WRITE(numout,*) 'mynode, npvm_mytid=', npvm_mytid,   &
349               &            ' after mpparent, npvm_tids(0) = ',   &
350               &            npvm_tids(0), ' iparent_tid=', iparent_tid
351         ENDIF
352         IF( iparent_tid < 0 )  THEN
353            WRITE(numout,*) 'mynode, npvm_mytid=', npvm_mytid,   &
354               &            ' after mpparent, npvm_tids(0) = ',   &
355               &            npvm_tids(0), ' iparent_tid=', iparent_tid
356            npvm_tids(0) = npvm_mytid
357            npvm_me = 0
358            IF( ndim_mpp > nprocmax ) THEN
359               WRITE(ctmp1,*) 'npvm_mytid=', npvm_mytid, ' too great'
360               CALL ctl_stop( ctmp1 )
361
362            ELSE
363               npvm_nproc = ndim_mpp
364            ENDIF
365
366            ! -------------------------
367            ! start up copies of myself
368            ! -------------------------
369            IF( npvm_nproc > 1 ) THEN
370               DO ji = 1, npvm_nproc-1
371                  npvm_tids(ji) = nt3d_tids(ji)
372               END DO
373               info=npvm_nproc-1
374 
375               IF( mynode_print /= 0 ) THEN
376                  WRITE(numout,*) 'mynode, npvm_mytid=',npvm_mytid,   &
377                     &            ' maitre=',executable,' info=', info   &
378                     &            ,' npvm_nproc=',npvm_nproc
379                  WRITE(numout,*) 'mynode, npvm_mytid=',npvm_mytid,   &
380                     &            ' npvm_tids ',(npvm_tids(ji),ji=0,npvm_nproc-1)
381               ENDIF
382
383               ! ---------------------------
384               ! multicast tids array to children
385               ! ---------------------------
386               CALL pvmfinitsend( pvmdefault, info )
387               CALL pvmfpack ( jpvmint, npvm_nproc, 1         , 1, info )
388               CALL pvmfpack ( jpvmint, npvm_tids , npvm_nproc, 1, info )
389               CALL pvmfmcast( npvm_nproc-1, npvm_tids(1), 10, info )
390            ENDIF
391         ELSE
392
393            ! ---------------------------------
394            ! receive the tids array and set me
395            ! ---------------------------------
396            IF( mynode_print /= 0 )   WRITE(numout,*) 'mynode, npvm_mytid=',npvm_mytid, ' pvmfrecv'
397            CALL pvmfrecv( iparent_tid, 10, info )
398            IF( mynode_print /= 0 )   WRITE(numout,*) 'mynode, npvm_mytid=',npvm_mytid, " fin pvmfrecv"
399            CALL pvmfunpack( jpvmint, npvm_nproc, 1         , 1, info )
400            CALL pvmfunpack( jpvmint, npvm_tids , npvm_nproc, 1, info )
401            IF( mynode_print /= 0 ) THEN
402               WRITE(numout,*) 'mynode, npvm_mytid=',npvm_mytid,   &
403                  &            ' esclave=', executable,' info=', info,' npvm_nproc=',npvm_nproc
404               WRITE(numout,*) 'mynode, npvm_mytid=', npvm_mytid,   &
405                  &            'npvm_tids', ( npvm_tids(ji), ji = 0, npvm_nproc-1 )
406            ENDIF
407            DO ji = 0, npvm_nproc-1
408               IF( npvm_mytid == npvm_tids(ji) ) npvm_me = ji
409            END DO
410         ENDIF
411
412         ! ------------------------------------------------------------
413         ! all nproc tasks are equal now
414         ! and can address each other by tids(0) thru tids(nproc-1)
415         ! for each process me => process number [0-(nproc-1)]
416         ! ------------------------------------------------------------
417         CALL pvmfjoingroup ( "bidon", info )
418         CALL pvmfbarrier   ( "bidon", npvm_nproc, info )
419         DO ji = 0, npvm_nproc-1
420            IF( ji == npvm_me ) THEN
421               CALL pvmfjoingroup ( opaall, npvm_inum )
422               IF( npvm_inum /= npvm_me )   WRITE(numout,*) 'mynode not arrived in the good order for opaall'
423            ENDIF
424            CALL pvmfbarrier( "bidon", npvm_nproc, info )
425         END DO
426         CALL pvmfbarrier( opaall, npvm_nproc, info )
427 
428      ELSE
429         ! ---   other passage in mynode
430      ENDIF
431 
432      npvm_ipas = nprocmax
433      mynode    = npvm_me
434      imypid    = npvm_mytid
435      imyhost   = npvm_tids(0)
436      IF( mynode_print /= 0 ) THEN
437         WRITE(numout,*)'mynode: npvm_mytid=', npvm_mytid, ' npvm_me=', npvm_me,   &
438            &           ' npvm_nproc=', npvm_nproc , ' npvm_ipas=', npvm_ipas
439      ENDIF
440#endif
441   END FUNCTION mynode
442
443
444   SUBROUTINE mpparent( kparent_tid )
445      !!----------------------------------------------------------------------
446      !!                  ***  routine mpparent  ***
447      !!
448      !! ** Purpose :   use an pvmfparent routine for T3E (key_mpp_shmem)
449      !!              or  only return -1 (key_mpp_mpi)
450      !!----------------------------------------------------------------------
451      !! * Arguments
452      INTEGER, INTENT(inout) ::   kparent_tid      ! ???
453 
454#if defined key_mpp_mpi
455      ! MPI version : retour -1
456
457      kparent_tid = -1
458
459#else
460      !! * Local variables   (SHMEN onto T3E version)
461      INTEGER ::   &
462           it3d_my_pe, LEADZ, ji, info
463 
464      CALL pvmfmytid( nt3d_mytid )
465      CALL pvmfgetpe( nt3d_mytid, it3d_my_pe )
466      IF( mpparent_print /= 0 ) THEN
467         WRITE(numout,*) 'mpparent: nt3d_mytid= ', nt3d_mytid ,' it3d_my_pe=',it3d_my_pe
468      ENDIF
469      IF( it3d_my_pe == 0 ) THEN
470         !-----------------------------------------------------------------!
471         !     process = 0 => receive other tids                           !
472         !-----------------------------------------------------------------!
473         kparent_tid = -1
474         IF(mpparent_print /= 0 ) THEN
475            WRITE(numout,*) 'mpparent, nt3d_mytid=',nt3d_mytid ,' kparent_tid=',kparent_tid
476         ENDIF
477         !          --- END receive dimension ---
478         IF( ndim_mpp > nprocmax ) THEN
479            WRITE(ctmp1,*) 'mytid=',nt3d_mytid,' too great'
480            CALL ctl_stop( ctmp1 )
481         ELSE
482            nt3d_nproc =  ndim_mpp
483         ENDIF
484         IF( mpparent_print /= 0 ) THEN
485            WRITE(numout,*) 'mpparent, nt3d_mytid=', nt3d_mytid , ' nt3d_nproc=', nt3d_nproc
486         ENDIF
487         !-------- receive tids from others process --------
488         DO ji = 1, nt3d_nproc-1
489            CALL pvmfrecv( ji , 100, info )
490            CALL pvmfunpack( jpvmint, nt3d_tids(ji), 1, 1, info )
491            IF( mpparent_print /= 0 ) THEN
492               WRITE(numout,*) 'mpparent, nt3d_mytid=', nt3d_mytid , ' receive=', nt3d_tids(ji), ' from = ', ji
493            ENDIF
494         END DO
495         nt3d_tids(0) = nt3d_mytid
496         IF( mpparent_print /= 0 ) THEN
497            WRITE(numout,*) 'mpparent, nt3d_mytid=', nt3d_mytid , ' nt3d_tids(ji) =', (nt3d_tids(ji),   &
498                 ji = 0, nt3d_nproc-1 )
499            WRITE(numout,*) 'mpparent, nt3d_mytid=', nt3d_mytid , ' kparent_tid=', kparent_tid
500         ENDIF
501
502      ELSE
503         !!----------------------------------------------------------------!
504         !     process <> 0 => send  other tids                            !
505         !!----------------------------------------------------------------!
506         kparent_tid = 0
507         CALL pvmfinitsend( pvmdataraw, info )
508         CALL pvmfpack( jpvmint, nt3d_mytid, 1, 1, info )
509         CALL pvmfsend( kparent_tid, 100, info )
510      ENDIF
511#endif
512
513   END SUBROUTINE mpparent
514
515#if defined key_mpp_shmem
516
517   SUBROUTINE mppshmem
518      !!----------------------------------------------------------------------
519      !!                  ***  routine mppshmem  ***
520      !!
521      !! ** Purpose :   SHMEM ROUTINE
522      !!
523      !!----------------------------------------------------------------------
524      nrs1sync_shmem = SHMEM_SYNC_VALUE
525      nrs2sync_shmem = SHMEM_SYNC_VALUE
526      nis1sync_shmem = SHMEM_SYNC_VALUE
527      nis2sync_shmem = SHMEM_SYNC_VALUE
528      nil1sync_shmem = SHMEM_SYNC_VALUE
529      nil2sync_shmem = SHMEM_SYNC_VALUE
530      ni11sync_shmem = SHMEM_SYNC_VALUE
531      ni12sync_shmem = SHMEM_SYNC_VALUE
532      ni21sync_shmem = SHMEM_SYNC_VALUE
533      ni22sync_shmem = SHMEM_SYNC_VALUE
534      CALL barrier()
535 
536   END SUBROUTINE mppshmem
537
538#endif
539
540   SUBROUTINE mpp_lnk_3d( ptab, cd_type, psgn, cd_mpp )
541      !!----------------------------------------------------------------------
542      !!                  ***  routine mpp_lnk_3d  ***
543      !!
544      !! ** Purpose :   Message passing manadgement
545      !!
546      !! ** Method  :   Use mppsend and mpprecv function for passing mask
547      !!      between processors following neighboring subdomains.
548      !!            domain parameters
549      !!                    nlci   : first dimension of the local subdomain
550      !!                    nlcj   : second dimension of the local subdomain
551      !!                    nbondi : mark for "east-west local boundary"
552      !!                    nbondj : mark for "north-south local boundary"
553      !!                    noea   : number for local neighboring processors
554      !!                    nowe   : number for local neighboring processors
555      !!                    noso   : number for local neighboring processors
556      !!                    nono   : number for local neighboring processors
557      !!
558      !! ** Action  :   ptab with update value at its periphery
559      !!
560      !!----------------------------------------------------------------------
561      !! * Arguments
562      CHARACTER(len=1) , INTENT( in ) ::   &
563         cd_type       ! define the nature of ptab array grid-points
564         !             ! = T , U , V , F , W points
565         !             ! = S : T-point, north fold treatment ???
566         !             ! = G : F-point, north fold treatment ???
567      REAL(wp), INTENT( in ) ::   &
568         psgn          ! control of the sign change
569         !             !   = -1. , the sign is changed if north fold boundary
570         !             !   =  1. , the sign is kept  if north fold boundary
571      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT( inout ) ::   &
572         ptab          ! 3D array on which the boundary condition is applied
573      CHARACTER(len=3), INTENT( in ), OPTIONAL ::    &
574         cd_mpp        ! fill the overlap area only
575
576      !! * Local variables
577      INTEGER ::   ji, jk, jl   ! dummy loop indices
578      INTEGER ::   imigr, iihom, ijhom, iloc, ijt, iju   ! temporary integers
579      INTEGER ::   ml_req1, ml_req2, ml_err     ! for key_mpi_isend
580      INTEGER ::   ml_stat(MPI_STATUS_SIZE)     ! for key_mpi_isend
581      !!----------------------------------------------------------------------
582
583      ! 1. standard boundary treatment
584      ! ------------------------------
585
586      IF( PRESENT( cd_mpp ) ) THEN
587         ! only fill extra allows with 1.
588         ptab(     1:nlci, nlcj+1:jpj, :) = 1.e0
589         ptab(nlci+1:jpi ,       :   , :) = 1.e0
590      ELSE     
591
592         !                                        ! East-West boundaries
593         !                                        ! ====================
594         IF( nbondi == 2 .AND.   &      ! Cyclic east-west
595            &   (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
596            ptab( 1 ,:,:) = ptab(jpim1,:,:)
597            ptab(jpi,:,:) = ptab(  2  ,:,:)
598
599         ELSE                           ! closed
600            SELECT CASE ( cd_type )
601            CASE ( 'T', 'U', 'V', 'W' )
602               ptab(     1       :jpreci,:,:) = 0.e0
603               ptab(nlci-jpreci+1:jpi   ,:,:) = 0.e0
604            CASE ( 'F' )
605               ptab(nlci-jpreci+1:jpi   ,:,:) = 0.e0
606            END SELECT
607         ENDIF
608
609         !                                        ! North-South boundaries
610         !                                        ! ======================
611         SELECT CASE ( cd_type )
612         CASE ( 'T', 'U', 'V', 'W' )
613            ptab(:,     1       :jprecj,:) = 0.e0
614            ptab(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
615         CASE ( 'F' )
616            ptab(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
617         END SELECT
618     
619      ENDIF
620
621      ! 2. East and west directions exchange
622      ! ------------------------------------
623
624      ! 2.1 Read Dirichlet lateral conditions
625
626      SELECT CASE ( nbondi )
627      CASE ( -1, 0, 1 )    ! all exept 2
628         iihom = nlci-nreci
629         DO jl = 1, jpreci
630            t3ew(:,jl,:,1) = ptab(jpreci+jl,:,:)
631            t3we(:,jl,:,1) = ptab(iihom +jl,:,:)
632         END DO
633      END SELECT
634
635      ! 2.2 Migrations
636
637#if defined key_mpp_shmem
638      !! * SHMEM version
639
640      imigr = jpreci * jpj * jpk
641
642      SELECT CASE ( nbondi )
643      CASE ( -1 )
644         CALL shmem_put( t3we(1,1,1,2), t3we(1,1,1,1), imigr, noea )
645      CASE ( 0 )
646         CALL shmem_put( t3ew(1,1,1,2), t3ew(1,1,1,1), imigr, nowe )
647         CALL shmem_put( t3we(1,1,1,2), t3we(1,1,1,1), imigr, noea )
648      CASE ( 1 )
649         CALL shmem_put( t3ew(1,1,1,2), t3ew(1,1,1,1), imigr, nowe )
650      END SELECT
651
652      CALL barrier()
653      CALL shmem_udcflush()
654
655#elif defined key_mpp_mpi
656      !! * Local variables   (MPI version)
657
658      imigr = jpreci * jpj * jpk
659
660      SELECT CASE ( nbondi ) 
661      CASE ( -1 )
662         CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req1 )
663         CALL mpprecv( 1, t3ew(1,1,1,2), imigr )
664         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
665      CASE ( 0 )
666         CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
667         CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req2 )
668         CALL mpprecv( 1, t3ew(1,1,1,2), imigr )
669         CALL mpprecv( 2, t3we(1,1,1,2), imigr )
670         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
671         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
672      CASE ( 1 )
673         CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
674         CALL mpprecv( 2, t3we(1,1,1,2), imigr )
675         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
676      END SELECT
677#endif
678
679      ! 2.3 Write Dirichlet lateral conditions
680
681      iihom = nlci-jpreci
682
683      SELECT CASE ( nbondi )
684      CASE ( -1 )
685         DO jl = 1, jpreci
686            ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
687         END DO
688      CASE ( 0 ) 
689         DO jl = 1, jpreci
690            ptab(jl      ,:,:) = t3we(:,jl,:,2)
691            ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
692         END DO
693      CASE ( 1 )
694         DO jl = 1, jpreci
695            ptab(jl      ,:,:) = t3we(:,jl,:,2)
696         END DO
697      END SELECT
698
699
700      ! 3. North and south directions
701      ! -----------------------------
702
703      ! 3.1 Read Dirichlet lateral conditions
704
705      IF( nbondj /= 2 ) THEN
706         ijhom = nlcj-nrecj
707         DO jl = 1, jprecj
708            t3sn(:,jl,:,1) = ptab(:,ijhom +jl,:)
709            t3ns(:,jl,:,1) = ptab(:,jprecj+jl,:)
710         END DO
711      ENDIF
712
713      ! 3.2 Migrations
714
715#if defined key_mpp_shmem
716      !! * SHMEM version
717
718      imigr = jprecj * jpi * jpk
719
720      SELECT CASE ( nbondj )
721      CASE ( -1 )
722         CALL shmem_put( t3sn(1,1,1,2), t3sn(1,1,1,1), imigr, nono )
723      CASE ( 0 )
724         CALL shmem_put( t3ns(1,1,1,2), t3ns(1,1,1,1), imigr, noso )
725         CALL shmem_put( t3sn(1,1,1,2), t3sn(1,1,1,1), imigr, nono )
726      CASE ( 1 )
727         CALL shmem_put( t3ns(1,1,1,2), t3ns(1,1,1,1), imigr, noso )
728      END SELECT
729
730      CALL barrier()
731      CALL shmem_udcflush()
732
733#elif defined key_mpp_mpi
734      !! * Local variables   (MPI version)
735 
736      imigr=jprecj*jpi*jpk
737
738      SELECT CASE ( nbondj )     
739      CASE ( -1 )
740         CALL mppsend( 4, t3sn(1,1,1,1), imigr, nono, ml_req1 )
741         CALL mpprecv( 3, t3ns(1,1,1,2), imigr )
742         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
743      CASE ( 0 )
744         CALL mppsend( 3, t3ns(1,1,1,1), imigr, noso, ml_req1 )
745         CALL mppsend( 4, t3sn(1,1,1,1), imigr, nono, ml_req2 )
746         CALL mpprecv( 3, t3ns(1,1,1,2), imigr )
747         CALL mpprecv( 4, t3sn(1,1,1,2), imigr )
748         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
749         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
750      CASE ( 1 ) 
751         CALL mppsend( 3, t3ns(1,1,1,1), imigr, noso, ml_req1 )
752         CALL mpprecv( 4, t3sn(1,1,1,2), imigr )
753         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
754      END SELECT
755
756#endif
757
758      ! 3.3 Write Dirichlet lateral conditions
759
760      ijhom = nlcj-jprecj
761
762      SELECT CASE ( nbondj )
763      CASE ( -1 )
764         DO jl = 1, jprecj
765            ptab(:,ijhom+jl,:) = t3ns(:,jl,:,2)
766         END DO
767      CASE ( 0 ) 
768         DO jl = 1, jprecj
769            ptab(:,jl      ,:) = t3sn(:,jl,:,2)
770            ptab(:,ijhom+jl,:) = t3ns(:,jl,:,2)
771         END DO
772      CASE ( 1 )
773         DO jl = 1, jprecj
774            ptab(:,jl,:) = t3sn(:,jl,:,2)
775         END DO
776      END SELECT
777
778
779      ! 4. north fold treatment
780      ! -----------------------
781
782      IF (PRESENT(cd_mpp)) THEN
783         ! No north fold treatment (it is assumed to be already OK)
784     
785      ELSE     
786
787      ! 4.1 treatment without exchange (jpni odd)
788      !     T-point pivot 
789
790      SELECT CASE ( jpni )
791
792      CASE ( 1 )  ! only one proc along I, no mpp exchange
793
794         SELECT CASE ( npolj )
795 
796         CASE ( 3 , 4 )    ! T pivot
797            iloc = jpiglo - 2 * ( nimpp - 1 )
798
799            SELECT CASE ( cd_type )
800
801            CASE ( 'T' , 'S', 'W' )
802               DO jk = 1, jpk
803                  DO ji = 2, nlci
804                     ijt=iloc-ji+2
805                     ptab(ji,nlcj,jk) = psgn * ptab(ijt,nlcj-2,jk)
806                  END DO
807                  DO ji = nlci/2+1, nlci
808                     ijt=iloc-ji+2
809                     ptab(ji,nlcj-1,jk) = psgn * ptab(ijt,nlcj-1,jk)
810                  END DO
811               END DO
812         
813            CASE ( 'U' )
814               DO jk = 1, jpk
815                  DO ji = 1, nlci-1
816                     iju=iloc-ji+1
817                     ptab(ji,nlcj,jk) = psgn * ptab(iju,nlcj-2,jk)
818                  END DO
819                  DO ji = nlci/2, nlci-1
820                     iju=iloc-ji+1
821                     ptab(ji,nlcj-1,jk) = psgn * ptab(iju,nlcj-1,jk)
822                  END DO
823               END DO
824
825            CASE ( 'V' )
826               DO jk = 1, jpk
827                  DO ji = 2, nlci
828                     ijt=iloc-ji+2
829                     ptab(ji,nlcj-1,jk) = psgn * ptab(ijt,nlcj-2,jk)
830                     ptab(ji,nlcj  ,jk) = psgn * ptab(ijt,nlcj-3,jk)
831                  END DO
832               END DO
833
834            CASE ( 'F', 'G' )
835               DO jk = 1, jpk
836                  DO ji = 1, nlci-1
837                     iju=iloc-ji+1
838                     ptab(ji,nlcj-1,jk) = psgn * ptab(iju,nlcj-2,jk)
839                     ptab(ji,nlcj  ,jk) = psgn * ptab(iju,nlcj-3,jk)
840                  END DO
841               END DO
842 
843          END SELECT
844       
845         CASE ( 5 , 6 ) ! F pivot
846            iloc=jpiglo-2*(nimpp-1)
847 
848            SELECT CASE ( cd_type )
849
850            CASE ( 'T' , 'S', 'W' )
851               DO jk = 1, jpk
852                  DO ji = 1, nlci
853                     ijt=iloc-ji+1
854                     ptab(ji,nlcj,jk) = psgn * ptab(ijt,nlcj-1,jk)
855                  END DO
856               END DO
857
858            CASE ( 'U' )
859               DO jk = 1, jpk
860                  DO ji = 1, nlci-1
861                     iju=iloc-ji
862                     ptab(ji,nlcj,jk) = psgn * ptab(iju,nlcj-1,jk)
863                  END DO
864               END DO
865
866            CASE ( 'V' )
867               DO jk = 1, jpk
868                  DO ji = 1, nlci
869                     ijt=iloc-ji+1
870                     ptab(ji,nlcj  ,jk) = psgn * ptab(ijt,nlcj-2,jk)
871                  END DO
872                  DO ji = nlci/2+1, nlci
873                     ijt=iloc-ji+1
874                     ptab(ji,nlcj-1,jk) = psgn * ptab(ijt,nlcj-1,jk)
875                  END DO
876               END DO
877
878            CASE ( 'F', 'G' )
879               DO jk = 1, jpk
880                  DO ji = 1, nlci-1
881                     iju=iloc-ji
882                     ptab(ji,nlcj,jk) = psgn * ptab(iju,nlcj-2,jk)
883                  END DO
884                  DO ji = nlci/2+1, nlci-1
885                     iju=iloc-ji
886                     ptab(ji,nlcj-1,jk) = psgn * ptab(iju,nlcj-1,jk)
887                  END DO
888               END DO
889            END SELECT  ! cd_type
890
891         END SELECT     !  npolj
892 
893      CASE DEFAULT ! more than 1 proc along I
894         IF ( npolj /= 0 ) CALL mpp_lbc_north (ptab, cd_type, psgn)  ! only for northern procs.
895
896      END SELECT ! jpni
897
898      ENDIF
899     
900
901      ! 5. East and west directions exchange
902      ! ------------------------------------
903
904      SELECT CASE ( npolj )
905
906      CASE ( 3, 4, 5, 6 )
907
908         ! 5.1 Read Dirichlet lateral conditions
909
910         SELECT CASE ( nbondi )
911
912         CASE ( -1, 0, 1 )
913            iihom = nlci-nreci
914            DO jl = 1, jpreci
915               t3ew(:,jl,:,1) = ptab(jpreci+jl,:,:)
916               t3we(:,jl,:,1) = ptab(iihom +jl,:,:)
917            END DO
918
919         END SELECT
920
921         ! 5.2 Migrations
922
923#if defined key_mpp_shmem
924         !! SHMEM version
925
926         imigr = jpreci * jpj * jpk
927
928         SELECT CASE ( nbondi )
929         CASE ( -1 )
930            CALL shmem_put( t3we(1,1,1,2), t3we(1,1,1,1), imigr, noea )
931         CASE ( 0 )
932            CALL shmem_put( t3ew(1,1,1,2), t3ew(1,1,1,1), imigr, nowe )
933            CALL shmem_put( t3we(1,1,1,2), t3we(1,1,1,1), imigr, noea )
934         CASE ( 1 )
935            CALL shmem_put( t3ew(1,1,1,2), t3ew(1,1,1,1), imigr, nowe )
936         END SELECT
937
938         CALL barrier()
939         CALL shmem_udcflush()
940
941#elif defined key_mpp_mpi
942         !! MPI version
943
944         imigr=jpreci*jpj*jpk
945 
946         SELECT CASE ( nbondi )
947         CASE ( -1 )
948            CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req1 )
949            CALL mpprecv( 1, t3ew(1,1,1,2), imigr )
950            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
951         CASE ( 0 )
952            CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
953            CALL mppsend( 2, t3we(1,1,1,1), imigr, noea, ml_req2 )
954            CALL mpprecv( 1, t3ew(1,1,1,2), imigr )
955            CALL mpprecv( 2, t3we(1,1,1,2), imigr )
956            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
957            IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
958         CASE ( 1 )
959            CALL mppsend( 1, t3ew(1,1,1,1), imigr, nowe, ml_req1 )
960            CALL mpprecv( 2, t3we(1,1,1,2), imigr )
961            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
962         END SELECT
963#endif
964
965         ! 5.3 Write Dirichlet lateral conditions
966
967         iihom = nlci-jpreci
968
969         SELECT CASE ( nbondi)
970         CASE ( -1 )
971            DO jl = 1, jpreci
972               ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
973            END DO
974         CASE ( 0 ) 
975            DO jl = 1, jpreci
976               ptab(jl      ,:,:) = t3we(:,jl,:,2)
977               ptab(iihom+jl,:,:) = t3ew(:,jl,:,2)
978            END DO
979         CASE ( 1 )
980            DO jl = 1, jpreci
981               ptab(jl      ,:,:) = t3we(:,jl,:,2)
982            END DO
983         END SELECT
984
985      END SELECT    ! npolj
986
987   END SUBROUTINE mpp_lnk_3d
988
989
990   SUBROUTINE mpp_lnk_2d( pt2d, cd_type, psgn, cd_mpp )
991      !!----------------------------------------------------------------------
992      !!                  ***  routine mpp_lnk_2d  ***
993      !!                 
994      !! ** Purpose :   Message passing manadgement for 2d array
995      !!
996      !! ** Method  :   Use mppsend and mpprecv function for passing mask
997      !!      between processors following neighboring subdomains.
998      !!            domain parameters
999      !!                    nlci   : first dimension of the local subdomain
1000      !!                    nlcj   : second dimension of the local subdomain
1001      !!                    nbondi : mark for "east-west local boundary"
1002      !!                    nbondj : mark for "north-south local boundary"
1003      !!                    noea   : number for local neighboring processors
1004      !!                    nowe   : number for local neighboring processors
1005      !!                    noso   : number for local neighboring processors
1006      !!                    nono   : number for local neighboring processors
1007      !!
1008      !!----------------------------------------------------------------------
1009      !! * Arguments
1010      CHARACTER(len=1) , INTENT( in ) ::   &
1011         cd_type       ! define the nature of pt2d array grid-points
1012         !             !  = T , U , V , F , W
1013         !             !  = S : T-point, north fold treatment
1014         !             !  = G : F-point, north fold treatment
1015         !             !  = I : sea-ice velocity at F-point with index shift
1016      REAL(wp), INTENT( in ) ::   &
1017         psgn          ! control of the sign change
1018         !             !   = -1. , the sign is changed if north fold boundary
1019         !             !   =  1. , the sign is kept  if north fold boundary
1020      REAL(wp), DIMENSION(jpi,jpj), INTENT( inout ) ::   &
1021         pt2d          ! 2D array on which the boundary condition is applied
1022      CHARACTER(len=3), INTENT( in ), OPTIONAL ::    &
1023         cd_mpp        ! fill the overlap area only
1024
1025      !! * Local variables
1026      INTEGER  ::   ji, jj, jl      ! dummy loop indices
1027      INTEGER  ::   &
1028         imigr, iihom, ijhom,    &  ! temporary integers
1029         iloc, ijt, iju             !    "          "
1030      INTEGER  ::   ml_req1, ml_req2, ml_err     ! for key_mpi_isend
1031      INTEGER  ::   ml_stat(MPI_STATUS_SIZE)     ! for key_mpi_isend
1032      !!----------------------------------------------------------------------
1033
1034      ! 1. standard boundary treatment
1035      ! ------------------------------
1036      IF (PRESENT(cd_mpp)) THEN
1037         ! only fill extra allows with 1.
1038         pt2d(     1:nlci, nlcj+1:jpj) = 1.e0
1039         pt2d(nlci+1:jpi ,       :   ) = 1.e0
1040     
1041      ELSE     
1042
1043         !                                        ! East-West boundaries
1044         !                                        ! ====================
1045         IF( nbondi == 2 .AND.   &      ! Cyclic east-west
1046            &    (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
1047            pt2d( 1 ,:) = pt2d(jpim1,:)
1048            pt2d(jpi,:) = pt2d(  2  ,:)
1049
1050         ELSE                           ! ... closed
1051            SELECT CASE ( cd_type )
1052            CASE ( 'T', 'U', 'V', 'W' , 'I' )
1053               pt2d(     1       :jpreci,:) = 0.e0
1054               pt2d(nlci-jpreci+1:jpi   ,:) = 0.e0
1055            CASE ( 'F' )
1056               pt2d(nlci-jpreci+1:jpi   ,:) = 0.e0
1057            END SELECT
1058         ENDIF
1059
1060         !                                        ! North-South boundaries
1061         !                                        ! ======================
1062         SELECT CASE ( cd_type )
1063         CASE ( 'T', 'U', 'V', 'W' , 'I' )
1064            pt2d(:,     1       :jprecj) = 0.e0
1065            pt2d(:,nlcj-jprecj+1:jpj   ) = 0.e0
1066         CASE ( 'F' )
1067            pt2d(:,nlcj-jprecj+1:jpj   ) = 0.e0
1068         END SELECT
1069
1070      ENDIF
1071
1072
1073      ! 2. East and west directions
1074      ! ---------------------------
1075
1076      ! 2.1 Read Dirichlet lateral conditions
1077
1078      SELECT CASE ( nbondi )
1079      CASE ( -1, 0, 1 )    ! all except 2
1080         iihom = nlci-nreci
1081         DO jl = 1, jpreci
1082            t2ew(:,jl,1) = pt2d(jpreci+jl,:)
1083            t2we(:,jl,1) = pt2d(iihom +jl,:)
1084         END DO
1085      END SELECT
1086
1087      ! 2.2 Migrations
1088
1089#if defined key_mpp_shmem
1090      !! * SHMEM version
1091
1092      imigr = jpreci * jpj
1093
1094      SELECT CASE ( nbondi )
1095      CASE ( -1 )
1096         CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr, noea )
1097      CASE ( 0 )
1098         CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr, nowe )
1099         CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr, noea )
1100      CASE ( 1 )
1101         CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr, nowe )
1102      END SELECT
1103
1104      CALL barrier()
1105      CALL shmem_udcflush()
1106
1107#elif defined key_mpp_mpi
1108      !! * MPI version
1109
1110      imigr = jpreci * jpj
1111
1112      SELECT CASE ( nbondi )
1113      CASE ( -1 )
1114         CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req1 )
1115         CALL mpprecv( 1, t2ew(1,1,2), imigr )
1116         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1117      CASE ( 0 )
1118         CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1119         CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req2 )
1120         CALL mpprecv( 1, t2ew(1,1,2), imigr )
1121         CALL mpprecv( 2, t2we(1,1,2), imigr )
1122         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1123         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1124      CASE ( 1 )
1125         CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1126         CALL mpprecv( 2, t2we(1,1,2), imigr )
1127         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1128      END SELECT
1129
1130#endif
1131
1132      ! 2.3 Write Dirichlet lateral conditions
1133
1134      iihom = nlci - jpreci
1135      SELECT CASE ( nbondi )
1136      CASE ( -1 )
1137         DO jl = 1, jpreci
1138            pt2d(iihom+jl,:) = t2ew(:,jl,2)
1139         END DO
1140      CASE ( 0 )
1141         DO jl = 1, jpreci
1142            pt2d(jl      ,:) = t2we(:,jl,2)
1143            pt2d(iihom+jl,:) = t2ew(:,jl,2)
1144         END DO
1145      CASE ( 1 )
1146         DO jl = 1, jpreci
1147            pt2d(jl      ,:) = t2we(:,jl,2)
1148         END DO
1149      END SELECT
1150
1151
1152      ! 3. North and south directions
1153      ! -----------------------------
1154
1155      ! 3.1 Read Dirichlet lateral conditions
1156
1157      IF( nbondj /= 2 ) THEN
1158         ijhom = nlcj-nrecj
1159         DO jl = 1, jprecj
1160            t2sn(:,jl,1) = pt2d(:,ijhom +jl)
1161            t2ns(:,jl,1) = pt2d(:,jprecj+jl)
1162         END DO
1163      ENDIF
1164
1165      ! 3.2 Migrations
1166
1167#if defined key_mpp_shmem
1168      !! * SHMEM version
1169
1170      imigr = jprecj * jpi
1171
1172      SELECT CASE ( nbondj )
1173      CASE ( -1 )
1174         CALL shmem_put( t2sn(1,1,2), t2sn(1,1,1), imigr, nono )
1175      CASE ( 0 )
1176         CALL shmem_put( t2ns(1,1,2), t2ns(1,1,1), imigr, noso )
1177         CALL shmem_put( t2sn(1,1,2), t2sn(1,1,1), imigr, nono )
1178      CASE ( 1 )
1179         CALL shmem_put( t2ns(1,1,2), t2ns(1,1,1), imigr, noso )
1180      END SELECT
1181      CALL barrier()
1182      CALL shmem_udcflush()
1183
1184#elif defined key_mpp_mpi
1185      !! * MPI version
1186
1187      imigr = jprecj * jpi
1188
1189      SELECT CASE ( nbondj )
1190      CASE ( -1 )
1191         CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req1 )
1192         CALL mpprecv( 3, t2ns(1,1,2), imigr )
1193         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1194      CASE ( 0 )
1195         CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
1196         CALL mppsend( 4, t2sn(1,1,1), imigr, nono, ml_req2 )
1197         CALL mpprecv( 3, t2ns(1,1,2), imigr )
1198         CALL mpprecv( 4, t2sn(1,1,2), imigr )
1199         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1200         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1201      CASE ( 1 )
1202         CALL mppsend( 3, t2ns(1,1,1), imigr, noso, ml_req1 )
1203         CALL mpprecv( 4, t2sn(1,1,2), imigr )
1204         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1205      END SELECT
1206 
1207#endif
1208
1209      ! 3.3 Write Dirichlet lateral conditions
1210
1211      ijhom = nlcj - jprecj
1212
1213      SELECT CASE ( nbondj )
1214      CASE ( -1 )
1215         DO jl = 1, jprecj
1216            pt2d(:,ijhom+jl) = t2ns(:,jl,2)
1217         END DO
1218      CASE ( 0 )
1219         DO jl = 1, jprecj
1220            pt2d(:,jl      ) = t2sn(:,jl,2)
1221            pt2d(:,ijhom+jl) = t2ns(:,jl,2)
1222         END DO
1223      CASE ( 1 ) 
1224         DO jl = 1, jprecj
1225            pt2d(:,jl      ) = t2sn(:,jl,2)
1226         END DO
1227      END SELECT 
1228 
1229
1230      ! 4. north fold treatment
1231      ! -----------------------
1232 
1233      IF (PRESENT(cd_mpp)) THEN
1234         ! No north fold treatment (it is assumed to be already OK)
1235     
1236      ELSE     
1237
1238      ! 4.1 treatment without exchange (jpni odd)
1239     
1240      SELECT CASE ( jpni )
1241 
1242      CASE ( 1 ) ! only one proc along I, no mpp exchange
1243 
1244         SELECT CASE ( npolj )
1245 
1246         CASE ( 3 , 4 )   !  T pivot
1247            iloc = jpiglo - 2 * ( nimpp - 1 )
1248 
1249            SELECT CASE ( cd_type )
1250 
1251            CASE ( 'T' , 'S', 'W' )
1252               DO ji = 2, nlci
1253                  ijt=iloc-ji+2
1254                  pt2d(ji,nlcj) = psgn * pt2d(ijt,nlcj-2)
1255               END DO
1256               DO ji = nlci/2+1, nlci
1257                  ijt=iloc-ji+2
1258                  pt2d(ji,nlcj-1) = psgn * pt2d(ijt,nlcj-1)
1259               END DO
1260 
1261            CASE ( 'U' )
1262               DO ji = 1, nlci-1
1263                  iju=iloc-ji+1
1264                  pt2d(ji,nlcj) = psgn * pt2d(iju,nlcj-2)
1265               END DO
1266               DO ji = nlci/2, nlci-1
1267                  iju=iloc-ji+1
1268                  pt2d(ji,nlcj-1) = psgn * pt2d(iju,nlcj-1)
1269               END DO
1270 
1271            CASE ( 'V' )
1272               DO ji = 2, nlci
1273                  ijt=iloc-ji+2
1274                  pt2d(ji,nlcj-1) = psgn * pt2d(ijt,nlcj-2)
1275                  pt2d(ji,nlcj  ) = psgn * pt2d(ijt,nlcj-3)
1276               END DO
1277 
1278            CASE ( 'F', 'G' )
1279               DO ji = 1, nlci-1
1280                  iju=iloc-ji+1
1281                  pt2d(ji,nlcj-1) = psgn * pt2d(iju,nlcj-2)
1282                  pt2d(ji,nlcj  ) = psgn * pt2d(iju,nlcj-3)
1283               END DO
1284 
1285            CASE ( 'I' )                                  ! ice U-V point
1286               pt2d(2,nlcj) = psgn * pt2d(3,nlcj-1)
1287               DO ji = 3, nlci
1288                  iju = iloc - ji + 3
1289                  pt2d(ji,nlcj) = psgn * pt2d(iju,nlcj-1)
1290               END DO
1291 
1292            END SELECT
1293 
1294         CASE ( 5 , 6 )                 ! F pivot
1295            iloc=jpiglo-2*(nimpp-1)
1296 
1297            SELECT CASE (cd_type )
1298 
1299            CASE ( 'T', 'S', 'W' )
1300               DO ji = 1, nlci
1301                  ijt=iloc-ji+1
1302                  pt2d(ji,nlcj) = psgn * pt2d(ijt,nlcj-1)
1303               END DO
1304 
1305            CASE ( 'U' )
1306               DO ji = 1, nlci-1
1307                  iju=iloc-ji
1308                  pt2d(ji,nlcj) = psgn * pt2d(iju,nlcj-1)
1309               END DO
1310
1311            CASE ( 'V' )
1312               DO ji = 1, nlci
1313                  ijt=iloc-ji+1
1314                  pt2d(ji,nlcj  ) = psgn * pt2d(ijt,nlcj-2)
1315               END DO
1316               DO ji = nlci/2+1, nlci
1317                  ijt=iloc-ji+1
1318                  pt2d(ji,nlcj-1) = psgn * pt2d(ijt,nlcj-1)
1319               END DO
1320 
1321            CASE ( 'F', 'G' )
1322               DO ji = 1, nlci-1
1323                  iju=iloc-ji
1324                  pt2d(ji,nlcj) = psgn * pt2d(iju,nlcj-2)
1325               END DO
1326               DO ji = nlci/2+1, nlci-1
1327                  iju=iloc-ji
1328                  pt2d(ji,nlcj-1) = psgn * pt2d(iju,nlcj-1)
1329               END DO
1330 
1331            CASE ( 'I' )                                  ! ice U-V point
1332               pt2d( 2 ,nlcj) = 0.e0
1333               DO ji = 2 , nlci-1
1334                  ijt = iloc - ji + 2
1335                  pt2d(ji,nlcj)= 0.5 * ( pt2d(ji,nlcj-1) + psgn * pt2d(ijt,nlcj-1) )
1336               END DO
1337 
1338            END SELECT   ! cd_type
1339 
1340         END SELECT   ! npolj
1341
1342      CASE DEFAULT   ! more than 1 proc along I
1343         IF( npolj /= 0 )   CALL mpp_lbc_north( pt2d, cd_type, psgn )   ! only for northern procs.
1344
1345      END SELECT   ! jpni
1346
1347      ENDIF
1348
1349      ! 5. East and west directions
1350      ! ---------------------------
1351
1352      SELECT CASE ( npolj )
1353
1354      CASE ( 3, 4, 5, 6 )
1355
1356         ! 5.1 Read Dirichlet lateral conditions
1357
1358         SELECT CASE ( nbondi )
1359         CASE ( -1, 0, 1 )
1360            iihom = nlci-nreci
1361            DO jl = 1, jpreci
1362               DO jj = 1, jpj
1363                  t2ew(jj,jl,1) = pt2d(jpreci+jl,jj)
1364                  t2we(jj,jl,1) = pt2d(iihom +jl,jj)
1365               END DO
1366            END DO
1367         END SELECT
1368
1369         ! 5.2 Migrations
1370
1371#if defined key_mpp_shmem
1372         !! * SHMEM version
1373
1374         imigr=jpreci*jpj
1375
1376         SELECT CASE ( nbondi )
1377         CASE ( -1 )
1378            CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr, noea )
1379         CASE ( 0 )
1380            CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr, nowe )
1381            CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr, noea )
1382         CASE ( 1 )
1383            CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr, nowe )
1384         END SELECT
1385
1386         CALL barrier()
1387         CALL shmem_udcflush()
1388 
1389#elif defined key_mpp_mpi
1390         !! * MPI version
1391 
1392         imigr=jpreci*jpj
1393 
1394         SELECT CASE ( nbondi )
1395         CASE ( -1 )
1396            CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req1 )
1397            CALL mpprecv( 1, t2ew(1,1,2), imigr )
1398            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1399         CASE ( 0 )
1400            CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1401            CALL mppsend( 2, t2we(1,1,1), imigr, noea, ml_req2 )
1402            CALL mpprecv( 1, t2ew(1,1,2), imigr )
1403            CALL mpprecv( 2, t2we(1,1,2), imigr )
1404            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1405            IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1406         CASE ( 1 )
1407            CALL mppsend( 1, t2ew(1,1,1), imigr, nowe, ml_req1 )
1408            CALL mpprecv( 2, t2we(1,1,2), imigr )
1409            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1410         END SELECT 
1411#endif
1412
1413         ! 5.3 Write Dirichlet lateral conditions
1414 
1415         iihom = nlci - jpreci
1416 
1417         SELECT CASE ( nbondi )
1418         CASE ( -1 )
1419            DO jl = 1, jpreci
1420               pt2d(iihom+jl,:) = t2ew(:,jl,2)
1421            END DO
1422         CASE ( 0 )
1423            DO jl = 1, jpreci
1424               pt2d(jl      ,:) = t2we(:,jl,2)
1425               pt2d(iihom+jl,:) = t2ew(:,jl,2)
1426            END DO
1427         CASE ( 1 )
1428            DO jl = 1, jpreci
1429               pt2d(jl,:) = t2we(:,jl,2)
1430            END DO
1431         END SELECT
1432 
1433      END SELECT   ! npolj
1434 
1435   END SUBROUTINE mpp_lnk_2d
1436
1437
1438   SUBROUTINE mpp_lnk_3d_gather( ptab1, cd_type1, ptab2, cd_type2, psgn )
1439      !!----------------------------------------------------------------------
1440      !!                  ***  routine mpp_lnk_3d_gather  ***
1441      !!
1442      !! ** Purpose :   Message passing manadgement for two 3D arrays
1443      !!
1444      !! ** Method  :   Use mppsend and mpprecv function for passing mask
1445      !!      between processors following neighboring subdomains.
1446      !!            domain parameters
1447      !!                    nlci   : first dimension of the local subdomain
1448      !!                    nlcj   : second dimension of the local subdomain
1449      !!                    nbondi : mark for "east-west local boundary"
1450      !!                    nbondj : mark for "north-south local boundary"
1451      !!                    noea   : number for local neighboring processors
1452      !!                    nowe   : number for local neighboring processors
1453      !!                    noso   : number for local neighboring processors
1454      !!                    nono   : number for local neighboring processors
1455      !!
1456      !! ** Action  :   ptab1 and ptab2  with update value at its periphery
1457      !!
1458      !!----------------------------------------------------------------------
1459      !! * Arguments
1460      CHARACTER(len=1) , INTENT( in ) ::   &
1461         cd_type1, cd_type2       ! define the nature of ptab array grid-points
1462         !                        ! = T , U , V , F , W points
1463         !                        ! = S : T-point, north fold treatment ???
1464         !                        ! = G : F-point, north fold treatment ???
1465      REAL(wp), INTENT( in ) ::   &
1466         psgn          ! control of the sign change
1467         !             !   = -1. , the sign is changed if north fold boundary
1468         !             !   =  1. , the sign is kept  if north fold boundary
1469      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT( inout ) ::   &
1470         ptab1, ptab2             ! 3D array on which the boundary condition is applied
1471
1472      !! * Local variables
1473      INTEGER ::   ji, jk, jl   ! dummy loop indices
1474      INTEGER ::   imigr, iihom, ijhom, iloc, ijt, iju   ! temporary integers
1475      INTEGER ::   ml_req1, ml_req2, ml_err     ! for key_mpi_isend
1476      INTEGER ::   ml_stat(MPI_STATUS_SIZE)     ! for key_mpi_isend
1477      !!----------------------------------------------------------------------
1478
1479      ! 1. standard boundary treatment
1480      ! ------------------------------
1481      !                                        ! East-West boundaries
1482      !                                        ! ====================
1483      IF( nbondi == 2 .AND.   &      ! Cyclic east-west
1484         &   (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
1485         ptab1( 1 ,:,:) = ptab1(jpim1,:,:)
1486         ptab1(jpi,:,:) = ptab1(  2  ,:,:)
1487         ptab2( 1 ,:,:) = ptab2(jpim1,:,:)
1488         ptab2(jpi,:,:) = ptab2(  2  ,:,:)
1489
1490      ELSE                           ! closed
1491         SELECT CASE ( cd_type1 )
1492         CASE ( 'T', 'U', 'V', 'W' )
1493            ptab1(     1       :jpreci,:,:) = 0.e0
1494            ptab1(nlci-jpreci+1:jpi   ,:,:) = 0.e0
1495         CASE ( 'F' )
1496            ptab1(nlci-jpreci+1:jpi   ,:,:) = 0.e0
1497         END SELECT
1498         SELECT CASE ( cd_type2 )
1499         CASE ( 'T', 'U', 'V', 'W' )
1500            ptab2(     1       :jpreci,:,:) = 0.e0
1501            ptab2(nlci-jpreci+1:jpi   ,:,:) = 0.e0
1502         CASE ( 'F' )
1503            ptab2(nlci-jpreci+1:jpi   ,:,:) = 0.e0
1504         END SELECT
1505      ENDIF
1506
1507      !                                        ! North-South boundaries
1508      !                                        ! ======================
1509      SELECT CASE ( cd_type1 )
1510      CASE ( 'T', 'U', 'V', 'W' )
1511         ptab1(:,     1       :jprecj,:) = 0.e0
1512         ptab1(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
1513      CASE ( 'F' )
1514         ptab1(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
1515      END SELECT
1516
1517      SELECT CASE ( cd_type2 )
1518      CASE ( 'T', 'U', 'V', 'W' )
1519         ptab2(:,     1       :jprecj,:) = 0.e0
1520         ptab2(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
1521      CASE ( 'F' )
1522         ptab2(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
1523      END SELECT
1524
1525
1526      ! 2. East and west directions exchange
1527      ! ------------------------------------
1528
1529      ! 2.1 Read Dirichlet lateral conditions
1530
1531      SELECT CASE ( nbondi )
1532      CASE ( -1, 0, 1 )    ! all exept 2
1533         iihom = nlci-nreci
1534         DO jl = 1, jpreci
1535            t4ew(:,jl,:,1,1) = ptab1(jpreci+jl,:,:)
1536            t4we(:,jl,:,1,1) = ptab1(iihom +jl,:,:)
1537            t4ew(:,jl,:,2,1) = ptab2(jpreci+jl,:,:)
1538            t4we(:,jl,:,2,1) = ptab2(iihom +jl,:,:)
1539         END DO
1540      END SELECT
1541
1542      ! 2.2 Migrations
1543
1544#if defined key_mpp_shmem
1545      !! * SHMEM version
1546
1547      imigr = jpreci * jpj * jpk *2
1548
1549      SELECT CASE ( nbondi )
1550      CASE ( -1 )
1551         CALL shmem_put( t4we(1,1,1,1,2), t4we(1,1,1,1,1), imigr, noea )
1552      CASE ( 0 )
1553         CALL shmem_put( t4ew(1,1,1,1,2), t4ew(1,1,1,1,1), imigr, nowe )
1554         CALL shmem_put( t4we(1,1,1,1,2), t4we(1,1,1,1,1), imigr, noea )
1555      CASE ( 1 )
1556         CALL shmem_put( t4ew(1,1,1,1,2), t4ew(1,1,1,1,1), imigr, nowe )
1557      END SELECT
1558
1559      CALL barrier()
1560      CALL shmem_udcflush()
1561
1562#elif defined key_mpp_mpi
1563      !! * Local variables   (MPI version)
1564
1565      imigr = jpreci * jpj * jpk *2
1566
1567      SELECT CASE ( nbondi ) 
1568      CASE ( -1 )
1569         CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req1 )
1570         CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr )
1571         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1572      CASE ( 0 )
1573         CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
1574         CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req2 )
1575         CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr )
1576         CALL mpprecv( 2, t4we(1,1,1,1,2), imigr )
1577         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1578         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
1579      CASE ( 1 )
1580         CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
1581         CALL mpprecv( 2, t4we(1,1,1,1,2), imigr )
1582         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1583      END SELECT
1584#endif
1585
1586      ! 2.3 Write Dirichlet lateral conditions
1587
1588      iihom = nlci-jpreci
1589
1590      SELECT CASE ( nbondi )
1591      CASE ( -1 )
1592         DO jl = 1, jpreci
1593            ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
1594            ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
1595         END DO
1596      CASE ( 0 ) 
1597         DO jl = 1, jpreci
1598            ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
1599            ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
1600            ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
1601            ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
1602         END DO
1603      CASE ( 1 )
1604         DO jl = 1, jpreci
1605            ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
1606            ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
1607         END DO
1608      END SELECT
1609
1610
1611      ! 3. North and south directions
1612      ! -----------------------------
1613
1614      ! 3.1 Read Dirichlet lateral conditions
1615
1616      IF( nbondj /= 2 ) THEN
1617         ijhom = nlcj-nrecj
1618         DO jl = 1, jprecj
1619            t4sn(:,jl,:,1,1) = ptab1(:,ijhom +jl,:)
1620            t4ns(:,jl,:,1,1) = ptab1(:,jprecj+jl,:)
1621            t4sn(:,jl,:,2,1) = ptab2(:,ijhom +jl,:)
1622            t4ns(:,jl,:,2,1) = ptab2(:,jprecj+jl,:)
1623         END DO
1624      ENDIF
1625
1626      ! 3.2 Migrations
1627
1628#if defined key_mpp_shmem
1629      !! * SHMEM version
1630
1631      imigr = jprecj * jpi * jpk * 2
1632
1633      SELECT CASE ( nbondj )
1634      CASE ( -1 )
1635         CALL shmem_put( t4sn(1,1,1,1,2), t4sn(1,1,1,1,1), imigr, nono )
1636      CASE ( 0 )
1637         CALL shmem_put( t4ns(1,1,1,1,2), t4ns(1,1,1,1,1), imigr, noso )
1638         CALL shmem_put( t4sn(1,1,1,1,2), t4sn(1,1,1,1,1), imigr, nono )
1639      CASE ( 1 )
1640         CALL shmem_put( t4ns(1,1,1,1,2), t4ns(1,1,1,1;,1), imigr, noso )
1641      END SELECT
1642
1643      CALL barrier()
1644      CALL shmem_udcflush()
1645
1646#elif defined key_mpp_mpi
1647      !! * Local variables   (MPI version)
1648 
1649      imigr=jprecj * jpi * jpk * 2
1650
1651      SELECT CASE ( nbondj )     
1652      CASE ( -1 )
1653         CALL mppsend( 4, t4sn(1,1,1,1,1), imigr, nono, ml_req1 )
1654         CALL mpprecv( 3, t4ns(1,1,1,1,2), imigr )
1655         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1656      CASE ( 0 )
1657         CALL mppsend( 3, t4ns(1,1,1,1,1), imigr, noso, ml_req1 )
1658         CALL mppsend( 4, t4sn(1,1,1,1,1), imigr, nono, ml_req2 )
1659         CALL mpprecv( 3, t4ns(1,1,1,1,2), imigr )
1660         CALL mpprecv( 4, t4sn(1,1,1,1,2), imigr )
1661         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1662         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
1663      CASE ( 1 ) 
1664         CALL mppsend( 3, t4ns(1,1,1,1,1), imigr, noso, ml_req1 )
1665         CALL mpprecv( 4, t4sn(1,1,1,1,2), imigr )
1666         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
1667      END SELECT
1668
1669#endif
1670
1671      ! 3.3 Write Dirichlet lateral conditions
1672
1673      ijhom = nlcj-jprecj
1674
1675      SELECT CASE ( nbondj )
1676      CASE ( -1 )
1677         DO jl = 1, jprecj
1678            ptab1(:,ijhom+jl,:) = t4ns(:,jl,:,1,2)
1679            ptab2(:,ijhom+jl,:) = t4ns(:,jl,:,2,2)
1680         END DO
1681      CASE ( 0 ) 
1682         DO jl = 1, jprecj
1683            ptab1(:,jl      ,:) = t4sn(:,jl,:,1,2)
1684            ptab1(:,ijhom+jl,:) = t4ns(:,jl,:,1,2)
1685            ptab2(:,jl      ,:) = t4sn(:,jl,:,2,2)
1686            ptab2(:,ijhom+jl,:) = t4ns(:,jl,:,2,2)
1687         END DO
1688      CASE ( 1 )
1689         DO jl = 1, jprecj
1690            ptab1(:,jl,:) = t4sn(:,jl,:,1,2)
1691            ptab2(:,jl,:) = t4sn(:,jl,:,2,2)
1692         END DO
1693      END SELECT
1694
1695
1696      ! 4. north fold treatment
1697      ! -----------------------
1698
1699      ! 4.1 treatment without exchange (jpni odd)
1700      !     T-point pivot 
1701
1702      SELECT CASE ( jpni )
1703
1704      CASE ( 1 )  ! only one proc along I, no mpp exchange
1705
1706      SELECT CASE ( npolj )
1707 
1708         CASE ( 3 , 4 )    ! T pivot
1709            iloc = jpiglo - 2 * ( nimpp - 1 )
1710
1711            SELECT CASE ( cd_type1 )
1712
1713            CASE ( 'T' , 'S', 'W' )
1714               DO jk = 1, jpk
1715                  DO ji = 2, nlci
1716                     ijt=iloc-ji+2
1717                     ptab1(ji,nlcj,jk) = psgn * ptab1(ijt,nlcj-2,jk)
1718                  END DO
1719                  DO ji = nlci/2+1, nlci
1720                     ijt=iloc-ji+2
1721                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(ijt,nlcj-1,jk)
1722                  END DO
1723               END DO
1724         
1725            CASE ( 'U' )
1726               DO jk = 1, jpk
1727                  DO ji = 1, nlci-1
1728                     iju=iloc-ji+1
1729                     ptab1(ji,nlcj,jk) = psgn * ptab1(iju,nlcj-2,jk)
1730                  END DO
1731                  DO ji = nlci/2, nlci-1
1732                     iju=iloc-ji+1
1733                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(iju,nlcj-1,jk)
1734                  END DO
1735               END DO
1736
1737            CASE ( 'V' )
1738               DO jk = 1, jpk
1739                  DO ji = 2, nlci
1740                     ijt=iloc-ji+2
1741                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(ijt,nlcj-2,jk)
1742                     ptab1(ji,nlcj  ,jk) = psgn * ptab1(ijt,nlcj-3,jk)
1743                  END DO
1744               END DO
1745
1746            CASE ( 'F', 'G' )
1747               DO jk = 1, jpk
1748                  DO ji = 1, nlci-1
1749                     iju=iloc-ji+1
1750                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(iju,nlcj-2,jk)
1751                     ptab1(ji,nlcj  ,jk) = psgn * ptab1(iju,nlcj-3,jk)
1752                  END DO
1753               END DO
1754 
1755            END SELECT
1756           
1757            SELECT CASE ( cd_type2 )
1758
1759            CASE ( 'T' , 'S', 'W' )
1760               DO jk = 1, jpk
1761                  DO ji = 2, nlci
1762                     ijt=iloc-ji+2
1763                     ptab2(ji,nlcj,jk) = psgn * ptab2(ijt,nlcj-2,jk)
1764                  END DO
1765                  DO ji = nlci/2+1, nlci
1766                     ijt=iloc-ji+2
1767                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(ijt,nlcj-1,jk)
1768                  END DO
1769               END DO
1770         
1771            CASE ( 'U' )
1772               DO jk = 1, jpk
1773                  DO ji = 1, nlci-1
1774                     iju=iloc-ji+1
1775                     ptab2(ji,nlcj,jk) = psgn * ptab2(iju,nlcj-2,jk)
1776                  END DO
1777                  DO ji = nlci/2, nlci-1
1778                     iju=iloc-ji+1
1779                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(iju,nlcj-1,jk)
1780                  END DO
1781               END DO
1782
1783            CASE ( 'V' )
1784               DO jk = 1, jpk
1785                  DO ji = 2, nlci
1786                     ijt=iloc-ji+2
1787                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(ijt,nlcj-2,jk)
1788                     ptab2(ji,nlcj  ,jk) = psgn * ptab2(ijt,nlcj-3,jk)
1789                  END DO
1790               END DO
1791
1792            CASE ( 'F', 'G' )
1793               DO jk = 1, jpk
1794                  DO ji = 1, nlci-1
1795                     iju=iloc-ji+1
1796                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(iju,nlcj-2,jk)
1797                     ptab2(ji,nlcj  ,jk) = psgn * ptab2(iju,nlcj-3,jk)
1798                  END DO
1799               END DO
1800 
1801          END SELECT
1802       
1803         CASE ( 5 , 6 ) ! F pivot
1804            iloc=jpiglo-2*(nimpp-1)
1805 
1806            SELECT CASE ( cd_type1 )
1807
1808            CASE ( 'T' , 'S', 'W' )
1809               DO jk = 1, jpk
1810                  DO ji = 1, nlci
1811                     ijt=iloc-ji+1
1812                     ptab1(ji,nlcj,jk) = psgn * ptab1(ijt,nlcj-1,jk)
1813                  END DO
1814               END DO
1815
1816            CASE ( 'U' )
1817               DO jk = 1, jpk
1818                  DO ji = 1, nlci-1
1819                     iju=iloc-ji
1820                     ptab1(ji,nlcj,jk) = psgn * ptab1(iju,nlcj-1,jk)
1821                  END DO
1822               END DO
1823
1824            CASE ( 'V' )
1825               DO jk = 1, jpk
1826                  DO ji = 1, nlci
1827                     ijt=iloc-ji+1
1828                     ptab1(ji,nlcj  ,jk) = psgn * ptab1(ijt,nlcj-2,jk)
1829                  END DO
1830                  DO ji = nlci/2+1, nlci
1831                     ijt=iloc-ji+1
1832                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(ijt,nlcj-1,jk)
1833                  END DO
1834               END DO
1835
1836            CASE ( 'F', 'G' )
1837               DO jk = 1, jpk
1838                  DO ji = 1, nlci-1
1839                     iju=iloc-ji
1840                     ptab1(ji,nlcj,jk) = psgn * ptab1(iju,nlcj-2,jk)
1841                  END DO
1842                  DO ji = nlci/2+1, nlci-1
1843                     iju=iloc-ji
1844                     ptab1(ji,nlcj-1,jk) = psgn * ptab1(iju,nlcj-1,jk)
1845                  END DO
1846               END DO
1847            END SELECT  ! cd_type1
1848
1849            SELECT CASE ( cd_type2 )
1850
1851            CASE ( 'T' , 'S', 'W' )
1852               DO jk = 1, jpk
1853                  DO ji = 1, nlci
1854                     ijt=iloc-ji+1
1855                     ptab2(ji,nlcj,jk) = psgn * ptab2(ijt,nlcj-1,jk)
1856                  END DO
1857               END DO
1858
1859            CASE ( 'U' )
1860               DO jk = 1, jpk
1861                  DO ji = 1, nlci-1
1862                     iju=iloc-ji
1863                     ptab2(ji,nlcj,jk) = psgn * ptab2(iju,nlcj-1,jk)
1864                  END DO
1865               END DO
1866
1867            CASE ( 'V' )
1868               DO jk = 1, jpk
1869                  DO ji = 1, nlci
1870                     ijt=iloc-ji+1
1871                     ptab2(ji,nlcj  ,jk) = psgn * ptab2(ijt,nlcj-2,jk)
1872                  END DO
1873                  DO ji = nlci/2+1, nlci
1874                     ijt=iloc-ji+1
1875                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(ijt,nlcj-1,jk)
1876                  END DO
1877               END DO
1878
1879            CASE ( 'F', 'G' )
1880               DO jk = 1, jpk
1881                  DO ji = 1, nlci-1
1882                     iju=iloc-ji
1883                     ptab2(ji,nlcj,jk) = psgn * ptab2(iju,nlcj-2,jk)
1884                  END DO
1885                  DO ji = nlci/2+1, nlci-1
1886                     iju=iloc-ji
1887                     ptab2(ji,nlcj-1,jk) = psgn * ptab2(iju,nlcj-1,jk)
1888                  END DO
1889               END DO
1890
1891            END SELECT  ! cd_type2
1892
1893         END SELECT     !  npolj
1894 
1895      CASE DEFAULT ! more than 1 proc along I
1896         IF ( npolj /= 0 ) THEN
1897            CALL mpp_lbc_north (ptab1, cd_type1, psgn)  ! only for northern procs.
1898            CALL mpp_lbc_north (ptab2, cd_type2, psgn)  ! only for northern procs.
1899         ENDIF
1900
1901      END SELECT ! jpni
1902
1903
1904      ! 5. East and west directions exchange
1905      ! ------------------------------------
1906
1907      SELECT CASE ( npolj )
1908
1909      CASE ( 3, 4, 5, 6 )
1910
1911         ! 5.1 Read Dirichlet lateral conditions
1912
1913         SELECT CASE ( nbondi )
1914
1915         CASE ( -1, 0, 1 )
1916            iihom = nlci-nreci
1917            DO jl = 1, jpreci
1918               t4ew(:,jl,:,1,1) = ptab1(jpreci+jl,:,:)
1919               t4we(:,jl,:,1,1) = ptab1(iihom +jl,:,:)
1920               t4ew(:,jl,:,2,1) = ptab2(jpreci+jl,:,:)
1921               t4we(:,jl,:,2,1) = ptab2(iihom +jl,:,:)
1922            END DO
1923
1924         END SELECT
1925
1926         ! 5.2 Migrations
1927
1928#if defined key_mpp_shmem
1929         !! SHMEM version
1930
1931         imigr = jpreci * jpj * jpk * 2
1932
1933         SELECT CASE ( nbondi )
1934         CASE ( -1 )
1935            CALL shmem_put( t4we(1,1,1,1,2), t4we(1,1,1,1,1), imigr, noea )
1936         CASE ( 0 )
1937            CALL shmem_put( t4ew(1,1,1,1,2), t4ew(1,1,1,1,1), imigr, nowe )
1938            CALL shmem_put( t4we(1,1,1,1,2), t4we(1,1,1,1,1), imigr, noea )
1939         CASE ( 1 )
1940            CALL shmem_put( t4ew(1,1,1,1,2), t4ew(1,1,1,1,1), imigr, nowe )
1941         END SELECT
1942
1943         CALL barrier()
1944         CALL shmem_udcflush()
1945
1946#elif defined key_mpp_mpi
1947         !! MPI version
1948
1949         imigr = jpreci * jpj * jpk * 2
1950 
1951         SELECT CASE ( nbondi )
1952         CASE ( -1 )
1953            CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req1 )
1954            CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr )
1955            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1956         CASE ( 0 )
1957            CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
1958            CALL mppsend( 2, t4we(1,1,1,1,1), imigr, noea, ml_req2 )
1959            CALL mpprecv( 1, t4ew(1,1,1,1,2), imigr )
1960            CALL mpprecv( 2, t4we(1,1,1,1,2), imigr )
1961            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1962            IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
1963         CASE ( 1 )
1964            CALL mppsend( 1, t4ew(1,1,1,1,1), imigr, nowe, ml_req1 )
1965            CALL mpprecv( 2, t4we(1,1,1,1,2), imigr )
1966            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
1967         END SELECT
1968#endif
1969
1970         ! 5.3 Write Dirichlet lateral conditions
1971
1972         iihom = nlci-jpreci
1973
1974         SELECT CASE ( nbondi)
1975         CASE ( -1 )
1976            DO jl = 1, jpreci
1977               ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
1978               ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
1979            END DO
1980         CASE ( 0 ) 
1981            DO jl = 1, jpreci
1982               ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
1983               ptab1(iihom+jl,:,:) = t4ew(:,jl,:,1,2)
1984               ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
1985               ptab2(iihom+jl,:,:) = t4ew(:,jl,:,2,2)
1986            END DO
1987         CASE ( 1 )
1988            DO jl = 1, jpreci
1989               ptab1(jl      ,:,:) = t4we(:,jl,:,1,2)
1990               ptab2(jl      ,:,:) = t4we(:,jl,:,2,2)
1991            END DO
1992         END SELECT
1993
1994      END SELECT    ! npolj
1995
1996   END SUBROUTINE mpp_lnk_3d_gather
1997
1998
1999   SUBROUTINE mpp_lnk_2d_e( pt2d, cd_type, psgn )
2000      !!----------------------------------------------------------------------
2001      !!                  ***  routine mpp_lnk_2d_e  ***
2002      !!                 
2003      !! ** Purpose :   Message passing manadgement for 2d array (with halo)
2004      !!
2005      !! ** Method  :   Use mppsend and mpprecv function for passing mask
2006      !!      between processors following neighboring subdomains.
2007      !!            domain parameters
2008      !!                    nlci   : first dimension of the local subdomain
2009      !!                    nlcj   : second dimension of the local subdomain
2010      !!                    jpr2di : number of rows for extra outer halo
2011      !!                    jpr2dj : number of columns for extra outer halo
2012      !!                    nbondi : mark for "east-west local boundary"
2013      !!                    nbondj : mark for "north-south local boundary"
2014      !!                    noea   : number for local neighboring processors
2015      !!                    nowe   : number for local neighboring processors
2016      !!                    noso   : number for local neighboring processors
2017      !!                    nono   : number for local neighboring processors
2018      !!   
2019      !! History :
2020      !!       
2021      !!   9.0  !  05-09  (R. Benshila, G. Madec)  original code
2022      !!
2023      !!----------------------------------------------------------------------
2024      !! * Arguments
2025      CHARACTER(len=1) , INTENT( in ) ::   &
2026         cd_type       ! define the nature of pt2d array grid-points
2027         !             !  = T , U , V , F , W
2028         !             !  = S : T-point, north fold treatment
2029         !             !  = G : F-point, north fold treatment
2030         !             !  = I : sea-ice velocity at F-point with index shift
2031      REAL(wp), INTENT( in ) ::   &
2032         psgn          ! control of the sign change
2033         !             !   = -1. , the sign is changed if north fold boundary
2034         !             !   =  1. , the sign is kept  if north fold boundary
2035      REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT( inout ) ::   &
2036         pt2d          ! 2D array on which the boundary condition is applied
2037
2038      !! * Local variables
2039      INTEGER  ::   ji, jl      ! dummy loop indices
2040      INTEGER  ::   &
2041         imigr, iihom, ijhom,    &  ! temporary integers
2042         iloc, ijt, iju             !    "          "
2043      INTEGER  ::   &
2044         ipreci, iprecj             ! temporary integers
2045      INTEGER  ::   ml_req1, ml_req2, ml_err     ! for isend
2046      INTEGER  ::   ml_stat(MPI_STATUS_SIZE)     ! for isend
2047     !!---------------------------------------------------------------------
2048
2049      ! take into account outer extra 2D overlap area
2050      ipreci = jpreci + jpr2di
2051      iprecj = jprecj + jpr2dj
2052
2053
2054      ! 1. standard boundary treatment
2055      ! ------------------------------
2056
2057      !                                        ! East-West boundaries
2058      !                                        ! ====================
2059      IF( nbondi == 2 .AND.   &      ! Cyclic east-west
2060         &    (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
2061         pt2d(1-jpr2di:     1    ,:) = pt2d(jpim1-jpr2di:  jpim1 ,:)
2062         pt2d(   jpi  :jpi+jpr2di,:) = pt2d(     2      :2+jpr2di,:)
2063
2064      ELSE                           ! ... closed
2065         SELECT CASE ( cd_type )
2066         CASE ( 'T', 'U', 'V', 'W' , 'I' )
2067            pt2d(  1-jpr2di   :jpreci    ,:) = 0.e0
2068            pt2d(nlci-jpreci+1:jpi+jpr2di,:) = 0.e0
2069         CASE ( 'F' )
2070            pt2d(nlci-jpreci+1:jpi+jpr2di,:) = 0.e0
2071         END SELECT
2072      ENDIF
2073
2074      !                                        ! North-South boundaries
2075      !                                        ! ======================
2076      SELECT CASE ( cd_type )
2077      CASE ( 'T', 'U', 'V', 'W' , 'I' )
2078         pt2d(:,  1-jpr2dj   :  jprecj  ) = 0.e0
2079         pt2d(:,nlcj-jprecj+1:jpj+jpr2dj) = 0.e0
2080      CASE ( 'F' )
2081         pt2d(:,nlcj-jprecj+1:jpj+jpr2dj) = 0.e0
2082      END SELECT
2083
2084
2085      ! 2. East and west directions
2086      ! ---------------------------
2087
2088      ! 2.1 Read Dirichlet lateral conditions
2089
2090      SELECT CASE ( nbondi )
2091      CASE ( -1, 0, 1 )    ! all except 2
2092         iihom = nlci-nreci-jpr2di
2093         DO jl = 1, ipreci
2094            tr2ew(:,jl,1) = pt2d(jpreci+jl,:)
2095            tr2we(:,jl,1) = pt2d(iihom +jl,:)
2096         END DO
2097      END SELECT
2098
2099      ! 2.2 Migrations
2100
2101#if defined key_mpp_shmem
2102      !! * SHMEM version
2103
2104      imigr = ipreci * ( jpj + 2*jpr2dj)
2105
2106      SELECT CASE ( nbondi )
2107      CASE ( -1 )
2108         CALL shmem_put( tr2we(1-jpr2dj,1,2), tr2we(1,1,1), imigr, noea )
2109      CASE ( 0 )
2110         CALL shmem_put( tr2ew(1-jpr2dj,1,2), tr2ew(1,1,1), imigr, nowe )
2111         CALL shmem_put( tr2we(1-jpr2dj,1,2), tr2we(1,1,1), imigr, noea )
2112      CASE ( 1 )
2113         CALL shmem_put( tr2ew(1-jpr2dj,1,2), tr2ew(1,1,1), imigr, nowe )
2114      END SELECT
2115
2116      CALL barrier()
2117      CALL shmem_udcflush()
2118
2119#elif defined key_mpp_mpi
2120      !! * MPI version
2121
2122      imigr = ipreci * ( jpj + 2*jpr2dj)
2123
2124      SELECT CASE ( nbondi )
2125      CASE ( -1 )
2126         CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req1 )
2127         CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr )
2128         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2129      CASE ( 0 )
2130         CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
2131         CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req2 )
2132         CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr )
2133         CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr )
2134         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2135         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
2136      CASE ( 1 )
2137         CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
2138         CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr )
2139         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2140      END SELECT
2141
2142#endif
2143
2144      ! 2.3 Write Dirichlet lateral conditions
2145
2146      iihom = nlci - jpreci
2147
2148      SELECT CASE ( nbondi )
2149      CASE ( -1 )
2150         DO jl = 1, ipreci
2151            pt2d(iihom+jl,:) = tr2ew(:,jl,2)
2152         END DO
2153      CASE ( 0 )
2154         DO jl = 1, ipreci
2155            pt2d(jl-jpr2di,:) = tr2we(:,jl,2)
2156            pt2d( iihom+jl,:) = tr2ew(:,jl,2)
2157         END DO
2158      CASE ( 1 )
2159         DO jl = 1, ipreci
2160            pt2d(jl-jpr2di,:) = tr2we(:,jl,2)
2161         END DO
2162      END SELECT
2163
2164
2165      ! 3. North and south directions
2166      ! -----------------------------
2167
2168      ! 3.1 Read Dirichlet lateral conditions
2169
2170      IF( nbondj /= 2 ) THEN
2171         ijhom = nlcj-nrecj-jpr2dj
2172         DO jl = 1, iprecj
2173            tr2sn(:,jl,1) = pt2d(:,ijhom +jl)
2174            tr2ns(:,jl,1) = pt2d(:,jprecj+jl)
2175         END DO
2176      ENDIF
2177
2178      ! 3.2 Migrations
2179
2180#if defined key_mpp_shmem
2181      !! * SHMEM version
2182
2183      imigr = iprecj * ( jpi + 2*jpr2di )
2184
2185      SELECT CASE ( nbondj )
2186      CASE ( -1 )
2187         CALL shmem_put( tr2sn(1-jpr2di,1,2), tr2sn(1,1,1), imigr, nono )
2188      CASE ( 0 )
2189         CALL shmem_put( tr2ns(1-jpr2di,1,2), tr2ns(1,1,1), imigr, noso )
2190         CALL shmem_put( tr2sn(1-jpr2di,1,2), tr2sn(1,1,1), imigr, nono )
2191      CASE ( 1 )
2192         CALL shmem_put( tr2ns(1-jpr2di,1,2), tr2ns(1,1,1), imigr, noso )
2193      END SELECT
2194      CALL barrier()
2195      CALL shmem_udcflush()
2196
2197#elif defined key_mpp_mpi
2198      !! * MPI version
2199
2200      imigr = iprecj * ( jpi + 2*jpr2di )
2201
2202      SELECT CASE ( nbondj )
2203      CASE ( -1 )
2204         CALL mppsend( 4, tr2sn(1-jpr2di,1,1), imigr, nono, ml_req1 )
2205         CALL mpprecv( 3, tr2ns(1-jpr2di,1,2), imigr )
2206         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2207      CASE ( 0 )
2208         CALL mppsend( 3, tr2ns(1-jpr2di,1,1), imigr, noso, ml_req1 )
2209         CALL mppsend( 4, tr2sn(1-jpr2di,1,1), imigr, nono, ml_req2 )
2210         CALL mpprecv( 3, tr2ns(1-jpr2di,1,2), imigr )
2211         CALL mpprecv( 4, tr2sn(1-jpr2di,1,2), imigr )
2212         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2213         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
2214      CASE ( 1 )
2215         CALL mppsend( 3, tr2ns(1-jpr2di,1,1), imigr, noso, ml_req1 )
2216         CALL mpprecv( 4, tr2sn(1-jpr2di,1,2), imigr )
2217         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2218      END SELECT
2219 
2220#endif
2221
2222      ! 3.3 Write Dirichlet lateral conditions
2223
2224      ijhom = nlcj - jprecj 
2225
2226      SELECT CASE ( nbondj )
2227      CASE ( -1 )
2228         DO jl = 1, iprecj
2229            pt2d(:,ijhom+jl) = tr2ns(:,jl,2)
2230         END DO
2231      CASE ( 0 )
2232         DO jl = 1, iprecj
2233            pt2d(:,jl-jpr2dj) = tr2sn(:,jl,2)
2234            pt2d(:,ijhom+jl ) = tr2ns(:,jl,2)
2235         END DO
2236      CASE ( 1 ) 
2237         DO jl = 1, iprecj
2238            pt2d(:,jl-jpr2dj) = tr2sn(:,jl,2)
2239         END DO
2240      END SELECT 
2241 
2242
2243      ! 4. north fold treatment
2244      ! -----------------------
2245 
2246      ! 4.1 treatment without exchange (jpni odd)
2247     
2248      SELECT CASE ( jpni )
2249 
2250      CASE ( 1 ) ! only one proc along I, no mpp exchange
2251 
2252         SELECT CASE ( npolj )
2253 
2254         CASE ( 3 , 4 )   !  T pivot
2255            iloc = jpiglo - 2 * ( nimpp - 1 )
2256 
2257            SELECT CASE ( cd_type )
2258 
2259            CASE ( 'T', 'S', 'W' )
2260               DO jl = 0, iprecj-1
2261                  DO ji = 2-jpr2di, nlci+jpr2di
2262                     ijt=iloc-ji+2
2263                     pt2d(ji,nlcj+jl) = psgn * pt2d(ijt,nlcj-2-jl)
2264                  END DO
2265               END DO
2266               DO ji = nlci/2+1, nlci+jpr2di
2267                  ijt=iloc-ji+2
2268                  pt2d(ji,nlcj-1) = psgn * pt2d(ijt,nlcj-1)
2269               END DO
2270 
2271            CASE ( 'U' )
2272               DO jl =0, iprecj-1
2273                  DO ji = 1-jpr2di, nlci-1-jpr2di
2274                     iju=iloc-ji+1
2275                     pt2d(ji,nlcj+jl) = psgn * pt2d(iju,nlcj-2-jl)
2276                  END DO
2277               END DO
2278               DO ji = nlci/2, nlci-1+jpr2di
2279                  iju=iloc-ji+1
2280                  pt2d(ji,nlcj-1) = psgn * pt2d(iju,nlcj-1)
2281               END DO
2282 
2283            CASE ( 'V' )
2284               DO jl = -1, iprecj-1
2285                  DO ji = 2-jpr2di, nlci+jpr2di
2286                     ijt=iloc-ji+2
2287                     pt2d(ji,nlcj+jl) = psgn * pt2d(ijt,nlcj-3-jl)
2288                  END DO
2289               END DO
2290 
2291            CASE ( 'F', 'G' )
2292               DO jl = -1, iprecj-1
2293                  DO ji = 1-jpr2di, nlci-1+jpr2di
2294                     iju=iloc-ji+1
2295                     pt2d(ji,nlcj+jl) = psgn * pt2d(iju,nlcj-3-jl)
2296                  END DO
2297               END DO
2298 
2299            CASE ( 'I' )                                  ! ice U-V point
2300               DO jl = 0, iprecj-1
2301                  pt2d(2,nlcj+jl) = psgn * pt2d(3,nlcj-1-jl)
2302                  DO ji = 3, nlci+jpr2di
2303                     iju = iloc - ji + 3
2304                     pt2d(ji,nlcj+jl) = psgn * pt2d(iju,nlcj-1-jl)
2305                  END DO
2306               END DO
2307 
2308            END SELECT
2309 
2310         CASE ( 5 , 6 )                 ! F pivot
2311            iloc=jpiglo-2*(nimpp-1)
2312 
2313            SELECT CASE (cd_type )
2314 
2315            CASE ( 'T', 'S', 'W' )
2316               DO jl = 0, iprecj-1
2317                  DO ji = 1-jpr2di, nlci+jpr2di
2318                     ijt=iloc-ji+1
2319                     pt2d(ji,nlcj+jl) = psgn * pt2d(ijt,nlcj-1-jl)
2320                  END DO
2321               END DO
2322 
2323            CASE ( 'U' )
2324               DO jl = 0, iprecj-1
2325                  DO ji = 1-jpr2di, nlci-1+jpr2di
2326                     iju=iloc-ji
2327                     pt2d(ji,nlcj+jl) = psgn * pt2d(iju,nlcj-1-jl)
2328                  END DO
2329               END DO
2330 
2331            CASE ( 'V' )
2332               DO jl = 0, iprecj-1
2333                  DO ji = 1-jpr2di, nlci+jpr2di
2334                     ijt=iloc-ji+1
2335                     pt2d(ji,nlcj+jl) = psgn * pt2d(ijt,nlcj-2-jl)
2336                  END DO
2337               END DO
2338               DO ji = nlci/2+1, nlci+jpr2di
2339                  ijt=iloc-ji+1
2340                  pt2d(ji,nlcj-1) = psgn * pt2d(ijt,nlcj-1)
2341               END DO
2342 
2343            CASE ( 'F', 'G' )
2344               DO jl = 0, iprecj-1
2345                  DO ji = 1-jpr2di, nlci-1+jpr2di
2346                     iju=iloc-ji
2347                     pt2d(ji,nlcj+jl) = psgn * pt2d(iju,nlcj-2-jl)
2348                  END DO
2349               END DO
2350               DO ji = nlci/2+1, nlci-1+jpr2di
2351                  iju=iloc-ji
2352                  pt2d(ji,nlcj-1) = psgn * pt2d(iju,nlcj-1)
2353               END DO
2354 
2355            CASE ( 'I' )                                  ! ice U-V point
2356               pt2d( 2 ,nlcj) = 0.e0
2357               DO jl = 0, iprecj-1
2358                  DO ji = 2 , nlci-1+jpr2di
2359                     ijt = iloc - ji + 2
2360                     pt2d(ji,nlcj+jl)= 0.5 * ( pt2d(ji,nlcj-1-jl) + psgn * pt2d(ijt,nlcj-1-jl) )
2361                  END DO
2362               END DO
2363 
2364            END SELECT   ! cd_type
2365 
2366         END SELECT   ! npolj
2367
2368      CASE DEFAULT   ! more than 1 proc along I
2369         IF( npolj /= 0 )   CALL mpp_lbc_north_e( pt2d, cd_type, psgn )   ! only for northern procs
2370         
2371      END SELECT   ! jpni
2372
2373
2374      ! 5. East and west directions
2375      ! ---------------------------
2376
2377      SELECT CASE ( npolj )
2378
2379      CASE ( 3, 4, 5, 6 )
2380
2381         ! 5.1 Read Dirichlet lateral conditions
2382
2383         SELECT CASE ( nbondi )
2384         CASE ( -1, 0, 1 )
2385            iihom = nlci-nreci-jpr2di
2386            DO jl = 1, ipreci
2387               tr2ew(:,jl,1) = pt2d(jpreci+jl,:)
2388               tr2we(:,jl,1) = pt2d(iihom +jl,:)
2389            END DO
2390         END SELECT
2391
2392         ! 5.2 Migrations
2393
2394#if defined key_mpp_shmem
2395         !! * SHMEM version
2396
2397         imigr = ipreci * ( jpj + 2*jpr2dj )
2398
2399         SELECT CASE ( nbondi )
2400         CASE ( -1 )
2401            CALL shmem_put( tr2we(1-jpr2dj,1,2), tr2we(1,1,1), imigr, noea )
2402         CASE ( 0 )
2403            CALL shmem_put( tr2ew(1-jpr2dj,1,2), tr2ew(1,1,1), imigr, nowe )
2404            CALL shmem_put( tr2we(1-jpr2dj,1,2), tr2we(1,1,1), imigr, noea )
2405         CASE ( 1 )
2406            CALL shmem_put( tr2ew(1-jpr2dj,1,2), tr2ew(1,1,1), imigr, nowe )
2407         END SELECT
2408
2409         CALL barrier()
2410         CALL shmem_udcflush()
2411 
2412#elif defined key_mpp_mpi
2413         !! * MPI version
2414 
2415         imigr=ipreci* ( jpj + 2*jpr2dj )
2416 
2417         SELECT CASE ( nbondi )
2418         CASE ( -1 )
2419            CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req1 )
2420            CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr )
2421            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2422         CASE ( 0 )
2423            CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
2424            CALL mppsend( 2, tr2we(1-jpr2dj,1,1), imigr, noea, ml_req2 )
2425            CALL mpprecv( 1, tr2ew(1-jpr2dj,1,2), imigr )
2426            CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr )
2427            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2428            IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
2429         CASE ( 1 )
2430            CALL mppsend( 1, tr2ew(1-jpr2dj,1,1), imigr, nowe, ml_req1 )
2431            CALL mpprecv( 2, tr2we(1-jpr2dj,1,2), imigr )
2432            IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2433         END SELECT 
2434#endif
2435
2436         ! 5.3 Write Dirichlet lateral conditions
2437 
2438         iihom = nlci - jpreci
2439 
2440         SELECT CASE ( nbondi )
2441         CASE ( -1 )
2442            DO jl = 1, ipreci
2443               pt2d(iihom+jl,:) = tr2ew(:,jl,2)
2444            END DO
2445         CASE ( 0 )
2446            DO jl = 1, ipreci
2447               pt2d(jl- jpr2di,:) = tr2we(:,jl,2)
2448               pt2d(iihom+jl,:) = tr2ew(:,jl,2)
2449            END DO
2450         CASE ( 1 )
2451            DO jl = 1, ipreci
2452               pt2d(jl-jpr2di,:) = tr2we(:,jl,2)
2453            END DO
2454         END SELECT
2455 
2456      END SELECT   ! npolj
2457 
2458   END SUBROUTINE mpp_lnk_2d_e
2459
2460
2461   SUBROUTINE mpplnks( ptab )
2462      !!----------------------------------------------------------------------
2463      !!                  ***  routine mpplnks  ***
2464      !!
2465      !! ** Purpose :   Message passing manadgement for add 2d array local boundary
2466      !!
2467      !! ** Method  :   Use mppsend and mpprecv function for passing mask between
2468      !!       processors following neighboring subdomains.
2469      !!            domain parameters
2470      !!                    nlci   : first dimension of the local subdomain
2471      !!                    nlcj   : second dimension of the local subdomain
2472      !!                    nbondi : mark for "east-west local boundary"
2473      !!                    nbondj : mark for "north-south local boundary"
2474      !!                    noea   : number for local neighboring processors
2475      !!                    nowe   : number for local neighboring processors
2476      !!                    noso   : number for local neighboring processors
2477      !!                    nono   : number for local neighboring processors
2478      !!
2479      !!----------------------------------------------------------------------
2480      !! * Arguments
2481      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) ::   &
2482         ptab                     ! 2D array
2483 
2484      !! * Local variables
2485      INTEGER ::   ji, jl         ! dummy loop indices
2486      INTEGER ::   &
2487         imigr, iihom, ijhom      ! temporary integers
2488      INTEGER ::   ml_req1, ml_req2, ml_err     ! for key_mpi_isend
2489      INTEGER ::   ml_stat(MPI_STATUS_SIZE)     ! for key_mpi_isend
2490      !!----------------------------------------------------------------------
2491
2492
2493      ! 1. north fold treatment
2494      ! -----------------------
2495
2496      ! 1.1 treatment without exchange (jpni odd)
2497 
2498      SELECT CASE ( npolj )
2499      CASE ( 4 )
2500         DO ji = 1, nlci
2501            ptab(ji,nlcj-2) = ptab(ji,nlcj-2) + t2p1(ji,1,1)
2502         END DO
2503      CASE ( 6 )
2504         DO ji = 1, nlci
2505            ptab(ji,nlcj-1) = ptab(ji,nlcj-1) + t2p1(ji,1,1)
2506         END DO
2507
2508      ! 1.2 treatment with exchange (jpni greater than 1)
2509      !
2510      CASE ( 3 )
2511#if defined key_mpp_shmem
2512 
2513         !! * SHMEN version
2514 
2515         imigr=jprecj*jpi
2516 
2517         CALL shmem_put(t2p1(1,1,2),t2p1(1,1,1),imigr,nono)
2518         CALL barrier()
2519         CALL shmem_udcflush()
2520
2521#  elif defined key_mpp_mpi
2522       !! * MPI version
2523
2524       imigr=jprecj*jpi
2525
2526       CALL mppsend(3,t2p1(1,1,1),imigr,nono, ml_req1)
2527       CALL mpprecv(3,t2p1(1,1,2),imigr)
2528       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2529
2530#endif     
2531
2532       ! Write north fold conditions
2533
2534       DO ji = 1, nlci
2535          ptab(ji,nlcj-2) = ptab(ji,nlcj-2)+t2p1(ji,1,2)
2536       END DO
2537
2538    CASE ( 5 )
2539
2540#if defined key_mpp_shmem
2541
2542       !! * SHMEN version
2543
2544       imigr=jprecj*jpi
2545
2546       CALL shmem_put(t2p1(1,1,2),t2p1(1,1,1),imigr,nono)
2547       CALL barrier()
2548       CALL shmem_udcflush()
2549
2550#  elif defined key_mpp_mpi
2551       !! * Local variables   (MPI version)
2552
2553       imigr=jprecj*jpi
2554
2555       CALL mppsend(3,t2p1(1,1,1),imigr,nono, ml_req1)
2556       CALL mpprecv(3,t2p1(1,1,2),imigr)
2557       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2558
2559#endif     
2560
2561       ! Write north fold conditions
2562
2563       DO ji = 1, nlci
2564          ptab(ji,nlcj-1) = ptab(ji,nlcj-1)+t2p1(ji,1,2)
2565       END DO
2566
2567    END SELECT
2568
2569
2570    ! 2. East and west directions
2571    ! ---------------------------
2572
2573    ! 2.1 Read Dirichlet lateral conditions
2574
2575    iihom = nlci-jpreci
2576
2577    SELECT CASE ( nbondi )
2578
2579    CASE ( -1, 0, 1 )  ! all except 2
2580       DO jl = 1, jpreci
2581             t2ew(:,jl,1) = ptab(  jl    ,:)
2582             t2we(:,jl,1) = ptab(iihom+jl,:)
2583       END DO
2584    END SELECT
2585
2586    ! 2.2 Migrations
2587
2588#if defined key_mpp_shmem
2589
2590    !! * SHMEN version
2591
2592    imigr=jpreci*jpj
2593
2594    SELECT CASE ( nbondi )
2595
2596    CASE ( -1 )
2597       CALL shmem_put(t2we(1,1,2),t2we(1,1,1),imigr,noea)
2598
2599    CASE ( 0 )
2600       CALL shmem_put(t2ew(1,1,2),t2ew(1,1,1),imigr,nowe)
2601       CALL shmem_put(t2we(1,1,2),t2we(1,1,1),imigr,noea)
2602
2603    CASE ( 1 )
2604       CALL shmem_put(t2ew(1,1,2),t2ew(1,1,1),imigr,nowe)
2605
2606    END SELECT
2607    CALL  barrier()
2608    CALL  shmem_udcflush()
2609
2610#  elif defined key_mpp_mpi
2611    !! * Local variables   (MPI version)
2612
2613    imigr=jpreci*jpj
2614
2615    SELECT CASE ( nbondi )
2616
2617    CASE ( -1 )
2618       CALL mppsend(2,t2we(1,1,1),imigr,noea, ml_req1)
2619       CALL mpprecv(1,t2ew(1,1,2),imigr)
2620       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2621    CASE ( 0 )
2622       CALL mppsend(1,t2ew(1,1,1),imigr,nowe, ml_req1)
2623       CALL mppsend(2,t2we(1,1,1),imigr,noea, ml_req2)
2624       CALL mpprecv(1,t2ew(1,1,2),imigr)
2625       CALL mpprecv(2,t2we(1,1,2),imigr)
2626       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2627       IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
2628
2629    CASE ( 1 )
2630       CALL mppsend(1,t2ew(1,1,1),imigr,nowe, ml_req1)
2631       CALL mpprecv(2,t2we(1,1,2),imigr)
2632       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2633
2634    END SELECT
2635
2636#endif
2637
2638    ! 2.3 Write Dirichlet lateral conditions
2639
2640       iihom = nlci-nreci
2641
2642    SELECT CASE ( nbondi )
2643
2644    CASE ( -1 )
2645       DO jl = 1, jpreci
2646             ptab(iihom +jl,:) = ptab(iihom +jl,:)+t2ew(:,jl,2)
2647       END DO
2648
2649    CASE ( 0 )
2650       DO jl = 1, jpreci
2651             ptab(jpreci+jl,:) = ptab(jpreci+jl,:)+t2we(:,jl,2)
2652             ptab(iihom +jl,:) = ptab(iihom +jl,:)+t2ew(:,jl,2)
2653       END DO
2654
2655    CASE ( 1 )
2656       DO jl = 1, jpreci
2657             ptab(jpreci+jl,:) = ptab(jpreci+jl,:)+t2we(:,jl,2)
2658       END DO
2659    END SELECT
2660
2661
2662    ! 3. North and south directions
2663    ! -----------------------------
2664
2665    ! 3.1 Read Dirichlet lateral conditions
2666
2667    ijhom = nlcj-jprecj
2668
2669    SELECT CASE ( nbondj )
2670
2671    CASE ( -1, 0, 1 )
2672       DO jl = 1, jprecj
2673             t2sn(:,jl,1) = ptab(:,ijhom+jl)
2674             t2ns(:,jl,1) = ptab(:,   jl   )
2675       END DO
2676
2677    END SELECT 
2678
2679    ! 3.2 Migrations
2680
2681#if defined key_mpp_shmem
2682
2683    !! * SHMEN version
2684
2685    imigr=jprecj*jpi
2686
2687    SELECT CASE ( nbondj )
2688
2689    CASE ( -1 )
2690       CALL shmem_put(t2sn(1,1,2),t2sn(1,1,1),imigr,nono)
2691
2692    CASE ( 0 )
2693       CALL shmem_put(t2ns(1,1,2),t2ns(1,1,1),imigr,noso)
2694       CALL shmem_put(t2sn(1,1,2),t2sn(1,1,1),imigr,nono)
2695
2696    CASE ( 1 )
2697       CALL shmem_put(t2ns(1,1,2),t2ns(1,1,1),imigr,noso)
2698
2699    END SELECT
2700    CALL  barrier()
2701    CALL  shmem_udcflush()
2702
2703#  elif defined key_mpp_mpi
2704    !! * Local variables   (MPI version)
2705
2706    imigr=jprecj*jpi
2707
2708    SELECT CASE ( nbondj )
2709
2710    CASE ( -1 )
2711       CALL mppsend(4,t2sn(1,1,1),imigr,nono, ml_req1)
2712       CALL mpprecv(3,t2ns(1,1,2),imigr)
2713       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2714
2715    CASE ( 0 )
2716       CALL mppsend(3,t2ns(1,1,1),imigr,noso, ml_req1)
2717       CALL mppsend(4,t2sn(1,1,1),imigr,nono, ml_req2)
2718       CALL mpprecv(3,t2ns(1,1,2),imigr)
2719       CALL mpprecv(4,t2sn(1,1,2),imigr)
2720       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2721       IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
2722
2723    CASE ( 1 )
2724       CALL mppsend(3,t2ns(1,1,1),imigr,noso, ml_req1)
2725       CALL mpprecv(4,t2sn(1,1,2),imigr)
2726       IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
2727    END SELECT
2728
2729#endif
2730
2731    ! 3.3 Write Dirichlet lateral conditions
2732
2733       ijhom = nlcj-nrecj
2734
2735    SELECT CASE ( nbondj )
2736
2737    CASE ( -1 )
2738       DO jl = 1, jprecj
2739             ptab(:,ijhom +jl) = ptab(:,ijhom +jl)+t2ns(:,jl,2)
2740       END DO
2741
2742    CASE ( 0 )
2743       DO jl = 1, jprecj
2744             ptab(:,jprecj+jl) = ptab(:,jprecj+jl)+t2sn(:,jl,2)
2745             ptab(:,ijhom +jl) = ptab(:,ijhom +jl)+t2ns(:,jl,2)
2746       END DO
2747
2748    CASE ( 1 ) 
2749       DO jl = 1, jprecj
2750             ptab(:,jprecj+jl) = ptab(:,jprecj+jl)+t2sn(:,jl,2)
2751       END DO
2752
2753    END SELECT
2754
2755  END SUBROUTINE mpplnks
2756
2757
2758   SUBROUTINE mppsend( ktyp, pmess, kbytes, kdest, md_req)
2759      !!----------------------------------------------------------------------
2760      !!                  ***  routine mppsend  ***
2761      !!                   
2762      !! ** Purpose :   Send messag passing array
2763      !!
2764      !!----------------------------------------------------------------------
2765      !! * Arguments
2766      REAL(wp), INTENT(inout) ::   pmess(*)       ! array of real
2767      INTEGER , INTENT( in  ) ::   kbytes,     &  ! size of the array pmess
2768         &                         kdest ,     &  ! receive process number
2769         &                         ktyp,       &  ! Tag of the message
2770         &                         md_req         ! Argument for isend
2771      !!----------------------------------------------------------------------
2772#if defined key_mpp_shmem
2773      !! * SHMEM version  :    routine not used
2774
2775#elif defined key_mpp_mpi
2776      !! * MPI version
2777      INTEGER ::   iflag
2778
2779      SELECT CASE ( c_mpi_send )
2780      CASE ( 'S' )                ! Standard mpi send (blocking)
2781         CALL mpi_send ( pmess, kbytes, mpi_double_precision, kdest, ktyp,   &
2782            &                          mpi_comm_world, iflag )
2783      CASE ( 'B' )                ! Buffer mpi send (blocking)
2784         CALL mpi_bsend( pmess, kbytes, mpi_double_precision, kdest, ktyp,   &
2785            &                          mpi_comm_world, iflag )
2786      CASE ( 'I' )                ! Immediate mpi send (non-blocking send)
2787         ! Be carefull, one more argument here : the mpi request identifier..
2788         CALL mpi_isend( pmess, kbytes, mpi_double_precision, kdest, ktyp,   &
2789            &                          mpi_comm_world, md_req, iflag )
2790      END SELECT
2791#endif
2792
2793   END SUBROUTINE mppsend
2794
2795
2796   SUBROUTINE mpprecv( ktyp, pmess, kbytes )
2797      !!----------------------------------------------------------------------
2798      !!                  ***  routine mpprecv  ***
2799      !!
2800      !! ** Purpose :   Receive messag passing array
2801      !!
2802      !!----------------------------------------------------------------------
2803      !! * Arguments
2804      REAL(wp), INTENT(inout) ::   pmess(*)       ! array of real
2805      INTEGER , INTENT( in  ) ::   kbytes,     &  ! suze of the array pmess
2806         &                         ktyp           ! Tag of the recevied message
2807      !!----------------------------------------------------------------------
2808#if defined key_mpp_shmem
2809      !! * SHMEM version  :    routine not used
2810
2811#  elif defined key_mpp_mpi
2812      !! * MPI version
2813      INTEGER :: istatus(mpi_status_size)
2814      INTEGER :: iflag
2815
2816      CALL mpi_recv( pmess, kbytes, mpi_double_precision, mpi_any_source, ktyp,   &
2817         &                          mpi_comm_world, istatus, iflag )
2818#endif
2819
2820   END SUBROUTINE mpprecv
2821
2822
2823   SUBROUTINE mppgather( ptab, kp, pio )
2824      !!----------------------------------------------------------------------
2825      !!                   ***  routine mppgather  ***
2826      !!                   
2827      !! ** Purpose :   Transfert between a local subdomain array and a work
2828      !!     array which is distributed following the vertical level.
2829      !!
2830      !! ** Method  :
2831      !!
2832      !!----------------------------------------------------------------------
2833      !! * Arguments
2834      REAL(wp), DIMENSION(jpi,jpj),       INTENT( in  ) ::   ptab   ! subdomain input array
2835      INTEGER ,                           INTENT( in  ) ::   kp     ! record length
2836      REAL(wp), DIMENSION(jpi,jpj,jpnij), INTENT( out ) ::   pio    ! subdomain input array
2837      !!---------------------------------------------------------------------
2838#if defined key_mpp_shmem
2839      !! * SHMEM version
2840
2841      CALL barrier()
2842      CALL shmem_put( pio(1,1,npvm_me+1), ptab, jpi*jpj, kp )
2843      CALL barrier()
2844
2845#elif defined key_mpp_mpi
2846      !! * Local variables   (MPI version)
2847      INTEGER :: itaille,ierror
2848 
2849      itaille=jpi*jpj
2850      CALL mpi_gather( ptab, itaille, mpi_double_precision, pio, itaille,   &
2851         &                            mpi_double_precision, kp , mpi_comm_world, ierror ) 
2852#endif
2853
2854   END SUBROUTINE mppgather
2855
2856
2857   SUBROUTINE mppscatter( pio, kp, ptab )
2858      !!----------------------------------------------------------------------
2859      !!                  ***  routine mppscatter  ***
2860      !!
2861      !! ** Purpose :   Transfert between awork array which is distributed
2862      !!      following the vertical level and the local subdomain array.
2863      !!
2864      !! ** Method :
2865      !!
2866      !!----------------------------------------------------------------------
2867      REAL(wp), DIMENSION(jpi,jpj,jpnij)  ::  pio        ! output array
2868      INTEGER                             ::   kp        ! Tag (not used with MPI
2869      REAL(wp), DIMENSION(jpi,jpj)        ::  ptab       ! subdomain array input
2870      !!---------------------------------------------------------------------
2871#if defined key_mpp_shmem
2872      !! * SHMEM version
2873
2874      CALL barrier()
2875      CALL shmem_get( ptab, pio(1,1,npvm_me+1), jpi*jpj, kp )
2876      CALL barrier()
2877
2878#  elif defined key_mpp_mpi
2879      !! * Local variables   (MPI version)
2880      INTEGER :: itaille, ierror
2881 
2882      itaille=jpi*jpj
2883
2884      CALL mpi_scatter( pio, itaille, mpi_double_precision, ptab, itaille,   &
2885         &                            mpi_double_precision, kp, mpi_comm_world, ierror )
2886#endif
2887
2888   END SUBROUTINE mppscatter
2889
2890
2891   SUBROUTINE mppisl_a_int( ktab, kdim )
2892      !!----------------------------------------------------------------------
2893      !!                  ***  routine mppisl_a_int  ***
2894      !!                   
2895      !! ** Purpose :   Massively parallel processors
2896      !!                Find the  non zero value
2897      !!
2898      !!----------------------------------------------------------------------
2899      !! * Arguments
2900      INTEGER, INTENT( in  )                  ::   kdim       ! ???
2901      INTEGER, INTENT(inout), DIMENSION(kdim) ::   ktab       ! ???
2902 
2903#if defined key_mpp_shmem
2904      !! * Local variables   (SHMEM version)
2905      INTEGER :: ji
2906      INTEGER, SAVE :: ibool=0
2907
2908      IF( kdim > jpmppsum ) CALL ctl_stop( 'mppisl_a_int routine : kdim is too big', &
2909           &                               'change jpmppsum dimension in mpp.h' )
2910
2911      DO ji = 1, kdim
2912         niitab_shmem(ji) = ktab(ji)
2913      END DO
2914      CALL  barrier()
2915      IF(ibool == 0 ) THEN
2916         CALL shmem_int8_min_to_all (ni11tab_shmem,niitab_shmem,kdim,0   &
2917              ,0,N$PES,ni11wrk_shmem,ni11sync_shmem)
2918         CALL shmem_int8_max_to_all (ni12tab_shmem,niitab_shmem,kdim,0   &
2919              ,0,N$PES,ni12wrk_shmem,ni12sync_shmem)
2920      ELSE
2921         CALL shmem_int8_min_to_all (ni11tab_shmem,niitab_shmem,kdim,0   &
2922              ,0,N$PES,ni21wrk_shmem,ni21sync_shmem)
2923         CALL shmem_int8_max_to_all (ni12tab_shmem,niitab_shmem,kdim,0   &
2924              ,0,N$PES,ni22wrk_shmem,ni22sync_shmem)
2925      ENDIF
2926      CALL  barrier()
2927      ibool=ibool+1
2928      ibool=MOD( ibool,2)
2929      DO ji = 1, kdim
2930         IF( ni11tab_shmem(ji) /= 0. ) THEN
2931            ktab(ji) = ni11tab_shmem(ji)
2932         ELSE
2933            ktab(ji) = ni12tab_shmem(ji)
2934         ENDIF
2935      END DO
2936 
2937#  elif defined key_mpp_mpi
2938      !! * Local variables   (MPI version)
2939      LOGICAL  :: lcommute
2940      INTEGER, DIMENSION(kdim) ::   iwork
2941      INTEGER  :: mpi_isl,ierror
2942 
2943      lcommute = .TRUE.
2944      CALL mpi_op_create( lc_isl, lcommute, mpi_isl, ierror )
2945      CALL mpi_allreduce( ktab, iwork, kdim, mpi_integer   &
2946           , mpi_isl, mpi_comm_world, ierror )
2947      ktab(:) = iwork(:)
2948#endif
2949
2950   END SUBROUTINE mppisl_a_int
2951
2952
2953   SUBROUTINE mppisl_int( ktab )
2954      !!----------------------------------------------------------------------
2955      !!                  ***  routine mppisl_int  ***
2956      !!                   
2957      !! ** Purpose :   Massively parallel processors
2958      !!                Find the non zero value
2959      !!
2960      !!----------------------------------------------------------------------
2961      !! * Arguments
2962      INTEGER , INTENT( inout ) ::   ktab        !
2963
2964#if defined key_mpp_shmem
2965      !! * Local variables   (SHMEM version)
2966      INTEGER, SAVE :: ibool=0
2967
2968      niitab_shmem(1) = ktab
2969      CALL  barrier()
2970      IF(ibool == 0 ) THEN
2971         CALL shmem_int8_min_to_all (ni11tab_shmem,niitab_shmem,1,0   &
2972              ,0,N$PES,ni11wrk_shmem,ni11sync_shmem)
2973         CALL shmem_int8_max_to_all (ni12tab_shmem,niitab_shmem,1,0   &
2974              ,0,N$PES,ni12wrk_shmem,ni12sync_shmem)
2975      ELSE
2976         CALL shmem_int8_min_to_all (ni11tab_shmem,niitab_shmem,1,0   &
2977              ,0,N$PES,ni21wrk_shmem,ni21sync_shmem)
2978         CALL shmem_int8_max_to_all (ni12tab_shmem,niitab_shmem,1,0   &
2979              ,0,N$PES,ni22wrk_shmem,ni22sync_shmem)
2980      ENDIF
2981      CALL  barrier()
2982      ibool=ibool+1
2983      ibool=MOD( ibool,2)
2984      IF( ni11tab_shmem(1) /= 0. ) THEN
2985         ktab = ni11tab_shmem(1)
2986      ELSE
2987         ktab = ni12tab_shmem(1)
2988      ENDIF
2989 
2990#  elif defined key_mpp_mpi
2991 
2992      !! * Local variables   (MPI version)
2993      LOGICAL :: lcommute
2994      INTEGER :: mpi_isl,ierror
2995      INTEGER ::   iwork
2996 
2997      lcommute = .TRUE.
2998      CALL mpi_op_create(lc_isl,lcommute,mpi_isl,ierror)
2999      CALL mpi_allreduce(ktab, iwork, 1,mpi_integer   &
3000           ,mpi_isl,mpi_comm_world,ierror)
3001      ktab = iwork
3002#endif
3003
3004   END SUBROUTINE mppisl_int
3005
3006
3007   SUBROUTINE mppmin_a_int( ktab, kdim )
3008      !!----------------------------------------------------------------------
3009      !!                  ***  routine mppmin_a_int  ***
3010      !!
3011      !! ** Purpose :   Find minimum value in an integer layout array
3012      !!
3013      !!----------------------------------------------------------------------
3014      !! * Arguments
3015      INTEGER , INTENT( in  )                  ::   kdim        ! size of array
3016      INTEGER , INTENT(inout), DIMENSION(kdim) ::   ktab        ! input array
3017 
3018#if defined key_mpp_shmem
3019      !! * Local declarations    (SHMEM version)
3020      INTEGER :: ji
3021      INTEGER, SAVE :: ibool=0
3022 
3023      IF( kdim > jpmppsum ) CALL ctl_stop( 'mppmin_a_int routine : kdim is too big', &
3024           &                               'change jpmppsum dimension in mpp.h' )
3025 
3026      DO ji = 1, kdim
3027         niltab_shmem(ji) = ktab(ji)
3028      END DO
3029      CALL  barrier()
3030      IF(ibool == 0 ) THEN
3031         CALL shmem_int8_min_to_all (niltab_shmem,niltab_shmem,kdim,0,0   &
3032              ,N$PES,nil1wrk_shmem,nil1sync_shmem )
3033      ELSE
3034         CALL shmem_int8_min_to_all (niltab_shmem,niltab_shmem,kdim,0,0   &
3035              ,N$PES,nil2wrk_shmem,nil2sync_shmem )
3036      ENDIF
3037      CALL  barrier()
3038      ibool=ibool+1
3039      ibool=MOD( ibool,2)
3040      DO ji = 1, kdim
3041         ktab(ji) = niltab_shmem(ji)
3042      END DO
3043 
3044#  elif defined key_mpp_mpi
3045 
3046      !! * Local variables   (MPI version)
3047      INTEGER :: ierror
3048      INTEGER, DIMENSION(kdim) ::   iwork
3049 
3050      CALL mpi_allreduce( ktab, iwork, kdim, mpi_integer,   &
3051           &                mpi_min, mpi_comm_world, ierror )
3052 
3053      ktab(:) = iwork(:)
3054#endif
3055
3056   END SUBROUTINE mppmin_a_int
3057
3058
3059   SUBROUTINE mppmin_int( ktab )
3060      !!----------------------------------------------------------------------
3061      !!                  ***  routine mppmin_int  ***
3062      !!
3063      !! ** Purpose :
3064      !!     Massively parallel processors
3065      !!     Find minimum value in an integer layout array
3066      !!
3067      !!----------------------------------------------------------------------
3068      !! * Arguments
3069      INTEGER, INTENT(inout) ::   ktab      ! ???
3070 
3071      !! * Local declarations
3072
3073#if defined key_mpp_shmem
3074
3075      !! * Local variables   (SHMEM version)
3076      INTEGER :: ji
3077      INTEGER, SAVE :: ibool=0
3078 
3079      niltab_shmem(1) = ktab
3080      CALL  barrier()
3081      IF(ibool == 0 ) THEN
3082         CALL shmem_int8_min_to_all (niltab_shmem,niltab_shmem, 1,0,0   &
3083              ,N$PES,nil1wrk_shmem,nil1sync_shmem )
3084      ELSE
3085         CALL shmem_int8_min_to_all (niltab_shmem,niltab_shmem, 1,0,0   &
3086              ,N$PES,nil2wrk_shmem,nil2sync_shmem )
3087      ENDIF
3088      CALL  barrier()
3089      ibool=ibool+1
3090      ibool=MOD( ibool,2)
3091      ktab = niltab_shmem(1)
3092 
3093#  elif defined key_mpp_mpi
3094
3095      !! * Local variables   (MPI version)
3096      INTEGER ::  ierror, iwork
3097 
3098      CALL mpi_allreduce(ktab,iwork, 1,mpi_integer   &
3099           &              ,mpi_min,mpi_comm_world,ierror)
3100 
3101      ktab = iwork
3102#endif
3103
3104   END SUBROUTINE mppmin_int
3105
3106
3107   SUBROUTINE mppsum_a_int( ktab, kdim )
3108      !!----------------------------------------------------------------------
3109      !!                  ***  routine mppsum_a_int  ***
3110      !!                   
3111      !! ** Purpose :   Massively parallel processors
3112      !!                Global integer sum
3113      !!
3114      !!----------------------------------------------------------------------
3115      !! * Arguments
3116      INTEGER, INTENT( in  )                   ::   kdim      ! ???
3117      INTEGER, INTENT(inout), DIMENSION (kdim) ::   ktab      ! ???
3118 
3119#if defined key_mpp_shmem
3120
3121      !! * Local variables   (SHMEM version)
3122      INTEGER :: ji
3123      INTEGER, SAVE :: ibool=0
3124
3125      IF( kdim > jpmppsum ) CALL ctl_stop( 'mppsum_a_int routine : kdim is too big', &
3126           &                               'change jpmppsum dimension in mpp.h' )
3127
3128      DO ji = 1, kdim
3129         nistab_shmem(ji) = ktab(ji)
3130      END DO
3131      CALL  barrier()
3132      IF(ibool == 0 ) THEN
3133         CALL shmem_int8_sum_to_all(nistab_shmem,nistab_shmem,kdim,0,0,   &
3134              N$PES,nis1wrk_shmem,nis1sync_shmem)
3135      ELSE
3136         CALL shmem_int8_sum_to_all(nistab_shmem,nistab_shmem,kdim,0,0,   &
3137              N$PES,nis2wrk_shmem,nis2sync_shmem)
3138      ENDIF
3139      CALL  barrier()
3140      ibool = ibool + 1
3141      ibool = MOD( ibool, 2 )
3142      DO ji = 1, kdim
3143         ktab(ji) = nistab_shmem(ji)
3144      END DO
3145 
3146#  elif defined key_mpp_mpi
3147
3148      !! * Local variables   (MPI version)
3149      INTEGER :: ierror
3150      INTEGER, DIMENSION (kdim) ::  iwork
3151 
3152      CALL mpi_allreduce(ktab, iwork,kdim,mpi_integer   &
3153           ,mpi_sum,mpi_comm_world,ierror)
3154 
3155      ktab(:) = iwork(:)
3156#endif
3157
3158   END SUBROUTINE mppsum_a_int
3159
3160
3161  SUBROUTINE mppsum_int( ktab )
3162    !!----------------------------------------------------------------------
3163    !!                 ***  routine mppsum_int  ***
3164    !!                 
3165    !! ** Purpose :   Global integer sum
3166    !!
3167    !!----------------------------------------------------------------------
3168    !! * Arguments
3169    INTEGER, INTENT(inout) ::   ktab
3170
3171#if defined key_mpp_shmem
3172
3173    !! * Local variables   (SHMEM version)
3174    INTEGER, SAVE :: ibool=0
3175
3176    nistab_shmem(1) = ktab
3177    CALL  barrier()
3178    IF(ibool == 0 ) THEN
3179       CALL shmem_int8_sum_to_all(nistab_shmem,nistab_shmem, 1,0,0,   &
3180            N$PES,nis1wrk_shmem,nis1sync_shmem)
3181    ELSE
3182       CALL shmem_int8_sum_to_all(nistab_shmem,nistab_shmem, 1,0,0,   &
3183            N$PES,nis2wrk_shmem,nis2sync_shmem)
3184    ENDIF
3185    CALL  barrier()
3186    ibool=ibool+1
3187    ibool=MOD( ibool,2)
3188    ktab = nistab_shmem(1)
3189
3190#  elif defined key_mpp_mpi
3191
3192    !! * Local variables   (MPI version)
3193    INTEGER :: ierror, iwork
3194
3195    CALL mpi_allreduce(ktab,iwork, 1,mpi_integer   &
3196         ,mpi_sum,mpi_comm_world,ierror)
3197
3198    ktab = iwork
3199
3200#endif
3201
3202  END SUBROUTINE mppsum_int
3203
3204
3205  SUBROUTINE mppisl_a_real( ptab, kdim )
3206    !!----------------------------------------------------------------------
3207    !!                 ***  routine mppisl_a_real  ***
3208    !!         
3209    !! ** Purpose :   Massively parallel processors
3210    !!           Find the non zero island barotropic stream function value
3211    !!
3212    !!   Modifications:
3213    !!        !  93-09 (M. Imbard)
3214    !!        !  96-05 (j. Escobar)
3215    !!        !  98-05 (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
3216    !!----------------------------------------------------------------------
3217    INTEGER , INTENT( in  )                  ::   kdim      ! ???
3218    REAL(wp), INTENT(inout), DIMENSION(kdim) ::   ptab      ! ???
3219
3220#if defined key_mpp_shmem
3221
3222    !! * Local variables   (SHMEM version)
3223    INTEGER :: ji
3224    INTEGER, SAVE :: ibool=0
3225
3226    IF( kdim > jpmppsum ) CALL ctl_stop( 'mppisl_a_real routine : kdim is too big', &
3227         &                               'change jpmppsum dimension in mpp.h' )
3228
3229    DO ji = 1, kdim
3230       wiltab_shmem(ji) = ptab(ji)
3231    END DO
3232    CALL  barrier()
3233    IF(ibool == 0 ) THEN
3234       CALL shmem_real8_min_to_all (wi1tab_shmem,wiltab_shmem,kdim,0   &
3235            ,0,N$PES,wi11wrk_shmem,ni11sync_shmem)
3236       CALL shmem_real8_max_to_all (wi2tab_shmem,wiltab_shmem,kdim,0   &
3237            ,0,N$PES,wi12wrk_shmem,ni12sync_shmem)
3238    ELSE
3239       CALL shmem_real8_min_to_all (wi1tab_shmem,wiltab_shmem,kdim,0   &
3240            ,0,N$PES,wi21wrk_shmem,ni21sync_shmem)
3241       CALL shmem_real8_max_to_all (wi2tab_shmem,wiltab_shmem,kdim,0   &
3242            ,0,N$PES,wi22wrk_shmem,ni22sync_shmem)
3243    ENDIF
3244    CALL  barrier()
3245    ibool=ibool+1
3246    ibool=MOD( ibool,2)
3247    DO ji = 1, kdim
3248       IF(wi1tab_shmem(ji) /= 0. ) THEN
3249          ptab(ji) = wi1tab_shmem(ji)
3250       ELSE
3251          ptab(ji) = wi2tab_shmem(ji)
3252       ENDIF
3253    END DO
3254
3255#  elif defined key_mpp_mpi
3256
3257    !! * Local variables   (MPI version)
3258    LOGICAL ::   lcommute = .TRUE.
3259    INTEGER ::   mpi_isl, ierror
3260    REAL(wp), DIMENSION(kdim) ::  zwork
3261
3262    CALL mpi_op_create(lc_isl,lcommute,mpi_isl,ierror)
3263    CALL mpi_allreduce(ptab, zwork,kdim,mpi_double_precision   &
3264         ,mpi_isl,mpi_comm_world,ierror)
3265    ptab(:) = zwork(:)
3266
3267#endif
3268
3269  END SUBROUTINE mppisl_a_real
3270
3271
3272   SUBROUTINE mppisl_real( ptab )
3273      !!----------------------------------------------------------------------
3274      !!                  ***  routine mppisl_real  ***
3275      !!                 
3276      !! ** Purpose :   Massively parallel processors
3277      !!       Find the  non zero island barotropic stream function value
3278      !!
3279      !!     Modifications:
3280      !!        !  93-09 (M. Imbard)
3281      !!        !  96-05 (j. Escobar)
3282      !!        !  98-05 (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
3283      !!----------------------------------------------------------------------
3284      REAL(wp), INTENT(inout) ::   ptab
3285
3286#if defined key_mpp_shmem
3287
3288      !! * Local variables   (SHMEM version)
3289      INTEGER, SAVE :: ibool=0
3290
3291      wiltab_shmem(1) = ptab
3292      CALL  barrier()
3293      IF(ibool == 0 ) THEN
3294         CALL shmem_real8_min_to_all (wi1tab_shmem,wiltab_shmem, 1,0   &
3295            ,0,N$PES,wi11wrk_shmem,ni11sync_shmem)
3296         CALL shmem_real8_max_to_all (wi2tab_shmem,wiltab_shmem, 1,0   &
3297            ,0,N$PES,wi12wrk_shmem,ni12sync_shmem)
3298      ELSE
3299         CALL shmem_real8_min_to_all (wi1tab_shmem,wiltab_shmem, 1,0   &
3300            ,0,N$PES,wi21wrk_shmem,ni21sync_shmem)
3301         CALL shmem_real8_max_to_all (wi2tab_shmem,wiltab_shmem, 1,0   &
3302            ,0,N$PES,wi22wrk_shmem,ni22sync_shmem)
3303      ENDIF
3304      CALL barrier()
3305      ibool = ibool + 1
3306      ibool = MOD( ibool, 2 )
3307      IF( wi1tab_shmem(1) /= 0. ) THEN
3308         ptab = wi1tab_shmem(1)
3309      ELSE
3310         ptab = wi2tab_shmem(1)
3311      ENDIF
3312
3313#  elif defined key_mpp_mpi
3314
3315      !! * Local variables   (MPI version)
3316      LOGICAL  ::   lcommute = .TRUE.
3317      INTEGER  ::   mpi_isl, ierror
3318      REAL(wp) ::   zwork
3319
3320      CALL mpi_op_create( lc_isl, lcommute, mpi_isl, ierror )
3321      CALL mpi_allreduce( ptab, zwork, 1, mpi_double_precision,   &
3322         &                                mpi_isl  , mpi_comm_world, ierror )
3323      ptab = zwork
3324
3325#endif
3326
3327   END SUBROUTINE mppisl_real
3328
3329
3330  FUNCTION lc_isl( py, px, kdim, kdtatyp )
3331    INTEGER :: kdim
3332    REAL(wp), DIMENSION(kdim) ::  px, py
3333    INTEGER :: kdtatyp, ji
3334    INTEGER :: lc_isl
3335    DO ji = 1, kdim
3336       IF( py(ji) /= 0. )   px(ji) = py(ji)
3337    END DO
3338    lc_isl=0
3339
3340  END FUNCTION lc_isl
3341
3342
3343  SUBROUTINE mppmax_a_real( ptab, kdim )
3344    !!----------------------------------------------------------------------
3345    !!                 ***  routine mppmax_a_real  ***
3346    !!                 
3347    !! ** Purpose :   Maximum
3348    !!
3349    !!----------------------------------------------------------------------
3350    !! * Arguments
3351    INTEGER , INTENT( in  )                  ::   kdim
3352    REAL(wp), INTENT(inout), DIMENSION(kdim) ::   ptab
3353
3354#if defined key_mpp_shmem
3355
3356    !! * Local variables   (SHMEM version)
3357    INTEGER :: ji
3358    INTEGER, SAVE :: ibool=0
3359
3360    IF( kdim > jpmppsum ) CALL ctl_stop( 'mppmax_a_real routine : kdim is too big', &
3361         &                               'change jpmppsum dimension in mpp.h' )
3362
3363    DO ji = 1, kdim
3364       wintab_shmem(ji) = ptab(ji)
3365    END DO
3366    CALL  barrier()
3367    IF(ibool == 0 ) THEN
3368       CALL shmem_real8_max_to_all (wintab_shmem,wintab_shmem,kdim,0   &
3369            ,0,N$PES,wi1wrk_shmem,ni1sync_shmem)
3370    ELSE
3371       CALL shmem_real8_max_to_all (wintab_shmem,wintab_shmem,kdim,0   &
3372            ,0,N$PES,wi2wrk_shmem,ni2sync_shmem)
3373    ENDIF
3374    CALL  barrier()
3375    ibool=ibool+1
3376    ibool=MOD( ibool,2)
3377    DO ji = 1, kdim
3378       ptab(ji) = wintab_shmem(ji)
3379    END DO
3380
3381#  elif defined key_mpp_mpi
3382
3383    !! * Local variables   (MPI version)
3384    INTEGER :: ierror
3385    REAL(wp), DIMENSION(kdim) ::  zwork
3386
3387    CALL mpi_allreduce(ptab, zwork,kdim,mpi_double_precision   &
3388         ,mpi_max,mpi_comm_world,ierror)
3389    ptab(:) = zwork(:)
3390
3391#endif
3392
3393  END SUBROUTINE mppmax_a_real
3394
3395
3396  SUBROUTINE mppmax_real( ptab )
3397    !!----------------------------------------------------------------------
3398    !!                  ***  routine mppmax_real  ***
3399    !!                   
3400    !! ** Purpose :   Maximum
3401    !!
3402    !!----------------------------------------------------------------------
3403    !! * Arguments
3404    REAL(wp), INTENT(inout) ::   ptab      ! ???
3405
3406#if defined key_mpp_shmem
3407
3408    !! * Local variables   (SHMEM version)
3409    INTEGER, SAVE :: ibool=0
3410
3411    wintab_shmem(1) = ptab
3412    CALL  barrier()
3413    IF(ibool == 0 ) THEN
3414       CALL shmem_real8_max_to_all (wintab_shmem,wintab_shmem, 1,0   &
3415            ,0,N$PES,wi1wrk_shmem,ni1sync_shmem)
3416    ELSE
3417       CALL shmem_real8_max_to_all (wintab_shmem,wintab_shmem, 1,0   &
3418            ,0,N$PES,wi2wrk_shmem,ni2sync_shmem)
3419    ENDIF
3420    CALL  barrier()
3421    ibool=ibool+1
3422    ibool=MOD( ibool,2)
3423    ptab = wintab_shmem(1)
3424
3425#  elif defined key_mpp_mpi
3426
3427    !! * Local variables   (MPI version)
3428    INTEGER  ::   ierror
3429    REAL(wp) ::   zwork
3430
3431    CALL mpi_allreduce( ptab, zwork  , 1             , mpi_double_precision,   &
3432       &                      mpi_max, mpi_comm_world, ierror     )
3433    ptab = zwork
3434
3435#endif
3436
3437  END SUBROUTINE mppmax_real
3438
3439
3440  SUBROUTINE mppmin_a_real( ptab, kdim )
3441    !!----------------------------------------------------------------------
3442    !!                 ***  routine mppmin_a_real  ***
3443    !!                 
3444    !! ** Purpose :   Minimum
3445    !!
3446    !!-----------------------------------------------------------------------
3447    !! * Arguments
3448    INTEGER , INTENT( in  )                  ::   kdim
3449    REAL(wp), INTENT(inout), DIMENSION(kdim) ::   ptab
3450
3451#if defined key_mpp_shmem
3452
3453    !! * Local variables   (SHMEM version)
3454    INTEGER :: ji
3455    INTEGER, SAVE :: ibool=0
3456
3457    IF( kdim > jpmppsum ) CALL ctl_stop( 'mpprmin routine : kdim is too big', &
3458         &                               'change jpmppsum dimension in mpp.h' )
3459
3460    DO ji = 1, kdim
3461       wintab_shmem(ji) = ptab(ji)
3462    END DO
3463    CALL  barrier()
3464    IF(ibool == 0 ) THEN
3465       CALL shmem_real8_min_to_all (wintab_shmem,wintab_shmem,kdim,0   &
3466            ,0,N$PES,wi1wrk_shmem,ni1sync_shmem)
3467    ELSE
3468       CALL shmem_real8_min_to_all (wintab_shmem,wintab_shmem,kdim,0   &
3469            ,0,N$PES,wi2wrk_shmem,ni2sync_shmem)
3470    ENDIF
3471    CALL  barrier()
3472    ibool=ibool+1
3473    ibool=MOD( ibool,2)
3474    DO ji = 1, kdim
3475       ptab(ji) = wintab_shmem(ji)
3476    END DO
3477
3478#  elif defined key_mpp_mpi
3479
3480    !! * Local variables   (MPI version)
3481    INTEGER :: ierror
3482    REAL(wp), DIMENSION(kdim) ::   zwork
3483
3484    CALL mpi_allreduce(ptab, zwork,kdim,mpi_double_precision   &
3485         ,mpi_min,mpi_comm_world,ierror)
3486    ptab(:) = zwork(:)
3487
3488#endif
3489
3490  END SUBROUTINE mppmin_a_real
3491
3492
3493  SUBROUTINE mppmin_real( ptab )
3494    !!----------------------------------------------------------------------
3495    !!                  ***  routine mppmin_real  ***
3496    !!
3497    !! ** Purpose :   minimum in Massively Parallel Processing
3498    !!                REAL scalar case
3499    !!
3500    !!-----------------------------------------------------------------------
3501    !! * Arguments
3502    REAL(wp), INTENT( inout ) ::   ptab        !
3503
3504#if defined key_mpp_shmem
3505
3506    !! * Local variables   (SHMEM version)
3507    INTEGER, SAVE :: ibool=0
3508
3509    wintab_shmem(1) = ptab
3510    CALL  barrier()
3511    IF(ibool == 0 ) THEN
3512       CALL shmem_real8_min_to_all (wintab_shmem,wintab_shmem, 1,0   &
3513            ,0,N$PES,wi1wrk_shmem,ni1sync_shmem)
3514    ELSE
3515       CALL shmem_real8_min_to_all (wintab_shmem,wintab_shmem, 1,0   &
3516            ,0,N$PES,wi2wrk_shmem,ni2sync_shmem)
3517    ENDIF
3518    CALL  barrier()
3519    ibool=ibool+1
3520    ibool=MOD( ibool,2)
3521    ptab = wintab_shmem(1)
3522
3523#  elif defined key_mpp_mpi
3524
3525    !! * Local variables   (MPI version)
3526    INTEGER  ::   ierror
3527    REAL(wp) ::   zwork
3528
3529    CALL mpi_allreduce( ptab, zwork, 1,mpi_double_precision   &
3530         &               ,mpi_min,mpi_comm_world,ierror)
3531    ptab = zwork
3532
3533#endif
3534
3535  END SUBROUTINE mppmin_real
3536
3537
3538  SUBROUTINE mppsum_a_real( ptab, kdim )
3539    !!----------------------------------------------------------------------
3540    !!                  ***  routine mppsum_a_real  ***
3541    !!
3542    !! ** Purpose :   global sum in Massively Parallel Processing
3543    !!                REAL ARRAY argument case
3544    !!
3545    !!-----------------------------------------------------------------------
3546    INTEGER , INTENT( in )                     ::   kdim      ! size of ptab
3547    REAL(wp), DIMENSION(kdim), INTENT( inout ) ::   ptab      ! input array
3548
3549#if defined key_mpp_shmem
3550
3551    !! * Local variables   (SHMEM version)
3552    INTEGER :: ji
3553    INTEGER, SAVE :: ibool=0
3554
3555    IF( kdim > jpmppsum ) CALL ctl_stop( 'mppsum_a_real routine : kdim is too big', &
3556         &                               'change jpmppsum dimension in mpp.h' )
3557
3558    DO ji = 1, kdim
3559       wrstab_shmem(ji) = ptab(ji)
3560    END DO
3561    CALL  barrier()
3562    IF(ibool == 0 ) THEN
3563       CALL shmem_real8_sum_to_all (wrstab_shmem,wrstab_shmem,kdim,0   &
3564            ,0,N$PES,wrs1wrk_shmem,nrs1sync_shmem )
3565    ELSE
3566       CALL shmem_real8_sum_to_all (wrstab_shmem,wrstab_shmem,kdim,0   &
3567            ,0,N$PES,wrs2wrk_shmem,nrs2sync_shmem )
3568    ENDIF
3569    CALL  barrier()
3570    ibool=ibool+1
3571    ibool=MOD( ibool,2)
3572    DO ji = 1, kdim
3573       ptab(ji) = wrstab_shmem(ji)
3574    END DO
3575
3576#  elif defined key_mpp_mpi
3577
3578    !! * Local variables   (MPI version)
3579    INTEGER                   ::   ierror    ! temporary integer
3580    REAL(wp), DIMENSION(kdim) ::   zwork     ! temporary workspace
3581
3582    CALL mpi_allreduce(ptab, zwork,kdim,mpi_double_precision   &
3583         &              ,mpi_sum,mpi_comm_world,ierror)
3584    ptab(:) = zwork(:)
3585
3586#endif
3587
3588  END SUBROUTINE mppsum_a_real
3589
3590
3591  SUBROUTINE mppsum_real( ptab )
3592    !!----------------------------------------------------------------------
3593    !!                  ***  routine mppsum_real  ***
3594    !!             
3595    !! ** Purpose :   global sum in Massively Parallel Processing
3596    !!                SCALAR argument case
3597    !!
3598    !!-----------------------------------------------------------------------
3599    REAL(wp), INTENT(inout) ::   ptab        ! input scalar
3600
3601#if defined key_mpp_shmem
3602
3603    !! * Local variables   (SHMEM version)
3604    INTEGER, SAVE :: ibool=0
3605
3606    wrstab_shmem(1) = ptab
3607    CALL  barrier()
3608    IF(ibool == 0 ) THEN
3609       CALL shmem_real8_sum_to_all (wrstab_shmem,wrstab_shmem, 1,0   &
3610            ,0,N$PES,wrs1wrk_shmem,nrs1sync_shmem )
3611    ELSE
3612       CALL shmem_real8_sum_to_all (wrstab_shmem,wrstab_shmem, 1,0   &
3613            ,0,N$PES,wrs2wrk_shmem,nrs2sync_shmem )
3614    ENDIF
3615    CALL  barrier()
3616    ibool = ibool + 1
3617    ibool = MOD( ibool, 2 )
3618    ptab = wrstab_shmem(1)
3619
3620#  elif defined key_mpp_mpi
3621
3622    !! * Local variables   (MPI version)
3623    INTEGER  ::   ierror
3624    REAL(wp) ::   zwork
3625
3626    CALL mpi_allreduce(ptab, zwork, 1,mpi_double_precision   &
3627         &              ,mpi_sum,mpi_comm_world,ierror)
3628    ptab = zwork
3629
3630#endif
3631
3632  END SUBROUTINE mppsum_real
3633
3634  SUBROUTINE mpp_minloc2d(ptab, pmask, pmin, ki,kj )
3635    !!------------------------------------------------------------------------
3636    !!             ***  routine mpp_minloc  ***
3637    !!
3638    !! ** Purpose :  Compute the global minimum of an array ptab
3639    !!              and also give its global position
3640    !!
3641    !! ** Method : Use MPI_ALLREDUCE with MPI_MINLOC
3642    !!
3643    !! ** Arguments : I : ptab =local 2D array
3644    !!                O : pmin = global minimum
3645    !!                O : ki,kj = global position of minimum
3646    !!
3647    !! ** Author : J.M. Molines 10/10/2004
3648    !!--------------------------------------------------------------------------
3649#ifdef key_mpp_shmem
3650    CALL ctl_stop( ' mpp_minloc not yet available in SHMEM' )
3651# elif key_mpp_mpi
3652    !! * Arguments
3653    REAL(wp), DIMENSION (jpi,jpj), INTENT (in)  :: ptab ,& ! Local 2D array
3654         &                                         pmask   ! Local mask
3655    REAL(wp)                     , INTENT (out) :: pmin    ! Global minimum of ptab
3656    INTEGER                      , INTENT (out) :: ki,kj   ! index of minimum in global frame
3657
3658    !! * Local variables
3659    REAL(wp) :: zmin   ! local minimum
3660    REAL(wp) ,DIMENSION(2,1) :: zain, zaout
3661    INTEGER, DIMENSION (2)  :: ilocs
3662    INTEGER :: ierror
3663
3664
3665    zmin  = MINVAL( ptab(:,:) , mask= pmask == 1.e0 )
3666    ilocs = MINLOC( ptab(:,:) , mask= pmask == 1.e0 )
3667
3668    ki = ilocs(1) + nimpp - 1
3669    kj = ilocs(2) + njmpp - 1
3670
3671    zain(1,:)=zmin
3672    zain(2,:)=ki+10000.*kj
3673
3674    CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MINLOC,MPI_COMM_WORLD,ierror)
3675
3676    pmin=zaout(1,1)
3677    kj= INT(zaout(2,1)/10000.)
3678    ki= INT(zaout(2,1) - 10000.*kj )
3679#endif
3680
3681  END SUBROUTINE mpp_minloc2d
3682
3683
3684  SUBROUTINE mpp_minloc3d(ptab, pmask, pmin, ki,kj ,kk)
3685    !!------------------------------------------------------------------------
3686    !!             ***  routine mpp_minloc  ***
3687    !!
3688    !! ** Purpose :  Compute the global minimum of an array ptab
3689    !!              and also give its global position
3690    !!
3691    !! ** Method : Use MPI_ALLREDUCE with MPI_MINLOC
3692    !!
3693    !! ** Arguments : I : ptab =local 2D array
3694    !!                O : pmin = global minimum
3695    !!                O : ki,kj = global position of minimum
3696    !!
3697    !! ** Author : J.M. Molines 10/10/2004
3698    !!--------------------------------------------------------------------------
3699#ifdef key_mpp_shmem
3700    CALL ctl_stop( ' mpp_minloc not yet available in SHMEM' )
3701# elif key_mpp_mpi
3702    !! * Arguments
3703    REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT (in)  :: ptab ,& ! Local 2D array
3704         &                                         pmask   ! Local mask
3705    REAL(wp)                     , INTENT (out) :: pmin    ! Global minimum of ptab
3706    INTEGER                      , INTENT (out) :: ki,kj,kk ! index of minimum in global frame
3707
3708    !! * Local variables
3709    REAL(wp) :: zmin   ! local minimum
3710    REAL(wp) ,DIMENSION(2,1) :: zain, zaout
3711    INTEGER, DIMENSION (3)  :: ilocs
3712    INTEGER :: ierror
3713
3714
3715    zmin  = MINVAL( ptab(:,:,:) , mask= pmask == 1.e0 )
3716    ilocs = MINLOC( ptab(:,:,:) , mask= pmask == 1.e0 )
3717
3718    ki = ilocs(1) + nimpp - 1
3719    kj = ilocs(2) + njmpp - 1
3720    kk = ilocs(3)
3721
3722    zain(1,:)=zmin
3723    zain(2,:)=ki+10000.*kj+100000000.*kk
3724
3725    CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MINLOC,MPI_COMM_WORLD,ierror)
3726
3727    pmin=zaout(1,1)
3728    kk= INT(zaout(2,1)/100000000.)
3729    kj= INT(zaout(2,1) - kk * 100000000. )/10000
3730    ki= INT(zaout(2,1) - kk * 100000000. -kj * 10000. )
3731#endif
3732
3733  END SUBROUTINE mpp_minloc3d
3734
3735
3736  SUBROUTINE mpp_maxloc2d(ptab, pmask, pmax, ki,kj )
3737    !!------------------------------------------------------------------------
3738    !!             ***  routine mpp_maxloc  ***
3739    !!
3740    !! ** Purpose :  Compute the global maximum of an array ptab
3741    !!              and also give its global position
3742    !!
3743    !! ** Method : Use MPI_ALLREDUCE with MPI_MINLOC
3744    !!
3745    !! ** Arguments : I : ptab =local 2D array
3746    !!                O : pmax = global maximum
3747    !!                O : ki,kj = global position of maximum
3748    !!
3749    !! ** Author : J.M. Molines 10/10/2004
3750    !!--------------------------------------------------------------------------
3751#ifdef key_mpp_shmem
3752    CALL ctl_stop( ' mpp_maxloc not yet available in SHMEM' )
3753# elif key_mpp_mpi
3754    !! * Arguments
3755    REAL(wp), DIMENSION (jpi,jpj), INTENT (in)  :: ptab ,& ! Local 2D array
3756         &                                         pmask   ! Local mask
3757    REAL(wp)                     , INTENT (out) :: pmax    ! Global maximum of ptab
3758    INTEGER                      , INTENT (out) :: ki,kj   ! index of maximum in global frame
3759
3760    !! * Local variables
3761    REAL(wp) :: zmax   ! local maximum
3762    REAL(wp) ,DIMENSION(2,1) :: zain, zaout
3763    INTEGER, DIMENSION (2)  :: ilocs
3764    INTEGER :: ierror
3765
3766
3767    zmax  = MAXVAL( ptab(:,:) , mask= pmask == 1.e0 )
3768    ilocs = MAXLOC( ptab(:,:) , mask= pmask == 1.e0 )
3769
3770    ki = ilocs(1) + nimpp - 1
3771    kj = ilocs(2) + njmpp - 1
3772
3773    zain(1,:)=zmax
3774    zain(2,:)=ki+10000.*kj
3775
3776    CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MAXLOC,MPI_COMM_WORLD,ierror)
3777
3778    pmax=zaout(1,1)
3779    kj= INT(zaout(2,1)/10000.)
3780    ki= INT(zaout(2,1) - 10000.*kj )
3781#endif
3782
3783  END SUBROUTINE mpp_maxloc2d
3784
3785  SUBROUTINE mpp_maxloc3d(ptab, pmask, pmax, ki,kj,kk )
3786    !!------------------------------------------------------------------------
3787    !!             ***  routine mpp_maxloc  ***
3788    !!
3789    !! ** Purpose :  Compute the global maximum of an array ptab
3790    !!              and also give its global position
3791    !!
3792    !! ** Method : Use MPI_ALLREDUCE with MPI_MINLOC
3793    !!
3794    !! ** Arguments : I : ptab =local 2D array
3795    !!                O : pmax = global maximum
3796    !!                O : ki,kj = global position of maximum
3797    !!
3798    !! ** Author : J.M. Molines 10/10/2004
3799    !!--------------------------------------------------------------------------
3800#ifdef key_mpp_shmem
3801    CALL ctl_stop( ' mpp_maxloc not yet available in SHMEM' )
3802# elif key_mpp_mpi
3803    !! * Arguments
3804    REAL(wp), DIMENSION (jpi,jpj,jpk), INTENT (in)  :: ptab ,& ! Local 2D array
3805         &                                         pmask   ! Local mask
3806    REAL(wp)                     , INTENT (out) :: pmax    ! Global maximum of ptab
3807    INTEGER                      , INTENT (out) :: ki,kj,kk   ! index of maximum in global frame
3808
3809    !! * Local variables
3810    REAL(wp) :: zmax   ! local maximum
3811    REAL(wp) ,DIMENSION(2,1) :: zain, zaout
3812    INTEGER, DIMENSION (3)  :: ilocs
3813    INTEGER :: ierror
3814
3815
3816    zmax  = MAXVAL( ptab(:,:,:) , mask= pmask == 1.e0 )
3817    ilocs = MAXLOC( ptab(:,:,:) , mask= pmask == 1.e0 )
3818
3819    ki = ilocs(1) + nimpp - 1
3820    kj = ilocs(2) + njmpp - 1
3821    kk = ilocs(3)
3822
3823    zain(1,:)=zmax
3824    zain(2,:)=ki+10000.*kj+100000000.*kk
3825
3826    CALL MPI_ALLREDUCE( zain,zaout, 1, MPI_2DOUBLE_PRECISION,MPI_MAXLOC,MPI_COMM_WORLD,ierror)
3827
3828    pmax=zaout(1,1)
3829    kk= INT(zaout(2,1)/100000000.)
3830    kj= INT(zaout(2,1) - kk * 100000000. )/10000
3831    ki= INT(zaout(2,1) - kk * 100000000. -kj * 10000. )
3832#endif
3833
3834  END SUBROUTINE mpp_maxloc3d
3835
3836  SUBROUTINE mppsync()
3837    !!----------------------------------------------------------------------
3838    !!                  ***  routine mppsync  ***
3839    !!                   
3840    !! ** Purpose :   Massively parallel processors, synchroneous
3841    !!
3842    !!-----------------------------------------------------------------------
3843
3844#if defined key_mpp_shmem
3845
3846    !! * Local variables   (SHMEM version)
3847    CALL barrier()
3848
3849#  elif defined key_mpp_mpi
3850
3851    !! * Local variables   (MPI version)
3852    INTEGER :: ierror
3853
3854    CALL mpi_barrier(mpi_comm_world,ierror)
3855
3856#endif
3857
3858  END SUBROUTINE mppsync
3859
3860
3861  SUBROUTINE mppstop
3862    !!----------------------------------------------------------------------
3863    !!                  ***  routine mppstop  ***
3864    !!                   
3865    !! ** purpose :   Stop massilively parallel processors method
3866    !!
3867    !!----------------------------------------------------------------------
3868    !! * Local declarations
3869    INTEGER ::   info
3870    !!----------------------------------------------------------------------
3871
3872    ! 1. Mpp synchroneus
3873    ! ------------------
3874
3875    CALL mppsync
3876#if defined key_mpp_mpi
3877    CALL mpi_finalize( info )
3878#endif
3879
3880  END SUBROUTINE mppstop
3881
3882
3883  SUBROUTINE mppobc( ptab, kd1, kd2, kl, kk, ktype, kij )
3884    !!----------------------------------------------------------------------
3885    !!                  ***  routine mppobc  ***
3886    !!
3887    !! ** Purpose :   Message passing manadgement for open boundary
3888    !!     conditions array
3889    !!
3890    !! ** Method  :   Use mppsend and mpprecv function for passing mask
3891    !!       between processors following neighboring subdomains.
3892    !!       domain parameters
3893    !!                    nlci   : first dimension of the local subdomain
3894    !!                    nlcj   : second dimension of the local subdomain
3895    !!                    nbondi : mark for "east-west local boundary"
3896    !!                    nbondj : mark for "north-south local boundary"
3897    !!                    noea   : number for local neighboring processors
3898    !!                    nowe   : number for local neighboring processors
3899    !!                    noso   : number for local neighboring processors
3900    !!                    nono   : number for local neighboring processors
3901    !!
3902    !! History :
3903    !!        !  98-07 (J.M. Molines) Open boundary conditions
3904    !!----------------------------------------------------------------------
3905    !! * Arguments
3906    INTEGER , INTENT( in ) ::   &
3907         kd1, kd2,   &  ! starting and ending indices
3908         kl ,        &  ! index of open boundary
3909         kk,         &  ! vertical dimension
3910         ktype,      &  ! define north/south or east/west cdt
3911         !              !  = 1  north/south  ;  = 2  east/west
3912         kij            ! horizontal dimension
3913    REAL(wp), DIMENSION(kij,kk), INTENT( inout )  ::   &
3914         ptab           ! variable array
3915
3916    !! * Local variables
3917    INTEGER  ::   ji, jj, jk, jl   ! dummy loop indices
3918    INTEGER  ::   &
3919         iipt0, iipt1, ilpt1,     &  ! temporary integers
3920         ijpt0, ijpt1,            &  !    "          "
3921         imigr, iihom, ijhom         !    "          "
3922    INTEGER ::   ml_req1, ml_req2, ml_err     ! for key_mpi_isend
3923    INTEGER ::   ml_stat(MPI_STATUS_SIZE)     ! for key_mpi_isend
3924    REAL(wp), DIMENSION(jpi,jpj) ::   &
3925         ztab                        ! temporary workspace
3926    !!----------------------------------------------------------------------
3927
3928
3929    ! boundary condition initialization
3930    ! ---------------------------------
3931
3932    ztab(:,:) = 0.e0
3933
3934    IF( ktype==1 ) THEN                                  ! north/south boundaries
3935       iipt0 = MAX( 1, MIN(kd1 - nimpp+1, nlci     ) )
3936       iipt1 = MAX( 0, MIN(kd2 - nimpp+1, nlci - 1 ) )
3937       ilpt1 = MAX( 1, MIN(kd2 - nimpp+1, nlci     ) )
3938       ijpt0 = MAX( 1, MIN(kl  - njmpp+1, nlcj     ) )
3939       ijpt1 = MAX( 0, MIN(kl  - njmpp+1, nlcj - 1 ) )
3940    ELSEIF( ktype==2 ) THEN                              ! east/west boundaries
3941       iipt0 = MAX( 1, MIN(kl  - nimpp+1, nlci     ) )
3942       iipt1 = MAX( 0, MIN(kl  - nimpp+1, nlci - 1 ) )
3943       ijpt0 = MAX( 1, MIN(kd1 - njmpp+1, nlcj     ) )
3944       ijpt1 = MAX( 0, MIN(kd2 - njmpp+1, nlcj - 1 ) )
3945       ilpt1 = MAX( 1, MIN(kd2 - njmpp+1, nlcj     ) )
3946    ELSE
3947       CALL ctl_stop( 'mppobc: bad ktype' )
3948    ENDIF
3949
3950    DO jk = 1, kk
3951       IF( ktype==1 ) THEN                               ! north/south boundaries
3952          DO jj = ijpt0, ijpt1
3953             DO ji = iipt0, iipt1
3954                ztab(ji,jj) = ptab(ji,jk)
3955             END DO
3956          END DO
3957       ELSEIF( ktype==2 ) THEN                           ! east/west boundaries
3958          DO jj = ijpt0, ijpt1
3959             DO ji = iipt0, iipt1
3960                ztab(ji,jj) = ptab(jj,jk)
3961             END DO
3962          END DO
3963       ENDIF
3964
3965
3966       ! 1. East and west directions
3967       ! ---------------------------
3968
3969       ! 1.1 Read Dirichlet lateral conditions
3970
3971       IF( nbondi /= 2 ) THEN
3972          iihom = nlci-nreci
3973
3974          DO jl = 1, jpreci
3975             t2ew(:,jl,1) = ztab(jpreci+jl,:)
3976             t2we(:,jl,1) = ztab(iihom +jl,:)
3977          END DO
3978       ENDIF
3979
3980       ! 1.2 Migrations
3981
3982#if defined key_mpp_shmem
3983       !! *  (SHMEM version)
3984       imigr=jpreci*jpj*jpbyt
3985
3986       IF( nbondi == -1 ) THEN
3987          CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr/jpbyt, noea )
3988       ELSEIF( nbondi == 0 ) THEN
3989          CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr/jpbyt, nowe )
3990          CALL shmem_put( t2we(1,1,2), t2we(1,1,1), imigr/jpbyt, noea )
3991       ELSEIF( nbondi == 1 ) THEN
3992          CALL shmem_put( t2ew(1,1,2), t2ew(1,1,1), imigr/jpbyt, nowe )
3993       ENDIF
3994       CALL barrier()
3995       CALL shmem_udcflush()
3996
3997#  elif key_mpp_mpi
3998       !! * (MPI version)
3999
4000       imigr=jpreci*jpj
4001
4002       IF( nbondi == -1 ) THEN
4003          CALL mppsend(2,t2we(1,1,1),imigr,noea, ml_req1)
4004          CALL mpprecv(1,t2ew(1,1,2),imigr)
4005          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4006       ELSEIF( nbondi == 0 ) THEN
4007          CALL mppsend(1,t2ew(1,1,1),imigr,nowe, ml_req1)
4008          CALL mppsend(2,t2we(1,1,1),imigr,noea, ml_req2)
4009          CALL mpprecv(1,t2ew(1,1,2),imigr)
4010          CALL mpprecv(2,t2we(1,1,2),imigr)
4011          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4012          IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
4013       ELSEIF( nbondi == 1 ) THEN
4014          CALL mppsend(1,t2ew(1,1,1),imigr,nowe, ml_req1)
4015          CALL mpprecv(2,t2we(1,1,2),imigr)
4016          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4017       ENDIF
4018#endif
4019
4020
4021       ! 1.3 Write Dirichlet lateral conditions
4022
4023       iihom = nlci-jpreci
4024       IF( nbondi == 0 .OR. nbondi == 1 ) THEN
4025          DO jl = 1, jpreci
4026             ztab(jl,:) = t2we(:,jl,2)
4027          END DO
4028       ENDIF
4029
4030       IF( nbondi == -1 .OR. nbondi == 0 ) THEN
4031          DO jl = 1, jpreci
4032             ztab(iihom+jl,:) = t2ew(:,jl,2)
4033          END DO
4034       ENDIF
4035
4036
4037       ! 2. North and south directions
4038       ! -----------------------------
4039
4040       ! 2.1 Read Dirichlet lateral conditions
4041
4042       IF( nbondj /= 2 ) THEN
4043          ijhom = nlcj-nrecj
4044          DO jl = 1, jprecj
4045             t2sn(:,jl,1) = ztab(:,ijhom +jl)
4046             t2ns(:,jl,1) = ztab(:,jprecj+jl)
4047          END DO
4048       ENDIF
4049
4050       ! 2.2 Migrations
4051
4052#if defined key_mpp_shmem
4053       !! * SHMEM version
4054
4055       imigr=jprecj*jpi*jpbyt
4056
4057       IF( nbondj == -1 ) THEN
4058          CALL shmem_put( t2sn(1,1,2), t2sn(1,1,1), imigr/jpbyt, nono )
4059       ELSEIF( nbondj == 0 ) THEN
4060          CALL shmem_put( t2ns(1,1,2), t2ns(1,1,1), imigr/jpbyt, noso )
4061          CALL shmem_put( t2sn(1,1,2), t2sn(1,1,1), imigr/jpbyt, nono )
4062       ELSEIF( nbondj == 1 ) THEN
4063          CALL shmem_put( t2ns(1,1,2), t2ns(1,1,1), imigr/jpbyt, noso )
4064       ENDIF
4065       CALL barrier()
4066       CALL shmem_udcflush()
4067
4068#  elif key_mpp_mpi
4069       !! * Local variables   (MPI version)
4070
4071       imigr=jprecj*jpi
4072
4073       IF( nbondj == -1 ) THEN
4074          CALL mppsend(4,t2sn(1,1,1),imigr,nono, ml_req1)
4075          CALL mpprecv(3,t2ns(1,1,2),imigr)
4076          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4077       ELSEIF( nbondj == 0 ) THEN
4078          CALL mppsend(3,t2ns(1,1,1),imigr,noso, ml_req1)
4079          CALL mppsend(4,t2sn(1,1,1),imigr,nono, ml_req2)
4080          CALL mpprecv(3,t2ns(1,1,2),imigr)
4081          CALL mpprecv(4,t2sn(1,1,2),imigr)
4082          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4083          IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
4084       ELSEIF( nbondj == 1 ) THEN
4085          CALL mppsend(3,t2ns(1,1,1),imigr,noso, ml_req1)
4086          CALL mpprecv(4,t2sn(1,1,2),imigr)
4087          IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
4088       ENDIF
4089
4090#endif
4091
4092       ! 2.3 Write Dirichlet lateral conditions
4093
4094       ijhom = nlcj - jprecj
4095       IF( nbondj == 0 .OR. nbondj == 1 ) THEN
4096          DO jl = 1, jprecj
4097             ztab(:,jl) = t2sn(:,jl,2)
4098          END DO
4099       ENDIF
4100
4101       IF( nbondj == 0 .OR. nbondj == -1 ) THEN
4102          DO jl = 1, jprecj
4103             ztab(:,ijhom+jl) = t2ns(:,jl,2)
4104          END DO
4105       ENDIF
4106
4107       IF( ktype==1 .AND. kd1 <= jpi+nimpp-1 .AND. nimpp <= kd2 ) THEN
4108          ! north/south boundaries
4109          DO jj = ijpt0,ijpt1
4110             DO ji = iipt0,ilpt1
4111                ptab(ji,jk) = ztab(ji,jj) 
4112             END DO
4113          END DO
4114       ELSEIF( ktype==2 .AND. kd1 <= jpj+njmpp-1 .AND. njmpp <= kd2 ) THEN
4115          ! east/west boundaries
4116          DO jj = ijpt0,ilpt1
4117             DO ji = iipt0,iipt1
4118                ptab(jj,jk) = ztab(ji,jj) 
4119             END DO
4120          END DO
4121       ENDIF
4122
4123    END DO
4124
4125  END SUBROUTINE mppobc
4126
4127
4128  SUBROUTINE mpp_ini_north
4129    !!----------------------------------------------------------------------
4130    !!               ***  routine mpp_ini_north  ***
4131    !!
4132    !! ** Purpose :   Initialize special communicator for north folding
4133    !!      condition together with global variables needed in the mpp folding
4134    !!
4135    !! ** Method  : - Look for northern processors
4136    !!              - Put their number in nrank_north
4137    !!              - Create groups for the world processors and the north processors
4138    !!              - Create a communicator for northern processors
4139    !!
4140    !! ** output
4141    !!      njmppmax = njmpp for northern procs
4142    !!      ndim_rank_north = number of processors in the northern line
4143    !!      nrank_north (ndim_rank_north) = number  of the northern procs.
4144    !!      ngrp_world = group ID for the world processors
4145    !!      ngrp_north = group ID for the northern processors
4146    !!      ncomm_north = communicator for the northern procs.
4147    !!      north_root = number (in the world) of proc 0 in the northern comm.
4148    !!
4149    !! History :
4150    !!        !  03-09 (J.M. Molines, MPI only )
4151    !!----------------------------------------------------------------------
4152#ifdef key_mpp_shmem
4153    CALL ctl_stop( ' mpp_ini_north not available in SHMEM' )
4154# elif key_mpp_mpi
4155    INTEGER :: ierr
4156    INTEGER :: jproc
4157    INTEGER :: ii,ji
4158    !!----------------------------------------------------------------------
4159
4160    njmppmax=MAXVAL(njmppt)
4161
4162    ! Look for how many procs on the northern boundary
4163    !
4164    ndim_rank_north=0
4165    DO jproc=1,jpnij
4166       IF ( njmppt(jproc) == njmppmax ) THEN
4167          ndim_rank_north = ndim_rank_north + 1
4168       END IF
4169    END DO
4170
4171
4172    ! Allocate the right size to nrank_north
4173    !
4174    ALLOCATE(nrank_north(ndim_rank_north))
4175
4176    ! Fill the nrank_north array with proc. number of northern procs.
4177    ! Note : the rank start at 0 in MPI
4178    !
4179    ii=0
4180    DO ji = 1, jpnij
4181       IF ( njmppt(ji) == njmppmax   ) THEN
4182          ii=ii+1
4183          nrank_north(ii)=ji-1
4184       END IF
4185    END DO
4186    ! create the world group
4187    !
4188    CALL MPI_COMM_GROUP(mpi_comm_world,ngrp_world,ierr)
4189    !
4190    ! Create the North group from the world group
4191    CALL MPI_GROUP_INCL(ngrp_world,ndim_rank_north,nrank_north,ngrp_north,ierr)
4192
4193    ! Create the North communicator , ie the pool of procs in the north group
4194    !
4195    CALL MPI_COMM_CREATE(mpi_comm_world,ngrp_north,ncomm_north,ierr)
4196
4197
4198    ! find proc number in the world of proc 0 in the north
4199    CALL MPI_GROUP_TRANSLATE_RANKS(ngrp_north,1,0,ngrp_world,north_root,ierr)
4200#endif
4201
4202  END SUBROUTINE mpp_ini_north
4203
4204
4205   SUBROUTINE mpp_lbc_north_3d ( pt3d, cd_type, psgn )
4206      !!---------------------------------------------------------------------
4207      !!                   ***  routine mpp_lbc_north_3d  ***
4208      !!
4209      !! ** Purpose :
4210      !!      Ensure proper north fold horizontal bondary condition in mpp configuration
4211      !!      in case of jpn1 > 1
4212      !!
4213      !! ** Method :
4214      !!      Gather the 4 northern lines of the global domain on 1 processor and
4215      !!      apply lbc north-fold on this sub array. Then scatter the fold array
4216      !!      back to the processors.
4217      !!
4218      !! History :
4219      !!   8.5  !  03-09  (J.M. Molines ) For mpp folding condition at north
4220      !!                                  from lbc routine
4221      !!   9.0  !  03-12  (J.M. Molines ) encapsulation into lib_mpp, coding rules of lbc_lnk
4222      !!----------------------------------------------------------------------
4223      !! * Arguments
4224      CHARACTER(len=1), INTENT( in ) ::   &
4225         cd_type       ! nature of pt3d grid-points
4226         !             !   = T ,  U , V , F or W  gridpoints
4227      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT( inout ) ::   &
4228         pt3d          ! 3D array on which the boundary condition is applied
4229      REAL(wp), INTENT( in ) ::   &
4230         psgn          ! control of the sign change
4231         !             !   = -1. , the sign is changed if north fold boundary
4232         !             !   =  1. , the sign is kept  if north fold boundary
4233
4234      !! * Local declarations
4235      INTEGER :: ji, jj, jk, jr, jproc
4236      INTEGER :: ierr
4237      INTEGER :: ildi,ilei,iilb
4238      INTEGER :: ijpj,ijpjm1,ij,ijt,iju
4239      INTEGER :: itaille
4240      REAL(wp), DIMENSION(jpiglo,4,jpk) :: ztab
4241      REAL(wp), DIMENSION(jpi,4,jpk,jpni) :: znorthgloio
4242      REAL(wp), DIMENSION(jpi,4,jpk) :: znorthloc
4243      !!----------------------------------------------------------------------
4244
4245    ! If we get in this routine it s because : North fold condition and mpp with more
4246    !   than one proc across i : we deal only with the North condition
4247
4248    ! 0. Sign setting
4249    ! ---------------
4250
4251    ijpj=4
4252    ijpjm1=3
4253
4254    ! put in znorthloc the last 4 jlines of pt3d
4255    DO jk = 1, jpk 
4256       DO jj = nlcj - ijpj +1, nlcj
4257          ij = jj - nlcj + ijpj
4258          znorthloc(:,ij,jk) = pt3d(:,jj,jk)
4259       END DO
4260    END DO
4261
4262
4263    IF (npolj /= 0 ) THEN
4264       ! Build in proc 0 of ncomm_north the znorthgloio
4265       znorthgloio(:,:,:,:) = 0_wp
4266
4267#ifdef key_mpp_shmem
4268       not done : compiler error
4269#elif defined key_mpp_mpi
4270       itaille=jpi*jpk*ijpj
4271       CALL MPI_GATHER(znorthloc,itaille,MPI_DOUBLE_PRECISION,znorthgloio,itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4272#endif
4273
4274    ENDIF
4275
4276    IF (narea == north_root+1 ) THEN
4277       ! recover the global north array
4278       ztab(:,:,:) = 0_wp
4279
4280       DO jr = 1, ndim_rank_north
4281          jproc = nrank_north(jr) + 1
4282          ildi  = nldit (jproc)
4283          ilei  = nleit (jproc)
4284          iilb  = nimppt(jproc)
4285          DO jk = 1, jpk 
4286             DO jj = 1, 4
4287                DO ji = ildi, ilei
4288                   ztab(ji+iilb-1,jj,jk) = znorthgloio(ji,jj,jk,jr)
4289                END DO
4290             END DO
4291          END DO
4292       END DO
4293
4294
4295       ! Horizontal slab
4296       ! ===============
4297
4298       DO jk = 1, jpk 
4299
4300
4301          ! 2. North-Fold boundary conditions
4302          ! ----------------------------------
4303
4304          SELECT CASE ( npolj )
4305
4306          CASE ( 3, 4 )                       ! *  North fold  T-point pivot
4307
4308             ztab( 1    ,ijpj,jk) = 0.e0
4309             ztab(jpiglo,ijpj,jk) = 0.e0
4310
4311             SELECT CASE ( cd_type )
4312
4313             CASE ( 'T' , 'S' , 'W' )                   ! T-, W-point
4314                DO ji = 2, jpiglo
4315                   ijt = jpiglo-ji+2
4316                   ztab(ji,ijpj,jk) = psgn * ztab(ijt,ijpj-2,jk)
4317                END DO
4318                DO ji = jpiglo/2+1, jpiglo
4319                   ijt = jpiglo-ji+2
4320                   ztab(ji,ijpjm1,jk) = psgn * ztab(ijt,ijpjm1,jk)
4321                END DO
4322
4323             CASE ( 'U' )                               ! U-point
4324                DO ji = 1, jpiglo-1
4325                   iju = jpiglo-ji+1
4326                   ztab(ji,ijpj,jk) = psgn * ztab(iju,ijpj-2,jk)
4327                END DO
4328                DO ji = jpiglo/2, jpiglo-1
4329                   iju = jpiglo-ji+1
4330                   ztab(ji,ijpjm1,jk) = psgn * ztab(iju,ijpjm1,jk)
4331                END DO
4332
4333             CASE ( 'V' )                               ! V-point
4334                DO ji = 2, jpiglo
4335                   ijt = jpiglo-ji+2
4336                   ztab(ji,ijpj-1,jk) = psgn * ztab(ijt,ijpj-2,jk)
4337                   ztab(ji,ijpj  ,jk) = psgn * ztab(ijt,ijpj-3,jk)
4338                END DO
4339
4340             CASE ( 'F' , 'G' )                         ! F-point
4341                DO ji = 1, jpiglo-1
4342                   iju = jpiglo-ji+1
4343                   ztab(ji,ijpj-1,jk) = psgn * ztab(iju,ijpj-2,jk)
4344                   ztab(ji,ijpj  ,jk) = psgn * ztab(iju,ijpj-3,jk)
4345                END DO
4346
4347             END SELECT
4348
4349          CASE ( 5, 6 )                        ! *  North fold  F-point pivot
4350
4351             ztab( 1    ,ijpj,jk) = 0.e0
4352             ztab(jpiglo,ijpj,jk) = 0.e0
4353
4354             SELECT CASE ( cd_type )
4355
4356             CASE ( 'T' , 'S' , 'W' )                   ! T-, W-point
4357                DO ji = 1, jpiglo
4358                   ijt = jpiglo-ji+1
4359                   ztab(ji,ijpj,jk) = psgn * ztab(ijt,ijpj-1,jk)
4360                END DO
4361
4362             CASE ( 'U' )                               ! U-point
4363                DO ji = 1, jpiglo-1
4364                   iju = jpiglo-ji
4365                   ztab(ji,ijpj,jk) = psgn * ztab(iju,ijpj-1,jk)
4366                END DO
4367
4368             CASE ( 'V' )                               ! V-point
4369                DO ji = 1, jpiglo
4370                   ijt = jpiglo-ji+1
4371                   ztab(ji,ijpj,jk) = psgn * ztab(ijt,ijpj-2,jk)
4372                END DO
4373                DO ji = jpiglo/2+1, jpiglo
4374                   ijt = jpiglo-ji+1
4375                   ztab(ji,ijpjm1,jk) = psgn * ztab(ijt,ijpjm1,jk)
4376                END DO
4377
4378             CASE ( 'F' , 'G' )                         ! F-point
4379                DO ji = 1, jpiglo-1
4380                   iju = jpiglo-ji
4381                   ztab(ji,ijpj  ,jk) = psgn * ztab(iju,ijpj-2,jk)
4382                END DO
4383                DO ji = jpiglo/2+1, jpiglo-1
4384                   iju = jpiglo-ji
4385                   ztab(ji,ijpjm1,jk) = psgn * ztab(iju,ijpjm1,jk)
4386                END DO
4387
4388             END SELECT
4389
4390          CASE DEFAULT                           ! *  closed
4391
4392             SELECT CASE ( cd_type) 
4393
4394             CASE ( 'T' , 'U' , 'V' , 'W' )             ! T-, U-, V-, W-points
4395                ztab(:, 1  ,jk) = 0.e0
4396                ztab(:,ijpj,jk) = 0.e0
4397
4398             CASE ( 'F' )                               ! F-point
4399                ztab(:,ijpj,jk) = 0.e0
4400
4401             END SELECT
4402
4403          END SELECT
4404
4405          !     End of slab
4406          !     ===========
4407
4408       END DO
4409
4410       !! Scatter back to pt3d
4411       DO jr = 1, ndim_rank_north
4412          jproc=nrank_north(jr)+1
4413          ildi=nldit (jproc)
4414          ilei=nleit (jproc)
4415          iilb=nimppt(jproc)
4416          DO jk=  1, jpk
4417             DO jj=1,ijpj
4418                DO ji=ildi,ilei
4419                   znorthgloio(ji,jj,jk,jr)=ztab(ji+iilb-1,jj,jk)
4420                END DO
4421             END DO
4422          END DO
4423       END DO
4424
4425    ENDIF      ! only done on proc 0 of ncomm_north
4426
4427#ifdef key_mpp_shmem
4428    not done yet in shmem : compiler error
4429#elif key_mpp_mpi
4430    IF ( npolj /= 0 ) THEN
4431       itaille=jpi*jpk*ijpj
4432       CALL MPI_SCATTER(znorthgloio,itaille,MPI_DOUBLE_PRECISION,znorthloc,itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4433    ENDIF
4434#endif
4435
4436    ! put in the last ijpj jlines of pt3d znorthloc
4437    DO jk = 1 , jpk 
4438       DO jj = nlcj - ijpj + 1 , nlcj
4439          ij = jj - nlcj + ijpj
4440          pt3d(:,jj,jk)= znorthloc(:,ij,jk)
4441       END DO
4442    END DO
4443
4444  END SUBROUTINE mpp_lbc_north_3d
4445
4446
4447  SUBROUTINE mpp_lbc_north_2d ( pt2d, cd_type, psgn)
4448    !!---------------------------------------------------------------------
4449    !!                   ***  routine mpp_lbc_north_2d  ***
4450    !!
4451    !! ** Purpose :
4452    !!      Ensure proper north fold horizontal bondary condition in mpp configuration
4453    !!      in case of jpn1 > 1 (for 2d array )
4454    !!
4455    !! ** Method :
4456    !!      Gather the 4 northern lines of the global domain on 1 processor and
4457    !!      apply lbc north-fold on this sub array. Then scatter the fold array
4458    !!      back to the processors.
4459    !!
4460    !! History :
4461    !!   8.5  !  03-09  (J.M. Molines ) For mpp folding condition at north
4462    !!                                  from lbc routine
4463    !!   9.0  !  03-12  (J.M. Molines ) encapsulation into lib_mpp, coding rules of lbc_lnk
4464    !!----------------------------------------------------------------------
4465
4466    !! * Arguments
4467    CHARACTER(len=1), INTENT( in ) ::   &
4468         cd_type       ! nature of pt2d grid-points
4469    !             !   = T ,  U , V , F or W  gridpoints
4470    REAL(wp), DIMENSION(jpi,jpj), INTENT( inout ) ::   &
4471         pt2d          ! 2D array on which the boundary condition is applied
4472    REAL(wp), INTENT( in ) ::   &
4473         psgn          ! control of the sign change
4474    !             !   = -1. , the sign is changed if north fold boundary
4475    !             !   =  1. , the sign is kept  if north fold boundary
4476
4477
4478    !! * Local declarations
4479
4480    INTEGER :: ji, jj,  jr, jproc
4481    INTEGER :: ierr
4482    INTEGER :: ildi,ilei,iilb
4483    INTEGER :: ijpj,ijpjm1,ij,ijt,iju
4484    INTEGER :: itaille
4485
4486    REAL(wp), DIMENSION(jpiglo,4) :: ztab
4487    REAL(wp), DIMENSION(jpi,4,jpni) :: znorthgloio
4488    REAL(wp), DIMENSION(jpi,4) :: znorthloc
4489    !!----------------------------------------------------------------------
4490    !!  OPA 8.5, LODYC-IPSL (2002)
4491    !!----------------------------------------------------------------------
4492    ! If we get in this routine it s because : North fold condition and mpp with more
4493    !   than one proc across i : we deal only with the North condition
4494
4495    ! 0. Sign setting
4496    ! ---------------
4497
4498    ijpj=4
4499    ijpjm1=3
4500
4501
4502    ! put in znorthloc the last 4 jlines of pt2d
4503    DO jj = nlcj - ijpj +1, nlcj
4504       ij = jj - nlcj + ijpj
4505       znorthloc(:,ij)=pt2d(:,jj)
4506    END DO
4507
4508    IF (npolj /= 0 ) THEN
4509       ! Build in proc 0 of ncomm_north the znorthgloio
4510       znorthgloio(:,:,:) = 0_wp
4511#ifdef key_mpp_shmem
4512       not done : compiler error
4513#elif defined key_mpp_mpi
4514       itaille=jpi*ijpj
4515       CALL MPI_GATHER(znorthloc,itaille,MPI_DOUBLE_PRECISION,znorthgloio,itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4516#endif
4517    ENDIF
4518
4519    IF (narea == north_root+1 ) THEN
4520       ! recover the global north array
4521       ztab(:,:) = 0_wp
4522
4523       DO jr = 1, ndim_rank_north
4524          jproc=nrank_north(jr)+1
4525          ildi=nldit (jproc)
4526          ilei=nleit (jproc)
4527          iilb=nimppt(jproc)
4528          DO jj=1,4
4529             DO ji=ildi,ilei
4530                ztab(ji+iilb-1,jj)=znorthgloio(ji,jj,jr)
4531             END DO
4532          END DO
4533       END DO
4534
4535
4536       ! 2. North-Fold boundary conditions
4537       ! ----------------------------------
4538
4539       SELECT CASE ( npolj )
4540
4541       CASE ( 3, 4 )                       ! *  North fold  T-point pivot
4542
4543          ztab( 1    ,ijpj) = 0.e0
4544          ztab(jpiglo,ijpj) = 0.e0
4545
4546          SELECT CASE ( cd_type )
4547
4548          CASE ( 'T' , 'W' , 'S' )                         ! T-, W-point
4549             DO ji = 2, jpiglo
4550                ijt = jpiglo-ji+2
4551                ztab(ji,ijpj) = psgn * ztab(ijt,ijpj-2)
4552             END DO
4553             DO ji = jpiglo/2+1, jpiglo
4554                ijt = jpiglo-ji+2
4555                ztab(ji,ijpjm1) = psgn * ztab(ijt,ijpjm1)
4556             END DO
4557
4558          CASE ( 'U' )                                     ! U-point
4559             DO ji = 1, jpiglo-1
4560                iju = jpiglo-ji+1
4561                ztab(ji,ijpj) = psgn * ztab(iju,ijpj-2)
4562             END DO
4563             DO ji = jpiglo/2, jpiglo-1
4564                iju = jpiglo-ji+1
4565                ztab(ji,ijpjm1) = psgn * ztab(iju,ijpjm1)
4566             END DO
4567
4568          CASE ( 'V' )                                     ! V-point
4569             DO ji = 2, jpiglo
4570                ijt = jpiglo-ji+2
4571                ztab(ji,ijpj-1) = psgn * ztab(ijt,ijpj-2)
4572                ztab(ji,ijpj  ) = psgn * ztab(ijt,ijpj-3)
4573             END DO
4574
4575          CASE ( 'F' , 'G' )                               ! F-point
4576             DO ji = 1, jpiglo-1
4577                iju = jpiglo-ji+1
4578                ztab(ji,ijpj-1) = psgn * ztab(iju,ijpj-2)
4579                ztab(ji,ijpj  ) = psgn * ztab(iju,ijpj-3)
4580             END DO
4581
4582          CASE ( 'I' )                                     ! ice U-V point
4583             ztab(2,ijpj) = psgn * ztab(3,ijpj-1)
4584             DO ji = 3, jpiglo
4585                iju = jpiglo - ji + 3
4586                ztab(ji,ijpj) = psgn * ztab(iju,ijpj-1)
4587             END DO
4588
4589          END SELECT
4590
4591       CASE ( 5, 6 )                        ! *  North fold  F-point pivot
4592
4593          ztab( 1 ,ijpj) = 0.e0
4594          ztab(jpiglo,ijpj) = 0.e0
4595
4596          SELECT CASE ( cd_type )
4597
4598          CASE ( 'T' , 'W' ,'S' )                          ! T-, W-point
4599             DO ji = 1, jpiglo
4600                ijt = jpiglo-ji+1
4601                ztab(ji,ijpj) = psgn * ztab(ijt,ijpj-1)
4602             END DO
4603
4604          CASE ( 'U' )                                     ! U-point
4605             DO ji = 1, jpiglo-1
4606                iju = jpiglo-ji
4607                ztab(ji,ijpj) = psgn * ztab(iju,ijpj-1)
4608             END DO
4609
4610          CASE ( 'V' )                                     ! V-point
4611             DO ji = 1, jpiglo
4612                ijt = jpiglo-ji+1
4613                ztab(ji,ijpj) = psgn * ztab(ijt,ijpj-2)
4614             END DO
4615             DO ji = jpiglo/2+1, jpiglo
4616                ijt = jpiglo-ji+1
4617                ztab(ji,ijpjm1) = psgn * ztab(ijt,ijpjm1)
4618             END DO
4619
4620          CASE ( 'F' , 'G' )                               ! F-point
4621             DO ji = 1, jpiglo-1
4622                iju = jpiglo-ji
4623                ztab(ji,ijpj  ) = psgn * ztab(iju,ijpj-2)
4624             END DO
4625             DO ji = jpiglo/2+1, jpiglo-1
4626                iju = jpiglo-ji
4627                ztab(ji,ijpjm1) = psgn * ztab(iju,ijpjm1)
4628             END DO
4629
4630             CASE ( 'I' )                                  ! ice U-V point
4631                ztab( 2 ,ijpj) = 0.e0
4632                DO ji = 2 , jpiglo-1
4633                   ijt = jpiglo - ji + 2
4634                   ztab(ji,ijpj)= 0.5 * ( ztab(ji,ijpj-1) + psgn * ztab(ijt,ijpj-1) )
4635                END DO
4636
4637          END SELECT
4638
4639       CASE DEFAULT                           ! *  closed : the code probably never go through
4640
4641            SELECT CASE ( cd_type) 
4642 
4643            CASE ( 'T' , 'U' , 'V' , 'W' )                 ! T-, U-, V-, W-points
4644               ztab(:, 1 ) = 0.e0
4645               ztab(:,ijpj) = 0.e0
4646
4647            CASE ( 'F' )                                   ! F-point
4648               ztab(:,ijpj) = 0.e0
4649
4650            CASE ( 'I' )                                   ! ice U-V point
4651               ztab(:, 1 ) = 0.e0
4652               ztab(:,ijpj) = 0.e0
4653
4654            END SELECT
4655
4656         END SELECT
4657
4658         !     End of slab
4659         !     ===========
4660
4661         !! Scatter back to pt2d
4662         DO jr = 1, ndim_rank_north
4663            jproc=nrank_north(jr)+1
4664            ildi=nldit (jproc)
4665            ilei=nleit (jproc)
4666            iilb=nimppt(jproc)
4667            DO jj=1,ijpj
4668               DO ji=ildi,ilei
4669                  znorthgloio(ji,jj,jr)=ztab(ji+iilb-1,jj)
4670               END DO
4671            END DO
4672         END DO
4673
4674      ENDIF      ! only done on proc 0 of ncomm_north
4675
4676#ifdef key_mpp_shmem
4677      not done yet in shmem : compiler error
4678#elif key_mpp_mpi
4679      IF ( npolj /= 0 ) THEN
4680         itaille=jpi*ijpj
4681         CALL MPI_SCATTER(znorthgloio,itaille,MPI_DOUBLE_PRECISION,znorthloc,itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4682      ENDIF
4683#endif
4684
4685      ! put in the last ijpj jlines of pt2d znorthloc
4686      DO jj = nlcj - ijpj + 1 , nlcj
4687         ij = jj - nlcj + ijpj
4688         pt2d(:,jj)= znorthloc(:,ij)
4689      END DO
4690
4691   END SUBROUTINE mpp_lbc_north_2d
4692
4693
4694   SUBROUTINE mpp_lbc_north_e ( pt2d, cd_type, psgn)
4695    !!---------------------------------------------------------------------
4696    !!                   ***  routine mpp_lbc_north_2d  ***
4697    !!
4698    !! ** Purpose :
4699    !!      Ensure proper north fold horizontal bondary condition in mpp configuration
4700    !!      in case of jpn1 > 1 (for 2d array with outer extra halo)
4701    !!
4702    !! ** Method :
4703    !!      Gather the 4+2*jpr2dj northern lines of the global domain on 1 processor and
4704    !!      apply lbc north-fold on this sub array. Then scatter the fold array
4705    !!      back to the processors.
4706    !!
4707    !! History :
4708    !!   8.5  !  03-09  (J.M. Molines ) For mpp folding condition at north
4709    !!                                  from lbc routine
4710    !!   9.0  !  03-12  (J.M. Molines ) encapsulation into lib_mpp, coding rules of lbc_lnk
4711    !!   9.0  !  05-09  (R. Benshila )   adapt mpp_lbc_north_2d
4712    !!----------------------------------------------------------------------
4713
4714    !! * Arguments
4715    CHARACTER(len=1), INTENT( in ) ::   &
4716         cd_type       ! nature of pt2d grid-points
4717    !             !   = T ,  U , V , F or W  gridpoints
4718    REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT( inout ) ::   &
4719         pt2d          ! 2D array on which the boundary condition is applied
4720    REAL(wp), INTENT( in ) ::   &
4721         psgn          ! control of the sign change
4722    !             !   = -1. , the sign is changed if north fold boundary
4723    !             !   =  1. , the sign is kept  if north fold boundary
4724
4725
4726    !! * Local declarations
4727
4728    INTEGER :: ji, jj,  jr, jproc, jl
4729    INTEGER :: ierr
4730    INTEGER :: ildi,ilei,iilb
4731    INTEGER :: ijpj,ijpjm1,ij,ijt,iju, iprecj
4732    INTEGER :: itaille
4733
4734    REAL(wp), DIMENSION(jpiglo,1-jpr2dj:4+jpr2dj) :: ztab
4735    REAL(wp), DIMENSION(jpi,1-jpr2dj:4+jpr2dj,jpni) :: znorthgloio
4736    REAL(wp), DIMENSION(jpi,1-jpr2dj:4+jpr2dj) :: znorthloc
4737
4738    ! If we get in this routine it s because : North fold condition and mpp with more
4739    !   than one proc across i : we deal only with the North condition
4740
4741    ! 0. Sign setting
4742    ! ---------------
4743
4744    ijpj=4
4745    ijpjm1=3
4746    iprecj = jpr2dj+jprecj
4747
4748    ! put in znorthloc the last 4 jlines of pt2d
4749    DO jj = nlcj - ijpj + 1 - jpr2dj, nlcj +jpr2dj
4750       ij = jj - nlcj + ijpj
4751       znorthloc(:,ij)=pt2d(1:jpi,jj)
4752    END DO
4753
4754    IF (npolj /= 0 ) THEN
4755       ! Build in proc 0 of ncomm_north the znorthgloio
4756       znorthgloio(:,:,:) = 0_wp
4757#ifdef key_mpp_shmem
4758       not done : compiler error
4759#elif defined key_mpp_mpi
4760       itaille=jpi*(ijpj+2*jpr2dj)
4761       CALL MPI_GATHER(znorthloc(1,1-jpr2dj),itaille,MPI_DOUBLE_PRECISION, &
4762                     & znorthgloio(1,1-jpr2dj,1),itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4763#endif
4764    ENDIF
4765
4766    IF (narea == north_root+1 ) THEN
4767       ! recover the global north array
4768       ztab(:,:) = 0_wp
4769
4770       DO jr = 1, ndim_rank_north
4771          jproc=nrank_north(jr)+1
4772          ildi=nldit (jproc)
4773          ilei=nleit (jproc)
4774          iilb=nimppt(jproc)
4775          DO jj=1-jpr2dj,ijpj+jpr2dj
4776             DO ji=ildi,ilei
4777                ztab(ji+iilb-1,jj)=znorthgloio(ji,jj,jr)
4778             END DO
4779          END DO
4780       END DO
4781
4782
4783       ! 2. North-Fold boundary conditions
4784       ! ----------------------------------
4785
4786       SELECT CASE ( npolj )
4787
4788       CASE ( 3, 4 )                       ! *  North fold  T-point pivot
4789
4790          ztab( 1    ,ijpj:ijpj+jpr2dj) = 0.e0
4791          ztab(jpiglo,ijpj:ijpj+jpr2dj) = 0.e0
4792
4793          SELECT CASE ( cd_type )
4794
4795          CASE ( 'T' , 'W' , 'S' )                         ! T-, W-point
4796             DO jl =0, iprecj-1
4797                DO ji = 2, jpiglo
4798                   ijt = jpiglo-ji+2
4799                   ztab(ji,ijpj+jl) = psgn * ztab(ijt,ijpj-2-jl)
4800                END DO
4801             END DO
4802             DO ji = jpiglo/2+1, jpiglo
4803                ijt = jpiglo-ji+2
4804                ztab(ji,ijpjm1) = psgn * ztab(ijt,ijpjm1)
4805             END DO
4806
4807          CASE ( 'U' )                                     ! U-point
4808             DO jl =0, iprecj-1
4809                DO ji = 1, jpiglo-1
4810                   iju = jpiglo-ji+1
4811                   ztab(ji,ijpj+jl) = psgn * ztab(iju,ijpj-2-jl)
4812                END DO
4813             END DO
4814             DO ji = jpiglo/2, jpiglo-1
4815                iju = jpiglo-ji+1
4816                ztab(ji,ijpjm1) = psgn * ztab(iju,ijpjm1)
4817             END DO
4818
4819          CASE ( 'V' )                                     ! V-point
4820            DO jl =-1, iprecj-1
4821               DO ji = 2, jpiglo
4822                  ijt = jpiglo-ji+2
4823                  ztab(ji,ijpj+jl) = psgn * ztab(ijt,ijpj-3-jl)
4824               END DO
4825            END DO
4826
4827          CASE ( 'F' , 'G' )                               ! F-point
4828            DO jl =-1, iprecj-1
4829               DO ji = 1, jpiglo-1
4830                  iju = jpiglo-ji+1
4831                  ztab(ji,ijpj+jl) = psgn * ztab(iju,ijpj-3-jl)
4832               END DO
4833             END DO
4834
4835          CASE ( 'I' )                                     ! ice U-V point
4836             DO jl =0, iprecj-1
4837                ztab(2,ijpj+jl) = psgn * ztab(3,ijpj-1+jl)
4838                DO ji = 3, jpiglo
4839                   iju = jpiglo - ji + 3
4840                   ztab(ji,ijpj+jl) = psgn * ztab(iju,ijpj-1-jl)
4841                END DO
4842             END DO
4843
4844          END SELECT
4845
4846       CASE ( 5, 6 )                        ! *  North fold  F-point pivot
4847
4848          ztab( 1 ,ijpj:ijpj+jpr2dj) = 0.e0
4849          ztab(jpiglo,ijpj:ijpj+jpr2dj) = 0.e0
4850
4851          SELECT CASE ( cd_type )
4852
4853          CASE ( 'T' , 'W' ,'S' )                          ! T-, W-point
4854             DO jl = 0, iprecj-1
4855                DO ji = 1, jpiglo
4856                   ijt = jpiglo-ji+1
4857                   ztab(ji,ijpj+jl) = psgn * ztab(ijt,ijpj-1-jl)
4858                END DO
4859             END DO
4860
4861          CASE ( 'U' )                                     ! U-point
4862             DO jl = 0, iprecj-1
4863                DO ji = 1, jpiglo-1
4864                   iju = jpiglo-ji
4865                   ztab(ji,ijpj+jl) = psgn * ztab(iju,ijpj-1-jl)
4866                END DO
4867             END DO
4868
4869          CASE ( 'V' )                                     ! V-point
4870             DO jl = 0, iprecj-1
4871                DO ji = 1, jpiglo
4872                   ijt = jpiglo-ji+1
4873                   ztab(ji,ijpj+jl) = psgn * ztab(ijt,ijpj-2-jl)
4874                END DO
4875             END DO
4876             DO ji = jpiglo/2+1, jpiglo
4877                ijt = jpiglo-ji+1
4878                ztab(ji,ijpjm1) = psgn * ztab(ijt,ijpjm1)
4879             END DO
4880
4881          CASE ( 'F' , 'G' )                               ! F-point
4882             DO jl = 0, iprecj-1
4883                DO ji = 1, jpiglo-1
4884                   iju = jpiglo-ji
4885                   ztab(ji,ijpj+jl) = psgn * ztab(iju,ijpj-2-jl)
4886                END DO
4887             END DO
4888             DO ji = jpiglo/2+1, jpiglo-1
4889                iju = jpiglo-ji
4890                ztab(ji,ijpjm1) = psgn * ztab(iju,ijpjm1)
4891             END DO
4892
4893             CASE ( 'I' )                                  ! ice U-V point
4894                ztab( 2 ,ijpj:ijpj+jpr2dj) = 0.e0
4895                DO jl = 0, jpr2dj
4896                   DO ji = 2 , jpiglo-1
4897                      ijt = jpiglo - ji + 2
4898                      ztab(ji,ijpj+jl)= 0.5 * ( ztab(ji,ijpj-1-jl) + psgn * ztab(ijt,ijpj-1-jl) )
4899                   END DO
4900                END DO
4901
4902          END SELECT
4903
4904       CASE DEFAULT                           ! *  closed : the code probably never go through
4905
4906            SELECT CASE ( cd_type) 
4907 
4908            CASE ( 'T' , 'U' , 'V' , 'W' )                 ! T-, U-, V-, W-points
4909               ztab(:, 1:1-jpr2dj     ) = 0.e0
4910               ztab(:,ijpj:ijpj+jpr2dj) = 0.e0
4911
4912            CASE ( 'F' )                                   ! F-point
4913               ztab(:,ijpj:ijpj+jpr2dj) = 0.e0
4914
4915            CASE ( 'I' )                                   ! ice U-V point
4916               ztab(:, 1:1-jpr2dj     ) = 0.e0
4917               ztab(:,ijpj:ijpj+jpr2dj) = 0.e0
4918
4919            END SELECT
4920
4921         END SELECT
4922
4923         !     End of slab
4924         !     ===========
4925
4926         !! Scatter back to pt2d
4927         DO jr = 1, ndim_rank_north
4928            jproc=nrank_north(jr)+1
4929            ildi=nldit (jproc)
4930            ilei=nleit (jproc)
4931            iilb=nimppt(jproc)
4932            DO jj=1-jpr2dj,ijpj+jpr2dj
4933               DO ji=ildi,ilei
4934                  znorthgloio(ji,jj,jr)=ztab(ji+iilb-1,jj)
4935               END DO
4936            END DO
4937         END DO
4938
4939      ENDIF      ! only done on proc 0 of ncomm_north
4940
4941#ifdef key_mpp_shmem
4942      not done yet in shmem : compiler error
4943#elif key_mpp_mpi
4944      IF ( npolj /= 0 ) THEN
4945         itaille=jpi*(ijpj+2*jpr2dj)
4946         CALL MPI_SCATTER(znorthgloio(1,1-jpr2dj,1),itaille,MPI_DOUBLE_PRECISION, &
4947                        & znorthloc(1,1-jpr2dj),itaille,MPI_DOUBLE_PRECISION,0,ncomm_north,ierr)
4948      ENDIF
4949#endif
4950
4951      ! put in the last ijpj jlines of pt2d znorthloc
4952      DO jj = nlcj - ijpj  -jpr2dj + 1 , nlcj +jpr2dj
4953         ij = jj - nlcj + ijpj 
4954         pt2d(1:jpi,jj)= znorthloc(:,ij)
4955      END DO
4956
4957   END SUBROUTINE mpp_lbc_north_e
4958
4959
4960   !!!!!
4961
4962
4963   !!
4964   !!    This is valid on IBM machine ONLY.
4965   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -*- Mode: F90 -*- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4966   !! mpi_init_opa.f90 : Redefinition du point d'entree MPI_INIT de la bibliotheque
4967   !!                MPI afin de faire, en plus de l'initialisation de
4968   !!                l'environnement MPI, l'allocation d'une zone tampon
4969   !!                qui sera ulterieurement utilisee automatiquement lors
4970   !!                de tous les envois de messages par MPI_BSEND
4971   !!
4972   !! Auteur : CNRS/IDRIS
4973   !! Date   : Tue Nov 13 12:02:14 2001
4974   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4975
4976   SUBROUTINE mpi_init_opa(code)
4977      IMPLICIT NONE
4978
4979!$AGRIF_DO_NOT_TREAT
4980#     include <mpif.h>
4981!$AGRIF_END_DO_NOT_TREAT
4982
4983      INTEGER                                 :: code,rang
4984 
4985      ! La valeur suivante doit etre au moins egale a la taille
4986      ! du plus grand message qui sera transfere dans le programme
4987      ! (de toute facon, il y aura un message d'erreur si cette
4988      ! valeur s'avere trop petite)
4989      INTEGER                                 :: taille_tampon
4990      CHARACTER(len=9)                        :: taille_tampon_alphanum
4991      REAL(kind=8), ALLOCATABLE, DIMENSION(:) :: tampon
4992 
4993      ! Le point d'entree dans la bibliotheque MPI elle-meme
4994      CALL mpi_init(code)
4995
4996      ! La definition de la zone tampon pour les futurs envois
4997      ! par MPI_BSEND (on alloue une fois pour toute cette zone
4998      ! tampon, qui sera automatiquement utilisee lors de chaque
4999      ! appel  a MPI_BSEND).
5000      ! La desallocation sera implicite quand on sortira de
5001      ! l'environnement MPI.
5002
5003      ! Recuperation de la valeur de la variable d'environnement
5004      ! BUFFER_LENGTH
5005      ! qui, si elle est definie, doit contenir une valeur superieure
5006      ! a  la taille en octets du plus gros message
5007      CALL getenv('BUFFER_LENGTH',taille_tampon_alphanum)
5008 
5009      ! Si la variable BUFFER_LENGTH n'est pas positionnee, on lui met par
5010      ! defaut la plus grande valeur de la variable MP_EAGER_LIMIT, soit
5011      ! 65 536 octets
5012      IF (taille_tampon_alphanum == ' ') THEN
5013         taille_tampon = 65536
5014      ELSE
5015         READ(taille_tampon_alphanum,'(i9)') taille_tampon
5016      END IF
5017
5018      ! On est limite en mode d'adressage 32 bits a  1750 Mo pour la zone
5019      ! "data" soit 7 segments, c.-a -d. 1750/8 = 210 Mo
5020      IF (taille_tampon > 210000000) THEN
5021         PRINT *,'Attention la valeur BUFFER_LENGTH doit etre <= 210000000'
5022         CALL mpi_abort(MPI_COMM_WORLD,2,code)
5023      END IF
5024
5025      CALL mpi_comm_rank(MPI_COMM_WORLD,rang,code)
5026      IF (rang == 0 ) PRINT *,'Taille du buffer alloue : ',taille_tampon
5027
5028      ! Allocation du tampon et attachement
5029      ALLOCATE(tampon(taille_tampon))
5030      CALL mpi_buffer_attach(tampon,taille_tampon,code)
5031
5032   END SUBROUTINE mpi_init_opa
5033
5034#else
5035   !!----------------------------------------------------------------------
5036   !!   Default case:            Dummy module        share memory computing
5037   !!----------------------------------------------------------------------
5038   INTERFACE mpp_sum
5039      MODULE PROCEDURE mpp_sum_a2s, mpp_sum_as, mpp_sum_ai, mpp_sum_s, mpp_sum_i
5040   END INTERFACE
5041   INTERFACE mpp_max
5042      MODULE PROCEDURE mppmax_a_real, mppmax_real
5043   END INTERFACE
5044   INTERFACE mpp_min
5045      MODULE PROCEDURE mppmin_a_int, mppmin_int, mppmin_a_real, mppmin_real
5046   END INTERFACE
5047   INTERFACE mpp_isl
5048      MODULE PROCEDURE mppisl_a_int, mppisl_int, mppisl_a_real, mppisl_real
5049   END INTERFACE
5050   INTERFACE mppobc
5051      MODULE PROCEDURE mppobc_1d, mppobc_2d, mppobc_3d, mppobc_4d
5052   END INTERFACE
5053  INTERFACE mpp_minloc
5054     MODULE PROCEDURE mpp_minloc2d ,mpp_minloc3d
5055  END INTERFACE
5056  INTERFACE mpp_maxloc
5057     MODULE PROCEDURE mpp_maxloc2d ,mpp_maxloc3d
5058  END INTERFACE
5059
5060
5061   LOGICAL, PUBLIC, PARAMETER ::   lk_mpp = .FALSE.      !: mpp flag
5062
5063CONTAINS
5064
5065   FUNCTION mynode() RESULT (function_value)
5066      function_value = 0
5067   END FUNCTION mynode
5068
5069   SUBROUTINE mppsync                       ! Dummy routine
5070   END SUBROUTINE mppsync
5071
5072   SUBROUTINE mpp_sum_as( parr, kdim )      ! Dummy routine
5073      REAL   , DIMENSION(:) :: parr
5074      INTEGER               :: kdim
5075      WRITE(*,*) 'mpp_sum_as: You should not have seen this print! error?', kdim, parr(1)
5076   END SUBROUTINE mpp_sum_as
5077
5078   SUBROUTINE mpp_sum_a2s( parr, kdim )      ! Dummy routine
5079      REAL   , DIMENSION(:,:) :: parr
5080      INTEGER               :: kdim
5081      WRITE(*,*) 'mpp_sum_a2s: You should not have seen this print! error?', kdim, parr(1,1)
5082   END SUBROUTINE mpp_sum_a2s
5083
5084   SUBROUTINE mpp_sum_ai( karr, kdim )      ! Dummy routine
5085      INTEGER, DIMENSION(:) :: karr
5086      INTEGER               :: kdim
5087      WRITE(*,*) 'mpp_sum_ai: You should not have seen this print! error?', kdim, karr(1)
5088   END SUBROUTINE mpp_sum_ai
5089
5090   SUBROUTINE mpp_sum_s( psca )            ! Dummy routine
5091      REAL                  :: psca
5092      WRITE(*,*) 'mpp_sum_s: You should not have seen this print! error?', psca
5093   END SUBROUTINE mpp_sum_s
5094
5095   SUBROUTINE mpp_sum_i( kint )            ! Dummy routine
5096      integer               :: kint
5097      WRITE(*,*) 'mpp_sum_i: You should not have seen this print! error?', kint
5098   END SUBROUTINE mpp_sum_i
5099
5100   SUBROUTINE mppmax_a_real( parr, kdim )
5101      REAL   , DIMENSION(:) :: parr
5102      INTEGER               :: kdim
5103      WRITE(*,*) 'mppmax_a_real: You should not have seen this print! error?', kdim, parr(1)
5104   END SUBROUTINE mppmax_a_real
5105
5106   SUBROUTINE mppmax_real( psca )
5107      REAL                  :: psca
5108      WRITE(*,*) 'mppmax_real: You should not have seen this print! error?', psca
5109   END SUBROUTINE mppmax_real
5110
5111   SUBROUTINE mppmin_a_real( parr, kdim )
5112      REAL   , DIMENSION(:) :: parr
5113      INTEGER               :: kdim
5114      WRITE(*,*) 'mppmin_a_real: You should not have seen this print! error?', kdim, parr(1)
5115   END SUBROUTINE mppmin_a_real
5116
5117   SUBROUTINE mppmin_real( psca )
5118      REAL                  :: psca
5119      WRITE(*,*) 'mppmin_real: You should not have seen this print! error?', psca
5120   END SUBROUTINE mppmin_real
5121
5122   SUBROUTINE mppmin_a_int( karr, kdim )
5123      INTEGER, DIMENSION(:) :: karr
5124      INTEGER               :: kdim
5125      WRITE(*,*) 'mppmin_a_int: You should not have seen this print! error?', kdim, karr(1)
5126   END SUBROUTINE mppmin_a_int
5127
5128   SUBROUTINE mppmin_int( kint )
5129      INTEGER               :: kint
5130      WRITE(*,*) 'mppmin_int: You should not have seen this print! error?', kint
5131   END SUBROUTINE mppmin_int
5132
5133   SUBROUTINE mppobc_1d( parr, kd1, kd2, kl, kk, ktype, kij )
5134    INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
5135    REAL, DIMENSION(:) ::   parr           ! variable array
5136      WRITE(*,*) 'mppobc: You should not have seen this print! error?',   &
5137         &        parr(1), kd1, kd2, kl, kk, ktype, kij
5138   END SUBROUTINE mppobc_1d
5139
5140   SUBROUTINE mppobc_2d( parr, kd1, kd2, kl, kk, ktype, kij )
5141    INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
5142    REAL, DIMENSION(:,:) ::   parr           ! variable array
5143      WRITE(*,*) 'mppobc: You should not have seen this print! error?',   &
5144         &        parr(1,1), kd1, kd2, kl, kk, ktype, kij
5145   END SUBROUTINE mppobc_2d
5146
5147   SUBROUTINE mppobc_3d( parr, kd1, kd2, kl, kk, ktype, kij )
5148    INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
5149    REAL, DIMENSION(:,:,:) ::   parr           ! variable array
5150      WRITE(*,*) 'mppobc: You should not have seen this print! error?',   &
5151         &        parr(1,1,1), kd1, kd2, kl, kk, ktype, kij
5152   END SUBROUTINE mppobc_3d
5153
5154   SUBROUTINE mppobc_4d( parr, kd1, kd2, kl, kk, ktype, kij )
5155    INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
5156    REAL, DIMENSION(:,:,:,:) ::   parr           ! variable array
5157      WRITE(*,*) 'mppobc: You should not have seen this print! error?',   &
5158         &        parr(1,1,1,1), kd1, kd2, kl, kk, ktype, kij
5159   END SUBROUTINE mppobc_4d
5160
5161
5162   SUBROUTINE mpplnks( parr )            ! Dummy routine
5163      REAL, DIMENSION(:,:) :: parr
5164      WRITE(*,*) 'mpplnks: You should not have seen this print! error?', parr(1,1)
5165   END SUBROUTINE mpplnks
5166
5167   SUBROUTINE mppisl_a_int( karr, kdim )
5168      INTEGER, DIMENSION(:) :: karr
5169      INTEGER               :: kdim
5170      WRITE(*,*) 'mppisl_a_int: You should not have seen this print! error?', kdim, karr(1)
5171   END SUBROUTINE mppisl_a_int
5172
5173   SUBROUTINE mppisl_int( kint )
5174      INTEGER               :: kint
5175      WRITE(*,*) 'mppisl_int: You should not have seen this print! error?', kint
5176   END SUBROUTINE mppisl_int
5177
5178   SUBROUTINE mppisl_a_real( parr, kdim )
5179      REAL   , DIMENSION(:) :: parr
5180      INTEGER               :: kdim
5181      WRITE(*,*) 'mppisl_a_real: You should not have seen this print! error?', kdim, parr(1)
5182   END SUBROUTINE mppisl_a_real
5183
5184   SUBROUTINE mppisl_real( psca )
5185      REAL                  :: psca
5186      WRITE(*,*) 'mppisl_real: You should not have seen this print! error?', psca
5187   END SUBROUTINE mppisl_real
5188
5189   SUBROUTINE mpp_minloc2d ( ptab, pmask, pmin, ki, kj )
5190      REAL                   :: pmin
5191      REAL , DIMENSION (:,:) :: ptab, pmask
5192      INTEGER :: ki, kj
5193      WRITE(*,*) 'mppisl_real: You should not have seen this print! error?', pmin, ki, kj
5194      WRITE(*,*) '   "      ":             "                 "            ', ptab(1,1), pmask(1,1)
5195   END SUBROUTINE mpp_minloc2d
5196
5197   SUBROUTINE mpp_minloc3d ( ptab, pmask, pmin, ki, kj, kk )
5198      REAL                     :: pmin
5199      REAL , DIMENSION (:,:,:) :: ptab, pmask
5200      INTEGER :: ki, kj, kk
5201      WRITE(*,*) 'mppisl_real: You should not have seen this print! error?', pmin, ki, kj, kk
5202      WRITE(*,*) '   "      ":             "                 "            ', ptab(1,1,1), pmask(1,1,1)
5203   END SUBROUTINE mpp_minloc3d
5204
5205   SUBROUTINE mpp_maxloc2d ( ptab, pmask, pmax, ki, kj )
5206      REAL                   :: pmax
5207      REAL , DIMENSION (:,:) :: ptab, pmask
5208      INTEGER :: ki, kj
5209      WRITE(*,*) 'mppisl_real: You should not have seen this print! error?', pmax, ki, kj
5210      WRITE(*,*) '   "      ":             "                 "            ', ptab(1,1), pmask(1,1)
5211   END SUBROUTINE mpp_maxloc2d
5212
5213   SUBROUTINE mpp_maxloc3d ( ptab, pmask, pmax, ki, kj, kk )
5214      REAL                     :: pmax
5215      REAL , DIMENSION (:,:,:) :: ptab, pmask
5216      INTEGER :: ki, kj, kk
5217      WRITE(*,*) 'mppisl_real: You should not have seen this print! error?', pmax, ki, kj, kk
5218      WRITE(*,*) '   "      ":             "                 "            ', ptab(1,1,1), pmask(1,1,1)
5219   END SUBROUTINE mpp_maxloc3d
5220
5221   SUBROUTINE mppstop
5222      WRITE(*,*) 'mppstop: You should not have seen this print! error?'
5223   END SUBROUTINE mppstop
5224
5225#endif
5226   !!----------------------------------------------------------------------
5227END MODULE lib_mpp
Note: See TracBrowser for help on using the repository browser.