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/OPA_SRC – NEMO

source: trunk/NEMO/OPA_SRC/lib_mpp.F90 @ 529

Last change on this file since 529 was 524, checked in by opalod, 18 years ago

RB:nemo_v1_buxfix_059: correction of isend definition for AGRIF

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