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 @ 551

Last change on this file since 551 was 532, checked in by opalod, 18 years ago

nemo_v1_update_76 : CT : add OASIS[3-4] interfaces to build coupled configurations

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