SURFEX v8.1
General documentation of Surfex
horibl_surf_gridin.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6  SUBROUTINE horibl_surf_gridin(KINLA,KINLO,KILEN,PARIN,KOLEN,&
7  ODVECT,KLUOUT,OGLOBS,OGLOBN,OGLOBLON,KP,&
8  PARIN0_OUT,PARIN_OUT,KLSMIN_OUT,KLSMIN,KLSMOUT,KMASK )
9 ! ###########################################################################
10 !
11 !!**** *HORIBL_SURF_GRIDIN* - horitontal bilinear interpolation
12 !!
13 !! PURPOSE
14 !! -------
15 !!
16 !! Interpolates a field, supports masks.
17 !!
18 !! METHOD
19 !! ------
20 !!
21 !! This routine performs a bilinear interpolation based on the 12 surrounding
22 !! points. It begins with an interpolation along the latitudes (with third order
23 !! polynoms interpolation with 4 points and linear interpolation for 2 points)
24 !! and then a second along the longitude (third order polynoms interpolation).
25 !! Two interpolations are performed : first along the parallels then between the
26 !! four resulting points.
27 !!
28 !! The disposition of the points is the following :
29 !!
30 !!
31 !! N 1 2
32 !!
33 !! ^ 3 4 5 6
34 !! | x
35 !! | 7 8 9 10
36 !! |
37 !! 11 12
38 !! S
39 !! W ---------------> E
40 !!
41 !! Note : the name 'south', 'north', may not be exact if the last data point is
42 !! to the south of first (delta latitude < 0). This does not affect computations.
43 !!
44 !! The formula used to compute the weight is :
45 !! (Lon - Lon.i) . (Lon - Lon.i) . (Lon - Lon.i)
46 !! Wi = ---------------------------------------------------
47 !! (Lon.i - Lon.j) . (Lon.i - Lon.k) . (Lon.i - Lon.l)
48 !! Where j,k,l are the other points of the line.
49 !!
50 !! When masks are used, points with different types than the output points are
51 !! not taken in account (in the formula, the corresponding coefficient is set
52 !! to 1). If no points of the same nature are available, the interpolation is
53 !! performed anyway with the 12 points. It is the task of the calling program
54 !! to react to this situation.
55 !!
56 !! When the inputs parameters define a circular map (or global), the inputs data
57 !! are extended. The value of the parameter ODVECT is used to know if the datas
58 !! are vectorial or scalar (this affects the sign of extended values).
59 !!
60 !! EXTERNAL
61 !! --------
62 !!
63 !! subroutine FMLOOK_ll : to retrieve the logical unit number of the listing file
64 !!
65 !! IMPLICIT ARGUMENTS
66 !! ------------------
67 !!
68 !! REFERENCE
69 !! ---------
70 !!
71 !! This routine is based on the one used by the software FULL-POS from Meteo France.
72 !! More informations may be found in 'Book 1'
73 !!
74 !! AUTHOR
75 !! ------
76 !!
77 !! J.Pettre & V.Bousquet
78 !!
79 !! MODIFICATIONS
80 !! -------------
81 !!
82 !! Original 07/01/1999
83 !! 21/04/1999 (V. Masson) set correct prefixes and bug in
84 !! a logical definition
85 !! 21/04/1999 (V. Masson) bug in north and south poles
86 !! extension for input map land-sea mask
87 !! 27/05/1999 (V. Masson) bug in 'grib south pole'
88 !! extrapolation (number of point per parallel)
89 !! 27/05/1999 (V. Masson) bug in 'grib pole' extrapolation
90 !! extra latitudes are now computed symetrically
91 !! to the poles.
92 !! 17/03/2010 (P. LeMoigne) bug in weights computations
93 !! 16/06/2010 (G. Tanguy) bug in 'grib north pole"
94 !! extrapolation (tabular ZARIN not totaly filled)
95 !!
96 !------------------------------------------------------------------------------
97 !
98 !* 0. DECLARATIONS
99 ! ---------------
100 !
101 USE modd_surfex_mpi, ONLY : nrank, npio, ncomm, nproc, idx_i
102 USE modd_surf_par, ONLY : xundef
103 !
104 USE yomhook ,ONLY : lhook, dr_hook
105 USE parkind1 ,ONLY : jprb
106 !
107 USE modi_abor1_sfx
108 !
109 IMPLICIT NONE
110 !
111 #ifdef SFX_MPI
112 include "mpif.h"
113 #endif
114 !
115 !* 0.1. Declaration of arguments
116 !
117 INTEGER, INTENT(IN) :: KINLA ! Number of parallels
118 INTEGER, DIMENSION(:), INTENT(IN) :: KINLO ! Number of point along a parallel
119 INTEGER, INTENT(IN) :: KILEN ! size of input arrays
120 REAL, DIMENSION(:,:), INTENT(IN) :: PARIN ! input array
121 INTEGER, INTENT(IN) :: KOLEN ! size of output array
122 LOGICAL, INTENT(IN) :: ODVECT ! data is vectorial (True/False)
123 INTEGER, INTENT(IN) :: KLUOUT ! output listing logical unit
124 LOGICAL, INTENT(IN) :: OGLOBS
125 LOGICAL, INTENT(IN) :: OGLOBN
126 LOGICAL, INTENT(IN) :: OGLOBLON
127 INTEGER, DIMENSION(:,:), INTENT(IN) :: KP
128 REAL, DIMENSION(:,:), POINTER :: PARIN0_OUT ! input array
129 REAL, DIMENSION(:,:,:), INTENT(OUT) :: PARIN_OUT
130 INTEGER, DIMENSION(:,:,:), INTENT(OUT) :: KLSMIN_OUT
131 INTEGER, DIMENSION(:), POINTER, OPTIONAL :: KMASK
132 INTEGER, DIMENSION(:,:), INTENT(IN), OPTIONAL :: KLSMIN ! input land/sea mask
133 INTEGER, DIMENSION(:), INTENT(IN), OPTIONAL :: KLSMOUT ! output land/sea mask
134 !
135 !* 0.2. Declaration of local variables
136 !
137 REAL, DIMENSION(:,:), ALLOCATABLE :: ZARIN ! Extended input datas
138 REAL, DIMENSION(:,:,:), ALLOCATABLE :: ZOUT
139 REAL :: ZVECT ! -1 if input is vectorial
140  ! Variables implied in the extension procedure
141 INTEGER, DIMENSION(:,:), ALLOCATABLE :: ILSMIN ! Extended land/sea mask
142 INTEGER, DIMENSION(:,:), ALLOCATABLE :: IP
143 INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: IOUT
144 #ifdef SFX_MPI
145 INTEGER, DIMENSION(MPI_STATUS_SIZE) :: ISTATUS
146 #endif
147 REAL, DIMENSION(:,:), ALLOCATABLE :: ZDARIN
148 INTEGER, DIMENSION(:,:), ALLOCATABLE :: IDLS
149 INTEGER, DIMENSION(2) :: IEXT
150 INTEGER :: IBIGSIZE ! Size of the extended map
151 INTEGER :: IMID ! Used for extensions around the poles
152 INTEGER :: IOF1 ! Offset in map
153 INTEGER :: IOF2 ! Offset in map
154  ! Loop counters
155 INTEGER :: JOP ! Output position
156 INTEGER :: JIP ! Input position
157 INTEGER :: JL, JI, JI2, JL2, JT, INL, JC ! Dummy counter
158 INTEGER :: ID1, ID2, ISIZE
159 INTEGER :: INFOMPI, I, J
160 INTEGER :: IKINLO
161 LOGICAL :: LDLSM ! Specify if land/sea mask is present or not
162 !
163 !------------------------------------------------------------------------------
164 REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_HANDLE_OMP
165 !------------------------------------------------------------------------------
166 !
167 !* 1. DETERMINATION of the latitude of the poles (depending of the latitude
168 ! ------------- of the first data point)
169 !
170 IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_1',0,zhook_handle)
171 !
172 IF (PRESENT(kmask)) NULLIFY(kmask)
173 !
174 inl = SIZE(parin_out,2)
175 !
176 ldlsm = .false.
177 IF (PRESENT(klsmin) .AND. PRESENT(klsmout)) ldlsm = .true.
178 !
179 !* 2.6 Compute the resulting map
180 !
181 zvect = 1.
182 IF (odvect) zvect=-1.
183 !
184 IF (nrank==npio) THEN
185 
186  ibigsize = kilen
187  IF (oglobs ) ibigsize=ibigsize+(4+kinlo( 1))+(4+kinlo( 2))
188  IF (oglobn ) ibigsize=ibigsize+(4+kinlo(kinla))+(4+kinlo(kinla-1))
189  IF (ogloblon) ibigsize=ibigsize+ 4*kinla
190  !
191  ALLOCATE (zarin(ibigsize,inl))
192  ALLOCATE (ilsmin(ibigsize,inl))
193  ALLOCATE (kmask(ibigsize))
194  kmask(:) = -1
195 !
196 ! 2.6.1 Compute the longitude extension
197 !
198 ! This is a basic copy of the data. If extension is possible, the first and last
199 ! two lines are copied twice this way :
200 !
201 ! /---------------\
202 ! | |
203 ! [.] [.] [.... ...] [.] [.]
204 ! | |
205 ! \------------/
206 !
207 ! A point represent a data.
208 !
209 
210  DO jt = 1,inl
211 
212  jip = 1
213  jop = 1
214  IF (oglobs) jop = jop + (4+kinlo(1)) + (4+kinlo(2))
215 
216  IF (ogloblon) THEN
217 
218  DO jl = 1,kinla
219  id1 = jip+kinlo(jl)
220  id2 = jop+2+kinlo(jl)
221 
222  kmask(jop ) = id1-2
223  kmask(jop+1) = id1-1
224  DO ji = jop+2,id2-1
225  kmask(ji) = jip + ji - (jop+2)
226  ENDDO
227  kmask(id2 ) = jip
228  kmask(id2+1) = jip+1
229 
230  zarin(jop ,jt) = parin(id1-2,jt)
231  zarin(jop+1,jt) = parin(id1-1,jt)
232  zarin(jop+2:id2-1,jt) = parin(jip:id1-1,jt)
233  zarin(id2 ,jt) = parin(jip ,jt)
234  zarin(id2+1,jt) = parin(jip+1,jt)
235 
236  IF (ldlsm) THEN
237  ilsmin(jop ,jt) = klsmin(id1-2,jt)
238  ilsmin(jop+1,jt) = klsmin(id1-1,jt)
239  ilsmin(jop+2:id2-1,jt) = klsmin(jip:id1-1,jt)
240  ilsmin(id2 ,jt) = klsmin(jip ,jt)
241  ilsmin(id2+1,jt) = klsmin(jip+1,jt)
242  END IF
243 
244  jip = jip + kinlo(jl)
245  jop = jop + kinlo(jl) + 4
246 
247  END DO
248 
249  ELSE
250 
251  DO ji = jop,jop+kilen-1
252  kmask(ji) = jip + ji - jop
253  ENDDO
254 
255  zarin(jop:jop+kilen-1,jt) = parin(jip:jip+kilen-1,jt)
256  IF (ldlsm) THEN
257  ilsmin(jop:jop+kilen-1,jt) = klsmin(jip:jip+kilen-1,jt)
258  END IF
259  END IF
260 !
261 ! 2.6.2 Compute the south pole extension
262 !
263 ! Pole extension is performed by copying the first half datas to the last half
264 ! datas of the extension parallel :
265 !
266 ! [.] [.] [....] [....] [.] [.]
267 ! ||||
268 ! /-------/
269 ! ||||
270 ! [.] [.] [....] [....] [.] [.]
271 !
272  DO jc = 1,4
273  !
274  IF (jc<3.AND.oglobs.OR.jc>2.AND.oglobn) THEN
275  !
276  IF (jc==1) THEN
277  iof1 = 4 + kinlo(2)
278  iof2 = iof1 + 4 + kinlo(1)
279  imid = (kinlo(1)+4) / 2
280  ikinlo = kinlo(1)
281  ELSEIF (jc==2) THEN
282  iof1 = 0
283  iof2 = iof2 + 4 + kinlo(2)
284  imid = (kinlo(2)+4) / 2
285  ikinlo = kinlo(2)
286  ELSEIF (jc==3) THEN
287  iof1 = ibigsize - (4+kinlo(kinla-1)) - (4+kinlo(kinla))
288  iof2 = iof1 - (4+kinlo(kinla))
289  imid = (kinlo(kinla)+4) / 2
290  ikinlo = kinlo(kinla)
291  ELSEIF (jc==4) THEN
292  iof1 = iof1 + (4+kinlo(kinla))
293  iof2 = iof2 - (4+kinlo(kinla-1))
294  imid = (kinlo(kinla-1)+4) / 2
295  ikinlo = kinlo(kinla-1)
296  ENDIF
297  !
298  DO ji = 1,imid
299  kmask(iof1+ji) = iof2 + imid + ji - 2
300  ENDDO
301  DO ji = imid+1,ikinlo+4
302  kmask(iof1+ji) = iof2 + 1 + 2 + ji - (imid + 1)
303  ENDDO
304  !
305  zarin(iof1+1:iof1+imid,jt) = zvect*zarin(iof2+1+imid-2:iof2+2*imid-2,jt)
306  zarin(iof1+imid+1:iof1+ikinlo+4,jt) = zvect*zarin(iof2+1+2:iof2+ikinlo+4-imid+2,jt)
307  IF (ldlsm) THEN
308  ilsmin(iof1+1:iof1+imid,jt) = ilsmin(iof2+1+imid-2:iof2+2*imid-2,jt)
309  ilsmin(iof1+imid+1:iof1+ikinlo+4,jt) = ilsmin(iof2+1+2:iof2+ikinlo+4-imid+2,jt)
310  END IF
311  !
312  END IF
313  !
314  ENDDO
315  !
316  ENDDO
317  !
318 ENDIF
319 !
320 IF (nproc>1) THEN
321 #ifdef SFX_MPI
322  CALL mpi_bcast(ibigsize,kind(ibigsize)/4,mpi_integer,npio,ncomm,infompi)
323  IF (nrank/=npio) ALLOCATE(kmask(ibigsize))
324  CALL mpi_bcast(kmask,SIZE(kmask)*kind(kmask)/4,mpi_integer,npio,ncomm,infompi)
325 #endif
326 ENDIF
327 !
328 IF (nrank==npio .AND. (ogloblon.OR.oglobn.OR.oglobs)) THEN
329  !
330  ALLOCATE(parin0_out(SIZE(zarin,1),SIZE(zarin,2)))
331  parin0_out = zarin
332  !
333 ELSE
334  !
335  ALLOCATE(parin0_out(0,0))
336  !
337 ENDIF
338 !
339 IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_1',1,zhook_handle)
340 
341 IF (nrank/=npio) THEN
342 IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_3',0,zhook_handle)
343  iext(1) = minval(kp)
344  iext(2) = maxval(kp)
345  idx_i = idx_i + 1
346 #ifdef SFX_MPI
347  CALL mpi_send(iext,2*kind(iext)/4,mpi_integer,npio,idx_i,ncomm,infompi)
348 #endif
349  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_3',1,zhook_handle)
350  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_4',0,zhook_handle)
351  isize = iext(2)-iext(1)+1
352  ALLOCATE(zdarin(isize,inl))
353  ALLOCATE(idls(isize,inl))
354  idx_i = idx_i + 1
355 #ifdef SFX_MPI
356  CALL mpi_recv(zdarin,SIZE(zdarin)*kind(zdarin)/4,mpi_real,npio,idx_i,ncomm,istatus,infompi)
357 #endif
358  idx_i = idx_i + 1
359 #ifdef SFX_MPI
360  CALL mpi_recv(idls,SIZE(idls)*kind(idls)/4,mpi_integer,npio,idx_i,ncomm,istatus,infompi)
361 #endif
362  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_4',1,zhook_handle)
363 ELSE
364 #ifdef SFX_MPI
365 !$OMP PARALLEL DO SCHEDULE(DYNAMIC,1) PRIVATE(J,IEXT,ISIZE,ZDARIN,IDLS,JT,JL,ISTATUS,INFOMPI,ZHOOK_HANDLE_OMP)
366 #endif
367  DO j=0,nproc-1
368  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_2',0,zhook_handle_omp)
369  IF (j/=npio) THEN
370 #ifdef SFX_MPI
371  CALL mpi_recv(iext,2*kind(iext)/4,mpi_integer,j,idx_i+1,ncomm,istatus,infompi)
372 #endif
373  ELSE
374  iext(1) = minval(kp)
375  iext(2) = maxval(kp)
376  ENDIF
377  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_2',1,zhook_handle_omp)
378  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_30',0,zhook_handle_omp)
379  isize = iext(2)-iext(1)+1
380  ALLOCATE(zdarin(isize,inl))
381  ALLOCATE(idls(isize,inl))
382  DO jt = 1,inl
383  DO jl = iext(1),iext(2)
384  zdarin(jl-iext(1)+1,jt) = zarin(jl,jt)
385  idls(jl-iext(1)+1,jt) = ilsmin(jl,jt)
386  ENDDO
387  ENDDO
388  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_30',1,zhook_handle_omp)
389  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_40',0,zhook_handle_omp)
390  IF (j/=npio) THEN
391 #ifdef SFX_MPI
392  CALL mpi_send(zdarin,SIZE(zdarin)*kind(zdarin)/4,mpi_real,j,idx_i+2,ncomm,infompi)
393  CALL mpi_send(idls,SIZE(idls)*kind(idls)/4,mpi_integer,j,idx_i+3,ncomm,infompi)
394 #endif
395  ELSE
396  DO jt = 1,inl
397  DO jl2 = 1,12
398  DO jl = 1,SIZE(kp,1)
399  id1 = kp(jl,jl2) - iext(1) + 1
400  parin_out(jl,jt,jl2) = zdarin(id1,jt)
401  klsmin_out(jl,jt,jl2) = idls(id1,jt)
402  ENDDO
403  ENDDO
404  ENDDO
405  ENDIF
406  DEALLOCATE(zdarin,idls)
407  IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_40',1,zhook_handle_omp)
408  ENDDO
409 #ifdef SFX_MPI
410 !$OMP END PARALLEL DO
411 #endif
412  idx_i = idx_i+3
413 ENDIF
414 !
415 IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_5',0,zhook_handle)
416 IF (nrank/=npio) THEN
417 DO jt = 1,inl
418  DO jl2 = 1,12
419  DO jl = 1,SIZE(kp,1)
420  id1 = kp(jl,jl2) - iext(1) + 1
421  parin_out(jl,jt,jl2) = zdarin(id1,jt)
422  klsmin_out(jl,jt,jl2) = idls(id1,jt)
423  ENDDO
424  ENDDO
425 ENDDO
426 ENDIF
427 !
428 IF (lhook) CALL dr_hook('HORIBL_SURF_GRIDIN_5',1,zhook_handle)
429 !
430 END SUBROUTINE horibl_surf_gridin
real, parameter xundef
integer, parameter jprb
Definition: parkind1.F90:32
subroutine horibl_surf_gridin(KINLA, KINLO, KILEN, PARIN, KOLEN, ODVECT, KLUOUT, OGLOBS, OGLOBN, OGLOBLON, KP, PARIN0_OUT, PARIN_OUT, KLSMIN_OUT, KLSMIN, KLSMOUT, KMASK)
logical lhook
Definition: yomhook.F90:15