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.
lbc_lnk_pt2pt_generic.h90 in NEMO/branches/2021/dev_r14312_MPI_Interface/src/OCE/LBC – NEMO

source: NEMO/branches/2021/dev_r14312_MPI_Interface/src/OCE/LBC/lbc_lnk_pt2pt_generic.h90 @ 14349

Last change on this file since 14349 was 14349, checked in by smasson, 4 years ago

dev_r14312_MPI_Interface: further simplifications of lbclk and lbcnfd, #2598

  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-fortran
File size: 14.1 KB
Line 
1
2   SUBROUTINE lbc_lnk_pt2pt_/**/PRECISION( cdname, ptab, cd_nat, psgn, kfld, kfillmode, pfillval, lsend, lrecv )
3      CHARACTER(len=*)              , INTENT(in   ) ::   cdname      ! name of the calling subroutine
4      TYPE(PTR_4d_/**/PRECISION),  DIMENSION(:), INTENT(inout) ::   ptab        ! pointer of arrays on which apply the b.c.
5      CHARACTER(len=1), DIMENSION(:), INTENT(in   ) ::   cd_nat      ! nature of array grid-points
6      REAL(PRECISION),  DIMENSION(:), INTENT(in   ) ::   psgn        ! sign used across the north fold boundary
7      INTEGER                       , INTENT(in   ) ::   kfld        ! number of pt3d arrays
8      INTEGER ,             OPTIONAL, INTENT(in   ) ::   kfillmode   ! filling method for halo over land (default = constant)
9      REAL(PRECISION),      OPTIONAL, INTENT(in   ) ::   pfillval    ! background value (used at closed boundaries)
10      LOGICAL, DIMENSION(4),OPTIONAL, INTENT(in   ) ::   lsend, lrecv  ! communication with other 4 proc
11      !
12      INTEGER  ::   ji, jj, jk, jl, jf, jn      ! dummy loop indices
13      INTEGER  ::   ipk, ipl, ipf      ! dimension of the input array
14      INTEGER  ::   ip0i, ip1i, im0i, im1i
15      INTEGER  ::   ip0j, ip1j, im0j, im1j
16      INTEGER  ::   ishti, ishtj, ishti2, ishtj2
17      INTEGER  ::   ifill_nfd, icomm, ierr
18      INTEGER  ::   idxs, idxr
19      INTEGER, DIMENSION(4)  ::   isizei, ishtsi, ishtri, ishtpi
20      INTEGER, DIMENSION(4)  ::   isizej, ishtsj, ishtrj, ishtpj
21      INTEGER, DIMENSION(4)  ::   ifill, iszall, ishts, ishtr
22      INTEGER, DIMENSION(4)  ::   ireq  ! mpi_request id
23      REAL(PRECISION) ::   zland
24      REAL(PRECISION), DIMENSION(:), ALLOCATABLE  ::   zsnd, zrcv          ! halos arrays
25      LOGICAL, DIMENSION(4)  ::   llsend, llrecv
26      LOGICAL  ::   ll_IdoNFold
27      !!----------------------------------------------------------------------
28      !
29      ! ----------------------------------------- !
30      !     1. local variables initialization     !
31      ! ----------------------------------------- !
32      !
33      ipk = SIZE(ptab(1)%pt4d,3)
34      ipl = SIZE(ptab(1)%pt4d,4)
35      ipf = kfld
36      !
37      IF( narea == 1 .AND. numcom == -1 ) CALL mpp_report( cdname, ipk, ipl, ipf, ld_lbc = .TRUE. )
38      !
39      ! take care of optional parameters
40      !
41      zland = 0._wp                                     ! land filling value: zero by default
42      IF( PRESENT( pfillval ) )   zland = pfillval      ! set land value
43      !
44      ! define llsend and llrecv: logicals which say if mpi-neibourgs for send or receive exist or not.
45      IF     ( PRESENT(lsend) .AND. PRESENT(lrecv) ) THEN   ! localy defined neighbourgs
46         llsend(1:4) = lsend(1:4)   ;   llrecv(1:4) = lrecv(1:4)
47      ELSE IF( PRESENT(lsend) .OR.  PRESENT(lrecv) ) THEN
48         WRITE(ctmp1,*) ' Routine ', cdname, '  is calling lbc_lnk with only one of the two arguments lsend or lrecv'
49         CALL ctl_stop( 'STOP', ctmp1 )
50      ELSE                                                  ! default neighbours
51         llsend(1:4) = mpinei(1:4) >= 0
52         llrecv(:) = llsend(:)
53      END IF
54      !
55      ! define ifill: which method should be used to fill each parts (sides+corners) of the halos
56      ! default definition
57      DO jn = 1, 4
58         IF(             llrecv(jn) ) THEN   ;   ifill(jn) = jpfillmpi    ! with an mpi communication
59         ELSEIF(    l_SelfPerio(jn) ) THEN   ;   ifill(jn) = jpfillperio  ! with self-periodicity
60         ELSEIF( PRESENT(kfillmode) ) THEN   ;   ifill(jn) = kfillmode    ! localy defined
61         ELSE                                ;   ifill(jn) = jpfillcst    ! constant value (zland)
62         END IF
63      END DO
64      ! north fold treatment
65      ll_IdoNFold = l_IdoNFold .AND. ifill(jpno) /= jpfillnothing
66      IF( ll_IdoNFold ) THEN
67         ifill_nfd = ifill(jpno)             ! if we are here, this means llrecv(jpno) = .false. and l_SelfPerio(jpno) = .false.
68         ifill( (/jpno/) ) = jpfillnothing   ! we do north fold -> do nothing for northern halo
69      ENDIF
70     
71      ! We first define the localization and size of the parts of the array that will be sent (s), received (r)
72      ! or used for periodocity (p). The localization is defined as "the bottom left corner - 1" in i and j directions.
73      ! This is a shift that will be applied later in the do loops to pick-up the appropriate part of the array
74      !                    !                       ________________________
75      ip0i =          0    !          im0j = inner |__|__|__________|__|__|
76      ip1i =      nn_hls   !   im1j = inner - halo |__|__|__________|__|__|
77      im1i = Nie0-nn_hls   !                       |  |  |          |  |  |
78      im0i = Nie0          !                       |  |  |          |  |  |
79      ip0j =          0    !                       |  |  |          |  |  |
80      ip1j =      nn_hls   !                       |__|__|__________|__|__|
81      im1j = Nje0-nn_hls   !           ip1j = halo |__|__|__________|__|__|
82      im0j = Nje0          !              ip0j = 0 |__|__|__________|__|__|
83      !                    !                    ip0i ip1i        im1i im0i
84      !
85      !     sides:       west    east   south   north
86      isizei(1:4) = (/ nn_hls, nn_hls,    jpi,    jpi /)   ! i- count
87      isizej(1:4) = (/    jpj,    jpj, nn_hls, nn_hls /)   ! j- count
88      ishtsi(1:4) = (/   ip1i,   im1i,   ip0i,   ip0i /)   ! i- shift send data
89      ishtsj(1:4) = (/   ip0j,   ip0j,   ip1j,   im1j /)   ! j- shift send data
90      ishtri(1:4) = (/   ip0i,   im0i,   ip0i,   ip0i /)   ! i- shift received data location
91      ishtrj(1:4) = (/   ip0j,   ip0j,   ip0j,   im0j /)   ! j- shift received data location
92      ishtpi(1:4) = (/   im1i,   ip1i,   ip0i,   ip0i /)   ! i- shift data used for periodicity
93      ishtpj(1:4) = (/   ip0j,   ip0j,   im1j,   ip1j /)   ! j- shift data used for periodicity
94      !
95      ! -------------------------------- !
96      !     2. Prepare MPI exchanges     !
97      ! -------------------------------- !
98      !
99      ireq(:) = MPI_REQUEST_NULL
100      iszall(:) = isizei(:) * isizej(:) * ipk * ipl * ipf
101      ishts(1) = 0
102      DO jn = 2,4
103         ishts(jn) = ishts(jn-1) + iszall(jn-1) * COUNT( (/llsend(jn-1)/) )   ! with _alltoallv: in units of sendtype
104      END DO
105      ishtr(1) = 0
106      DO jn = 2,4
107         ishtr(jn) = ishtr(jn-1) + iszall(jn-1) * COUNT( (/llrecv(jn-1)/) )   ! with _alltoallv: in units of sendtype
108      END DO
109
110      ! Allocate local temporary arrays to be sent/received.
111      ALLOCATE( zsnd( SUM(iszall, mask = llsend) ), zrcv( SUM(iszall, mask = llrecv) ) )
112      !
113      ! -------------------------------------------------- !
114      !     3. Do east and west MPI exchange if needed     !
115      ! -------------------------------------------------- !
116      !
117      ! fill sending buffer with ARRAY_IN
118      idxs = 1
119      DO jn = 1, 2
120         IF( llsend(jn) ) THEN
121            ishti = ishtsi(jn)
122            ishtj = ishtsj(jn)
123            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
124               zsnd(idxs) = ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl)
125               idxs = idxs + 1
126            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
127         END IF
128      END DO
129      !
130#if ! defined key_mpi_off
131      IF( ln_timing ) CALL tic_tac(.TRUE.)
132      !
133      icomm = mpi_comm_oce        ! shorter name
134      ! non-blocking send of the western/eastern side using local temporary arrays
135      jn = jpwe
136      IF( llsend(jn) )   CALL MPI_ISEND( zsnd(ishts(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 1, icomm, ireq(jn), ierr )
137      jn = jpea
138      IF( llsend(jn) )   CALL MPI_ISEND( zsnd(ishts(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 2, icomm, ireq(jn), ierr )
139      ! blocking receive of the western/eastern halo in local temporary arrays
140      jn = jpwe
141      IF( llrecv(jn) )   CALL MPI_RECV(  zrcv(ishtr(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 2, icomm, MPI_STATUS_IGNORE, ierr )
142      jn = jpea
143      IF( llrecv(jn) )   CALL MPI_RECV(  zrcv(ishtr(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 1, icomm, MPI_STATUS_IGNORE, ierr )
144      !
145      IF( ln_timing ) CALL tic_tac(.FALSE.)
146#endif
147      !
148      ! ----------------------------------- !
149      !     4. Fill east and west halos     !
150      ! ----------------------------------- !
151      !
152      idxr = 1
153      DO jn = 1, 2
154         ishti = ishtri(jn)
155         ishtj = ishtrj(jn)
156         SELECT CASE ( ifill(jn) )
157         CASE ( jpfillnothing )               ! no filling
158         CASE ( jpfillmpi   )                 ! fill with data received by MPI
159            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
160               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = zrcv(idxr)
161               idxr = idxr + 1
162            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
163         CASE ( jpfillperio )                 ! use periodicity
164            ishti2 = ishtpi(jn)
165            ishtj2 = ishtpj(jn)
166            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
167               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = ptab(jf)%pt4d(ishti2+ji,ishtj2+jj,jk,jl)
168            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
169         CASE ( jpfillcopy  )                 ! filling with inner domain values
170            ishti2 = ishtsi(jn)
171            ishtj2 = ishtsj(jn)
172            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
173               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = ptab(jf)%pt4d(ishti2+ji,ishtj2+jj,jk,jl)
174            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
175         CASE ( jpfillcst   )                 ! filling with constant value
176            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
177               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = zland
178            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
179         END SELECT
180      END DO
181      !
182      ! ------------------------------- !
183      !     5. north fold treatment     !
184      ! ------------------------------- !
185      !
186      ! do it before south directions so concerned processes can do it without waiting for the comm with the sourthern neighbor
187      !
188      IF( ll_IdoNFold ) THEN
189         IF( jpni == 1 )  THEN   ;   CALL lbc_nfd( ptab, cd_nat, psgn                  , ipf )   ! self NFold
190         ELSE                    ;   CALL mpp_nfd( ptab, cd_nat, psgn, ifill_nfd, zland, ipf )   ! mpi  NFold
191         ENDIF
192      ENDIF
193      !
194      ! ---------------------------------------------------- !
195      !     6. Do north and south MPI exchange if needed     !
196      ! ---------------------------------------------------- !
197      !
198      DO jn = 3, 4
199         IF( llsend(jn) ) THEN
200            ishti = ishtsi(jn)
201            ishtj = ishtsj(jn)
202            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
203               zsnd(idxs) = ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl)
204               idxs = idxs + 1
205            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
206         END IF
207      END DO
208      !
209#if ! defined key_mpi_off
210      IF( ln_timing ) CALL tic_tac(.TRUE.)
211      !
212      ! non-blocking send of the western/eastern side using local temporary arrays
213      jn = jpso
214      IF( llsend(jn) )   CALL MPI_ISEND( zsnd(ishts(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 3, icomm, ireq(jn), ierr )
215      jn = jpno
216      IF( llsend(jn) )   CALL MPI_ISEND( zsnd(ishts(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 4, icomm, ireq(jn), ierr )
217      ! blocking receive of the western/eastern halo in local temporary arrays
218      jn = jpso
219      IF( llrecv(jn) )   CALL MPI_RECV(  zrcv(ishtr(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 4, icomm, MPI_STATUS_IGNORE, ierr )
220      jn = jpno
221      IF( llrecv(jn) )   CALL MPI_RECV(  zrcv(ishtr(jn)+1), iszall(jn), MPI_TYPE, mpinei(jn), 3, icomm, MPI_STATUS_IGNORE, ierr )
222      !
223      IF( ln_timing ) CALL tic_tac(.FALSE.)
224#endif
225      !
226      ! ------------------------------------- !
227      !     7. Fill south and north halos     !
228      ! ------------------------------------- !
229      !
230      DO jn = 3, 4
231         ishti = ishtri(jn)
232         ishtj = ishtrj(jn)
233         SELECT CASE ( ifill(jn) )
234         CASE ( jpfillnothing )               ! no filling
235         CASE ( jpfillmpi   )                 ! fill with data received by MPI
236            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
237               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = zrcv(idxr)
238               idxr = idxr + 1
239            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
240         CASE ( jpfillperio )                 ! use periodicity
241            ishti2 = ishtpi(jn)
242            ishtj2 = ishtpj(jn)
243            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
244               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = ptab(jf)%pt4d(ishti2+ji,ishtj2+jj,jk,jl)
245            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
246         CASE ( jpfillcopy  )                 ! filling with inner domain values
247            ishti2 = ishtsi(jn)
248            ishtj2 = ishtsj(jn)
249            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
250               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = ptab(jf)%pt4d(ishti2+ji,ishtj2+jj,jk,jl)
251            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
252         CASE ( jpfillcst   )                 ! filling with constant value
253            DO jf = 1, ipf  ;  DO jl = 1, ipl  ;  DO jk = 1, ipk  ;  DO jj = 1,isizej(jn)  ;  DO ji = 1,isizei(jn)
254               ptab(jf)%pt4d(ishti+ji,ishtj+jj,jk,jl) = zland
255            END DO   ;   END DO   ;   END DO   ;   END DO   ;   END DO
256         END SELECT
257      END DO
258      !
259      ! -------------------------------------------- !
260      !     8. deallocate local temporary arrays     !
261      ! -------------------------------------------- !
262      !
263      CALL mpi_waitall(4, ireq, MPI_STATUSES_IGNORE, ierr)
264      DEALLOCATE( zsnd, zrcv )
265      !
266   END SUBROUTINE lbc_lnk_pt2pt_/**/PRECISION
267
Note: See TracBrowser for help on using the repository browser.