SURFEX v8.1
General documentation of Surfex
hor_extrapol_surf.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 hor_extrapol_surf(KLUOUT,HCOORTYPE,KILEN,PILA1,PILA2,PILO1,PILO2,&
7  KINLA,KINLO,KP,PFIELD_IN,PLAT,PLON,PFIELD,OINTERP,&
8  PILATARRAY)
9 ! ###################################################################
10 !
11 !!**** *HOR_EXTRAPOL_SURF* extrapolate a surface field
12 !!
13 !! PURPOSE
14 !! -------
15 !!
16 !! METHOD
17 !! ------
18 !! For each point to interpolate, the nearest valid point value is set.
19 !!
20 !! EXTERNAL
21 !! --------
22 !!
23 !! IMPLICIT ARGUMENTS
24 !! ------------------
25 !!
26 !! REFERENCE
27 !! ---------
28 !!
29 !! AUTHOR
30 !! ------
31 !!
32 !! V. Masson Meteo-France
33 !!
34 !! MODIFICATION
35 !! ------------
36 !!
37 !! Original 01/12/98
38 !! V. Masson 01/2004 extrapolation in latitude and longitude
39 !! M. Jidane 11/2013 add OpenMP directives
40 !----------------------------------------------------------------------------
41 !
42 !* 0. DECLARATION
43 ! -----------
44 !
45 USE modd_surfex_mpi, ONLY : nrank, nproc, npio, ncomm, idx_i
46 USE modd_surf_par, ONLY : xundef
47 USE modd_csts, ONLY : xpi
49 !
50 USE modi_abor1_sfx
51 !
52 USE yomhook ,ONLY : lhook, dr_hook
53 USE parkind1 ,ONLY : jprb
54 !
55 IMPLICIT NONE
56 !
57 #ifdef SFX_MPI
58 include "mpif.h"
59 #endif
60 !
61 !* 0.1 Declaration of arguments
62 ! ------------------------
63 !
64 INTEGER, INTENT(IN) :: KLUOUT ! output listing logical unit
65  CHARACTER(LEN=4), INTENT(IN) :: HCOORTYPE! type of coordinate
66  INTEGER, INTENT(IN) :: KILEN
67 REAL, INTENT(IN) :: PILA1
68 REAL, INTENT(IN) :: PILA2
69 REAL, INTENT(IN) :: PILO1
70 REAL, INTENT(IN) :: PILO2
71 INTEGER, INTENT(IN) :: KINLA
72 INTEGER, DIMENSION(:), INTENT(IN) :: KINLO
73 INTEGER, DIMENSION(:,:), INTENT(IN) :: KP
74 REAL, DIMENSION(:,:), INTENT(IN) :: PFIELD_IN! input field on grid mesh
75 REAL, DIMENSION(:), INTENT(IN) :: PLAT ! latitude of each grid mesh.
76 REAL, DIMENSION(:), INTENT(IN) :: PLON ! longitude of each grid mesh.
77 REAL, DIMENSION(:,:), INTENT(INOUT) :: PFIELD ! field on grid mesh
78 LOGICAL,DIMENSION(:), INTENT(IN) :: OINTERP ! .true. where physical value is needed
79 REAL, DIMENSION(:), INTENT(IN), OPTIONAL :: PILATARRAY
80 !
81 !* 0.2 Declaration of local variables
82 ! ------------------------------
83 !
84 REAL, DIMENSION(:), ALLOCATABLE :: ZTLONMIN, ZTLONMAX, ZTLATMIN, ZTLATMAX
85 REAL, DIMENSION(:,:), ALLOCATABLE :: ZFIELD
86 REAL :: ZLAT ! latitude of point to define
87 REAL :: ZLON ! longitude of point to define
88 REAL :: ZDIST ! current distance to valid point (in lat/lon grid)
89 REAL, DIMENSION(:), ALLOCATABLE :: ZNDIST! smallest distance to valid point
90 REAL :: ZCOSLA! cosine of latitude
91 REAL :: ZLONSC! longitude of valid point
92 REAL :: ZIDLO, ZIDLOMAX, ZIDLOMIN, ZIDLAMAX, ZIDLAMIN
93 REAL, DIMENSION(:,:), ALLOCATABLE :: ZCOOR
94 REAL, DIMENSION(:), ALLOCATABLE :: ZIDLA
95 REAL, DIMENSION(:), ALLOCATABLE :: ZLA ! input "latitude" coordinate
96 REAL, DIMENSION(:), ALLOCATABLE :: ZLO ! input "longitude" coordinate
97 REAL(KIND=JPRB) :: ZRAD ! conversion degrees to radians
98 !
99 INTEGER, DIMENSION(:), ALLOCATABLE :: IMASK, IMASKR
100 INTEGER, DIMENSION(:,:), ALLOCATABLE :: IVAL_EXT
101 INTEGER, DIMENSION(NPROC) :: INO_TAB
102 INTEGER :: INO ! output array size
103 INTEGER, DIMENSION(2) :: ITSIZE, ITDIM
104 INTEGER, DIMENSION(2,0:NPROC-1) :: IBOR
105 INTEGER :: ISIZE, ISIZE_MAX, J, ID0, ICOMPT, ICPT
106 INTEGER :: INFOMPI, IDX, INL
107 INTEGER :: JI, JL, JLAT, JLON, JIPOS, JP ! loop index on points
108 INTEGER :: JISC ! loop index on valid points
109 #ifdef SFX_MPI
110 INTEGER, DIMENSION(MPI_STATUS_SIZE) :: ISTATUS
111 #endif
112 LOGICAL :: GLALO ! flag true is second coordinate is a longitude or pseudo-lon.
113  ! false if metric coordinates
114 REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_HANDLE_OMP
115 !-------------------------------------------------------------------------------
116 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_1',0,zhook_handle)
117 !
118 ino = SIZE(pfield,1)
119 inl = SIZE(pfield,2)
120 !
121 ALLOCATE(zndist(inl))
122 !
123 !-------------------------------------------------------------------------------
124 !
125 glalo = hcoortype=='LALO'
126 !
127 !-------------------------------------------------------------------------------
128 !
129 ALLOCATE(zidla(kinla))
130 !
131 ALLOCATE(zla(kilen))
132 ALLOCATE(zlo(kilen))
133 !
134 zidlomax = 0.
135 zidlomin = xundef
136 jipos = 0
137 IF (PRESENT(pilatarray)) THEN
138  zidla(1) = 0.
139  DO jlat=2,kinla
140  zidla(jlat) = pilatarray(jlat) - pilatarray(jlat-1)
141  ENDDO
142 ELSE
143  zidla(:) = (pila2 - pila1) / (kinla - 1)
144 ENDIF
145 !
146 zidlamax = maxval(abs(zidla))
147 zidlamin = minval(abs(zidla(2:kinla)))
148 !
149 DO jlat=1,kinla
150  IF (glalo) THEN
151  zidlo = (pilo2-pilo1) / kinlo(jlat)
152  ELSE
153  zidlo = (pilo2-pilo1) / (kinlo(jlat)-1)
154  ENDIF
155  DO jlon=1,kinlo(jlat)
156  jipos = jipos + 1
157  zla(jipos) = pila1 + sum(zidla(2:jlat))
158  zlo(jipos) = pilo1 + (jlon-1) * zidlo
159  END DO
160  zidlo = abs(zidlo)
161  IF (zidlo>zidlomax) zidlomax = zidlo
162  IF (zidlo<zidlomin) zidlomin = zidlo
163 END DO
164 !
165 !-------------------------------------------------------------------------------
166 !
167 !* 4. Loop on points to define
168 ! ------------------------
169 !
170 ALLOCATE(ztlonmin(ino),ztlonmax(ino),ztlatmin(ino),ztlatmax(ino))
171 ztlonmin(:) = 0.
172 ztlonmax(:) = 0.
173 ztlatmin(:) = 0.
174 ztlatmax(:) = 0.
175 !
176 zrad=xpi/180.0_jprb
177 !
178 !1: ZTLONMIN, ZTLONMAX, ZTLATMIN, ZTLATMAX contain for each point to extrapol
179 ! the limits of the domain where to search for the valid points, according
180 ! to NHALO_PREP
181 icpt = 0
182 isize_max = 0
183 isize = 0
184 DO ji=1,ino
185  !
186  IF (all(pfield(ji,:)/=xundef)) cycle
187  IF (.NOT. ointerp(ji)) cycle
188  icpt = icpt + 1
189  !
190  IF (nhalo_prep>0) THEN
191  ztlonmin(ji) = minval(zlo(kp(ji,:)))-zidlomax*nhalo_prep
192  ztlonmax(ji) = maxval(zlo(kp(ji,:)))+zidlomax*nhalo_prep
193  ztlatmin(ji) = minval(zla(kp(ji,:)))-zidlamax*nhalo_prep
194  ztlatmax(ji) = maxval(zla(kp(ji,:)))+zidlamax*nhalo_prep
195  ELSE
196  ztlonmin(ji) = minval(zlo(:))
197  ztlonmax(ji) = maxval(zlo(:))
198  ztlatmin(ji) = minval(zla(:))
199  ztlatmax(ji) = maxval(zla(:))
200  ENDIF
201  isize = ceiling((ztlonmax(ji)-ztlonmin(ji)+1)/zidlomin)*&
202  ceiling((ztlatmax(ji)-ztlatmin(ji)+1)/zidlamin)
203  IF (isize>isize_max) isize_max = isize
204  !
205 ENDDO
206 !
207 !number of points to extrapol and maximum number of points to sound
208 itsize(1) = icpt
209 itsize(2) = isize_max
210 !
211 !NPIO knows the numbers of points to extrapolate for all tasks
212 IF (nproc>1) THEN
213 #ifdef SFX_MPI
214  CALL mpi_gather(itsize,2*kind(itsize)/4,mpi_integer,&
215  ibor,2*kind(ibor)/4,mpi_integer,&
216  npio,ncomm,infompi)
217 #endif
218 ELSE
219  ibor(:,0) = itsize(:)
220 ENDIF
221 !
222 !imask associated the number of the point to extrapolate to its real index in
223 !the field
224 ALLOCATE(imask(itsize(1)))
225 imask(:) = 0
226 !
227 IF (nrank==npio) THEN
228  ALLOCATE(ival_ext(maxval(ibor(1,:)),maxval(ibor(2,:))))
229  ALLOCATE(zcoor(maxval(ibor(1,:)),2))
230 ELSE
231  ALLOCATE(ival_ext(itsize(1),itsize(2)))
232  ALLOCATE(zcoor(itsize(1),2))
233 ENDIF
234 ival_ext(:,:) = 0
235 zcoor(:,:) = 0.
236 !
237 !
238 icpt = 0
239 !2: loop on the points
240 DO ji=1,ino
241  !
242  IF (all(pfield(ji,:)/=xundef)) cycle
243  IF (.NOT. ointerp(ji)) cycle
244  !
245  icpt = icpt + 1
246  !imask associated the number of the point to extrapolate to its real index in
247  !the field
248  imask(icpt) = ji
249  !
250  icompt = 0
251  jisc = 0
252  !
253  !coordinates of the point in the grid
254  zcoor(icpt,1) = plat(ji)
255  zcoor(icpt,2) = plon(ji)
256  !
257  !loop on the grid
258  DO jlat = 1,kinla
259  zlat = pila1 + sum(zidla(2:jlat))
260  IF (zlat>=ztlatmin(ji) .AND. zlat<=ztlatmax(ji)) THEN
261  IF (glalo) THEN
262  zidlo = (pilo2-pilo1) / kinlo(jlat)
263  ELSE
264  zidlo = (pilo2-pilo1) / (kinlo(jlat)-1)
265  ENDIF
266  IF (jlat>1) jisc = sum(kinlo(1:jlat-1))
267  DO jlon = 1,kinlo(jlat)
268  zlon = pilo1 + (jlon-1) * zidlo
269  IF (zlon>=ztlonmin(ji) .AND. zlon<=ztlonmax(ji)) THEN
270  icompt = icompt + 1
271  !ival_ext contains the indexes of the points needed to interpolate
272  !in the complete grid
273  ival_ext(icpt,icompt) = jisc + jlon
274  ENDIF
275  ENDDO
276  ENDIF
277  ENDDO
278  !
279 ENDDO
280 !
281 DEALLOCATE(zidla)
282 !
283 !
284 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_1',1,zhook_handle)
285 !
286 IF (nrank/=npio) THEN
287 
288  IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_2',0,zhook_handle)
289 
290  !if some points of this task need to be extrapolated
291  IF (sum(itsize)/=0) THEN
292 
293  !zfield will contain the values of the field
294  ALLOCATE(zfield(itsize(1),inl))
295 
296  idx_i = idx_i + 1
297  !sends indexes to npio
298 #ifdef SFX_MPI
299  CALL mpi_send(ival_ext,SIZE(ival_ext)*kind(ival_ext)/4,mpi_integer,npio,idx_i,ncomm,infompi)
300 #endif
301 
302  idx_i = idx_i + 1
303  !send coords of the points to extrapolate
304 #ifdef SFX_MPI
305  CALL mpi_send(zcoor,SIZE(zcoor)*kind(zcoor)/4,mpi_real,npio,idx_i,ncomm,infompi)
306 #endif
307 
308  idx_i = idx_i + 1
309  !receives values of the field from NPIO
310 #ifdef SFX_MPI
311  CALL mpi_recv(zfield,SIZE(zfield)*kind(zfield)/4,mpi_real,npio,idx_i,ncomm,istatus,infompi)
312 #endif
313 
314  DO ji=1,itsize(1)
315  pfield(imask(ji),:) = zfield(ji,:)
316  ENDDO
317  DEALLOCATE(zfield)
318 
319  ELSE
320  idx_i = idx_i + 3
321  ENDIF
322 
323  IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_2',1,zhook_handle)
324 
325 ELSE
326 
327 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_31',0,zhook_handle_omp)
328  DO jp = npio,nproc-1+npio
329 
330  j = jp
331  IF (jp>nproc-1) j = jp-nproc
332 
333  IF (sum(ibor(:,j))/=0) THEN
334 
335  ALLOCATE(zfield(ibor(1,j),inl))
336  zfield=xundef
337 
338  IF (j/=npio) THEN
339 
340  !receives indexes and coordinaites
341 #ifdef SFX_MPI
342  CALL mpi_recv(ival_ext(1:ibor(1,j),1:ibor(2,j)), ibor(1,j)*ibor(2,j)*kind(ival_ext)/4, &
343  mpi_integer, j, idx_i+1, ncomm, istatus, infompi)
344  CALL mpi_recv(zcoor(1:ibor(1,j),:), ibor(1,j)*SIZE(zcoor,2)*kind(zcoor)/4,&
345  mpi_real, j, idx_i+2, ncomm, istatus, infompi)
346 #endif
347 
348  ENDIF
349 
350 !$OMP PARALLEL DO PRIVATE(JI,ZNDIST,IDX,ZCOSLA,JISC,ID0,ZLONSC,ZDIST)
351  DO ji=1,ibor(1,j)
352  zndist(:) = xundef
353  idx = ibor(2,j)+1
354  zcosla=cos(zcoor(ji,1)*zrad)
355  DO jisc = 1,ibor(2,j)
356  !index in the whole grid of the point used to interpolate
357  id0 = ival_ext(ji,jisc)
358  IF (id0==0) EXIT
359  IF (any(pfield_in(id0,:)/=xundef)) THEN
360  zlonsc = zlo(id0)
361  IF (glalo) THEN
362  IF (zlonsc-zcoor(ji,2)> 180.) zlonsc = zlonsc - 360.
363  IF (zlonsc-zcoor(ji,2)<-180.) zlonsc = zlonsc + 360.
364  zdist= (zla(id0)-zcoor(ji,1)) ** 2 + ((zlonsc-zcoor(ji,2))*zcosla) ** 2
365  ELSE
366  zdist= (zla(id0)-zcoor(ji,1)) ** 2 + (zlonsc-zcoor(ji,2)) ** 2
367  END IF
368  DO jl=1,inl
369  IF (zdist<=zndist(jl)) THEN
370  IF (pfield_in(id0,jl)/=xundef) THEN
371  zfield(ji,jl) = pfield_in(id0,jl)
372  zndist(jl) = zdist
373  ENDIF
374  ENDIF
375  ENDDO
376  ENDIF
377  END DO
378  ENDDO
379 !$OMP END PARALLEL DO
380  !
381  IF (j/=npio) THEN
382  !send values found to extrapolate
383 #ifdef SFX_MPI
384  CALL mpi_send(zfield,SIZE(zfield)*kind(zfield)/4,mpi_real,j,idx_i+3,ncomm,infompi)
385 #endif
386  ELSE
387  DO ji = 1,ibor(1,j)
388  pfield(imask(ji),:) = zfield(ji,:)
389  ENDDO
390  ENDIF
391  !
392  DEALLOCATE(zfield)
393  !
394  ENDIF
395  !
396  ENDDO
397 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_31',1,zhook_handle_omp)
398 !
399 DEALLOCATE(zndist)
400  !
401 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_32',0,zhook_handle)
402  !
403  idx_i = idx_i + 3
404  !
405 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_32',1,zhook_handle)
406  !
407 ENDIF
408 !
409 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_4',0,zhook_handle)
410 !
411 DEALLOCATE(zcoor)
412 DEALLOCATE(ival_ext)
413 DEALLOCATE(imask)
414 !
415 IF (ALLOCATED(zla)) DEALLOCATE(zla)
416 IF (ALLOCATED(zlo)) DEALLOCATE(zlo)
417 DEALLOCATE(ztlonmin,ztlonmax,ztlatmin,ztlatmax)
418 !
419 DO jl=1,inl
420  IF (any(pfield(:,jl)==xundef .AND. ointerp(:))) THEN
421  WRITE(*,*) 'LAYER ',jl,': NO EXTRAPOLATION : INCREASE YOUR HALO_PREP IN NAM_PREP_SURF_ATM'
422  CALL abor1_sfx('NO EXTRAPOLATION : INCREASE YOUR HALO_PREP IN NAM_PREP_SURF_ATM')
423  ENDIF
424  WHERE (.NOT. ointerp(:)) pfield(:,jl) = xundef
425 ENDDO
426 !
427 !-------------------------------------------------------------------------------
428 IF (lhook) CALL dr_hook('HOR_EXTRAPOL_SURF_4',1,zhook_handle)
429 !
430 END SUBROUTINE hor_extrapol_surf
subroutine hor_extrapol_surf(KLUOUT, HCOORTYPE, KILEN, PILA1, PILA2, PI
real, save xpi
Definition: modd_csts.F90:43
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
real, parameter xundef
integer, parameter jprb
Definition: parkind1.F90:32
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
logical lhook
Definition: yomhook.F90:15