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_tam.F90 in branches/TAM_V3_2_2/NEMOTAM/OPATAM_SRC – NEMO

source: branches/TAM_V3_2_2/NEMOTAM/OPATAM_SRC/lib_mpp_tam.F90 @ 3317

Last change on this file since 3317 was 2578, checked in by rblod, 13 years ago

first import of NEMOTAM 3.2.2

File size: 66.2 KB
Line 
1#if defined key_mpp_mpi
2#if defined key_sp
3#define mpivar mpi_real
4#else
5#define mpivar mpi_double_precision
6#endif
7#endif
8MODULE lib_mpp_tam
9   !!======================================================================
10   !!                       ***  MODULE  lib_mpp_tam  ***
11   !! Ocean numerics:  massively parallel processing library (TAM counterpart)
12   !!=====================================================================
13   !! History of the direct module:
14   !!            OPA  !  1994  (M. Guyon, J. Escobar, M. Imbard)  Original code
15   !!            7.0  !  1997  (A.M. Treguier)  SHMEM additions
16   !!            8.0  !  1998  (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
17   !!                 !  1998  (J.M. Molines) Open boundary conditions
18   !!   NEMO     1.0  !  2003  (J.-M. Molines, G. Madec)  F90, free form
19   !!                 !  2003  (J.M. Molines) add mpp_ini_north(_3d,_2d)
20   !!             -   !  2004  (R. Bourdalle Badie)  isend option in mpi
21   !!                 !  2004  (J.M. Molines) minloc, maxloc
22   !!             -   !  2005  (G. Madec, S. Masson)  npolj=5,6 F-point & ice cases
23   !!             -   !  2005  (R. Redler) Replacement of MPI_COMM_WORLD except for MPI_Abort
24   !!             -   !  2005  (R. Benshila, G. Madec)  add extra halo case
25   !!             -   !  2008  (R. Benshila) add mpp_ini_ice
26   !!            3.2  !  2009  (R. Benshila) SHMEM suppression, north fold in lbc_nfd
27   !!            3.2  !  2009  (O. Marti)    add mpp_ini_znl
28   !! History of the TAM:
29   !!            2.?  !  2007  (K. Mogensen) Original code (lib_mppadj)
30   !!            3.0  !  2009  (A. Vidard) nemo v3 update
31   !!            3.2  !  2010  (A. Vidard) 3.2 version, complete rewrite
32   !!----------------------------------------------------------------------
33#if   defined key_mpp_mpi 
34   !!----------------------------------------------------------------------
35   !!   'key_mpp_mpi'             MPI massively parallel processing library
36   !!----------------------------------------------------------------------
37   !!   mpp_lnk     : interface (defined in lbclnk) for message passing of 2d or 3d arrays (mpp_lnk_2d, mpp_lnk_3d)
38   !!   mpp_lnk_3d_gather :  Message passing manadgement for two 3D arrays
39   !!   mpp_lnk_e   : interface (defined in lbclnk) for message passing of 2d array with extra halo (mpp_lnk_2d_e)
40   !!   mppobc      : variant of mpp_lnk for open boundary condition
41   !!   mpp_lbc_north : north fold processors gathering
42   !!   mpp_lbc_north_e : variant of mpp_lbc_north for extra outer halo
43   !!----------------------------------------------------------------------
44   !! History of the direct module:
45   !!        !  94 (M. Guyon, J. Escobar, M. Imbard)  Original code
46   !!        !  97  (A.M. Treguier)  SHMEM additions
47   !!        !  98  (M. Imbard, J. Escobar, L. Colombet ) SHMEM and MPI
48   !!   9.0  !  03  (J.-M. Molines, G. Madec)  F90, free form
49   !!        !  04  (R. Bourdalle Badie)  isend option in mpi
50   !!        !  05  (G. Madec, S. Masson)  npolj=5,6 F-point & ice cases
51   !!        !  05  (R. Redler) Replacement of MPI_COMM_WORLD except for MPI_Abort
52   !!        !  09  (R. Benshila) SHMEM suppression, north fold in lbc_nfd
53   !! History of the TAM:
54   !!            2.?  !  2007  (K. Mogensen) Original code (lib_mppadj)
55   !!            3.0  !  2009  (A. Vidard) nemo v3 update
56   !!            3.2  !  2010  (A. Vidard) 3.2 version, complete rewrite
57   !!----------------------------------------------------------------------
58   !!  OPA 9.0 , LOCEAN-IPSL (2005)
59   !! $Id$
60   !! This software is governed by the CeCILL licence see modipsl/doc/NEMO_CeCILL.txt
61   !!---------------------------------------------------------------------
62   !! * Modules used
63   USE dom_oce                    ! ocean space and time domain
64   USE in_out_manager             ! I/O manager
65   USE lib_mpp
66   USE lbcnfd_tam                 ! north fold treatment
67   USE mppsumtam, ONLY : &
68      & mpp_sum_nfd 
69
70   IMPLICIT NONE
71   PRIVATE
72   
73   PUBLIC   mpp_lbc_north_adj, mpp_lbc_north_e_adj
74   PUBLIC   mpp_lnk_3d_adj, mpp_lnk_3d_gather_adj, mpp_lnk_2d_adj, mpp_lnk_2d_e_adj
75   PUBLIC   mppobc_adj
76
77   !! * Interfaces
78   !! define generic interface for these routine as they are called sometimes
79   !! with scalar arguments instead of array arguments, which causes problems
80   !! for the compilation on AIX system as well as NEC and SGI. Ok on COMPACQ
81   INTERFACE mpp_lbc_north_adj
82      MODULE PROCEDURE mpp_lbc_north_3d_adj, mpp_lbc_north_2d_adj 
83   END INTERFACE
84   !! ========================= !!
85   !!  MPI  variable definition !!
86   !! ========================= !!
87!$AGRIF_DO_NOT_TREAT
88#  include <mpif.h>
89!$AGRIF_END_DO_NOT_TREAT
90   
91   ! message passing arrays
92   ! Note: the adjoint of t4ns is t4sn:
93   REAL(wp), DIMENSION(jpi,jprecj,jpk,2,2) ::   t4ns_ad, t4sn_ad   ! 2 x 3d for north-south & south-north
94   REAL(wp), DIMENSION(jpj,jpreci,jpk,2,2) ::   t4ew_ad, t4we_ad   ! 2 x 3d for east-west & west-east
95   REAL(wp), DIMENSION(jpi,jprecj,jpk,2,2) ::   t4p1_ad, t4p2_ad   ! 2 x 3d for north fold
96   REAL(wp), DIMENSION(jpi,jprecj,jpk,2)   ::   t3ns_ad, t3sn_ad   ! 3d for north-south & south-north
97   REAL(wp), DIMENSION(jpj,jpreci,jpk,2)   ::   t3ew_ad, t3we_ad   ! 3d for east-west & west-east
98   REAL(wp), DIMENSION(jpi,jprecj,jpk,2)   ::   t3p1_ad, t3p2_ad   ! 3d for north fold
99   REAL(wp), DIMENSION(jpi,jprecj,2)       ::   t2ns_ad, t2sn_ad   ! 2d for north-south & south-north
100   REAL(wp), DIMENSION(jpj,jpreci,2)       ::   t2ew_ad, t2we_ad   ! 2d for east-west & west-east
101   REAL(wp), DIMENSION(jpi,jprecj,2)       ::   t2p1_ad, t2p2_ad   ! 2d for north fold
102   REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,jprecj+jpr2dj,2) ::   &
103      &                                         tr2ns_ad, tr2sn_ad ! 2d for north-south & south-north + extra outer halo
104   REAL(wp), DIMENSION(1-jpr2dj:jpj+jpr2dj,jpreci+jpr2di,2) ::   &
105      &                                         tr2ew_ad, tr2we_ad ! 2d for east-west   & west-east   + extra outer halo
106   !!----------------------------------------------------------------------
107   !! NEMO/OPA 3.2 , LOCEAN-IPSL (2009)
108   !! $Id$
109   !! Software governed by the CeCILL licence (modipsl/doc/NEMO_CeCILL.txt)
110   !!----------------------------------------------------------------------
111
112CONTAINS
113
114
115   SUBROUTINE mpp_lnk_3d_adj( ptab_ad, cd_type, psgn, cd_mpp, pval )
116      !!----------------------------------------------------------------------
117      !!                  ***  routine mpp_lnk_3d  ***
118      !!
119      !! ** Purpose :   Message passing manadgement
120      !!
121      !! ** Method  :   Use mppsend and mpprecv function for passing mask
122      !!      between processors following neighboring subdomains.
123      !!            domain parameters
124      !!                    nlci   : first dimension of the local subdomain
125      !!                    nlcj   : second dimension of the local subdomain
126      !!                    nbondi : mark for "east-west local boundary"
127      !!                    nbondj : mark for "north-south local boundary"
128      !!                    noea   : number for local neighboring processors
129      !!                    nowe   : number for local neighboring processors
130      !!                    noso   : number for local neighboring processors
131      !!                    nono   : number for local neighboring processors
132      !!
133      !! ** Action  :   ptab_ad with update value at its periphery
134      !!
135      !!----------------------------------------------------------------------
136      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab_ad  ! 3D array on which the boundary condition is applied
137      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type  ! define the nature of ptab array grid-points
138      !                                                             ! = T , U , V , F , W points
139      REAL(wp)                        , INTENT(in   ) ::   psgn     ! =-1 the sign change across the north fold boundary
140      !                                                             ! =  1. , the sign is kept
141      CHARACTER(len=3), OPTIONAL      , INTENT(in   ) ::   cd_mpp   ! fill the overlap area only
142      REAL(wp)        , OPTIONAL      , INTENT(in   ) ::   pval     ! background value (used at closed boundaries)
143      !!
144      INTEGER  ::   ji, jj, jk, jl             ! dummy loop indices
145      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
146      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
147      REAL(wp) ::   zland
148      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
149      !!----------------------------------------------------------------------
150      t3ns_ad = 0.0_wp ; t3sn_ad = 0.0_wp
151      t3we_ad = 0.0_wp ; t3ew_ad = 0.0_wp
152      IF( PRESENT( pval ) ) THEN   ;   zland = pval      ! set land value
153      ELSE                         ;   zland = 0.e0      ! zero by default
154      ENDIF
155
156
157      ! 4. north fold treatment
158      ! -----------------------
159      !
160      IF( npolj /= 0 .AND. .NOT. PRESENT(cd_mpp) ) THEN
161         !
162         SELECT CASE ( jpni )
163         CASE ( 1 )     ;   CALL lbc_nfd_adj      ( ptab_ad, cd_type, psgn )   ! only 1 northern proc, no mpp
164         CASE DEFAULT   ;   CALL mpp_lbc_north_adj( ptab_ad, cd_type, psgn )   ! for all northern procs.
165         END SELECT
166         !
167      ENDIF
168
169      ! 3. North and south directions
170      ! -----------------------------
171      ! always closed : we play only with the neigbours
172      !
173      !                           ! Write Dirichlet lateral conditions
174      ijhom = nlcj-jprecj
175      !
176      SELECT CASE ( nbondj )
177      CASE ( -1 )
178         DO jl = 1, jprecj
179            t3ns_ad(:,jl,:,2)     = t3ns_ad(:,jl,:,2) + ptab_ad(:,ijhom+jl,:)
180            ptab_ad(:,ijhom+jl,:) = 0._wp
181         END DO
182      CASE ( 0 ) 
183         DO jl = 1, jprecj
184            t3ns_ad(:,jl,:,2)     = t3ns_ad(:,jl,:,2) + ptab_ad(:,ijhom+jl,:)
185            ptab_ad(:,ijhom+jl,:) = 0.0_wp
186            t3sn_ad(:,jl,:,2)     = t3sn_ad(:,jl,:,2) + ptab_ad(:,jl      ,:)
187            ptab_ad(:,jl      ,:) = 0.0_wp
188         END DO
189      CASE ( 1 )
190         DO jl = 1, jprecj
191            t3sn_ad(:,jl,:,2) = t3sn_ad(:,jl,:,2) + ptab_ad(:,jl,:)
192            ptab_ad(:,jl,:)   = 0.0_wp
193         END DO
194      END SELECT
195!
196      !                           ! Migrations
197      imigr = jprecj * jpi * jpk
198      SELECT CASE ( nbondj )     
199      CASE ( -1 )
200         CALL mppsend( 4, t3ns_ad(1,1,1,2), imigr, nono, ml_req1 )
201         CALL mpprecv( 3, t3sn_ad(1,1,1,1), imigr )
202         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
203      CASE ( 0 )
204         CALL mppsend( 3, t3sn_ad(1,1,1,2), imigr, noso, ml_req1 )
205         CALL mppsend( 4, t3ns_ad(1,1,1,2), imigr, nono, ml_req2 )
206         CALL mpprecv( 3, t3sn_ad(1,1,1,1), imigr )
207         CALL mpprecv( 4, t3ns_ad(1,1,1,1), imigr )
208         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
209         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
210      CASE ( 1 ) 
211         CALL mppsend( 3, t3sn_ad(1,1,1,2), imigr, noso, ml_req1 )
212         CALL mpprecv( 4, t3ns_ad(1,1,1,1), imigr )
213         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
214      END SELECT
215      !
216      !
217      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
218         ijhom = nlcj-nrecj
219         DO jl = 1, jprecj
220            ptab_ad(:,jprecj+jl,:) = ptab_ad(:,jprecj+jl,:) + t3ns_ad(:,jl,:,1)
221            t3ns_ad(:,jl,:,1)      = 0.0_wp
222            ptab_ad(:,ijhom +jl,:) = ptab_ad(:,ijhom +jl,:) + t3sn_ad(:,jl,:,1)
223            t3sn_ad(:,jl,:,1)      = 0.0_wp
224         END DO
225      ENDIF
226      !
227      ! 2. East and west directions exchange
228      ! ------------------------------------
229      iihom = nlci-jpreci
230      !
231      SELECT CASE ( nbondi )
232      CASE ( -1 )
233         DO jl = 1, jpreci
234            t3ew_ad(:,jl,:,2)     = t3ew_ad(:,jl,:,2) + ptab_ad(iihom+jl,:,:)
235            ptab_ad(iihom+jl,:,:) = 0.0_wp
236         END DO
237      CASE ( 0 ) 
238         DO jl = 1, jpreci
239            t3ew_ad(:,jl,:,2)     = t3ew_ad(:,jl,:,2) + ptab_ad(iihom+jl,:,:)
240            ptab_ad(iihom+jl,:,:) = 0.0_wp
241            t3we_ad(:,jl,:,2)     = t3we_ad(:,jl,:,2) + ptab_ad(jl      ,:,:)
242            ptab_ad(jl      ,:,:) = 0.0_wp
243         END DO
244      CASE ( 1 )
245         DO jl = 1, jpreci
246            t3we_ad(:,jl,:,2)     = t3we_ad(:,jl,:,2) + ptab_ad(jl      ,:,:)
247            ptab_ad(jl      ,:,:) = 0.0_wp
248         END DO
249      END SELECT
250      !                           ! Write Dirichlet lateral conditions
251      !                           ! Migrations
252      imigr = jpreci * jpj * jpk
253      !
254      SELECT CASE ( nbondi ) 
255      CASE ( -1 )
256         CALL mppsend( 2, t3ew_ad(1,1,1,2), imigr, noea, ml_req1 )
257         CALL mpprecv( 1, t3we_ad(1,1,1,1), imigr )
258         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
259      CASE ( 0 )
260         CALL mppsend( 1, t3we_ad(1,1,1,2), imigr, nowe, ml_req1 )
261         CALL mppsend( 2, t3ew_ad(1,1,1,2), imigr, noea, ml_req2 )
262         CALL mpprecv( 1, t3we_ad(1,1,1,1), imigr )
263         CALL mpprecv( 2, t3ew_ad(1,1,1,1), imigr )
264         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
265         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
266      CASE ( 1 )
267         CALL mppsend( 1, t3we_ad(1,1,1,2), imigr, nowe, ml_req1 )
268         CALL mpprecv( 2, t3ew_ad(1,1,1,1), imigr )
269         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
270      END SELECT
271      !
272      ! we play with the neigbours AND the row number because of the periodicity
273      !
274      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
275      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
276         iihom = nlci-nreci
277         DO jl = 1, jpreci
278            ptab_ad(iihom +jl,:,:) = ptab_ad(iihom +jl,:,:) + t3we_ad(:,jl,:,1)
279            t3we_ad(:,jl,:,1) = 0.0_wp
280            ptab_ad(jpreci+jl,:,:) = ptab_ad(jpreci+jl,:,:) + t3ew_ad(:,jl,:,1)
281            t3ew_ad(:,jl,:,1) = 0.0_wp
282         END DO
283      END SELECT 
284      !
285      ! 1. standard boundary treatment
286      ! ------------------------------
287      IF( PRESENT( cd_mpp ) ) THEN      ! only fill added line/raw with existing values
288         !
289         ! WARNING ptab is defined only between nld and nle
290         DO jk = 1, jpk
291            DO ji = nlci+1, jpi                 ! added column(s) (full)
292               ptab_ad(nlei,      nlej   ,jk) = ptab_ad(nlei,nlej     ,jk) + SUM(ptab_ad(ji,nlej+1:jpj   ,jk))
293               ptab_ad(ji  ,nlej+1:jpj   ,jk) = 0.0_wp
294               ptab_ad(nlei,nldj         ,jk) = ptab_ad(nlei,nldj     ,jk) + SUM(ptab_ad(ji,1     :nldj-1,jk))
295               ptab_ad(ji  ,1     :nldj-1,jk) = 0.0_wp
296               ptab_ad(nlei,nldj  :nlej  ,jk) = ptab_ad(nlei,nldj:nlej,jk) + ptab_ad(ji,nldj  :nlej  ,jk)
297               ptab_ad(ji  ,nldj  :nlej  ,jk) = 0.0_wp
298            END DO
299            DO jj = nlcj+1, jpj                 ! added line(s)   (inner only)
300               ptab_ad(nlei         ,nlej,jk) = ptab_ad(nlei     ,nlej,jk) + SUM(ptab_ad(nlei+1:nlci  ,jj,jk))
301               ptab_ad(nlei+1:nlci  ,jj  ,jk) = 0.0_wp
302               ptab_ad(nldi         ,nlej,jk) = ptab_ad(nldi     ,nlej,jk) + SUM(ptab_ad(1     :nldi-1,jj,jk))
303               ptab_ad(1     :nldi-1,jj  ,jk) = 0.0_wp
304               ptab_ad(nldi  :nlei  ,nlej,jk) = ptab_ad(nldi:nlei,nlej,jk) + ptab_ad(nldi  :nlei  ,jj,jk)
305               ptab_ad(nldi  :nlei  ,jj  ,jk) = 0.0_wp
306            END DO
307         END DO
308         !
309      ELSE                              ! standard close or cyclic treatment
310         !
311         !                                   ! North-South boundaries (always closed)
312                                      ptab_ad(:,nlcj-jprecj+1:jpj   ,:) = 0.0_wp       ! north
313         IF( .NOT. cd_type == 'F' )   ptab_ad(:,     1       :jprecj,:) = 0.0_wp       ! south except F-point
314         !                                   ! East-West boundaries
315         !                                        !* Cyclic east-west
316         IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
317            ptab_ad( 2   ,:,:) = ptab_ad(  2  ,:,:) + ptab_ad(jpi,:,:) 
318            ptab_ad(jpi  ,:,:) = 0.0_wp
319            ptab_ad(jpim1,:,:) = ptab_ad(jpim1,:,:) + ptab_ad( 1 ,:,:)
320            ptab_ad( 1   ,:,:) = 0.0_wp
321         ELSE                                     !* closed
322            IF( .NOT. cd_type == 'F' )   ptab_ad(     1       :jpreci,:,:) = 0.0_wp    ! south except F-point
323                                         ptab_ad(nlci-jpreci+1:jpi   ,:,:) = 0.0_wp    ! north
324         ENDIF
325         !
326      ENDIF
327      !
328   END SUBROUTINE mpp_lnk_3d_adj
329
330
331   SUBROUTINE mpp_lnk_2d_adj( pt2d_ad, cd_type, psgn, cd_mpp, pval )
332      !!----------------------------------------------------------------------
333      !!                  ***  routine mpp_lnk_2d  ***
334      !!                 
335      !! ** Purpose :   Message passing manadgement for 2d array
336      !!
337      !! ** Method  :   Use mppsend and mpprecv function for passing mask
338      !!      between processors following neighboring subdomains.
339      !!            domain parameters
340      !!                    nlci   : first dimension of the local subdomain
341      !!                    nlcj   : second dimension of the local subdomain
342      !!                    nbondi : mark for "east-west local boundary"
343      !!                    nbondj : mark for "north-south local boundary"
344      !!                    noea   : number for local neighboring processors
345      !!                    nowe   : number for local neighboring processors
346      !!                    noso   : number for local neighboring processors
347      !!                    nono   : number for local neighboring processors
348      !!
349      !!----------------------------------------------------------------------
350      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) ::   pt2d_ad  ! 2D array on which the boundary condition is applied
351      CHARACTER(len=1)            , INTENT(in   ) ::   cd_type  ! define the nature of ptab array grid-points
352      !                                                         ! = T , U , V , F , W and I points
353      REAL(wp)                    , INTENT(in   ) ::   psgn     ! =-1 the sign change across the north fold boundary
354      !                                                         ! =  1. , the sign is kept
355      CHARACTER(len=3), OPTIONAL  , INTENT(in   ) ::   cd_mpp   ! fill the overlap area only
356      REAL(wp)        , OPTIONAL  , INTENT(in   ) ::   pval     ! background value (used at closed boundaries)
357      !!
358      INTEGER  ::   ji, jj, jl   ! dummy loop indices
359      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
360      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
361      REAL(wp) ::   zland
362      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
363      !!----------------------------------------------------------------------
364      t2ns_ad = 0.0_wp ; t2sn_ad = 0.0_wp
365      t2we_ad = 0.0_wp ; t2ew_ad = 0.0_wp
366      IF( PRESENT( pval ) ) THEN   ;   zland = pval      ! set land value
367      ELSE                         ;   zland = 0.e0      ! zero by default
368      ENDIF
369
370      ! 4. north fold treatment
371      ! -----------------------
372      !
373      IF( npolj /= 0 .AND. .NOT. PRESENT(cd_mpp) ) THEN
374         !
375         SELECT CASE ( jpni )
376         CASE ( 1 )     ;   CALL lbc_nfd_adj      ( pt2d_ad, cd_type, psgn )   ! only 1 northern proc, no mpp
377         CASE DEFAULT   ;   CALL mpp_lbc_north_adj( pt2d_ad, cd_type, psgn )   ! for all northern procs.
378         END SELECT
379         !
380      ENDIF
381      !
382      ! 3. North and south directions
383      ! -----------------------------
384      !                           ! Write Dirichlet lateral conditions
385      ijhom = nlcj - jprecj
386      !
387      SELECT CASE ( nbondj )
388      CASE ( -1 )
389         DO jl = 1, jprecj
390            t2ns_ad(:,jl,2)     = t2ns_ad(:,jl,2) + pt2d_ad(:,ijhom+jl)
391            pt2d_ad(:,ijhom+jl) = t2ns_ad(:,jl,2)
392         END DO
393      CASE ( 0 )
394         DO jl = 1, jprecj
395            t2ns_ad(:,jl,2)     = t2ns_ad(:,jl,2) + pt2d_ad(:,ijhom+jl)
396            pt2d_ad(:,ijhom+jl) = 0.0_wp
397            t2sn_ad(:,jl,2)     = t2sn_ad(:,jl,2) + pt2d_ad(:,jl      )
398            pt2d_ad(:,jl      ) = 0.0_wp
399         END DO
400      CASE ( 1 ) 
401         DO jl = 1, jprecj
402            t2sn_ad(:,jl,2) = t2sn_ad(:,jl,2) + pt2d_ad(:,jl      ) 
403            pt2d_ad(:,jl      ) = 0.0_wp
404         END DO
405      END SELECT
406      !
407      !                           ! Migrations
408      imigr = jprecj * jpi
409      !
410      SELECT CASE ( nbondj )
411      CASE ( -1 )
412         CALL mppsend( 4, t2ns_ad(1,1,2), imigr, nono, ml_req1 )
413         CALL mpprecv( 3, t2sn_ad(1,1,1), imigr )
414         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
415      CASE ( 0 )
416         CALL mppsend( 3, t2sn_ad(1,1,2), imigr, noso, ml_req1 )
417         CALL mppsend( 4, t2ns_ad(1,1,2), imigr, nono, ml_req2 )
418         CALL mpprecv( 3, t2sn_ad(1,1,1), imigr )
419         CALL mpprecv( 4, t2ns_ad(1,1,1), imigr )
420         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
421         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
422      CASE ( 1 )
423         CALL mppsend( 3, t2sn_ad(1,1,2), imigr, noso, ml_req1 )
424         CALL mpprecv( 4, t2ns_ad(1,1,1), imigr )
425         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
426      END SELECT
427      !
428      ! always closed : we play only with the neigbours
429      !
430      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
431         ijhom = nlcj-nrecj
432         DO jl = 1, jprecj
433            pt2d_ad(:,jprecj+jl) = pt2d_ad(:,jprecj+jl) + t2ns_ad(:,jl,1)
434            t2ns_ad(:,jl,1) = 0.0_wp
435            pt2d_ad(:,ijhom +jl) = pt2d_ad(:,ijhom +jl) + t2sn_ad(:,jl,1)
436            t2sn_ad(:,jl,1) = 0.0_wp
437         END DO
438      ENDIF
439      ! 2. East and west directions exchange
440      ! ------------------------------------
441      !                           ! Write Dirichlet lateral conditions
442      iihom = nlci - jpreci
443      !
444      SELECT CASE ( nbondi )
445      CASE ( -1 )
446         DO jl = 1, jpreci
447            t2ew_ad(:,jl,2)     = t2ew_ad(:,jl,2) + pt2d_ad(iihom+jl,:)
448            pt2d_ad(iihom+jl,:) = 0.0_wp
449         END DO
450      CASE ( 0 )
451         DO jl = 1, jpreci
452            t2ew_ad(:,jl,2)     = t2ew_ad(:,jl,2) + pt2d_ad(iihom+jl,:)
453            pt2d_ad(iihom+jl,:) = 0.0_wp
454            t2we_ad(:,jl,2)     = t2we_ad(:,jl,2) + pt2d_ad(jl      ,:)
455            pt2d_ad(jl      ,:) = 0.0_wp
456         END DO
457      CASE ( 1 )
458         DO jl = 1, jpreci
459            t2we_ad(:,jl,2) = t2we_ad(:,jl,2) + pt2d_ad(jl,:)
460            pt2d_ad(jl,:)   = 0.0_wp
461         END DO
462      END SELECT
463      !
464      !                           ! Migrations
465      imigr = jpreci * jpj
466      !
467      SELECT CASE ( nbondi )
468      CASE ( -1 )
469         CALL mppsend( 2, t2ew_ad(1,1,2), imigr, noea, ml_req1 )
470         CALL mpprecv( 1, t2we_ad(1,1,1), imigr )
471         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
472      CASE ( 0 )
473         CALL mppsend( 1, t2we_ad(1,1,2), imigr, nowe, ml_req1 )
474         CALL mppsend( 2, t2ew_ad(1,1,2), imigr, noea, ml_req2 )
475         CALL mpprecv( 1, t2we_ad(1,1,1), imigr )
476         CALL mpprecv( 2, t2ew_ad(1,1,1), imigr )
477         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
478         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
479      CASE ( 1 )
480         CALL mppsend( 1, t2we_ad(1,1,2), imigr, nowe, ml_req1 )
481         CALL mpprecv( 2, t2ew_ad(1,1,1), imigr )
482         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
483      END SELECT
484      !
485      ! we play with the neigbours AND the row number because of the periodicity
486      !
487      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
488      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
489         iihom = nlci-nreci
490         DO jl = 1, jpreci
491            pt2d_ad(iihom +jl,:) = pt2d_ad(iihom +jl,:) + t2we_ad(:,jl,1)
492            t2we_ad(:,jl,1)      = 0.0_wp
493            pt2d_ad(jpreci+jl,:) = pt2d_ad(jpreci+jl,:) + t2ew_ad(:,jl,1)
494            t2ew_ad(:,jl,1)      = 0.0_wp
495         END DO
496      END SELECT
497      !
498      ! 1. standard boundary treatment
499      ! ------------------------------
500      !
501      IF( PRESENT( cd_mpp ) ) THEN      ! only fill added line/raw with existing values
502         !
503         ! WARNING pt2d is defined only between nld and nle
504         DO ji = nlci+1, jpi                 ! added column(s) (full)
505            pt2d_ad(nlei,       nlej  ) = pt2d_ad(nlei,     nlej) + SUM(pt2d_ad(ji,nlej+1:jpj   ))
506            pt2d_ad(ji  ,nlej+1:jpj   ) = 0.0_wp
507            pt2d_ad(nlei,nldj         ) = pt2d_ad(nlei,nldj     ) + SUM(pt2d_ad(ji,1     :nldj-1))
508            pt2d_ad(ji  ,1     :nldj-1) = 0.0_wp
509            pt2d_ad(nlei,nldj  :nlej  ) = pt2d_ad(nlei,nldj:nlej) + pt2d_ad(ji,nldj  :nlej  )
510            pt2d_ad(ji  ,nldj  :nlej  ) = 0.0_wp
511         END DO
512         DO jj = nlcj+1, jpj                 ! added line(s)   (inner only)
513            pt2d_ad(nlei         ,nlej) = pt2d_ad(     nlei,     nlej) + SUM(pt2d_ad(nlei+1:nlci  , jj))
514            pt2d_ad(nlei+1:nlci  ,jj  ) = 0.0_wp
515            pt2d_ad(nldi         ,nlej) = pt2d_ad(nldi     ,     nlej) + SUM(pt2d_ad(1     :nldi-1, jj))
516            pt2d_ad(1     :nldi-1,jj  ) = 0.0_wp
517            pt2d_ad(nldi  :nlei  ,nlej) = pt2d_ad(nldi:nlei,     nlej) + pt2d_ad(nldi  :nlei  , jj)
518            pt2d_ad(nldi  :nlei  , jj ) = 0.0_wp
519         END DO
520         !
521      ELSE                              ! standard close or cyclic treatment
522         !
523         !                                   ! North-South boundaries (always closed)
524            IF( .NOT. cd_type == 'F' )   pt2d_ad(:,     1       :jprecj) = 0.0_wp !south except F-point
525                                         pt2d_ad(:,nlcj-jprecj+1:jpj   ) = 0.0_wp ! north
526         !                                   ! East-West boundaries
527         IF( nbondi == 2 .AND.   &                ! Cyclic east-west
528            &    (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
529            pt2d_ad(  2  ,:) = pt2d_ad(  2  ,:) + pt2d_ad(jpi,:) ! east
530            pt2d_ad(jpi  ,:) = 0.0_wp
531            pt2d_ad(jpim1,:) = pt2d_ad(jpim1,:) + pt2d_ad( 1 ,:) ! west
532            pt2d_ad( 1   ,:) = 0.0_wp                                   
533         ELSE                                     ! closed
534            IF( .NOT. cd_type == 'F' )   pt2d_ad(     1       :jpreci,:) = 0.0_wp   ! south except F-point
535                                         pt2d_ad(nlci-jpreci+1:jpi   ,:) = 0.0_wp   ! north
536         ENDIF
537         !
538      ENDIF
539
540   END SUBROUTINE mpp_lnk_2d_adj
541
542
543   SUBROUTINE mpp_lnk_3d_gather_adj( ptab1_ad, cd_type1, ptab2_ad, cd_type2, psgn )
544      !!----------------------------------------------------------------------
545      !!                  ***  routine mpp_lnk_3d_gather  ***
546      !!
547      !! ** Purpose :   Message passing manadgement for two 3D arrays
548      !!
549      !! ** Method  :   Use mppsend and mpprecv function for passing mask
550      !!      between processors following neighboring subdomains.
551      !!            domain parameters
552      !!                    nlci   : first dimension of the local subdomain
553      !!                    nlcj   : second dimension of the local subdomain
554      !!                    nbondi : mark for "east-west local boundary"
555      !!                    nbondj : mark for "north-south local boundary"
556      !!                    noea   : number for local neighboring processors
557      !!                    nowe   : number for local neighboring processors
558      !!                    noso   : number for local neighboring processors
559      !!                    nono   : number for local neighboring processors
560      !!
561      !! ** Action  :   ptab1 and ptab2  with update value at its periphery
562      !!
563      !!----------------------------------------------------------------------
564      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab1_ad  ! first and second 3D array on which
565      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   ptab2_ad  ! the boundary condition is applied
566      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type1  ! nature of ptab1 and ptab2 arrays
567      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type2  ! i.e. grid-points = T , U , V , F or W points
568      REAL(wp)                        , INTENT(in   ) ::   psgn      ! =-1 the sign change across the north fold boundary
569      !!                                                             ! =  1. , the sign is kept
570      INTEGER  ::   jl   ! dummy loop indices
571      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
572      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
573      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
574      !!----------------------------------------------------------------------
575      t4ns_ad = 0.0_wp ; t4sn_ad = 0.0_wp
576      t4we_ad = 0.0_wp ; t4ew_ad = 0.0_wp
577      ! 4. north fold treatment
578      ! -----------------------
579      IF( npolj /= 0 ) THEN
580         !
581         SELECT CASE ( jpni )
582         CASE ( 1 )                                           
583            CALL lbc_nfd_adj      ( ptab2_ad, cd_type2, psgn )
584            CALL lbc_nfd_adj      ( ptab1_ad, cd_type1, psgn )   ! only for northern procs.
585         CASE DEFAULT
586            CALL mpp_lbc_north_adj( ptab2_ad, cd_type2, psgn)
587            CALL mpp_lbc_north_adj( ptab1_ad, cd_type1, psgn )   ! for all northern procs.
588         END SELECT 
589         !
590      ENDIF
591      !
592      ! 3. North and south directions
593      ! -----------------------------
594      !                           ! Write Dirichlet lateral conditions
595      ijhom = nlcj - jprecj
596      !
597      SELECT CASE ( nbondj )
598      CASE ( -1 )
599         DO jl = 1, jprecj
600            t4ns_ad(:,jl,:,2,2)    = t4ns_ad(:,jl,:,2,2) + ptab2_ad(:,ijhom+jl,:)
601            ptab2_ad(:,ijhom+jl,:) = 0.0_wp
602            t4ns_ad(:,jl,:,1,2)    = t4ns_ad(:,jl,:,1,2) + ptab1_ad(:,ijhom+jl,:) 
603            ptab1_ad(:,ijhom+jl,:) = 0.0_wp
604         END DO
605      CASE ( 0 ) 
606         DO jl = 1, jprecj
607            t4ns_ad(:,jl,:,2,2)    = t4ns_ad(:,jl,:,2,2) + ptab2_ad(:,ijhom+jl,:)
608            ptab2_ad(:,ijhom+jl,:) = 0.0_wp
609            t4sn_ad(:,jl,:,2,2)    = t4sn_ad(:,jl,:,2,2) + ptab2_ad(:,jl      ,:)
610            ptab2_ad(:,jl      ,:) = 0.0_wp
611            t4ns_ad(:,jl,:,1,2)    = t4ns_ad(:,jl,:,1,2) + ptab1_ad(:,ijhom+jl,:)
612            ptab1_ad(:,ijhom+jl,:) = 0.0_wp
613            t4sn_ad(:,jl,:,1,2)    = t4sn_ad(:,jl,:,1,2) + ptab1_ad(:,jl      ,:)
614            ptab1_ad(:,jl      ,:) = 0.0_wp
615         END DO
616      CASE ( 1 )
617         DO jl = 1, jprecj
618            t4sn_ad(:,jl,:,2,2) = t4sn_ad(:,jl,:,2,2) + ptab2_ad(:,jl,:)
619            ptab2_ad(:,jl,:) = 0.0_wp
620            t4sn_ad(:,jl,:,1,2) = t4sn_ad(:,jl,:,1,2) + ptab1_ad(:,jl,:)
621            ptab1_ad(:,jl,:) = 0.0_wp
622         END DO
623      END SELECT
624      !                           ! Migrations
625      imigr = jprecj * jpi * jpk * 2
626      !
627      SELECT CASE ( nbondj )     
628      CASE ( -1 )
629         CALL mppsend( 4, t4ns_ad(1,1,1,1,2), imigr, nono, ml_req1 )
630         CALL mpprecv( 3, t4sn_ad(1,1,1,1,1), imigr )
631         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
632      CASE ( 0 )
633         CALL mppsend( 3, t4sn_ad(1,1,1,1,2), imigr, noso, ml_req1 )
634         CALL mppsend( 4, t4ns_ad(1,1,1,1,2), imigr, nono, ml_req2 )
635         CALL mpprecv( 3, t4sn_ad(1,1,1,1,1), imigr )
636         CALL mpprecv( 4, t4ns_ad(1,1,1,1,1), imigr )
637         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
638         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
639      CASE ( 1 ) 
640         CALL mppsend( 3, t4sn_ad(1,1,1,1,2), imigr, noso, ml_req1 )
641         CALL mpprecv( 4, t4ns_ad(1,1,1,1,1), imigr )
642         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
643      END SELECT
644      !
645      ! always closed : we play only with the neigbours
646      !
647      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
648         ijhom = nlcj - nrecj
649         DO jl = 1, jprecj
650            ptab2_ad(:,jprecj+jl,:) = ptab2_ad(:,jprecj+jl,:) + t4ns_ad(:,jl,:,2,1) 
651            t4ns_ad(:,jl,:,2,1)     = 0.0_wp
652            ptab2_ad(:,ijhom +jl,:) = ptab2_ad(:,ijhom +jl,:) + t4sn_ad(:,jl,:,2,1)
653            t4sn_ad(:,jl,:,2,1)     = 0.0_wp
654            ptab1_ad(:,jprecj+jl,:) = ptab1_ad(:,jprecj+jl,:) + t4ns_ad(:,jl,:,1,1)
655            t4ns_ad(:,jl,:,1,1)     = 0.0_wp
656            ptab1_ad(:,ijhom +jl,:) = ptab1_ad(:,ijhom +jl,:) + t4sn_ad(:,jl,:,1,1)
657            t4sn_ad(:,jl,:,1,1)     = 0.0_wp
658         END DO
659      ENDIF
660      !
661      ! 2. East and west directions exchange
662      ! ------------------------------------
663      !                           ! Write Dirichlet lateral conditions
664      iihom = nlci - jpreci
665      !
666      SELECT CASE ( nbondi )
667      CASE ( -1 )
668         DO jl = 1, jpreci
669            t4ew_ad(:,jl,:,2,2)    = t4ew_ad(:,jl,:,2,2) + ptab2_ad(iihom+jl,:,:)
670            ptab2_ad(iihom+jl,:,:) = 0.0_wp
671            t4ew_ad(:,jl,:,1,2)    = t4ew_ad(:,jl,:,1,2) + ptab1_ad(iihom+jl,:,:)
672            ptab1_ad(iihom+jl,:,:) = 0.0_wp
673         END DO
674      CASE ( 0 ) 
675         DO jl = 1, jpreci
676            t4ew_ad(:,jl,:,2,2)    = t4ew_ad(:,jl,:,2,2) + ptab2_ad(iihom+jl,:,:)
677            ptab2_ad(iihom+jl,:,:) = 0.0_wp
678            t4we_ad(:,jl,:,2,2)    = t4we_ad(:,jl,:,2,2) + ptab2_ad(jl      ,:,:)
679            ptab2_ad(jl      ,:,:) = 0.0_wp
680            t4ew_ad(:,jl,:,1,2)    = t4ew_ad(:,jl,:,1,2) + ptab1_ad(iihom+jl,:,:) 
681            ptab1_ad(iihom+jl,:,:) = 0.0_wp
682            t4we_ad(:,jl,:,1,2)    = t4we_ad(:,jl,:,1,2) + ptab1_ad(jl      ,:,:)
683            ptab1_ad(jl      ,:,:) = 0.0_wp
684         END DO
685      CASE ( 1 )
686         DO jl = 1, jpreci
687            t4we_ad(:,jl,:,2,2) = t4we_ad(:,jl,:,2,2) + ptab2_ad(jl      ,:,:)
688            t4we_ad(:,jl,:,1,2) = t4we_ad(:,jl,:,1,2) + ptab1_ad(jl      ,:,:)
689            ptab1_ad(jl      ,:,:) = 0.0_wp
690            ptab2_ad(jl      ,:,:) = 0.0_wp
691         END DO
692      END SELECT
693      !
694      !                           ! Migrations
695      imigr = jpreci * jpj * jpk *2
696      !
697      SELECT CASE ( nbondi ) 
698      CASE ( -1 )
699         CALL mppsend( 2, t4ew_ad(1,1,1,1,2), imigr, noea, ml_req1 )
700         CALL mpprecv( 1, t4we_ad(1,1,1,1,1), imigr )
701         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
702      CASE ( 0 )
703         CALL mppsend( 1, t4we_ad(1,1,1,1,2), imigr, nowe, ml_req1 )
704         CALL mppsend( 2, t4ew_ad(1,1,1,1,2), imigr, noea, ml_req2 )
705         CALL mpprecv( 1, t4we_ad(1,1,1,1,1), imigr )
706         CALL mpprecv( 2, t4ew_ad(1,1,1,1,1), imigr )
707         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
708         IF(l_isend) CALL mpi_wait(ml_req2, ml_stat, ml_err)
709      CASE ( 1 )
710         CALL mppsend( 1, t4we_ad(1,1,1,1,2), imigr, nowe, ml_req1 )
711         CALL mpprecv( 2, t4ew_ad(1,1,1,1,1), imigr )
712         IF(l_isend) CALL mpi_wait(ml_req1, ml_stat, ml_err)
713      END SELECT
714      !
715      ! we play with the neigbours AND the row number because of the periodicity
716      !
717      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
718      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
719         iihom = nlci-nreci
720         DO jl = 1, jpreci
721            ptab2_ad(iihom +jl,:,:) = ptab2_ad(iihom +jl,:,:) + t4we_ad(:,jl,:,2,1)
722            t4we_ad(:,jl,:,2,1)     = 0.0_wp
723            ptab2_ad(jpreci+jl,:,:) = ptab2_ad(jpreci+jl,:,:) + t4ew_ad(:,jl,:,2,1)
724            t4ew_ad(:,jl,:,2,1)     = 0.0_wp
725            ptab1_ad(iihom +jl,:,:) = ptab1_ad(iihom +jl,:,:) + t4we_ad(:,jl,:,1,1)
726            t4we_ad(:,jl,:,1,1)     = 0.0_wp
727            ptab1_ad(jpreci+jl,:,:) = ptab1_ad(jpreci+jl,:,:) + t4ew_ad(:,jl,:,1,1)
728            t4ew_ad(:,jl,:,1,1)     = 0.0_wp
729         END DO
730      END SELECT
731      ! 1. standard boundary treatment
732      ! ------------------------------
733      !                                      ! East-West boundaries
734      !                                           !* Cyclic east-west
735      !                                      ! North-South boundaries
736                                    ptab2_ad(:,nlcj-jprecj+1:jpj   ,:) = 0.e0
737                                    ptab1_ad(:,nlcj-jprecj+1:jpj   ,:) = 0.e0    ! north
738      IF( .NOT. cd_type2 == 'F' )   ptab2_ad(:,     1       :jprecj,:) = 0.e0
739      IF( .NOT. cd_type1 == 'F' )   ptab1_ad(:,     1       :jprecj,:) = 0.e0    ! south except at F-point
740      IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
741         ptab2_ad(  2  ,:,:) = ptab2_ad(  2  ,:,:) + ptab2_ad(jpi,:,:)
742         ptab2_ad(jpi,:,:)   = 0.0_wp
743         ptab2_ad(jpim1,:,:) = ptab2_ad(jpim1,:,:) + ptab2_ad( 1 ,:,:)
744         ptab2_ad( 1 ,:,:)   = 0.0_wp
745         ptab1_ad(  2  ,:,:) = ptab1_ad(  2  ,:,:) + ptab1_ad(jpi,:,:)
746         ptab1_ad(jpi,:,:)   = 0.0_wp
747         ptab1_ad(jpim1,:,:) = ptab1_ad(jpim1,:,:) + ptab1_ad( 1 ,:,:)
748         ptab1_ad( 1 ,:,:)   = 0.0_wp
749      ELSE                                        !* closed
750         IF( .NOT. cd_type1 == 'F' )   ptab1_ad(     1       :jpreci,:,:) = 0.e0    ! south except at F-point
751         IF( .NOT. cd_type2 == 'F' )   ptab2_ad(     1       :jpreci,:,:) = 0.e0
752                                       ptab1_ad(nlci-jpreci+1:jpi   ,:,:) = 0.e0    ! north
753                                       ptab2_ad(nlci-jpreci+1:jpi   ,:,:) = 0.e0
754      ENDIF
755
756   END SUBROUTINE mpp_lnk_3d_gather_adj
757
758
759   SUBROUTINE mpp_lnk_2d_e_adj( pt2d_ad, cd_type, psgn )
760      !!----------------------------------------------------------------------
761      !!                  ***  routine mpp_lnk_2d_e  ***
762      !!                 
763      !! ** Purpose :   Message passing manadgement for 2d array (with halo)
764      !!
765      !! ** Method  :   Use mppsend and mpprecv function for passing mask
766      !!      between processors following neighboring subdomains.
767      !!            domain parameters
768      !!                    nlci   : first dimension of the local subdomain
769      !!                    nlcj   : second dimension of the local subdomain
770      !!                    jpr2di : number of rows for extra outer halo
771      !!                    jpr2dj : number of columns for extra outer halo
772      !!                    nbondi : mark for "east-west local boundary"
773      !!                    nbondj : mark for "north-south local boundary"
774      !!                    noea   : number for local neighboring processors
775      !!                    nowe   : number for local neighboring processors
776      !!                    noso   : number for local neighboring processors
777      !!                    nono   : number for local neighboring processors
778      !!
779      !!----------------------------------------------------------------------
780      REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT(inout) ::   pt2d_ad ! 2D array with extra halo
781      CHARACTER(len=1)                                            , INTENT(in   ) ::   cd_type  ! nature of ptab array grid-points
782      !                                                                                         ! = T , U , V , F , W and I points
783      REAL(wp)                                                    , INTENT(in   ) ::   psgn     ! =-1 the sign change across the
784      !!                                                                                        ! north boundary, =  1. otherwise
785      INTEGER  ::   jl   ! dummy loop indices
786      INTEGER  ::   imigr, iihom, ijhom        ! temporary integers
787      INTEGER  ::   ipreci, iprecj             ! temporary integers
788      INTEGER  ::   ml_req1, ml_req2, ml_err   ! for key_mpi_isend
789      INTEGER, DIMENSION(MPI_STATUS_SIZE) ::   ml_stat   ! for key_mpi_isend
790      !!----------------------------------------------------------------------
791
792      ipreci = jpreci + jpr2di      ! take into account outer extra 2D overlap area
793      iprecj = jprecj + jpr2dj
794      tr2ns_ad = 0.0_wp ; tr2sn_ad = 0.0_wp
795      tr2we_ad = 0.0_wp ; tr2ew_ad = 0.0_wp
796      ! 3. North and south directions
797      ! -----------------------------
798      !                           ! Write Dirichlet lateral conditions
799      ijhom = nlcj - jprecj 
800      !
801      SELECT CASE ( nbondj )
802      CASE ( -1 )
803         DO jl = 1, iprecj
804            tr2ns_ad(:,jl,2) = tr2ns_ad(:,jl,2) + pt2d_ad(:,ijhom+jl)
805            pt2d_ad(:,ijhom+jl) = 0.0_wp
806         END DO
807      CASE ( 0 )
808         DO jl = 1, iprecj
809            tr2ns_ad(:,jl,2)     = tr2ns_ad(:,jl,2) + pt2d_ad(:,ijhom+jl )
810            pt2d_ad(:,ijhom+jl ) = 0.0_wp
811            tr2sn_ad(:,jl,2)     = tr2sn_ad(:,jl,2) + pt2d_ad(:,jl-jpr2dj)
812            pt2d_ad(:,jl-jpr2dj) = 0.0_wp
813         END DO
814      CASE ( 1 ) 
815         DO jl = 1, iprecj
816            tr2sn_ad(:,jl,2) = tr2sn_ad(:,jl,2) + pt2d_ad(:,jl-jpr2dj)
817            pt2d_ad(:,jl-jpr2dj) = 0.0_wp
818         END DO
819      END SELECT
820      !                           ! Migrations
821      imigr = iprecj * ( jpi + 2*jpr2di )
822      !
823      SELECT CASE ( nbondj )
824      CASE ( -1 )
825         CALL mppsend( 4, tr2ns_ad(1-jpr2di,1,2), imigr, nono, ml_req1 )
826         CALL mpprecv( 3, tr2sn_ad(1-jpr2di,1,1), imigr )
827         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
828      CASE ( 0 )
829         CALL mppsend( 3, tr2sn_ad(1-jpr2di,1,2), imigr, noso, ml_req1 )
830         CALL mppsend( 4, tr2ns_ad(1-jpr2di,1,2), imigr, nono, ml_req2 )
831         CALL mpprecv( 3, tr2sn_ad(1-jpr2di,1,1), imigr )
832         CALL mpprecv( 4, tr2ns_ad(1-jpr2di,1,1), imigr )
833         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
834         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
835      CASE ( 1 )
836         CALL mppsend( 3, tr2sn_ad(1-jpr2di,1,2), imigr, noso, ml_req1 )
837         CALL mpprecv( 4, tr2ns_ad(1-jpr2di,1,1), imigr )
838         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
839      END SELECT
840      !
841      ! always closed : we play only with the neigbours
842      !
843      IF( nbondj /= 2 ) THEN      ! Read Dirichlet lateral conditions
844         ijhom = nlcj-nrecj-jpr2dj
845         DO jl = 1, iprecj
846            pt2d_ad(:,jprecj+jl) = pt2d_ad(:,jprecj+jl) + tr2ns_ad(:,jl,1)
847            tr2ns_ad(:,jl,1) = 0.0_wp
848            pt2d_ad(:,ijhom +jl) = pt2d_ad(:,ijhom +jl) + tr2sn_ad(:,jl,1)
849            tr2sn_ad(:,jl,1) = 0.0_wp
850         END DO
851      ENDIF
852      !
853      ! 2. East and west directions exchange
854      ! ------------------------------------
855      !                           ! Write Dirichlet lateral conditions
856      iihom = nlci - jpreci
857      !
858      SELECT CASE ( nbondi )
859      CASE ( -1 )
860         DO jl = 1, ipreci
861            tr2ew_ad(:,jl,2)    = tr2ew_ad(:,jl,2) + pt2d_ad(iihom+jl,:)
862            pt2d_ad(iihom+jl,:) = 0.0_wp
863         END DO
864      CASE ( 0 )
865         DO jl = 1, ipreci
866            tr2ew_ad(:,jl,2)  = tr2ew_ad(:,jl,2) + pt2d_ad( iihom+jl,:)
867            pt2d_ad( iihom+jl,:) = 0.0_wp
868            tr2we_ad(:,jl,2)  = tr2we_ad(:,jl,2) + pt2d_ad(jl-jpr2di,:)
869            pt2d_ad(jl-jpr2di,:) = 0.0_wp
870         END DO
871      CASE ( 1 )
872         DO jl = 1, ipreci
873            tr2we_ad(:,jl,2)     = tr2we_ad(:,jl,2) + pt2d_ad(jl-jpr2di,:) 
874            pt2d_ad(jl-jpr2di,:) = 0.0_wp
875         END DO
876      END SELECT
877      !                           ! Migrations
878      imigr = ipreci * ( jpj + 2*jpr2dj)
879      !
880      SELECT CASE ( nbondi )
881      CASE ( -1 )
882         CALL mppsend( 2, tr2ew_ad(1-jpr2dj,1,2), imigr, noea, ml_req1 )
883         CALL mpprecv( 1, tr2we_ad(1-jpr2dj,1,1), imigr )
884         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
885      CASE ( 0 )
886         CALL mppsend( 1, tr2we_ad(1-jpr2dj,1,2), imigr, nowe, ml_req1 )
887         CALL mppsend( 2, tr2ew_ad(1-jpr2dj,1,2), imigr, noea, ml_req2 )
888         CALL mpprecv( 1, tr2we_ad(1-jpr2dj,1,1), imigr )
889         CALL mpprecv( 2, tr2ew_ad(1-jpr2dj,1,1), imigr )
890         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
891         IF(l_isend) CALL mpi_wait(ml_req2,ml_stat,ml_err)
892      CASE ( 1 )
893         CALL mppsend( 1, tr2we_ad(1-jpr2dj,1,2), imigr, nowe, ml_req1 )
894         CALL mpprecv( 2, tr2ew_ad(1-jpr2dj,1,1), imigr )
895         IF(l_isend) CALL mpi_wait(ml_req1,ml_stat,ml_err)
896      END SELECT
897      !
898      ! we play with the neigbours AND the row number because of the periodicity
899      !
900      SELECT CASE ( nbondi )      ! Read Dirichlet lateral conditions
901      CASE ( -1, 0, 1 )                ! all exept 2 (i.e. close case)
902         iihom = nlci-nreci-jpr2di
903         DO jl = 1, ipreci
904            pt2d_ad(iihom +jl,:) = pt2d_ad(iihom +jl,:) + tr2we_ad(:,jl,1)
905            tr2we_ad(:,jl,1)     = 0.0_wp
906            pt2d_ad(jpreci+jl,:) = pt2d_ad(jpreci+jl,:) + tr2ew_ad(:,jl,1)
907            tr2ew_ad(:,jl,1)     = 0.0_wp
908         END DO
909      END SELECT
910      !
911      ! 1. standard boundary treatment
912      ! ------------------------------
913      ! Order matters Here !!!!
914      !
915      ! north fold treatment
916      ! -----------------------
917      IF( npolj /= 0 ) THEN
918         !
919         SELECT CASE ( jpni )
920         CASE ( 1 )     ;   CALL lbc_nfd_adj        ( pt2d_ad(1:jpi,1:jpj+jpr2dj), cd_type, psgn, pr2dj=jpr2dj )
921         CASE DEFAULT   ;   CALL mpp_lbc_north_e_adj( pt2d_ad                    , cd_type, psgn               )
922         END SELECT 
923         !
924      ENDIF
925      !                                      ! East-West boundaries
926      !                                           !* Cyclic east-west
927      IF( nbondi == 2 .AND. (nperio == 1 .OR. nperio == 4 .OR. nperio == 6) ) THEN
928         pt2d_ad(     2      :2+jpr2di  ,:) = pt2d_ad(     2      :2+jpr2di  ,:) &
929            &                               + pt2d_ad(    jpi     :jpi+jpr2di,:)! west
930         pt2d_ad(   jpi      :jpi+jpr2di,:) = 0.0_wp
931         pt2d_ad(jpim1-jpr2di:  jpim1   ,:) = pt2d_ad(jpim1-jpr2di:  jpim1   ,:) &
932            &                               + pt2d_ad(1-jpr2di    :     1    ,:)! east
933         pt2d_ad(1-jpr2di    :     1    ,:) = 0.0_wp
934         !
935      ELSE                                        !* closed
936                                      pt2d_ad(nlci-jpreci+1:jpi+jpr2di,:) = 0.e0    ! north
937         IF( .NOT. cd_type == 'F' )   pt2d_ad(  1-jpr2di   :jpreci    ,:) = 0.e0    ! south except at F-point
938      ENDIF
939      !
940      !                                      !* North-South boundaries (always colsed)
941                                   pt2d_ad(:,nlcj-jprecj+1:jpj+jpr2dj) = 0.e0    ! north
942      IF( .NOT. cd_type == 'F' )   pt2d_ad(:,  1-jpr2dj   :  jprecj  ) = 0.e0    ! south except at F-point
943                               
944
945   END SUBROUTINE mpp_lnk_2d_e_adj
946
947
948
949   SUBROUTINE mppobc_adj( ptab_ad, kd1, kd2, kl, kk, ktype, kij )
950      !!----------------------------------------------------------------------
951      !!                  ***  routine mppobc  ***
952      !!
953      !! ** Purpose :   Message passing manadgement for open boundary
954      !!     conditions array
955      !!
956      !! ** Method  :   Use mppsend and mpprecv function for passing mask
957      !!       between processors following neighboring subdomains.
958      !!       domain parameters
959      !!                    nlci   : first dimension of the local subdomain
960      !!                    nlcj   : second dimension of the local subdomain
961      !!                    nbondi : mark for "east-west local boundary"
962      !!                    nbondj : mark for "north-south local boundary"
963      !!                    noea   : number for local neighboring processors
964      !!                    nowe   : number for local neighboring processors
965      !!                    noso   : number for local neighboring processors
966      !!                    nono   : number for local neighboring processors
967      !!
968      !!----------------------------------------------------------------------
969      INTEGER , INTENT(in   )                     ::   kd1, kd2   ! starting and ending indices
970      INTEGER , INTENT(in   )                     ::   kl         ! index of open boundary
971      INTEGER , INTENT(in   )                     ::   kk         ! vertical dimension
972      INTEGER , INTENT(in   )                     ::   ktype      ! define north/south or east/west cdt
973      !                                                           !  = 1  north/south  ;  = 2  east/west
974      INTEGER , INTENT(in   )                     ::   kij        ! horizontal dimension
975      REAL(wp), INTENT(inout), DIMENSION(kij,kk)  ::   ptab_ad    ! variable array
976      !!
977      INTEGER  ::   ji, jj, jk, jl   ! dummy loop indices
978      INTEGER  ::   iipt0, iipt1, ilpt1   ! temporary integers
979      INTEGER  ::   ijpt0, ijpt1          !    -          -
980      INTEGER  ::   imigr, iihom, ijhom   !    -          -
981      INTEGER ::   ml_req1, ml_req2, ml_err    ! for key_mpi_isend
982      INTEGER ::   ml_stat(MPI_STATUS_SIZE)    ! for key_mpi_isend
983      REAL(wp), DIMENSION(jpi,jpj) ::   ztabad ! temporary workspace
984      !!----------------------------------------------------------------------
985
986      ! boundary condition initialization
987      ! ---------------------------------
988      ztabad(:,:) = 0.e0
989      !
990      IF( ktype==1 ) THEN                                  ! north/south boundaries
991         iipt0 = MAX( 1, MIN(kd1 - nimpp+1, nlci     ) )
992         iipt1 = MAX( 0, MIN(kd2 - nimpp+1, nlci - 1 ) )
993         ilpt1 = MAX( 1, MIN(kd2 - nimpp+1, nlci     ) )
994         ijpt0 = MAX( 1, MIN(kl  - njmpp+1, nlcj     ) )
995         ijpt1 = MAX( 0, MIN(kl  - njmpp+1, nlcj - 1 ) )
996      ELSEIF( ktype==2 ) THEN                              ! east/west boundaries
997         iipt0 = MAX( 1, MIN(kl  - nimpp+1, nlci     ) )
998         iipt1 = MAX( 0, MIN(kl  - nimpp+1, nlci - 1 ) )
999         ijpt0 = MAX( 1, MIN(kd1 - njmpp+1, nlcj     ) )
1000         ijpt1 = MAX( 0, MIN(kd2 - njmpp+1, nlcj - 1 ) )
1001         ilpt1 = MAX( 1, MIN(kd2 - njmpp+1, nlcj     ) )
1002      ELSE
1003         CALL ctl_stop( 'mppobc: bad ktype' )
1004      ENDIF
1005     
1006      ! Communication level by level
1007      ! ----------------------------
1008!!gm Remark : this is very time consumming!!!
1009      !                                         ! ------------------------ !
1010      DO jk = 1, kk                             !   Loop over the levels   !
1011         !                                      ! ------------------------ !
1012         !
1013         ! 2. North and south directions
1014         ! -----------------------------
1015         !
1016         !                              ! Write Dirichlet lateral conditions
1017         ijhom = nlcj - jprecj
1018         IF( ktype==1 .AND. kd1 <= jpi+nimpp-1 .AND. nimpp <= kd2 ) THEN
1019            DO jj = ijpt0, ijpt1            ! north/south boundaries
1020               DO ji = iipt0,ilpt1
1021                  ztabad(ji,jj)  = ztabad(ji,jj) + ptab_ad(ji,jk)
1022                  ptab_ad(ji,jk) = 0.0_wp
1023               END DO
1024            END DO
1025         ELSEIF( ktype==2 .AND. kd1 <= jpj+njmpp-1 .AND. njmpp <= kd2 ) THEN
1026            DO jj = ijpt0, ilpt1            ! east/west boundaries
1027               DO ji = iipt0,iipt1
1028                  ztabad(ji,jj)  = ztabad(ji,jj) + ptab_ad(jj,jk)
1029                  ptab_ad(jj,jk) = 0.0_wp
1030               END DO
1031            END DO
1032         ENDIF
1033         IF( nbondj == 0 .OR. nbondj == -1 ) THEN
1034            DO jl = 1, jprecj
1035               t2ns_ad(:,jl,2)    = t2ns_ad(:,jl,2) + ztabad(:,ijhom+jl)
1036               ztabad(:,ijhom+jl) = 0.0_wp
1037            END DO
1038         ENDIF
1039         IF( nbondj == 0 .OR. nbondj == 1 ) THEN
1040            DO jl = 1, jprecj
1041               t2sn_ad(:,jl,2) = t2sn_ad(:,jl,2) + ztabad(:,jl)
1042               ztabad(:,jl)    = 0.0_wp
1043            END DO
1044         ENDIF
1045         !
1046         !                              ! Migrations
1047         imigr = jprecj * jpi
1048         !
1049         IF( nbondj == -1 ) THEN
1050            CALL mppsend( 4, t2ns_ad(1,1,2), imigr, nono, ml_req1 )
1051            CALL mpprecv( 3, t2sn_ad(1,1,1), imigr )
1052            IF(l_isend) CALL mpi_wait( ml_req1, ml_stat, ml_err )
1053         ELSEIF( nbondj == 0 ) THEN
1054            CALL mppsend( 3, t2sn_ad(1,1,2), imigr, noso, ml_req1 )
1055            CALL mppsend( 4, t2ns_ad(1,1,2), imigr, nono, ml_req2 )
1056            CALL mpprecv( 3, t2sn_ad(1,1,1), imigr )
1057            CALL mpprecv( 4, t2ns_ad(1,1,1), imigr )
1058            IF( l_isend )   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1059            IF( l_isend )   CALL mpi_wait( ml_req2, ml_stat, ml_err )
1060         ELSEIF( nbondj == 1 ) THEN
1061            CALL mppsend( 3, t2sn_ad(1,1,2), imigr, noso, ml_req1 )
1062            CALL mpprecv( 4, t2ns_ad(1,1,1), imigr)
1063            IF( l_isend )   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1064         ENDIF
1065         IF( nbondj /= 2 ) THEN         ! Read Dirichlet lateral conditions
1066            ijhom = nlcj-nrecj
1067            DO jl = 1, jprecj
1068               ztabad(:,jprecj+jl) = ztabad(:,jprecj+jl) + t2ns_ad(:,jl,1)
1069               t2ns_ad(:,jl,1) = ztabad(:,jprecj+jl)
1070               t2sn_ad(:,jl,1) = ztabad(:,ijhom +jl)
1071            END DO
1072         ENDIF
1073         !
1074         ! 1. East and west directions
1075         ! ---------------------------
1076         !
1077         !                              ! Write Dirichlet lateral conditions
1078         iihom = nlci-jpreci
1079         !
1080         IF( nbondi == -1 .OR. nbondi == 0 ) THEN
1081            DO jl = 1, jpreci
1082               t2ew_ad(:,jl,2) = t2ew_ad(:,jl,2) + ztabad(iihom+jl,:)
1083               ztabad(iihom+jl,:) = 0.0_wp
1084            END DO
1085         ENDIF
1086         IF( nbondi == 0 .OR. nbondi == 1 ) THEN
1087            DO jl = 1, jpreci
1088               t2we_ad(:,jl,2) = t2we_ad(:,jl,2) + ztabad(jl,:)
1089               ztabad(jl,:) = 0.0_wp
1090            END DO
1091         ENDIF
1092         !                              ! Migrations
1093         imigr=jpreci*jpj
1094         !
1095         IF( nbondi == -1 ) THEN
1096            CALL mppsend( 2, t2ew_ad(1,1,2), imigr, noea, ml_req1 )
1097            CALL mpprecv( 1, t2we_ad(1,1,1), imigr )
1098            IF(l_isend)   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1099         ELSEIF( nbondi == 0 ) THEN
1100            CALL mppsend( 1, t2we_ad(1,1,2), imigr, nowe, ml_req1 )
1101            CALL mppsend( 2, t2ew_ad(1,1,2), imigr, noea, ml_req2 )
1102            CALL mpprecv( 1, t2we_ad(1,1,1), imigr )
1103            CALL mpprecv( 2, t2ew_ad(1,1,1), imigr )
1104            IF(l_isend)   CALL mpi_wait( ml_req1, ml_stat, ml_err )
1105            IF(l_isend)   CALL mpi_wait( ml_req2, ml_stat, ml_err )
1106         ELSEIF( nbondi == 1 ) THEN
1107            CALL mppsend( 1, t2we_ad(1,1,2), imigr, nowe, ml_req1 )
1108            CALL mpprecv( 2, t2ew_ad(1,1,1), imigr )
1109            IF(l_isend) CALL mpi_wait( ml_req1, ml_stat, ml_err )
1110         ENDIF
1111         !
1112         IF( nbondi /= 2 ) THEN         ! Read Dirichlet lateral conditions
1113            iihom = nlci-nreci
1114            DO jl = 1, jpreci
1115               ztabad(iihom +jl,:)  = ztabad(iihom +jl,:) + t2we_ad(:,jl,1)
1116               t2we_ad(:,jl,1)      = 0.0_wp
1117               ztabad(jpreci+jl,:)  = ztabad(jpreci+jl,:) + t2ew_ad(:,jl,1)
1118               t2ew_ad(:,jl,1)      = 0.0_wp
1119            END DO
1120         ENDIF
1121         !
1122         IF( ktype == 1 ) THEN                               ! north/south boundaries
1123            DO jj = ijpt0, ijpt1
1124               DO ji = iipt0, iipt1
1125                  ptab_ad(ji,jk) = ptab_ad(ji,jk) + ztabad(ji,jj)
1126                  ztabad(ji,jj)  = 0.0_wp
1127               END DO
1128            END DO
1129         ELSEIF( ktype == 2 ) THEN                           ! east/west boundaries
1130            DO jj = ijpt0, ijpt1
1131               DO ji = iipt0, iipt1
1132                  ptab_ad(jj,jk) = ptab_ad(jj,jk) + ztabad(ji,jj)
1133                  ztabad(ji,jj) = 0.0_wp
1134               END DO
1135            END DO
1136         ENDIF
1137         !
1138      END DO
1139      !
1140   END SUBROUTINE mppobc_adj
1141   
1142   SUBROUTINE mpp_lbc_north_3d_adj( pt3d_ad, cd_type, psgn )
1143      !!---------------------------------------------------------------------
1144      !!                   ***  routine mpp_lbc_north_3d  ***
1145      !!
1146      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
1147      !!              in mpp configuration in case of jpn1 > 1
1148      !!
1149      !! ** Method  :   North fold condition and mpp with more than one proc
1150      !!              in i-direction require a specific treatment. We gather
1151      !!              the 4 northern lines of the global domain on 1 processor
1152      !!              and apply lbc north-fold on this sub array. Then we
1153      !!              scatter the north fold array back to the processors.
1154      !!
1155      !!----------------------------------------------------------------------
1156      REAL(wp), DIMENSION(jpi,jpj,jpk), INTENT(inout) ::   pt3d_ad   ! 3D array on which the b.c. is applied
1157      CHARACTER(len=1)                , INTENT(in   ) ::   cd_type   ! nature of pt3d grid-points
1158      !                                                              !   = T ,  U , V , F or W  gridpoints
1159      REAL(wp)                        , INTENT(in   ) ::   psgn      ! = -1. the sign change across the north fold
1160      !!                                                             ! =  1. , the sign is kept
1161      INTEGER ::   ji, jj, jr
1162      INTEGER ::   ierr, itaille, ildi, ilei, iilb
1163      INTEGER ::   ijpj, ijpjm1, ij, iproc
1164      REAL(wp), DIMENSION(jpiglo,4,jpk)      ::   ztabad
1165      REAL(wp), DIMENSION(jpi   ,4,jpk)      ::   znorthlocad
1166      REAL(wp), DIMENSION(jpi   ,4,jpk,jpni) ::   znorthgloioad
1167      !!----------------------------------------------------------------------
1168      !   
1169      ijpj   = 4
1170      ijpjm1 = 3
1171      ztabad(:,:,:) = 0.0_wp  ;  znorthlocad (:,:,:)= 0.0_wp  ;  znorthgloioad(:,:,:,:) = 0.0_wp
1172      !
1173      DO jj = nlcj-ijpj+1, nlcj             ! Scatter back to pt3d
1174         ij = jj - nlcj + ijpj
1175         DO ji= 1, nlci
1176            ztabad(ji+nimpp-1,ij,:) = ztabad(ji+nimpp-1,ij,:) + pt3d_ad(ji,jj,:)
1177            pt3d_ad(ji,jj,:) = 0.0_wp
1178         END DO
1179      END DO
1180      !
1181      CALL lbc_nfd_adj( ztabad, cd_type, psgn )   ! North fold boundary condition
1182      !
1183      !                                     ! recover the global north array
1184      DO jr = 1, ndim_rank_north
1185         iproc = nrank_north(jr) + 1
1186         ildi  = nldit (iproc)
1187         ilei  = nleit (iproc)
1188         iilb  = nimppt(iproc)
1189         DO jj = 1, 4
1190            DO ji = ildi, ilei
1191               znorthgloioad(ji,jj,:,jr) = znorthgloioad(ji,jj,:,jr) + ztabad(ji+iilb-1,jj,:)
1192               ztabad(ji+iilb-1,jj,:)    = 0.0_wp
1193            END DO
1194         END DO
1195      END DO
1196      !                                     ! Build in procs of ncomm_north the znorthgloio
1197      itaille = jpi * jpk * ijpj
1198      ! specific treatment of adjoint of mpi_allgather
1199      znorthgloioad = mpp_sum_nfd(znorthgloioad,jpi,4,jpk,jpni,ncomm_north) 
1200      jr=  ndim_rank_north-jpnij+nproc+1
1201      znorthlocad(:,:,:) = znorthgloioad(:,:,:,jr)
1202
1203      DO jj = nlcj - ijpj +1, nlcj          ! put in znorthloc the last 4 jlines of pt3d
1204         ij = jj - nlcj + ijpj
1205         pt3d_ad(:,jj,:) = pt3d_ad(:,jj,:) + znorthlocad(:,ij,:)
1206         znorthlocad(:,ij,:) = 0.0_wp
1207      END DO
1208      !
1209      !
1210   END SUBROUTINE mpp_lbc_north_3d_adj
1211
1212
1213   SUBROUTINE mpp_lbc_north_2d_adj( pt2d_ad, cd_type, psgn)
1214      !!---------------------------------------------------------------------
1215      !!                   ***  routine mpp_lbc_north_2d  ***
1216      !!
1217      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
1218      !!              in mpp configuration in case of jpn1 > 1 (for 2d array )
1219      !!
1220      !! ** Method  :   North fold condition and mpp with more than one proc
1221      !!              in i-direction require a specific treatment. We gather
1222      !!              the 4 northern lines of the global domain on 1 processor
1223      !!              and apply lbc north-fold on this sub array. Then we
1224      !!              scatter the north fold array back to the processors.
1225      !!
1226      !!----------------------------------------------------------------------
1227      REAL(wp), DIMENSION(jpi,jpj), INTENT(inout) ::   pt2d_ad   ! 3D array on which the b.c. is applied
1228      CHARACTER(len=1)            , INTENT(in   ) ::   cd_type   ! nature of pt3d grid-points
1229      !                                                          !   = T ,  U , V , F or W  gridpoints
1230      REAL(wp)                    , INTENT(in   ) ::   psgn      ! = -1. the sign change across the north fold
1231      !!                                                             ! =  1. , the sign is kept
1232      INTEGER ::   ji, jj, jr
1233      INTEGER ::   ierr, itaille, ildi, ilei, iilb
1234      INTEGER ::   ijpj, ijpjm1, ij, iproc
1235      REAL(wp), DIMENSION(jpiglo,4)      ::   ztabad
1236      REAL(wp), DIMENSION(jpi   ,4)      ::   znorthlocad
1237      REAL(wp), DIMENSION(jpi   ,4,jpni) ::   znorthgloioad
1238      !!----------------------------------------------------------------------
1239      !
1240      ijpj   = 4
1241      ijpjm1 = 3
1242      ztabad = 0.0_wp  ;  znorthlocad = 0.0_wp  ;  znorthgloioad = 0.0_wp
1243      !
1244      DO jj = nlcj-ijpj+1, nlcj             ! Scatter back to pt2d
1245         ij = jj - nlcj + ijpj
1246         DO ji = 1, nlci
1247            ztabad(ji+nimpp-1,ij) = ztabad(ji+nimpp-1,ij) + pt2d_ad(ji,jj)
1248            pt2d_ad(ji,jj)        = 0.0_wp
1249         END DO
1250      END DO
1251      !
1252      CALL lbc_nfd_adj( ztabad, cd_type, psgn )   ! North fold boundary condition
1253      !
1254      DO jr = 1, ndim_rank_north            ! recover the global north array
1255         iproc = nrank_north(jr) + 1
1256         ildi=nldit (iproc)
1257         ilei=nleit (iproc)
1258         iilb=nimppt(iproc)
1259         DO jj = 1, 4
1260            DO ji = ildi, ilei
1261               znorthgloioad(ji,jj,jr) = znorthgloioad(ji,jj,jr) + ztabad(ji+iilb-1,jj)
1262               ztabad(ji+iilb-1,jj) = 0.0_wp
1263            END DO
1264         END DO
1265      END DO
1266      !
1267      !                                     ! Build in procs of ncomm_north the znorthgloio
1268      itaille = jpi * ijpj
1269      ! specific treatment of adjoint of mpi_allgather
1270      znorthgloioad = mpp_sum_nfd(znorthgloioad,jpi,4,jpni,ncomm_north) 
1271      jr=  ndim_rank_north-jpnij+nproc+1
1272      znorthlocad(:,:) = znorthgloioad(:,:,jr)
1273
1274      DO jj = nlcj-ijpj+1, nlcj             ! put in znorthloc the last 4 jlines of pt2d
1275         ij = jj - nlcj + ijpj
1276         pt2d_ad(:,jj) = pt2d_ad(:,jj) + znorthlocad(:,ij)
1277         znorthlocad(:,ij) = 0.0_wp
1278      END DO
1279      !
1280   END SUBROUTINE mpp_lbc_north_2d_adj
1281
1282
1283   SUBROUTINE mpp_lbc_north_e_adj( pt2d_ad, cd_type, psgn)
1284      !!---------------------------------------------------------------------
1285      !!                   ***  routine mpp_lbc_north_2d  ***
1286      !!
1287      !! ** Purpose :   Ensure proper north fold horizontal bondary condition
1288      !!              in mpp configuration in case of jpn1 > 1 and for 2d
1289      !!              array with outer extra halo
1290      !!
1291      !! ** Method  :   North fold condition and mpp with more than one proc
1292      !!              in i-direction require a specific treatment. We gather
1293      !!              the 4+2*jpr2dj northern lines of the global domain on 1
1294      !!              processor and apply lbc north-fold on this sub array.
1295      !!              Then we scatter the north fold array back to the processors.
1296      !!
1297      !!----------------------------------------------------------------------
1298      REAL(wp), DIMENSION(1-jpr2di:jpi+jpr2di,1-jpr2dj:jpj+jpr2dj), INTENT(inout) ::   pt2d_ad  ! 2D array with extra halo
1299      CHARACTER(len=1)                                            , INTENT(in   ) ::   cd_type  ! nature of pt3d grid-points
1300      !                                                                                         !   = T ,  U , V , F or W -points
1301      REAL(wp)                                                    , INTENT(in   ) ::   psgn     ! = -1. the sign change across the 
1302      !!                                                                                        ! north fold, =  1. otherwise
1303      INTEGER ::   ji, jj, jr
1304      INTEGER ::   ierr, itaille, ildi, ilei, iilb
1305      INTEGER ::   ijpj, ij, iproc
1306      REAL(wp), DIMENSION(jpiglo,4+2*jpr2dj)      ::   ztabad
1307      REAL(wp), DIMENSION(jpi   ,4+2*jpr2dj)      ::   znorthlocad
1308      REAL(wp), DIMENSION(jpi   ,4+2*jpr2dj,jpni) ::   znorthgloioad
1309      !!----------------------------------------------------------------------
1310      !
1311      ijpj=4
1312      ztabad = 0.0_wp  ;  znorthlocad = 0.0_wp  ;  znorthgloioad = 0.0_wp
1313
1314      ij = jpr2dj
1315      !! Scatter back to pt2d
1316      DO jj = nlcj - ijpj + 1 , nlcj +jpr2dj
1317      ij  = ij +1 
1318         DO ji= 1, nlci
1319            ztabad(ji+nimpp-1,ij) = ztabad(ji+nimpp-1,ij) + pt2d_ad(ji,jj)
1320            pt2d_ad(ji,jj)        = 0.0_wp
1321         END DO
1322      END DO
1323      ! 2. North-Fold boundary conditions
1324      ! ----------------------------------
1325      CALL lbc_nfd_adj( ztabad(:,:), cd_type, psgn, jpr2dj)!, pr2dj = jpr2dj )
1326      !
1327      DO jr = 1, ndim_rank_north            ! recover the global north array
1328         iproc = nrank_north(jr) + 1
1329         ildi = nldit (iproc)
1330         ilei = nleit (iproc)
1331         iilb = nimppt(iproc)
1332         DO jj = 1, ijpj+2*jpr2dj
1333            DO ji = ildi, ilei
1334               znorthgloioad(ji,jj,jr) = znorthgloioad(ji,jj,jr) + ztabad(ji+iilb-1,jj)
1335               ztabad(ji+iilb-1,jj)    = 0.0_wp
1336            END DO
1337         END DO
1338      END DO
1339      !
1340      itaille = jpi * ( ijpj + 2 * jpr2dj )
1341      ! specific treatment of adjoint of mpi_allgather
1342      znorthgloioad = mpp_sum_nfd(znorthgloioad,jpi,4,jpni,ncomm_north) 
1343      jr=  ndim_rank_north-jpnij+nproc+1
1344      znorthlocad(:,:) = znorthgloioad(:,:,jr)
1345
1346      ij=0
1347      ! put in znorthloc the last 4 jlines of pt2d
1348      DO jj = nlcj - ijpj + 1 - jpr2dj, nlcj +jpr2dj
1349         ij = ij + 1
1350         DO ji = 1, jpi
1351            pt2d_ad(ji,jj)     = pt2d_ad(ji,jj) + znorthlocad(ji,ij)
1352            znorthlocad(ji,ij) = 0.0_wp
1353         END DO
1354      END DO
1355      !
1356   END SUBROUTINE mpp_lbc_north_e_adj
1357
1358#else
1359   !!----------------------------------------------------------------------
1360   !!   Default case:            Dummy module        share memory computing
1361   !!----------------------------------------------------------------------
1362   INTERFACE mppobc_adj
1363      MODULE PROCEDURE mppobc_adj_1d, mppobc_adj_2d, mppobc_adj_3d, mppobc_adj_4d
1364   END INTERFACE
1365
1366
1367   LOGICAL, PUBLIC, PARAMETER ::   lk_mpp = .FALSE.      !: mpp flag
1368   INTEGER :: ncomm_ice
1369
1370CONTAINS
1371
1372   SUBROUTINE mppobc_adj_1d( parr, kd1, kd2, kl, kk, ktype, kij )
1373      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
1374      REAL, DIMENSION(:) ::   parr           ! variable array
1375      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1), kd1, kd2, kl, kk, ktype, kij
1376   END SUBROUTINE mppobc_adj_1d
1377
1378   SUBROUTINE mppobc_adj_2d( parr, kd1, kd2, kl, kk, ktype, kij )
1379      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
1380      REAL, DIMENSION(:,:) ::   parr           ! variable array
1381      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1), kd1, kd2, kl, kk, ktype, kij
1382   END SUBROUTINE mppobc_adj_2d
1383
1384   SUBROUTINE mppobc_adj_3d( parr, kd1, kd2, kl, kk, ktype, kij )
1385      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
1386      REAL, DIMENSION(:,:,:) ::   parr           ! variable array
1387      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1,1), kd1, kd2, kl, kk, ktype, kij
1388   END SUBROUTINE mppobc_adj_3d
1389
1390   SUBROUTINE mppobc_adj_4d( parr, kd1, kd2, kl, kk, ktype, kij )
1391      INTEGER  ::   kd1, kd2, kl , kk, ktype, kij
1392      REAL, DIMENSION(:,:,:,:) ::   parr           ! variable array
1393      WRITE(*,*) 'mppobc: You should not have seen this print! error?', parr(1,1,1,1), kd1, kd2, kl, kk, ktype, kij
1394   END SUBROUTINE mppobc_adj_4d
1395
1396
1397#endif
1398   !!----------------------------------------------------------------------
1399END MODULE lib_mpp_tam
Note: See TracBrowser for help on using the repository browser.