SURFEX v7.3
General documentation of Surfex
 All Classes Files Functions Variables Typedefs
/home/dasprezs/EXPORT_v7_3/src/SURFEX/adapt_horibl_surf.F90
Go to the documentation of this file.
00001 !     #########
00002     SUBROUTINE ADAPT_HORIBL_SURF(PILATARRAY,PILA1,PILO1,PILA2,PILO2,KINLA,KINLO,&
00003                                    KILEN,PARIN,KOLEN,PXOUT,PYOUT,PAROUT,ODVECT, &
00004                                    KLUOUT,OINTERP,KLSMIN,KLSMOUT                  )  
00005 !   ###########################################################################
00006 !
00007 !!****  *HORIBL_SURF* - horitontal bilinear interpolation
00008 !!
00009 !!    PURPOSE
00010 !!    -------
00011 !!
00012 !!    Interpolates a field, supports masks.
00013 !!
00014 !!    METHOD
00015 !!    ------
00016 !!
00017 !!    This routine performs a bilinear interpolation based on the 12 surrounding
00018 !!    points. It begins with an interpolation along the latitudes (with third order
00019 !!    polynoms interpolation with 4 points and linear interpolation for 2 points)
00020 !!    and then a second along the longitude (third order polynoms interpolation).
00021 !!    Two interpolations are performed : first along the parallels then between the
00022 !!    four resulting points.
00023 !!
00024 !!    The disposition of the points is the following :
00025 !!
00026 !!
00027 !!            N         1   2
00028 !!
00029 !!            ^     3   4   5   6
00030 !!            |           x
00031 !!            |     7   8   9  10
00032 !!            |
00033 !!                     11  12
00034 !!            S
00035 !!              W ---------------> E
00036 !!
00037 !!   Note : the name 'south', 'north', may not be exact if the last data point is
00038 !!     to the south of first (delta latitude < 0). This does not affect computations.
00039 !!
00040 !!   The formula used to compute the weight is :
00041 !!        (Lon   - Lon.i) . (Lon   - Lon.i) . (Lon   - Lon.i)
00042 !!   Wi = ---------------------------------------------------
00043 !!        (Lon.i - Lon.j) . (Lon.i - Lon.k) . (Lon.i - Lon.l)
00044 !!   Where j,k,l are the other points of the line.
00045 !!
00046 !!   When masks are used, points with different types than the output points are
00047 !!   not taken in account (in the formula, the corresponding coefficient is set
00048 !!   to 1). If no points of the same nature are available, the interpolation is
00049 !!   performed anyway with the 12 points. It is the task of the calling program
00050 !!   to react to this situation.
00051 !!
00052 !!   When the inputs parameters define a circular map (or global), the inputs data
00053 !!   are extended. The value of the parameter ODVECT is used to know if the datas
00054 !!   are vectorial or scalar (this affects the sign of extended values).
00055 !!
00056 !!   EXTERNAL
00057 !!   --------
00058 !!
00059 !!   subroutine FMLOOK_ll : to retrieve the logical unit number of the listing file
00060 !!
00061 !!   IMPLICIT ARGUMENTS
00062 !!   ------------------
00063 !!
00064 !!   REFERENCE
00065 !!   ---------
00066 !!
00067 !!   This routine is based on the one used by the software FULL-POS from Meteo France.
00068 !!   More informations may be found in 'Book 1'
00069 !!
00070 !!   AUTHOR
00071 !!   ------
00072 !!
00073 !!   J.Pettre & V.Bousquet
00074 !!
00075 !!   MODIFICATIONS
00076 !!   -------------
00077 !!
00078 !!   Original       07/01/1999
00079 !!                  21/04/1999 (V. Masson) set correct prefixes and bug in
00080 !!                             a logical definition
00081 !!                  21/04/1999 (V. Masson) bug in north and south poles
00082 !!                             extension for input map land-sea mask
00083 !!                  27/05/1999 (V. Masson) bug in 'grib south pole'
00084 !!                             extrapolation (number of point per parallel)
00085 !!                  27/05/1999 (V. Masson) bug in 'grib pole' extrapolation
00086 !!                             extra latitudes are now computed symetrically
00087 !!                             to the poles.
00088 !!
00089 !------------------------------------------------------------------------------
00090 !
00091 !
00092 !*      0. DECLARATIONS
00093 !       ---------------
00094 !
00095 USE MODI_HOR_EXTRAPOL_SURF
00096 !
00097 USE MODD_SURF_PAR,  ONLY : XUNDEF
00098 !
00099 !
00100 USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
00101 USE PARKIND1  ,ONLY : JPRB
00102 !
00103 USE MODI_ABOR1_SFX
00104 !
00105 IMPLICIT NONE
00106 !
00107 !*      0.1. Declaration of arguments
00108 !
00109 REAL,                      INTENT(IN)  :: PILA1   ! Lat. (y) of first input point
00110 REAL,                      INTENT(IN)  :: PILO1   ! Lon. (x) of first input point
00111 REAL,                      INTENT(IN)  :: PILA2   ! Lat. (y) of last input point
00112 REAL,                      INTENT(IN)  :: PILO2   ! Lon. (x) of last input point
00113 INTEGER,                   INTENT(IN)  :: KINLA   ! Number of parallels
00114 INTEGER, DIMENSION(KINLA), INTENT(IN)  :: KINLO   ! Number of point along a parallel
00115 INTEGER,                   INTENT(IN)  :: KILEN   ! size of input arrays
00116 REAL,    DIMENSION(KINLA), INTENT(IN)  :: PILATARRAY! latitudes array
00117 REAL,    DIMENSION(KILEN), INTENT(IN)  :: PARIN   ! input array
00118 INTEGER,                   INTENT(IN)  :: KOLEN   ! size of output array
00119 REAL,    DIMENSION(KOLEN), INTENT(IN)  :: PXOUT   ! X (lon.) of output points
00120 REAL,    DIMENSION(KOLEN), INTENT(IN)  :: PYOUT   ! Y (lat.) of output points
00121 REAL,    DIMENSION(KOLEN), INTENT(OUT) :: PAROUT  ! output array
00122 LOGICAL, DIMENSION(KOLEN), INTENT(IN)  :: OINTERP ! .true. where physical value is needed
00123 LOGICAL,                   INTENT(IN)  :: ODVECT  ! data is vectorial (True/False)
00124 INTEGER,                   INTENT(IN)  :: KLUOUT  ! output listing logical unit
00125 INTEGER, DIMENSION(KILEN), INTENT(IN), OPTIONAL  :: KLSMIN  ! input land/sea mask
00126 INTEGER, DIMENSION(KOLEN), INTENT(IN), OPTIONAL  :: KLSMOUT ! output land/sea mask
00127 !
00128 !*      0.2. Declaration of local variables
00129 !
00130  ! Variables used to perform the interpolation
00131 REAL                               :: ZOLA     ! Latitude of the output point
00132 REAL                               :: ZOLO     ! Longitude of the output point
00133 REAL                               :: ZIDLA    ! Delta latitude
00134 REAL, DIMENSION(KINLA+1)           :: ZIDLAT   ! Deltai latitude
00135 REAL                               :: ZIDLO    ! Delta longitude
00136 INTEGER, DIMENSION(:), ALLOCATABLE :: IOFS     ! Offset of each parallel in the array
00137   ! Number of the surrounding latitudes
00138 INTEGER                            :: IOSS,IOS,ION,IONN
00139   ! Posiiton in the array of the twelwe surrounding points
00140 INTEGER                            :: IP1,IP2,IP3,IP4,IP5,IP6,IP7,IP8,IP9,IP10, 
00141                                         IP11,IP12  
00142   ! Latitudes and longitudes of the surrounding points
00143 REAL                               :: ZLANN,ZLAN,ZLAS,ZLASS
00144 REAL                               :: ZLOP1,ZLOP2,ZLOP3,ZLOP4 ,ZLOP5 ,ZLOP6,    
00145                                         ZLOP7,ZLOP8,ZLOP9,ZLOP10,ZLOP11,ZLOP12  
00146   ! Weights of the latitudes and of the points
00147 REAL                               :: ZWNN,ZWN,ZWS,ZWSS
00148 REAL                               :: ZW1,ZW2,ZW3,ZW4,ZW5,ZW6,ZW7,ZW8,ZW9,ZW10, 
00149                                         ZW11,ZW12  
00150   ! Land/sea mask coefficient for each point : 0 -> point not taken in account,
00151   !                                            1 -> point taken in account
00152 REAL                               :: ZLSM1,ZLSM2 ,ZLSM3 ,ZLSM4 ,ZLSM5 ,ZLSM6,ZLSM7,ZLSM8, 
00153                                         ZLSM9,ZLSM10,ZLSM11,ZLSM12,ZLSMNN,ZLSMN,ZLSMS,ZLSMSS,
00154                                         ZLSMTOT  
00155  ! Variables implied in the extension procedure
00156 REAL                               :: ZILO1     ! Longitude of the first data point
00157 REAL                               :: ZILO2     ! Longitude of the last data point
00158 LOGICAL                            :: GGLOBLON  ! True if the map is circular
00159 LOGICAL                            :: GGLOBN    ! True if the map has the north pole
00160 LOGICAL                            :: GGLOBS    ! True if the map has the south pole
00161 INTEGER                            :: IBIGSIZE  ! Size of the extended map
00162 INTEGER                            :: IMIDDLE   ! Used for extensions around the poles
00163 INTEGER                            :: IOFFSET1  ! Offset in map
00164 INTEGER                            :: IOFFSET2  ! Offset in map
00165 REAL                               :: ZSOUTHPOLE! south pole latitude (-90 or  90)
00166 REAL                               :: ZNORTHPOLE! north pole latitude ( 90 or -90)
00167 REAL,    DIMENSION(:), ALLOCATABLE :: ZLA       ! input "latitude"  coordinate
00168 REAL,    DIMENSION(:), ALLOCATABLE :: ZLO       ! input "longitude" coordinate
00169 REAL,    DIMENSION(:), ALLOCATABLE :: ZARIN     ! Extended input datas
00170 INTEGER, DIMENSION(:), ALLOCATABLE :: ILSMIN    ! Extended land/sea mask
00171 INTEGER, DIMENSION(:), ALLOCATABLE :: IINLO     ! Extended KINLO
00172 INTEGER                            :: IINLA     ! Number of parallel
00173 REAL                               :: ZVECT     ! -1 if input is vectorial
00174 LOGICAL                            :: LDLSM     ! Specify if land/sea mask is present or not
00175  ! Loop counters
00176 INTEGER                            :: JOPOS     ! Output position
00177 INTEGER                            :: JIPOS     ! Input position
00178 INTEGER                            :: JLOOP1    ! Dummy counter
00179 !
00180 !
00181 !------------------------------------------------------------------------------
00182 REAL                               :: ZMAX      ! Max of 12 surrounding values
00183 REAL                               :: ZMIN      ! Min of 12 surrounding values
00184 INTEGER                            :: JLOOP2    ! Dummy counter
00185 INTEGER,    DIMENSION(12)          :: IP        ! Array for IPn
00186 INTEGER                            :: JLAT      ! latitude  loop counter
00187 INTEGER                            :: JLON      ! longitude loop counter
00188 REAL(KIND=JPRB) :: ZHOOK_HANDLE
00189 !------------------------------------------------------------------------------
00190 !
00191 !*     1. DETERMINATION  of the latitude of the poles (depending of the latitude
00192 !         -------------                                 of the first data point)
00193 !
00194 IF (LHOOK) CALL DR_HOOK('ADAPT_HORIBL_SURF',0,ZHOOK_HANDLE)
00195 IF (PILA1>0.) THEN
00196   ZSOUTHPOLE= 90.
00197   ZNORTHPOLE=-90.
00198 ELSE
00199   ZSOUTHPOLE=-90.
00200   ZNORTHPOLE= 90.
00201 END IF
00202 !
00203 !------------------------------------------------------------------------------
00204 !
00205 !*     2. EXTEND DATA GRID
00206 !         ----------------
00207   ! Land / Sea mask
00208 LDLSM = .FALSE.
00209 IF (PRESENT(KLSMIN) .AND. PRESENT(KLSMOUT)) LDLSM = .TRUE.
00210 !
00211 !*    2.1 Alias input data
00212 !
00213 ZILO1 = PILO1
00214 ZILO2 = PILO2
00215 ZVECT = 1.
00216 IF (ODVECT) ZVECT=-1.
00217 !
00218 !*   2.2 Center input domain in order to have Lo1 < Lo 2
00219 !
00220 IF (ZILO2 < 0.)    ZILO2 = ZILO2 + 360.
00221 IF (ZILO1 < 0.)    ZILO1 = ZILO1 + 360.
00222 IF (ZILO2 < ZILO1) ZILO1 = ZILO1 - 360.
00223 !
00224 !*   2.3 Extend one point (needed for reduced grids)
00225 !
00226 ! Longitude coordinate of points are found by :
00227 !                      i
00228 !  Lon(i) = Lon1 + ------------- . (Lon2 - Lon1)
00229 !                   Npts(Lat)-1
00230 ! Where i goes from 0 to Npts(Lat)-1. The result of this is that the last point of
00231 ! each parallel is located at Lon2. This is not the case for reduced grid where the
00232 ! position of the last point depends upon the number of points of the parallel. For
00233 ! reduced grid, the right formula to use is the following :
00234 !                       i
00235 !  Lon(i) = Lon1 + ----------- . (Lon2' - Lon1)
00236 !                   Npts(Lat)
00237 ! Where Lon2' = Lon1 + 2.PI.
00238 !
00239 !                                              Lon2 - Lon1
00240 ! This can be generalized with Lon2' = Lon2 + -------------
00241 !                                              Nptsmax - 1
00242 !
00243 JOPOS = MAXVAL(KINLO(1:KINLA))
00244 ZILO2 = ZILO1 + (ZILO2 - ZILO1) * JOPOS / (JOPOS - 1.)
00245 !
00246 !
00247 !* 2.4 Test if the input is global or partially global
00248 !
00249 ! Note that we must have a global map to make extension around the poles
00250 GGLOBN   = .FALSE.
00251 GGLOBS   = .FALSE.
00252 GGLOBLON = .FALSE.
00253 IF (ZILO2-360.>ZILO1-1.E-3) GGLOBLON = .TRUE.
00254 ZIDLA = (PILA2 - PILA1) / (KINLA - 1)
00255 ZIDLAT(KINLA+1)=0.
00256 DO JLAT=2,KINLA
00257   ZIDLAT(JLAT)=PILATARRAY(JLAT)-PILATARRAY(JLAT-1)
00258 END DO
00259 ZIDLAT(1)=ZIDLAT(2)
00260 IF ((PILA1-ZIDLA>= 90.) .OR. (PILA1-ZIDLA<=-90.)) GGLOBS=GGLOBLON
00261 IF ((PILA2+ZIDLA>= 90.) .OR. (PILA2+ZIDLA<=-90.)) GGLOBN=GGLOBLON
00262 ! Aladin case (input PILA2, PILO2 are in meters) no extension
00263 IF ( PILA2 > 100. ) THEN
00264   GGLOBN   = .FALSE.
00265   GGLOBS   = .FALSE.
00266   GGLOBLON = .FALSE.
00267 END IF
00268 !
00269 !* 2.5  Compute the size of the resulting map
00270 !
00271 IBIGSIZE = KILEN
00272 IF (GGLOBS  ) IBIGSIZE=IBIGSIZE+(4+KINLO(    1))+(4+KINLO(      2))
00273 IF (GGLOBN  ) IBIGSIZE=IBIGSIZE+(4+KINLO(KINLA))+(4+KINLO(KINLA-1))
00274 IF (GGLOBLON) IBIGSIZE=IBIGSIZE+ 4*KINLA
00275 !
00276 !* 2.6 Compute the resulting map
00277 !
00278 ALLOCATE (ZARIN(IBIGSIZE))
00279 ALLOCATE (ILSMIN(IBIGSIZE))
00280 !
00281 ! 2.6.1 Compute the longitude extension
00282 !
00283 ! This is a basic copy of the data. If extension is possible, the first and last
00284 ! two lines are copied twice this way :
00285 !
00286 !    /---------------\
00287 !    |               |
00288 !   [.] [.] [....   ...] [.] [.]
00289 !        |            |
00290 !        \------------/
00291 !
00292 ! A point represent a data.
00293 !
00294 JIPOS = 1
00295 JOPOS = 1
00296 IF (GGLOBS) JOPOS=JOPOS+(4+KINLO(1))+(4+KINLO(2))
00297 IF (GGLOBLON) THEN
00298   DO JLOOP1 = 1, KINLA
00299     ZARIN(JOPOS  ) = PARIN(JIPOS+KINLO(JLOOP1)-2)
00300     ZARIN(JOPOS+1) = PARIN(JIPOS+KINLO(JLOOP1)-1)
00301     ZARIN(JOPOS+2:JOPOS+2+KINLO(JLOOP1)-1) = PARIN(JIPOS:JIPOS+KINLO(JLOOP1)-1)
00302     ZARIN(JOPOS+2+KINLO(JLOOP1)  ) = PARIN(JIPOS  )
00303     ZARIN(JOPOS+2+KINLO(JLOOP1)+1) = PARIN(JIPOS+1)
00304     IF (LDLSM) THEN
00305       ILSMIN(JOPOS  ) = KLSMIN(JIPOS+KINLO(JLOOP1)-2)
00306       ILSMIN(JOPOS+1) = KLSMIN(JIPOS+KINLO(JLOOP1)-1)
00307       ILSMIN(JOPOS+2:JOPOS+2+KINLO(JLOOP1)-1) = KLSMIN(JIPOS:JIPOS+KINLO(JLOOP1)-1)
00308       ILSMIN(JOPOS+2+KINLO(JLOOP1)  ) = KLSMIN(JIPOS  )
00309       ILSMIN(JOPOS+2+KINLO(JLOOP1)+1) = KLSMIN(JIPOS+1)
00310     END IF
00311     JIPOS = JIPOS + KINLO(JLOOP1)
00312     JOPOS = JOPOS + KINLO(JLOOP1) + 4
00313   END DO
00314 ELSE
00315   ZARIN(JOPOS:JOPOS+KILEN-1) = PARIN(JIPOS:JIPOS+KILEN-1)
00316   IF (LDLSM) THEN
00317     ILSMIN(JOPOS:JOPOS+KILEN-1) = KLSMIN(JIPOS:JIPOS+KILEN-1)
00318   END IF
00319 END IF
00320 !
00321 ! 2.6.2 Compute the south pole extension
00322 !
00323 ! Pole extension is performed by copying the first half datas to the last half
00324 ! datas of the extension parallel :
00325 !
00326 !  [.] [.] [....] [....] [.] [.]
00327 !                  ||||
00328 !            /-------/
00329 !           ||||
00330 !  [.] [.] [....] [....] [.] [.]
00331 !
00332 IF (GGLOBS) THEN ! South pole (south meaning begining of the grib)
00333   IOFFSET1 = 4 + KINLO(2)
00334   IOFFSET2 = IOFFSET1 + 4 + KINLO(1)
00335   IMIDDLE = (KINLO(1)+4) / 2
00336   ZARIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00337       ZVECT*ZARIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00338   ZARIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00339       ZVECT*ZARIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00340   IF (LDLSM) THEN
00341     ILSMIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00342         ILSMIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00343     ILSMIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00344         ILSMIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00345   END IF
00346   IOFFSET2 = IOFFSET2 + 4 + KINLO(1)
00347   IMIDDLE = (KINLO(2)+4) / 2
00348   ZARIN(1:IMIDDLE) = ZVECT*ZARIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)
00349   ZARIN(IMIDDLE+1:KINLO(2)+4) = &
00350       ZVECT*ZARIN(IOFFSET2+1+2:IOFFSET2+KINLO(2)+4-IMIDDLE+2)  
00351   IF (LDLSM) THEN
00352     ILSMIN(1:IMIDDLE) = ILSMIN(IOFFSET2+1+IMIDDLE:IOFFSET2+2*IMIDDLE)
00353     ILSMIN(IMIDDLE+1:KINLO(2)+4) = ILSMIN(IOFFSET2+1+2:IOFFSET2+KINLO(2)+4-IMIDDLE+2)
00354   END IF
00355 END IF
00356 !
00357 ! 2.6.3 Compute the north pole extension
00358 !
00359 IF (GGLOBN) THEN ! North pole (north meaning end of the grib)
00360   IOFFSET1 = IBIGSIZE - (4+KINLO(KINLA-1)) - (4+KINLO(KINLA))
00361   IOFFSET2 = IOFFSET1 - (4+KINLO(KINLA))
00362   IMIDDLE = (KINLO(KINLA)+4) / 2
00363   ZARIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00364       ZVECT*ZARIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00365   ZARIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00366       ZVECT*ZARIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00367   IF (LDLSM) THEN
00368     ILSMIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00369         ILSMIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00370     ILSMIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00371         ILSMIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00372   END IF
00373   IOFFSET1 = IOFFSET1 + (4+KINLO(KINLA))
00374   IOFFSET2 = IOFFSET2 - (4+KINLO(KINLA-1))
00375   IMIDDLE = (KINLO(KINLA-1)+4) / 2
00376   ZARIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00377       ZVECT*ZARIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00378   ZARIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00379       ZVECT*ZARIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00380   IF (LDLSM) THEN
00381     ILSMIN(IOFFSET1+1:IOFFSET1+IMIDDLE) = &
00382         ILSMIN(IOFFSET2+1+IMIDDLE-2:IOFFSET2+2*IMIDDLE-2)  
00383     ILSMIN(IOFFSET1+IMIDDLE+1:IOFFSET1+KINLO(1)+4) = &
00384         ILSMIN(IOFFSET2+1+2:IOFFSET2+KINLO(1)+4-IMIDDLE+2)  
00385   END IF
00386 END IF
00387 !
00388 !*  2.7  Compute the resulting parameters of the map
00389 !
00390 IINLA = KINLA
00391 IF (GGLOBS) IINLA = IINLA + 2
00392 IF (GGLOBN) IINLA = IINLA + 2
00393 !
00394 ALLOCATE (IINLO(IINLA))
00395 IOFFSET1 = 0
00396 IF (GGLOBS) THEN
00397   IINLO(IOFFSET1+1) = KINLO(2)
00398   IINLO(IOFFSET1+2) = KINLO(1)
00399   IOFFSET1 = IOFFSET1 + 2
00400 END IF
00401 IINLO(IOFFSET1+1:IOFFSET1+KINLA) = KINLO(1:KINLA)
00402 IOFFSET1 = IOFFSET1 + KINLA
00403 IF (GGLOBN) THEN
00404   IINLO(IOFFSET1+1) = KINLO(KINLA)
00405   IINLO(IOFFSET1+2) = KINLO(KINLA-1)
00406   IOFFSET1 = IOFFSET1 + 2
00407 END IF
00408 !
00409 !*  2.8  Compute Offset array used to acces the lines
00410 !
00411 ALLOCATE (IOFS(IINLA))
00412 IOFS(1) = 1
00413 IF (GGLOBLON) IOFS(1)=IOFS(1)+2
00414 DO JLOOP1=2, IINLA
00415   IOFS(JLOOP1) = IOFS(JLOOP1-1) + IINLO(JLOOP1-1)
00416   IF (GGLOBLON) IOFS(JLOOP1) = IOFS(JLOOP1) + 4
00417 END DO
00418 !
00419 !------------------------------------------------------------------------------
00420 !
00421 !*     3.   LOOP OVER ALL THE POINTS OF THE OUTPUT GRID
00422 !           -------------------------------------------
00423 !
00424 PAROUT(:) = XUNDEF
00425 !
00426 JOPOS = 0
00427 DO JLOOP1 = 1, KOLEN
00428   JOPOS = JOPOS + 1
00429   IF (.NOT. OINTERP(JOPOS)) CYCLE
00430   ZOLA  = PYOUT(JOPOS)
00431   ZOLO  = PXOUT(JOPOS)
00432   IF (ZOLO < ZILO1) ZOLO = ZOLO + 360.
00433   IF (ZOLO > ZILO2) ZOLO = ZOLO - 360.
00434 !
00435 !* 3.1 Locate the 12 input points around the interpolated output point
00436 !*
00437 !*            N         1   2
00438 !*
00439 !*            ^     3   4   5   6
00440 !*            |           x
00441 !*            |     7   8   9  10
00442 !*            |
00443 !*                     11  12
00444 !*            S
00445 !*              W ---------------> E
00446 !*
00447 !* Note : the name 'south', 'north', may not be exact if the point 2 is
00448 !*   to the south of point 1 (IDLA < 0). This does not affect computation.
00449 !
00450     ! 3.1.1. find positions of latitudes
00451   DO JLAT=1,KINLA
00452     IF((ZOLA>=(PILATARRAY(JLAT)-ZIDLAT(JLAT  )/2.)).AND.(ZOLA<(PILATARRAY(JLAT)&
00453            +ZIDLAT(JLAT+1)/2.)))  IOS = JLAT  
00454   ENDDO
00455   ZLAS = PILATARRAY(IOS)
00456   IF (GGLOBS)  IOS  = IOS + 2
00457   IOSS = IOS - 1
00458   ION  = IOS + 1
00459   IONN = ION + 1
00460   IF (IOSS==0) THEN
00461     ZLASS=PILATARRAY(1)-ZIDLAT(1)/2.
00462   ELSE
00463     ZLASS = PILATARRAY(IOS-1)
00464   ENDIF
00465   ZLAN  = PILATARRAY(IOS+1)
00466   ZLANN = PILATARRAY(ION+1)
00467       !
00468       ! extra latitudes are computed symetrically compared to the poles
00469       !
00470   IF (GGLOBS .AND. IOS==2) THEN
00471     ZLASS = 2. * ZSOUTHPOLE - ZLANN
00472     ZLAS  = 2. * ZSOUTHPOLE - ZLAN
00473   END IF
00474   IF (GGLOBS .AND. IOS==3) THEN
00475     ZLASS = 2. * ZSOUTHPOLE - ZLAS
00476   END IF
00477   IF (GGLOBN .AND. IOS==IINLA-2) THEN
00478     ZLANN = 2. * ZNORTHPOLE - ZLASS
00479     ZLAN  = 2. * ZNORTHPOLE - ZLAS
00480   END IF
00481   IF (GGLOBN .AND. IOS==IINLA-3) THEN
00482      ZLANN = 2. * ZNORTHPOLE - ZLAN
00483   END IF
00484 !
00485   IF ((IOSS<1).OR.(IONN>IINLA).OR. &
00486        (IOSS<1).OR.(IONN>IINLA)) THEN  
00487     WRITE (KLUOUT,'(A)') &
00488         ' -> [HORIBL_SURF.F90] Input domain is smaller than output one - latitude. Abort'  
00489       CALL ABOR1_SFX('ADAPT_HORIBLE_SURF: INPUT DOMAIN TOO SMALL - LATITUDE')
00490   END IF
00491 !
00492       ! 3.1.2. northern
00493   ZIDLO = (ZILO2 - ZILO1) / (IINLO(IONN))
00494   IP1   = INT((ZOLO - ZILO1) / ZIDLO)
00495   IP2   = IP1  + 1
00496   ZLOP1 = ZILO1 + IP1 * ZIDLO
00497   ZLOP2 = ZLOP1 + ZIDLO
00498 !
00499       ! 3.1.3. north
00500   ZIDLO = (ZILO2 - ZILO1) / (IINLO(ION ))
00501   IP4   = INT((ZOLO - ZILO1) / ZIDLO)
00502   IP3   = IP4  - 1
00503   IP5   = IP4  + 1
00504   IP6   = IP5  + 1
00505   ZLOP4 = ZILO1 + IP4 * ZIDLO
00506   ZLOP3 = ZLOP4 - ZIDLO
00507   ZLOP5 = ZLOP4 + ZIDLO
00508   ZLOP6 = ZLOP5 + ZIDLO
00509 !
00510       ! 3.1.4. south
00511   ZIDLO = (ZILO2 - ZILO1) / (IINLO(IOS ))
00512   IP8   = INT((ZOLO - ZILO1) / ZIDLO)
00513   IP7   = IP8  - 1
00514   IP9   = IP8  + 1
00515   IP10  = IP9  + 1
00516   ZLOP8 = ZILO1 + IP8 * ZIDLO
00517   ZLOP7 = ZLOP8 - ZIDLO
00518   ZLOP9 = ZLOP8 + ZIDLO
00519   ZLOP10= ZLOP9 + ZIDLO
00520 !
00521       ! 3.1.5. southern
00522   ZIDLO = (ZILO2 - ZILO1) / (IINLO(IOSS))
00523   IP11  = INT((ZOLO - ZILO1) / ZIDLO)
00524   IP12  = IP11 + 1
00525   ZLOP11= ZILO1 + IP11* ZIDLO
00526   ZLOP12= ZLOP11+ ZIDLO
00527 !
00528       ! 3.1.6. check position of points
00529   IF (GGLOBLON) THEN
00530     IF ((IP1 <-2) .OR. (IP2 >IINLO(IONN)+1) .OR. &
00531           (IP3 <-2) .OR. (IP6 >IINLO(ION )+1) .OR. &
00532           (IP7 <-2) .OR. (IP10>IINLO(IOS )+1) .OR. &
00533         (IP11<-2) .OR. (IP12>IINLO(IOSS)+1)) THEN  
00534       WRITE (KLUOUT,'(A,A)')                                         &
00535            ' -> [HORIBL_SURF.F90] Input domain is smaller than output one ', &
00536            '- longitude global, abort'  
00537       CALL ABOR1_SFX('ADAPT_HORIBLE_SURF: INPUT DOMAIN TOO SMALL - LONGITUDE GLOBAL')
00538     END IF
00539   ELSE
00540     IF ((IP1 <0) .OR. (IP2 >IINLO(IONN)-1) .OR. &
00541           (IP3 <0) .OR. (IP6 >IINLO(ION )-1) .OR. &
00542           (IP7 <0) .OR. (IP10>IINLO(IOS )-1) .OR. &
00543           (IP11<0) .OR. (IP12>IINLO(IOSS)-1)) THEN  
00544       WRITE (KLUOUT,'(A,A)')                                        &
00545           ' -> [HORIBL_SURF.F90] Input domain is smaller than output one ', &
00546           '- longitude local, abort'  
00547       CALL ABOR1_SFX('ADAPT_HORIBLE_SURF: INPUT DOMAIN TOO SMALL - LONGITUDE LOCAL')
00548     END IF
00549   END IF
00550 !
00551       ! 3.1.7. add parallel offset
00552   IP1 =IP1 + IOFS(IONN)
00553   IP2 =IP2 + IOFS(IONN)
00554   IP3 =IP3 + IOFS(ION )
00555   IP4 =IP4 + IOFS(ION )
00556   IP5 =IP5 + IOFS(ION )
00557   IP6 =IP6 + IOFS(ION )
00558   IP7 =IP7 + IOFS(IOS )
00559   IP8 =IP8 + IOFS(IOS )
00560   IP9 =IP9 + IOFS(IOS )
00561   IP10=IP10+ IOFS(IOS )
00562   IP11=IP11+ IOFS(IOSS)
00563   IP12=IP12+ IOFS(IOSS)
00564 !
00565 !*  3.2 Land / Sea mask
00566 !
00567   ZLSM1  = 1.
00568   ZLSM2  = 1.
00569   ZLSM3  = 1.
00570   ZLSM4  = 1.
00571   ZLSM5  = 1.
00572   ZLSM6  = 1.
00573   ZLSM7  = 1.
00574   ZLSM8  = 1.
00575   ZLSM9  = 1.
00576   ZLSM10 = 1.
00577   ZLSM11 = 1.
00578   ZLSM12 = 1.
00579   ZLSMNN = 1.
00580   ZLSMN  = 1.
00581   ZLSMS  = 1.
00582   ZLSMSS = 1.
00583   IF (LDLSM) THEN
00584     IF (ILSMIN(IP1 ).NE.KLSMOUT(JOPOS)) ZLSM1  = 0.
00585     IF (ILSMIN(IP2 ).NE.KLSMOUT(JOPOS)) ZLSM2  = 0.
00586     IF (ILSMIN(IP3 ).NE.KLSMOUT(JOPOS)) ZLSM3  = 0.
00587     IF (ILSMIN(IP4 ).NE.KLSMOUT(JOPOS)) ZLSM4  = 0.
00588     IF (ILSMIN(IP5 ).NE.KLSMOUT(JOPOS)) ZLSM5  = 0.
00589     IF (ILSMIN(IP6 ).NE.KLSMOUT(JOPOS)) ZLSM6  = 0.
00590     IF (ILSMIN(IP7 ).NE.KLSMOUT(JOPOS)) ZLSM7  = 0.
00591     IF (ILSMIN(IP8 ).NE.KLSMOUT(JOPOS)) ZLSM8  = 0.
00592     IF (ILSMIN(IP9 ).NE.KLSMOUT(JOPOS)) ZLSM9  = 0.
00593     IF (ILSMIN(IP10).NE.KLSMOUT(JOPOS)) ZLSM10 = 0.
00594     IF (ILSMIN(IP11).NE.KLSMOUT(JOPOS)) ZLSM11 = 0.
00595     IF (ILSMIN(IP12).NE.KLSMOUT(JOPOS)) ZLSM12 = 0.
00596     ZLSMNN = MIN(ZLSM1 +ZLSM2,1.)
00597     ZLSMN  = MIN(ZLSM3 +ZLSM4 +ZLSM5 +ZLSM6,1.)
00598     ZLSMS  = MIN(ZLSM7 +ZLSM8 +ZLSM9 +ZLSM10,1.)
00599     ZLSMSS = MIN(ZLSM11+ZLSM12,1.)
00600     ZLSMTOT = MIN(ZLSMNN+ZLSMN+ZLSMS+ZLSMSS,1.)
00601     IF (ZLSMNN < 1.E-3) THEN
00602       ZLSM1 = 1.
00603       ZLSM2 = 1.
00604     END IF
00605     IF (ZLSMN  < 1.E-3) THEN
00606       ZLSM3 = 1.
00607       ZLSM4 = 1.
00608       ZLSM5 = 1.
00609       ZLSM6 = 1.
00610     END IF
00611     IF (ZLSMS  < 1.E-3) THEN
00612       ZLSM7 = 1.
00613       ZLSM8 = 1.
00614       ZLSM9 = 1.
00615       ZLSM10= 1.
00616     END IF
00617     IF (ZLSMSS < 1.E-3) THEN
00618       ZLSM11= 1.
00619       ZLSM12= 1.
00620     END IF
00621     IF (ZLSMTOT < 1.E-3) THEN
00622       ZLSMNN = 1.
00623       ZLSMN  = 1.
00624       ZLSMS  = 1.
00625       ZLSMSS = 1.
00626     END IF
00627   ENDIF
00628 !
00629 !*  3.3 Weight of points
00630 !
00631       ! 3.3.1 northern
00632   ZW1  = ZLSM1 * (1.+ZLSM2 *(ZOLO -ZLOP1 )/(ZLOP1 -ZLOP2 ))
00633   ZW2  = 1. - ZW1
00634   ZWNN = ZLSMNN* (1.+ZLSMN *(ZOLA -ZLANN)/(ZLANN-ZLAN )) &
00635                  * (1.+ZLSMS *(ZOLA -ZLANN)/(ZLANN-ZLAS )) &
00636                  * (1.+ZLSMSS*(ZOLA -ZLANN)/(ZLANN-ZLASS))  
00637 !
00638       ! 3.3.2. north
00639   ZW3  = ZLSM3 * (1.+ZLSM4 *(ZOLO -ZLOP3 )/(ZLOP3 -ZLOP4 )) &
00640                  * (1.+ZLSM5 *(ZOLO -ZLOP3 )/(ZLOP3 -ZLOP5 )) &
00641                  * (1.+ZLSM6 *(ZOLO -ZLOP3 )/(ZLOP3 -ZLOP6 ))  
00642   ZW4  = ZLSM4 * (1.+ZLSM3 *(ZOLO -ZLOP4 )/(ZLOP4 -ZLOP3 )) &
00643                  * (1.+ZLSM5 *(ZOLO -ZLOP4 )/(ZLOP4 -ZLOP5 )) &
00644                  * (1.+ZLSM6 *(ZOLO -ZLOP4 )/(ZLOP4 -ZLOP6 ))  
00645   ZW5  = ZLSM5 * (1.+ZLSM3 *(ZOLO -ZLOP5 )/(ZLOP5 -ZLOP3 )) &
00646                  * (1.+ZLSM4 *(ZOLO -ZLOP5 )/(ZLOP5 -ZLOP4 )) &
00647                  * (1.+ZLSM6 *(ZOLO -ZLOP5 )/(ZLOP5 -ZLOP6 ))  
00648   ZW6 = 1. - ZW3 - ZW4 - ZW5
00649   ZWN  = ZLSMN * (1.+ZLSMNN*(ZOLA -ZLAN )/(ZLAN -ZLANN)) &
00650                  * (1.+ZLSMS *(ZOLA -ZLAN )/(ZLAN -ZLAS )) &
00651                  * (1.+ZLSMSS*(ZOLA -ZLAN )/(ZLAN -ZLASS))  
00652 !
00653       ! 3.3.3. south
00654   ZW7  = ZLSM7 * (1.+ZLSM8 *(ZOLO -ZLOP7 )/(ZLOP7 -ZLOP8 )) &
00655                  * (1.+ZLSM9 *(ZOLO -ZLOP7 )/(ZLOP7 -ZLOP9 )) &
00656                  * (1.+ZLSM10*(ZOLO -ZLOP7 )/(ZLOP7 -ZLOP10))  
00657   ZW8  = ZLSM8 * (1.+ZLSM7 *(ZOLO -ZLOP8 )/(ZLOP8 -ZLOP7 )) &
00658                  * (1.+ZLSM9 *(ZOLO -ZLOP8 )/(ZLOP8 -ZLOP9 )) &
00659                  * (1.+ZLSM10*(ZOLO -ZLOP8 )/(ZLOP8 -ZLOP10))  
00660   ZW9  = ZLSM9 * (1.+ZLSM7 *(ZOLO -ZLOP9 )/(ZLOP9 -ZLOP7 )) &
00661                  * (1.+ZLSM8 *(ZOLO -ZLOP9 )/(ZLOP9 -ZLOP8 )) &
00662                  * (1.+ZLSM10*(ZOLO -ZLOP9 )/(ZLOP9 -ZLOP10))  
00663   ZW10 = 1. - ZW7 - ZW8 - ZW9
00664   ZWS  = ZLSMS * (1.+ZLSMNN*(ZOLA -ZLAS )/(ZLAS -ZLANN)) &
00665                  * (1.+ZLSMN *(ZOLA -ZLAS )/(ZLAS -ZLAN )) &
00666                  * (1.+ZLSMSS*(ZOLA -ZLAS )/(ZLAS -ZLASS))  
00667 !
00668       ! 3.3.4. southern
00669   ZW11 = ZLSM11* (1.+ZLSM12*(ZOLO -ZLOP11)/(ZLOP11-ZLOP12))
00670   ZW12 = 1. - ZW11
00671   ZWSS = 1. - ZWNN - ZWN - ZWS
00672 !
00673       ! 3.3.5. longitude weight x latitude weight
00674   ZW1  = ZW1  * ZWNN
00675   ZW2  = ZW2  * ZWNN
00676   ZW3  = ZW3  * ZWN
00677   ZW4  = ZW4  * ZWN
00678   ZW5  = ZW5  * ZWN
00679   ZW6  = ZW6  * ZWN
00680   ZW7  = ZW7  * ZWS
00681   ZW8  = ZW8  * ZWS
00682   ZW9  = ZW9  * ZWS
00683   ZW10 = ZW10 * ZWS
00684   ZW11 = ZW11 * ZWSS
00685   ZW12 = ZW12 * ZWSS
00686 !
00687   PAROUT (JOPOS) = ZW1  * ZARIN(IP1 ) + &
00688                      ZW2  * ZARIN(IP2 ) + &
00689                      ZW3  * ZARIN(IP3 ) + &
00690                      ZW4  * ZARIN(IP4 ) + &
00691                      ZW5  * ZARIN(IP5 ) + &
00692                      ZW6  * ZARIN(IP6 ) + &
00693                      ZW7  * ZARIN(IP7 ) + &
00694                      ZW8  * ZARIN(IP8 ) + &
00695                      ZW9  * ZARIN(IP9 ) + &
00696                      ZW10 * ZARIN(IP10) + &
00697                      ZW11 * ZARIN(IP11) + &
00698                      ZW12 * ZARIN(IP12)  
00699 !
00700 ! For surface fields, the interpoalted value is bounded
00701 ! by the min max values of the initial field
00702 
00703   IF (PRESENT(KLSMIN)) THEN
00704 
00705     IP(1)=IP1
00706     IP(2)=IP2
00707     IP(3)=IP3
00708     IP(4)=IP4
00709     IP(5)=IP5
00710     IP(6)=IP6
00711     IP(7)=IP7
00712     IP(8)=IP8
00713     IP(9)=IP9
00714     IP(10)=IP10
00715     IP(11)=IP11
00716     IP(12)=IP12
00717 
00718     ZMIN=XUNDEF
00719     ZMAX=XUNDEF
00720 
00721     DO JLOOP2=1,12
00722       IF (ZARIN(IP(JLOOP2))==XUNDEF) CYCLE
00723 
00724       IF ((ZMAX==XUNDEF)) THEN
00725         ZMAX=ZARIN(IP(JLOOP2))
00726         ZMIN=ZARIN(IP(JLOOP2))
00727       ELSE
00728         ZMAX=MAX(ZMAX,ZARIN(IP(JLOOP2)))
00729         ZMIN=MIN(ZMIN,ZARIN(IP(JLOOP2)))
00730       ENDIF
00731 
00732     END DO
00733 
00734     PAROUT(JOPOS) = MAX(MIN(PAROUT(JOPOS),ZMAX),ZMIN)
00735 
00736   ENDIF
00737 
00738 END DO
00739 !
00740 DEALLOCATE (IINLO)
00741 DEALLOCATE (ZARIN)
00742 DEALLOCATE (ILSMIN)
00743 DEALLOCATE (IOFS)
00744 !
00745 WHERE(ABS(PAROUT-XUNDEF)<1.E-6) PAROUT=XUNDEF
00746 !
00747 !------------------------------------------------------------------------------
00748 !
00749 !*     4.   EXTRAPOLATIONS IF SOME POINTS WERE NOT INTERPOLATED
00750 !           ---------------------------------------------------
00751 !
00752 !* no missing point
00753 IF (COUNT(PAROUT(:)==XUNDEF .AND. OINTERP(:))==0 .AND. LHOOK) CALL DR_HOOK('ADAPT_HORIBL_SURF',1,ZHOOK_HANDLE)
00754 IF (COUNT(PAROUT(:)==XUNDEF .AND. OINTERP(:))==0) RETURN
00755 !
00756 !* no data point
00757 IF (COUNT(PARIN(:)/=XUNDEF)==0 .AND. LHOOK) CALL DR_HOOK('ADAPT_HORIBL_SURF',1,ZHOOK_HANDLE)
00758 IF (COUNT(PARIN(:)/=XUNDEF)==0) RETURN
00759 !
00760 WRITE(KLUOUT,*) ' Remaining horizontal extrapolations'
00761 WRITE(KLUOUT,*) ' Total number of input data     : ',COUNT(PARIN(:)/=XUNDEF)
00762 WRITE(KLUOUT,*) ' Number of points to interpolate: ',COUNT(PAROUT(:)==XUNDEF .AND. OINTERP(:))
00763 !
00764 !* input grid coordinates
00765 !
00766 ALLOCATE(ZLA(KILEN))
00767 ALLOCATE(ZLO(KILEN))
00768 !
00769 JIPOS = 0
00770 DO JLAT=1,KINLA
00771   ZIDLO = (ZILO2-ZILO1) / KINLO(JLAT)
00772   DO JLON=1,KINLO(JLAT)
00773     JIPOS = JIPOS + 1
00774     ZLA(JIPOS) = PILATARRAY(JLAT)
00775     ZLO(JIPOS) = ZILO1 + (JLON-1) * ZIDLO
00776   END DO
00777 END DO
00778 !
00779  CALL HOR_EXTRAPOL_SURF(KLUOUT,'LALO',ZLA,ZLO,PARIN,PYOUT,PXOUT,PAROUT,OINTERP)
00780 !
00781 DEALLOCATE(ZLA)
00782 DEALLOCATE(ZLO)
00783 IF (LHOOK) CALL DR_HOOK('ADAPT_HORIBL_SURF',1,ZHOOK_HANDLE)
00784 !
00785 !------------------------------------------------------------------------------
00786 !
00787 !
00788 END SUBROUTINE ADAPT_HORIBL_SURF