SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
bilin.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 bilin (KLUOUT,PX1,PY1,PFIELD1,PX2,PY2,PFIELD2,OINTERP)
7 ! #########################################################################
8 !
9 !!**** *BILINEAR * - subroutine to interpolate surface FIELD
10 !!
11 !! PURPOSE
12 !! -------
13 !!
14 !!
15 !!** METHOD
16 !! ------
17 !!
18 !! Interpolation is bilinear, and uses 9 grid points, located in the
19 !! center of model 1 grid mesh, and at the boundaries of this grid
20 !! mesh (2 X limits, 2 Y limits and 4 corners).
21 !! This implies that the grid mesh values located around the model 1
22 !! grid mesh are not used directly. The values at the boundaries of the
23 !! grid mesh are defined by the average between the middle point
24 !! (this grid mesh value), and the one in the considered direction.
25 !! So the eight grid meshes around the considered grid mesh are used
26 !! equally.
27 !! This is important to note that these average values are erased
28 !! and replaced by zero if they are at the limit of any grid
29 !! mesh with the zero value. This allows to insure zero value in model 2
30 !! grid meshes where there was not the considered class in corresponding
31 !! model 1 grid mesh, and to insure continuity of the FIELD type
32 !! at such boundaries.
33 !!
34 !!
35 !! The arrays and array index are defined on the following (model1) grid:
36 !!
37 !!
38 !! XFIELD XFIELD XFIELD
39 !! * * *
40 !! i-1,j+1 i,j+1 i+1,j+1
41 !!
42 !!
43 !!
44 !! ZFIELD_XY ZFIELD_Y ZFIELD_XY
45 !! * * *
46 !! i,j+1 i,j+1 i+1,j+1
47 !!
48 !!
49 !!
50 !! XFIELD ZFIELD_X XFIELD ZFIELD_X XFIELD
51 !! * * * * *
52 !! i-1,j i,j i,j i+1,j i+1,j
53 !!
54 !!
55 !!
56 !! ZFIELD_XY ZFIELD_Y ZFIELD_XY
57 !! * * *
58 !! i,j i,j i+1,j
59 !!
60 !!
61 !!
62 !! XFIELD XFIELD XFIELD
63 !! * * *
64 !! i-1,j-1 i,j-1 i+1,j-1
65 !!
66 !!
67 !!
68 !!
69 !!
70 !! AUTHOR
71 !! ------
72 !!
73 !! V. Masson * METEO-FRANCE *
74 !!
75 !! MODIFICATIONS
76 !! -------------
77 !!
78 !! Original 01/2004
79 ! TD&DD: added OpenMP directives
80 
81 !-------------------------------------------------------------------------------
82 !
83 !* 0. DECLARATIONS
84 ! ------------
85 !
86 USE modi_hor_extrapol_surf_cheap
87 !
88 USE modd_surf_par, ONLY : xundef
89 !
90 !
91 USE yomhook ,ONLY : lhook, dr_hook
92 USE parkind1 ,ONLY : jprb
93 !
94 IMPLICIT NONE
95 !
96 !* 0.1 Declarations of dummy arguments :
97 !
98 INTEGER, INTENT(IN) :: kluout ! output listing logical unit
99 REAL, DIMENSION(:), INTENT(IN) :: px1 ! X coordinate of the regular input grid
100 REAL, DIMENSION(:), INTENT(IN) :: py1 ! Y coordinate of the regular input grid
101 REAL, DIMENSION(:,:), INTENT(IN) :: pfield1 ! FIELD on regular input grid
102 REAL, DIMENSION(:), INTENT(IN) :: px2 ! X coordinate of all points of output grid
103 REAL, DIMENSION(:), INTENT(IN) :: py2 ! Y coordinate of all points of output grid
104 REAL, DIMENSION(:), INTENT(OUT) :: pfield2 ! FIELD on model 2
105 LOGICAL, DIMENSION(:),INTENT(IN) :: ointerp ! .true. where physical value is needed
106 !
107 !
108 !* 0.2 Declarations of local variables for print on FM file
109 !
110 !
111 REAL, DIMENSION (:,:), ALLOCATABLE :: zw ! weight. 1 if defined,
112  ! 0 if FIELD=XUNDEF
113 REAL, DIMENSION (:,:), ALLOCATABLE :: zw_field ! weight. * FIELD
114 REAL, DIMENSION (:,:), ALLOCATABLE :: zfield_x ! FIELD at mesh interface
115 REAL, DIMENSION (:,:), ALLOCATABLE :: zfield_y ! FIELD at mesh interface
116 REAL, DIMENSION (:,:), ALLOCATABLE :: zfield_xy! FIELD at mesh corner
117 REAL, DIMENSION (SIZE(PX1)+1) :: zx ! X coordinate of left limit of input meshes
118 REAL, DIMENSION (SIZE(PY1)+1) :: zy ! Y coordinate of bottom limit of input meshes
119 !
120 INTEGER, DIMENSION(SIZE(PFIELD2)) :: ici, icj
121 REAL :: zc1_x ! coefficient for left points
122 REAL :: zc2_x ! coefficient for middle points
123 REAL :: zc3_x ! coefficient for right points
124 REAL :: zc1_y ! coefficient for bottom points
125 REAL :: zc2_y ! coefficient for middle points
126 REAL :: zc3_y ! coefficient for top points
127 !
128 INTEGER :: iiu ! model 1 X size
129 INTEGER :: iju ! model 1 Y size
130 !
131 INTEGER :: ji ! grid 1 x index
132 INTEGER :: jj ! grid 1 y index
133 INTEGER :: iin ! loop counter on all input points
134 !
135 INTEGER :: jl ! grid 2 index
136 !
137 REAL :: zeps=1.e-3
138 REAL(KIND=JPRB) :: zhook_handle
139 !-------------------------------------------------------------------------------
140 !
141 IF (lhook) CALL dr_hook('BILIN_1',0,zhook_handle)
142 
143 iiu=SIZE(pfield1,1)
144 iju=SIZE(pfield1,2)
145 !
146 !* weighting factor
147 !
148 ALLOCATE(zw(iiu,iju))
149 WHERE (pfield1/=xundef)
150  zw=1.
151 ELSEWHERE
152  zw=0.
153 END WHERE
154 !
155 !* weighted FIELD
156 !
157 ALLOCATE(zw_field(iiu,iju))
158 zw_field=zw*pfield1
159 !
160 !-------------------------------------------------------------------------------
161 !
162 !* 1. FIELD type at grid mesh interfaces (in X directions)
163 ! ----------------------------------
164 !
165 ALLOCATE(zfield_x(iiu+1,iju))
166 !
167 !* 1.1 Standard case
168 ! -------------
169 !
170 IF (iiu>1) &
171 zfield_x(2:iiu ,:) = (zw_field(1:iiu-1,:)+zw_field(2:iiu,:)) &
172  / max(zw(1:iiu-1,:)+zw(2:iiu,:),zeps)
173 zfield_x(1 ,:) = zw_field(1 ,:)
174 zfield_x( iiu+1,:) = zw_field(iiu,:)
175 !
176 !
177 !* 1.2 FIELD type value is 0 in the grid mesh
178 ! --------------------------------------
179 !
180 WHERE ( pfield1(1:iiu,:)==0.)
181  zfield_x(1:iiu,:) = 0.
182 END WHERE
183 !
184 WHERE ( pfield1(1:iiu,:)==0.)
185  zfield_x(2:iiu+1,:) = 0.
186 END WHERE
187 !
188 !-------------------------------------------------------------------------------
189 !
190 !* 2. FIELD type at grid mesh interfaces (in X directions)
191 ! ----------------------------------
192 !
193 ALLOCATE(zfield_y(iiu,iju+1))
194 !
195 !* 2.1 Standard case
196 ! -------------
197 !
198 IF (iju>1) &
199 zfield_y(:,2:iju ) = (zw_field(:,1:iju-1)+zw_field(:,2:iju)) &
200  / max(zw(:,1:iju-1)+zw(:,2:iju),zeps)
201 zfield_y(:,1 ) = zw_field(:,1 )
202 zfield_y(:, iju+1) = zw_field(:, iju )
203 !
204 !
205 !* 2.3 FIELD type value is 0 in the grid mesh
206 ! --------------------------------------
207 !
208 WHERE ( pfield1(:,1:iju)==0.)
209  zfield_y(:,1:iju) = 0.
210 END WHERE
211 !
212 WHERE ( pfield1(:,1:iju)==0.)
213  zfield_y(:,2:iju+1) = 0.
214 END WHERE
215 !
216 !-------------------------------------------------------------------------------
217 !
218 !* 3. FIELD type at grid mesh corners
219 ! -------------------------------
220 !
221 ALLOCATE(zfield_xy(iiu+1,iju+1))
222 !
223 !* 3.1 Standard case
224 ! -------------
225 !
226 
227 IF (iiu>1 .AND. iju>1) &
228 zfield_xy(2:iiu ,2:iju ) = ( zw_field(1:iiu-1,1:iju-1) &
229  + zw_field(1:iiu-1,2:iju ) &
230  + zw_field(2:iiu ,1:iju-1) &
231  + zw_field(2:iiu ,2:iju ) ) &
232  / max( zw(1:iiu-1,1:iju-1) &
233  + zw(1:iiu-1,2:iju ) &
234  + zw(2:iiu ,1:iju-1) &
235  + zw(2:iiu ,2:iju ) , zeps)
236 !
237 IF (iju>1) &
238 zfield_xy(1 ,2:iju ) = ( zw_field(1 ,1:iju-1) &
239  + zw_field(1 ,2:iju ) ) &
240  / max( zw(1 ,1:iju-1) &
241  + zw(1 ,2:iju ) , zeps)
242 !
243 IF (iju>1) &
244 zfield_xy( iiu+1,2:iju ) = ( zw_field(iiu ,1:iju-1) &
245  + zw_field(iiu ,2:iju ) ) &
246  / max( zw(iiu ,1:iju-1) &
247  + zw(iiu ,2:iju ) , zeps)
248 !
249 IF (iiu>1) &
250 zfield_xy(2:iiu ,1 ) = ( zw_field(1:iiu-1,1 ) &
251  + zw_field(2:iiu ,1 ) ) &
252  / max( zw(1:iiu-1,1 ) &
253  + zw(2:iiu ,1 ) , zeps)
254 !
255 IF (iiu>1) &
256 zfield_xy(2:iiu ,iju+1 ) = ( zw_field(1:iiu-1,iju ) &
257  + zw_field(2:iiu ,iju ) ) &
258  / max( zw(1:iiu-1,iju ) &
259  + zw(2:iiu ,iju ) , zeps)
260 !
261 zfield_xy(1 ,1 ) = ( pfield1(1 ,1 ) )
262 zfield_xy(iiu+1 ,1 ) = ( pfield1(iiu ,1 ) )
263 zfield_xy(1 ,iju+1 ) = ( pfield1(1 ,iju ) )
264 zfield_xy(iiu+1 ,iju+1 ) = ( pfield1(iiu ,iju ) )
265 !
266 !* 3.2 FIELD type value is 0 in one grid mesh
267 ! --------------------------------------
268 !
269 WHERE ( pfield1(1:iiu,1:iju)==0.)
270  zfield_xy(1:iiu,1:iju) = 0.
271 END WHERE
272 !
273 WHERE ( pfield1(1:iiu,1:iju)==0.)
274  zfield_xy(1:iiu,2:iju+1) = 0.
275 END WHERE
276 !
277 WHERE ( pfield1(1:iiu,1:iju)==0.)
278  zfield_xy(2:iiu+1,1:iju) = 0.
279 END WHERE
280 !
281 WHERE ( pfield1(1:iiu,1:iju)==0.)
282  zfield_xy(2:iiu+1,2:iju+1) = 0.
283 END WHERE
284 !
285 !-------------------------------------------------------------------------------
286 !
287 !* 4. Coordinates of points between input grid points
288 ! -----------------------------------------------
289 !
290 IF (iiu>1) THEN
291  zx(iiu+1) = 1.5*px1(iiu) -0.5*px1(iiu-1)
292  zx(2:iiu) = 0.5*px1(1:iiu-1)+0.5*px1(2:iiu)
293  zx(1) = 1.5*px1(1) -0.5*px1(2)
294 ELSE
295  zx(1) = px1(1) - 1.e6 ! uniform field in X direction if only 1 point is
296  zx(2) = px1(1) + 1.e6 ! available. Arbitrary mesh length of 2000km assumed
297 END IF
298 !
299 IF (iju>1) THEN
300  zy(iju+1) = 1.5*py1(iju) -0.5*py1(iju-1)
301  zy(2:iju) = 0.5*py1(1:iju-1)+0.5*py1(2:iju)
302  zy(1) = 1.5*py1(1) -0.5*py1(2)
303 ELSE
304  zy(1) = py1(1) - 1.e6 ! uniform field in Y direction if only 1 point is
305  zy(2) = py1(1) + 1.e6 ! available. Arbitrary mesh length of 2000km assumed
306 END IF
307 !
308 !-------------------------------------------------------------------------------
309 !
310 !* 5. Interpolation
311 ! -------------
312 !
313 pfield2(:) = xundef
314 !
315 !* loop on all output grid points
316 !
317 IF (lhook) CALL dr_hook('BILIN_1',1,zhook_handle)
318 IF (lhook) CALL dr_hook('BILIN_2',0,zhook_handle)
319 !
320 ici(:) = 1
321 icj(:) = 1
322 !$OMP PARALLEL DO PRIVATE(JL,JJ)
323 DO jl=1,SIZE(pfield2)
324  DO jj=SIZE(zx),1,-1
325  IF (zx(jj)<=px2(jl)) THEN
326  ici(jl) = jj
327  EXIT
328  ENDIF
329  ENDDO
330  DO jj=SIZE(zy),1,-1
331  IF (zy(jj)<=py2(jl)) THEN
332  icj(jl) = jj
333  EXIT
334  ENDIF
335  ENDDO
336 ENDDO
337 !$OMP END PARALLEL DO
338 
339 IF (lhook) CALL dr_hook('BILIN_2',1,zhook_handle)
340 IF (lhook) CALL dr_hook('BILIN_3',0,zhook_handle)
341 
342 DO jl=1,SIZE(pfield2,1)
343 !
344 !* interpolation weights in X direction
345 !
346  ji=ici(jl)
347  ji=max(min(ji,iiu),0)
348  IF (px1(ji)<=px2(jl)) THEN
349  zc2_x = (px2(jl)-zx(ji+1))/(px1(ji)-zx(ji+1))
350  zc2_x = max(min(zc2_x,1.),0.)
351  zc3_x = 1. - zc2_x
352  zc1_x = 0.
353  ELSE
354  zc2_x = (px2(jl)-zx(ji))/(px1(ji)-zx(ji))
355  zc2_x = max(min(zc2_x,1.),0.)
356  zc1_x = 1. - zc2_x
357  zc3_x = 0.
358  END IF
359 !
360 ! interpolation weights in Y direction
361 !
362  jj=icj(jl)
363  jj=max(min(jj,iju),0)
364  IF (py1(jj)<=py2(jl)) THEN
365  zc2_y = (py2(jl)-zy(jj+1))/(py1(jj)-zy(jj+1))
366  zc2_y = max(min(zc2_y,1.),0.)
367  zc3_y = 1. - zc2_y
368  zc1_y = 0.
369  ELSE
370  zc2_y = (py2(jl)-zy(jj))/(py1(jj)-zy(jj))
371  zc2_y = max(min(zc2_y,1.),0.)
372  zc1_y = 1. - zc2_y
373  zc3_y = 0.
374  END IF
375 !
376 !* interpolation
377 !
378  IF(pfield1(ji,jj) /= xundef) &
379  pfield2(jl) = &
380  zc1_y * ( zc1_x * zfield_xy(ji ,jj ) &
381  + zc2_x * zfield_y(ji ,jj ) &
382  + zc3_x * zfield_xy(ji+1,jj ) ) &
383  + zc2_y * ( zc1_x * zfield_x(ji ,jj ) &
384  + zc2_x * pfield1(ji ,jj ) &
385  + zc3_x * zfield_x(ji+1,jj ) ) &
386  + zc3_y * ( zc1_x * zfield_xy(ji ,jj+1) &
387  + zc2_x * zfield_y(ji ,jj+1) &
388  + zc3_x * zfield_xy(ji+1,jj+1) )
389 
390 END DO
391 !
392 IF (lhook) CALL dr_hook('BILIN_3',1,zhook_handle)
393 IF (lhook) CALL dr_hook('BILIN_4',0,zhook_handle)
394 !
395 !-------------------------------------------------------------------------------
396 !
397 DEALLOCATE(zw)
398 DEALLOCATE(zw_field)
399 DEALLOCATE(zfield_x )
400 DEALLOCATE(zfield_y )
401 DEALLOCATE(zfield_xy)
402 !
403 !-------------------------------------------------------------------------------
404 !
405 WHERE(abs(pfield2-xundef)<1.e-6) pfield2=xundef
406 !
407 !------------------------------------------------------------------------------
408 !
409 !* 6. EXTRAPOLATIONS IF SOME POINTS WERE NOT INTERPOLATED
410 ! ---------------------------------------------------
411 !
412 !* no missing point
413 IF (count(pfield2(:)==xundef .AND. ointerp(:))==0 .AND. lhook) CALL dr_hook('BILIN',1,zhook_handle)
414 IF (count(pfield2(:)==xundef .AND. ointerp(:))==0) RETURN
415 !
416 !* no data point
417 IF (count(pfield1(:,:)/=xundef)==0 .AND. lhook) CALL dr_hook('BILIN',1,zhook_handle)
418 IF (count(pfield1(:,:)/=xundef)==0) RETURN
419 !
420 WRITE(kluout,*) ' Remaining horizontal extrapolations'
421 WRITE(kluout,*) ' Total number of input data : ',count(pfield1(:,:)/=xundef)
422 WRITE(kluout,*) ' Number of points to interpolate: ',count(pfield2(:)==xundef .AND. ointerp(:))
423 !
424 !* input grid coordinates
425 !
426  CALL hor_extrapol_surf_cheap(kluout,'XY ',py1,px1,pfield1,py2,px2,pfield2,ointerp)
427 !
428 IF (lhook) CALL dr_hook('BILIN_4',1,zhook_handle)
429 !-------------------------------------------------------------------------------
430 !
431 END SUBROUTINE bilin
subroutine bilin(KLUOUT, PX1, PY1, PFIELD1, PX2, PY2, PFIELD2, OINTERP)
Definition: bilin.F90:6
subroutine hor_extrapol_surf_cheap(KLUOUT, HCOORTYPE, PLAT_IN, PLON_IN, PFIELD_IN, PLAT, PLON, PFIELD, OINTERP)