SURFEX v8.1
General documentation of Surfex
horibl_surf_coef.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_coef(KOLEN,OINTERP,OGLOBLON,PILO1,PILO2,POLO,&
7  KO,KINLO,KP,PLOP )
8 ! ###########################################################################
9 !
10 !!**** *HORIBL_SURF_COEF* - horitontal bilinear interpolation
11 !!
12 !! PURPOSE
13 !! -------
14 !!
15 !! Interpolates a field, supports masks.
16 !!
17 !! METHOD
18 !! ------
19 !!
20 !! This routine performs a bilinear interpolation based on the 12 surrounding
21 !! points. It begins with an interpolation along the latitudes (with third order
22 !! polynoms interpolation with 4 points and linear interpolation for 2 points)
23 !! and then a second along the longitude (third order polynoms interpolation).
24 !! Two interpolations are performed : first along the parallels then between the
25 !! four resulting points.
26 !!
27 !! The disposition of the points is the following :
28 !!
29 !!
30 !! N 1 2
31 !!
32 !! ^ 3 4 5 6
33 !! | x
34 !! | 7 8 9 10
35 !! |
36 !! 11 12
37 !! S
38 !! W ---------------> E
39 !!
40 !! Note : the name 'south', 'north', may not be exact if the last data point is
41 !! to the south of first (delta latitude < 0). This does not affect computations.
42 !!
43 !! The formula used to compute the weight is :
44 !! (Lon - Lon.i) . (Lon - Lon.i) . (Lon - Lon.i)
45 !! Wi = ---------------------------------------------------
46 !! (Lon.i - Lon.j) . (Lon.i - Lon.k) . (Lon.i - Lon.l)
47 !! Where j,k,l are the other points of the line.
48 !!
49 !! When masks are used, points with different types than the output points are
50 !! not taken in account (in the formula, the corresponding coefficient is set
51 !! to 1). If no points of the same nature are available, the interpolation is
52 !! performed anyway with the 12 points. It is the task of the calling program
53 !! to react to this situation.
54 !!
55 !! When the inputs parameters define a circular map (or global), the inputs data
56 !! are extended. The value of the parameter ODVECT is used to know if the datas
57 !! are vectorial or scalar (this affects the sign of extended values).
58 !!
59 !! EXTERNAL
60 !! --------
61 !!
62 !! subroutine FMLOOK_ll : to retrieve the logical unit number of the listing file
63 !!
64 !! IMPLICIT ARGUMENTS
65 !! ------------------
66 !!
67 !! REFERENCE
68 !! ---------
69 !!
70 !! This routine is based on the one used by the software FULL-POS from Meteo France.
71 !! More informations may be found in 'Book 1'
72 !!
73 !! AUTHOR
74 !! ------
75 !!
76 !! J.Pettre & V.Bousquet
77 !!
78 !! MODIFICATIONS
79 !! -------------
80 !!
81 !! Original 07/01/1999
82 !! 21/04/1999 (V. Masson) set correct prefixes and bug in
83 !! a logical definition
84 !! 21/04/1999 (V. Masson) bug in north and south poles
85 !! extension for input map land-sea mask
86 !! 27/05/1999 (V. Masson) bug in 'grib south pole'
87 !! extrapolation (number of point per parallel)
88 !! 27/05/1999 (V. Masson) bug in 'grib pole' extrapolation
89 !! extra latitudes are now computed symetrically
90 !! to the poles.
91 !! 17/03/2010 (P. LeMoigne) bug in weights computations
92 !! 16/06/2010 (G. Tanguy) bug in 'grib north pole"
93 !! extrapolation (tabular ZARIN not totaly filled)
94 !!
95 !------------------------------------------------------------------------------
96 !
97 !
98 !* 0. DECLARATIONS
99 ! ---------------
100 !
101 USE modd_surf_par, ONLY : xundef
102 !
103 USE yomhook ,ONLY : lhook, dr_hook
104 USE parkind1 ,ONLY : jprb
105 !
106 USE modi_abor1_sfx
107 !
108 IMPLICIT NONE
109 !
110 !* 0.1. Declaration of arguments
111 !
112 INTEGER, INTENT(IN) :: KOLEN ! size of output array
113 LOGICAL, DIMENSION(:), INTENT(IN) :: OINTERP ! .true. where physical value is needed
114 !
115 LOGICAL, INTENT(IN) :: OGLOBLON ! True if the map is circular
116 REAL, INTENT(IN) :: PILO1 ! Longitude of the first data point
117 REAL, INTENT(IN) :: PILO2 ! Longitude of the last data point
118 REAL, DIMENSION(:), INTENT(IN) :: POLO
119 INTEGER, DIMENSION(:,:), INTENT(IN) :: KO
120 !
121 INTEGER, DIMENSION(:), INTENT(IN) :: KINLO ! Extended KINLO
122 !
123 ! Posiiton in the array of the twelwe surrounding points
124 INTEGER, DIMENSION(:,:), INTENT(OUT) :: KP
125  ! Latitudes and longitudes of the surrounding points
126 REAL, DIMENSION(:,:), INTENT(OUT) :: PLOP
127 !
128 !* 0.2. Declaration of local variables
129 !
130  ! Variables used to perform the interpolation
131 REAL :: ZIDLO ! Delta longitude
132 INTEGER, DIMENSION(:), ALLOCATABLE :: IOFS ! Offset of each parallel in the array
133 !
134 INTEGER :: IINLA
135 INTEGER :: JL, IS1, IS2, JI
136 REAL(KIND=JPRB) :: ZHOOK_HANDLE
137 !------------------------------------------------------------------------------
138 !
139 !* 1. DETERMINATION of the latitude of the poles (depending of the latitude
140 ! ------------- of the first data point)
141 !
142 IF (lhook) CALL dr_hook('HORIBL_SURF_COEF',0,zhook_handle)
143 !
144 !------------------------------------------------------------------------------
145 !
146 !* 3. LOOP OVER ALL THE POINTS OF THE OUTPUT GRID
147 ! -------------------------------------------
148 !
149 iinla = SIZE(kinlo)
150 ALLOCATE (iofs(iinla))
151 iofs(1) = 1
152 IF (ogloblon) iofs(1)=iofs(1)+2
153 DO jl = 2,iinla
154  iofs(jl) = iofs(jl-1) + kinlo(jl-1)
155  IF (ogloblon) iofs(jl) = iofs(jl) + 4
156 END DO
157 !
158 DO jl = 1, kolen
159  !
160  IF (.NOT. ointerp(jl)) cycle
161  !
162  ! 3.1.2. northern
163  zidlo = (pilo2 - pilo1) / (kinlo(ko(jl,1)))
164  kp(jl,1) = int((polo(jl) - pilo1) / zidlo)
165  kp(jl,2) = kp(jl,1) + 1
166  IF (.NOT.ogloblon) kp(jl,2) = min(kinlo(ko(jl,1))-1, kp(jl,2))
167  plop(jl,1) = pilo1 + kp(jl,1) * zidlo
168  plop(jl,2) = plop(jl,1) + zidlo
169 !
170  ! 3.1.3. north
171  zidlo = (pilo2 - pilo1) / (kinlo(ko(jl,2) ))
172  kp(jl,4) = int((polo(jl) - pilo1) / zidlo)
173  kp(jl,3) = kp(jl,4) - 1
174  kp(jl,5) = kp(jl,4) + 1
175  kp(jl,6) = kp(jl,4) + 2
176  IF (.NOT.ogloblon) THEN
177  kp(jl,3) = max(0,kp(jl,3))
178  kp(jl,5:6) = min(kinlo(ko(jl,2))-1,kp(jl,5:6))
179  ENDIF
180  plop(jl,4) = pilo1 + kp(jl,4) * zidlo
181  plop(jl,3) = plop(jl,4) - zidlo
182  plop(jl,5) = plop(jl,4) + zidlo
183  plop(jl,6) = plop(jl,4) + 2*zidlo
184 !
185  ! 3.1.4. south
186  zidlo = (pilo2 - pilo1) / (kinlo(ko(jl,3) ))
187  kp(jl,8) = int((polo(jl) - pilo1) / zidlo)
188  kp(jl,7) = kp(jl,8) - 1
189  kp(jl,9) = kp(jl,8) + 1
190  kp(jl,10) = kp(jl,8) + 2
191  IF (.NOT.ogloblon) THEN
192  kp(jl,7) = max(0,kp(jl,7))
193  kp(jl,9:10) = min(kinlo(ko(jl,3))-1,kp(jl,9:10))
194  ENDIF
195  plop(jl,8) = pilo1 + kp(jl,8) * zidlo
196  plop(jl,7) = plop(jl,8) - zidlo
197  plop(jl,9) = plop(jl,8) + zidlo
198  plop(jl,10) = plop(jl,8) + 2*zidlo
199 !
200  ! 3.1.5. southern
201  zidlo = (pilo2 - pilo1) / (kinlo(ko(jl,4)))
202  kp(jl,11) = int((polo(jl) - pilo1) / zidlo)
203  kp(jl,12) = kp(jl,11) + 1
204  IF (.NOT.ogloblon) kp(jl,12) = min(kinlo(ko(jl,4))-1,kp(jl,12))
205  plop(jl,11) = pilo1 + kp(jl,11) * zidlo
206  plop(jl,12) = plop(jl,11) + zidlo
207 !
208  ! 3.1.6. check position of points
209  IF (ogloblon) THEN
210  is1 = -2
211  is2 = 1
212  ELSE
213  is1 = 0
214  is2 = -1
215  ENDIF
216  !
217  IF ((kp(jl,1) <is1) .OR. (kp(jl,2) >kinlo(ko(jl,1))+is2) .OR. &
218  (kp(jl,3) <is1) .OR. (kp(jl,6) >kinlo(ko(jl,2))+is2) .OR. &
219  (kp(jl,7) <is1) .OR. (kp(jl,10)>kinlo(ko(jl,3))+is2) .OR. &
220  (kp(jl,11)<is1) .OR. (kp(jl,12)>kinlo(ko(jl,4))+is2)) THEN
221  CALL abor1_sfx('HORIBLE_SURF: INPUT DOMAIN SMALLER THAN OUTPUT ONE - LONGITUDE GLOBAL')
222  END IF
223 !
224  ! 3.1.7. add parallel offset
225  kp(jl,1:2) = kp(jl,1:2) + iofs(ko(jl,1))
226  kp(jl,3:6) = kp(jl,3:6) + iofs(ko(jl,2))
227  kp(jl,7:10) = kp(jl,7:10) + iofs(ko(jl,3))
228  kp(jl,11:12)= kp(jl,11:12) + iofs(ko(jl,4))
229 !
230 END DO
231 !
232 !
233 IF (lhook) CALL dr_hook('HORIBL_SURF_COEF',1,zhook_handle)
234 !
235 !------------------------------------------------------------------------------
236 !
237 !
238 END SUBROUTINE horibl_surf_coef
subroutine horibl_surf_coef(KOLEN, OINTERP, OGLOBLON, PILO1, PILO2, POLO, KO, KINLO, KP, PLOP)
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
real, parameter xundef
integer, parameter jprb
Definition: parkind1.F90:32
logical lhook
Definition: yomhook.F90:15