SURFEX v7.3
General documentation of Surfex
 All Classes Files Functions Variables Typedefs
/home/dasprezs/EXPORT_v7_3/src/SURFEX/read_direct_gauss.F90
Go to the documentation of this file.
00001 !     #########
00002       SUBROUTINE READ_DIRECT_GAUSS(HPROGRAM,HSCHEME,HSUBROUTINE,HFILENAME,HFIELD)
00003 !     #########################################################
00004 !
00005 !!**** *READ_DIRECT_GAUSS1* reads a latlon file and call treatment subroutine
00006 !!
00007 !!    PURPOSE
00008 !!    -------
00009 !!
00010 !!    METHOD
00011 !!    ------
00012 !!   
00013 !!    EXTERNAL
00014 !!    --------
00015 !!
00016 !!    IMPLICIT ARGUMENTS
00017 !!    ------------------
00018 !!
00019 !!    REFERENCE
00020 !!    ---------
00021 !!
00022 !!    AUTHOR
00023 !!    ------
00024 !!
00025 !!    V. Masson        Meteo-France
00026 !!    B. Decharme      
00027 !!
00028 !!    MODIFICATION
00029 !!    ------------
00030 !!
00031 !!    Original    04/2009
00032 !!
00033 !----------------------------------------------------------------------------
00034 !
00035 !*    0.     DECLARATION
00036 !            -----------
00037 !
00038 USE MODD_ARCH, ONLY : LITTLE_ENDIAN_ARCH
00039 !
00040 USE MODD_SURF_PAR, ONLY : XUNDEF
00041 !
00042 USE MODD_GET_MESH_INDEX_GAUSS, ONLY : IMASK_GAUSS
00043 !
00044 USE MODI_GET_LUOUT
00045 USE MODI_OPEN_NAMELIST
00046 USE MODI_CLOSE_NAMELIST
00047 USE MODI_OPEN_FILE
00048 USE MODI_CLOSE_FILE
00049 USE MODI_READHEAD
00050 USE MODI_PT_BY_PT_TREATMENT
00051 USE MODE_CHAR2REAL
00052 !
00053 !
00054 USE YOMHOOK   ,ONLY : LHOOK,   DR_HOOK
00055 USE PARKIND1  ,ONLY : JPRB
00056 !
00057 USE MODI_ABOR1_SFX
00058 !
00059 USE MODI_REFRESH_PGDWORK
00060 !
00061 IMPLICIT NONE
00062 !
00063 !*    0.1    Declaration of arguments
00064 !            ------------------------
00065 !
00066  CHARACTER(LEN=6),  INTENT(IN) :: HPROGRAM      ! Type of program
00067  CHARACTER(LEN=6),  INTENT(IN) :: HSCHEME       ! Scheme treated
00068  CHARACTER(LEN=6),  INTENT(IN) :: HSUBROUTINE   ! Name of the subroutine to call
00069  CHARACTER(LEN=28), INTENT(IN) :: HFILENAME     ! Name of the field file.
00070  CHARACTER(LEN=20), INTENT(IN) :: HFIELD        ! Name of the field.
00071 !
00072 !*    0.2    Declaration of local variables read in the data file head
00073 !            ---------------------------------------------------------
00074 !
00075 REAL    :: ZGLBLATMIN                 ! minimum latitude of data box in the file
00076 REAL    :: ZGLBLONMIN                 ! minimum longitude of data box in the file
00077 REAL    :: ZGLBLATMAX                 ! maximum latitude of data box in the file
00078 REAL    :: ZGLBLONMAX                 ! maximum longitude of data box in the file
00079 INTEGER :: INBLINE                    ! number of latitude rows (number of lines
00080 INTEGER :: INBCOL                     ! number of longitude rows (number of columns)
00081 REAL    :: ZNODATA                    ! value below which data are not considered
00082 !
00083 !*    0.3    Declaration of local variables
00084 !            ------------------------------
00085 !
00086 INTEGER :: IGLB, IGLBHDR              ! logical units
00087 INTEGER :: ILUOUT                     ! output listing logical unit
00088 INTEGER :: IERR                       ! return codes
00089 !
00090  CHARACTER(LEN=28) :: YFILENAME        ! Name of the field file without header
00091  CHARACTER(LEN=28) :: YFILEHDR         ! Name of the field file header
00092 !
00093  CHARACTER(LEN=7)  :: YTYPE            ! type of numerical field stored in the
00094 !                                     ! direct access file ('INTEGER','REAL   ')
00095 INTEGER           :: IBITS            ! number of bits of a record in the
00096 !                                     ! direct access file (16,32,64)
00097 INTEGER :: JLOOP                      ! loop index
00098  CHARACTER(LEN=100):: YSTRING          ! string
00099  CHARACTER(LEN=88 ):: YSTRING1         ! part of string STRING
00100 INTEGER           :: IINDEX           ! index of a character in string STRING1
00101 !
00102 REAL    :: ZDLAT                      ! latitude mesh in the data file
00103 REAL    :: ZDLON                      ! longitude mesh in the data file
00104 INTEGER :: JLINE                      ! index of line
00105 INTEGER :: JCOL                       ! index of column
00106 INTEGER, DIMENSION(2) :: ICOL1, ICOL2 ! limits of index of columns
00107 INTEGER               :: ILINE1,ILINE2! limits of index of lines
00108 INTEGER               :: ICOL         ! number of columns in mask domain
00109 INTEGER               :: ICOLINDEX    ! column index in record
00110 REAL, DIMENSION(:), POINTER :: ZLAT   ! latitude of data points
00111 REAL, DIMENSION(:), POINTER :: ZLON   ! longitude of data points
00112 !
00113 INTEGER :: JLON, JLAT                 ! loop counters
00114 REAL    :: ZLONMIN                    ! minimum longitude of mask mesh
00115 REAL    :: ZLONMAX                    ! maximum longitude of mask mesh
00116 REAL    :: ZLATMIN                    ! minimum latitude of mask mesh
00117 REAL    :: ZLATMAX                    ! maximum latitude of mask mesh
00118 REAL    :: ZSHIFT                     ! shift on longitudes
00119 REAL    :: ZFACT                      ! Factor integer to real
00120 !
00121  CHARACTER,        DIMENSION(:), ALLOCATABLE :: IVALUE8 ! value of a data point
00122  CHARACTER(LEN=2), DIMENSION(:), ALLOCATABLE :: IVALUE16 ! value of a data point
00123  CHARACTER(LEN=4), DIMENSION(:), ALLOCATABLE :: IVALUE32R ! value of a data point
00124 INTEGER (KIND=4), DIMENSION(:), ALLOCATABLE :: IVALUE32 ! value of a data point
00125 INTEGER (KIND=8), DIMENSION(:), ALLOCATABLE :: IVALUE64 ! value of a data point
00126 REAL    (KIND=4), DIMENSION(:), ALLOCATABLE :: ZVALUE32 ! value of a data point
00127  CHARACTER(LEN=8), DIMENSION(:), ALLOCATABLE :: ZVALUE64 ! value of a data point
00128 !
00129 REAL, DIMENSION(:), ALLOCATABLE   :: ZVALUE             ! value of a record of data points
00130 !
00131 REAL, DIMENSION(:), ALLOCATABLE   :: ZVALUE_WORK        ! value of a valid data points 
00132 REAL, DIMENSION(:), ALLOCATABLE   :: ZLAT_WORK          ! latitude  of a valid data points 
00133 REAL, DIMENSION(:), ALLOCATABLE   :: ZLON_WORK          ! longitude of a valid data points 
00134 INTEGER                           :: IWORK, IMASK              ! index of these data
00135 LOGICAL                           :: GSWAP              ! T: swap has been done
00136 !
00137 !
00138 INTEGER          :: IRECLENGTH        ! record length
00139 INTEGER          :: IREC              ! record number
00140 REAL(KIND=JPRB) :: ZHOOK_HANDLE
00141 !----------------------------------------------------------------------------
00142 !
00143 IF (LHOOK) CALL DR_HOOK('READ_DIRECT_GAUSS',0,ZHOOK_HANDLE)
00144  CALL GET_LUOUT(HPROGRAM,ILUOUT)
00145 !
00146 !*    1.     Openning of global field
00147 !            ------------------------
00148 !
00149 !*    1.1    Logical unit attributions
00150 !            -------------------------
00151 !
00152 YFILENAME=ADJUSTL(ADJUSTR(HFILENAME)//'.dir')
00153 YFILEHDR =ADJUSTL(ADJUSTR(HFILENAME)//'.hdr')
00154 !
00155 !*    1.2    Openning of header
00156 !            ------------------
00157 !
00158  CALL OPEN_NAMELIST(HPROGRAM,IGLBHDR,YFILEHDR)
00159 !
00160 !*    1.3    Reading in header of direct access characteristics
00161 !            --------------------------------------------------
00162 !
00163 DO JLOOP=1,9
00164   READ(IGLBHDR,'(A100)') YSTRING
00165   IF (YSTRING(1:10)=='recordtype') EXIT
00166 END DO
00167 !
00168 REWIND(IGLBHDR)
00169 !
00170 YSTRING1=YSTRING(12:100)
00171 !
00172 !* string analysis
00173 !
00174 IINDEX=INDEX(YSTRING1,'n')  ! n for integer
00175 IF (IINDEX/=0) THEN
00176   YTYPE='INTEGER'
00177 ELSE
00178   YTYPE='REAL   '
00179 END IF
00180 IINDEX=INDEX(YSTRING1,'8')
00181 IF (IINDEX/=0) IBITS=8
00182 IINDEX=INDEX(YSTRING1,'1')
00183 IF (IINDEX/=0) IBITS=16
00184 IINDEX=INDEX(YSTRING1,'3')
00185 IF (IINDEX/=0) IBITS=32
00186 IINDEX=INDEX(YSTRING1,'4')
00187 IF (IINDEX/=0) IBITS=64
00188 !
00189 IF(YTYPE=='INTEGER')THEN
00190   IF(HFIELD=='CTI'.OR.HFIELD=='sand fraction'.OR. &
00191      HFIELD=='clay fraction'.OR.HFIELD=='organic carbon')THEN
00192     ZFACT=100.0
00193   ELSEIF (HFIELD=='water depth') THEN
00194     ZFACT=10.0
00195   ELSE
00196     ZFACT=1.0
00197   ENDIF
00198 ELSE
00199   ZFACT=1.0  
00200 ENDIF
00201 !
00202 !----------------------------------------------------------------------------
00203 !
00204 !*    2.     Reading of the global field
00205 !            ---------------------------
00206 !
00207 !*    2.1    Head of data file
00208 !            -----------------
00209 !
00210  CALL READHEAD(IGLBHDR,ZGLBLATMIN,ZGLBLATMAX,ZGLBLONMIN,ZGLBLONMAX, &
00211                 INBLINE,INBCOL,ZNODATA,ZDLAT,ZDLON,ZLAT,ZLON,IERR)  
00212 IF (IERR/=0) CALL ABOR1_SFX('READ_DIRECT_GAUSS: PB IN FILE HEADER')
00213 !
00214 !*    2.2    Closing of header
00215 !            -----------------
00216 !
00217  CALL CLOSE_NAMELIST(HPROGRAM,IGLBHDR)
00218 !
00219 !*    2.3    Dimension of work arrays
00220 !            ------------------------
00221 !
00222 ALLOCATE(ZLAT_WORK  (INBCOL*INBLINE))
00223 ALLOCATE(ZLON_WORK  (INBCOL*INBLINE))
00224 ALLOCATE(ZVALUE_WORK(INBCOL*INBLINE))
00225 ALLOCATE(IMASK_GAUSS(INBCOL*INBLINE))
00226 !
00227 !----------------------------------------------------------------------------
00228 !
00229 !*    3.     Adapt subgrid mesh to input file resolution
00230 !            -------------------------------------------
00231 !
00232 !Now do in pgd_gauss_index
00233 !
00234 !----------------------------------------------------------------------------
00235 !
00236 !*    7.     Openning of direct access file
00237 !            ------------------------------
00238 !
00239 !*    7.1    Record length
00240 !            -------------
00241 !
00242 IRECLENGTH = IBITS/8 * INBCOL
00243 ALLOCATE (ZVALUE(INBCOL))
00244 ALLOCATE (IVALUE8 (INBCOL))
00245 ALLOCATE (IVALUE16(INBCOL))
00246 ALLOCATE (IVALUE32(INBCOL))
00247 ALLOCATE (IVALUE32R(INBCOL))
00248 ALLOCATE (IVALUE64(INBCOL))
00249 ALLOCATE (ZVALUE32(INBCOL))
00250 ALLOCATE (ZVALUE64(INBCOL))
00251 !
00252 !*    7.2    Openning of direct access file
00253 !            ------------------------------
00254 !
00255  CALL OPEN_FILE(HPROGRAM,IGLB,YFILENAME,'UNFORMATTED',           &
00256                  HACTION='READ',HACCESS='DIRECT',KRECL=IRECLENGTH )  
00257 !
00258 !----------------------------------------------------------------------------
00259 !
00260 !*    4.     loop on mask meshes (lat)
00261 !            -------------------
00262 !
00263 GSWAP = .FALSE.
00264 !
00265 JLAT  = 0
00266 !
00267 DO 
00268 !
00269   JLAT = JLAT + 1
00270   IF (JLAT==361) EXIT
00271 !
00272   IF(JLAT==1)THEN ! Initialise work interger and array
00273     IWORK          = 0
00274     IMASK          = 0
00275     IMASK_GAUSS(:) = 0
00276     ZLAT_WORK  (:) = XUNDEF
00277     ZLON_WORK  (:) = XUNDEF
00278     ZVALUE_WORK(:) = XUNDEF
00279   ENDIF
00280 !
00281   ZLATMIN = (JLAT-180)/2. - 0.5
00282   ZLATMAX = (JLAT-180)/2.
00283 !
00284 !----------------------------------------------------------------------------
00285 !
00286 !*    5.     index limits on latitude
00287 !            ------------------------
00288 !
00289   ILINE1=MAX(MIN(INT((ZGLBLATMAX-ZDLAT/2.-ZLATMAX)/ZDLAT+1.),INBLINE),0)+1
00290   ILINE2=MAX(MIN(INT((ZGLBLATMAX-ZDLAT/2.-ZLATMIN)/ZDLAT+1.),INBLINE),0)
00291   IF ( .NOT. ANY(ZLAT(:)<ZLATMAX .AND. ZLAT(:)>=ZLATMIN) ) CYCLE
00292 !
00293 !----------------------------------------------------------------------------
00294 !
00295 !*    8.     Loop on lines
00296 !            -------------
00297 !
00298   DO JLINE = ILINE1,ILINE2
00299 !
00300 !----------------------------------------------------------------------------
00301 !
00302 !*   10.     Reading in the direct access file
00303 !            ---------------------------------
00304 !
00305 !*   10.1    Record number
00306 !            -------------
00307 !
00308     IREC=JLINE
00309 ! 
00310 !*   10.2    Reading the correct data type and conversion into real
00311 !            ------------------------------------------------------
00312 !
00313     IF      (YTYPE=='INTEGER' .AND. IBITS== 8) THEN
00314       READ(IGLB,REC=IREC) IVALUE8(:)
00315       ZVALUE(:)=IVALUE8(:)
00316       ! negative values are shifted to positive values according to binary coding
00317       WHERE (ZVALUE(:)<0.) ZVALUE(:) = NINT(256.+ZVALUE(:))
00318       !
00319     ELSE IF (YTYPE=='INTEGER' .AND. IBITS==16) THEN
00320       READ(IGLB,REC=IREC) IVALUE16(:)
00321       ZVALUE(:)=IVALUE16(:)
00322       IF (      ANY(ABS(ZVALUE)>15000)   ) THEN
00323         IF (GSWAP) CALL ABOR1_SFX('READ_DIRECT_GAUSS: SWAP ALREADY DONE, CANNOT BE REDONE')
00324         LITTLE_ENDIAN_ARCH = .NOT. LITTLE_ENDIAN_ARCH
00325         GSWAP = .TRUE.
00326         WRITE(ILUOUT,*) '*******************************************************************'
00327         WRITE(ILUOUT,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
00328                            LITTLE_ENDIAN_ARCH  
00329         WRITE(ILUOUT,*) '*******************************************************************'
00330         JLAT = 0
00331         CALL REFRESH_PGDWORK
00332         EXIT   ! rereads the file
00333       END IF
00334 
00335     ELSE IF (YTYPE=='INTEGER' .AND. IBITS==32) THEN
00336       READ(IGLB,REC=IREC) IVALUE32(:)
00337       ZVALUE(:)=IVALUE32(:)
00338     ELSE IF (YTYPE=='INTEGER' .AND. IBITS==64) THEN
00339       READ(IGLB,REC=IREC) IVALUE64(:)
00340       ZVALUE(:)=IVALUE64(:)
00341     ELSE IF (YTYPE=='REAL   ' .AND. IBITS==32) THEN
00342       READ(IGLB,REC=IREC) IVALUE32R(:)
00343       ZVALUE(:)=IVALUE32R(:)
00344       IF (      ANY(ABS(ZVALUE)>0. .AND. ABS(ZVALUE)<1.E-50) &
00345            .OR. ANY(ABS(ZVALUE)>1.E20)                       ) THEN
00346         IF (GSWAP) CALL ABOR1_SFX('READ_DIRECT: SWAP ALREADY DONE, CANNOT BE REDONE')
00347         LITTLE_ENDIAN_ARCH = .NOT. LITTLE_ENDIAN_ARCH
00348         GSWAP = .TRUE.
00349         WRITE(ILUOUT,*) '*******************************************************************'
00350         WRITE(ILUOUT,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
00351                          LITTLE_ENDIAN_ARCH
00352         WRITE(ILUOUT,*) '*******************************************************************'
00353         JLAT = 0
00354         CALL REFRESH_PGDWORK
00355         EXIT
00356       END IF                      
00357     ELSE IF (YTYPE=='REAL   ' .AND. IBITS==64) THEN
00358       READ(IGLB,REC=IREC) ZVALUE64(:)
00359       ZVALUE(:)=ZVALUE64(:)
00360       IF (      ANY(ABS(ZVALUE)>0. .AND. ABS(ZVALUE)<1.E-50) &
00361              .OR. ANY(ABS(ZVALUE)>1.E20)                       ) THEN  
00362         IF (GSWAP) CALL ABOR1_SFX('READ_DIRECT_GAUSS: SWAP ALREADY DONE, CANNOT BE REDONE')
00363         LITTLE_ENDIAN_ARCH = .NOT. LITTLE_ENDIAN_ARCH
00364         GSWAP = .TRUE.
00365         WRITE(ILUOUT,*) '*******************************************************************'
00366         WRITE(ILUOUT,*) 'Architecture of the machine needs to swap LITTLE_ENDIAN_ARCH to ', &
00367                            LITTLE_ENDIAN_ARCH  
00368         WRITE(ILUOUT,*) '*******************************************************************'
00369         JLAT = 0
00370         CALL REFRESH_PGDWORK
00371         EXIT
00372       END IF
00373     ELSE
00374       CALL ABOR1_SFX('READ_DIRECT_GAUSS1: DATA TYPE NOT SUPPORTED')
00375     END IF
00376 !
00377     IF(HFIELD=='CTI')THEN
00378       WHERE(ZVALUE(:)<0.0)ZVALUE(:)=ZNODATA
00379     ENDIF
00380 !
00381     WHERE(ZVALUE(:)/=ZNODATA)ZVALUE(:)=ZVALUE(:)/ZFACT
00382 !
00383 !----------------------------------------------------------------------------
00384 !
00385 !*    4.     loop on mask meshes (lon)
00386 !            -------------------
00387 !
00388     DO JLON=1,720
00389 !
00390       ZLONMIN =  JLON     /2. - 0.5
00391       ZLONMAX =  JLON     /2.
00392 !
00393 !----------------------------------------------------------------------------
00394 !
00395 !*    5.     limits on longitude
00396 !            -------------------
00397 !
00398 !*    5.1    left domain border is set just higher than the global field min. longitude
00399 !            -----------------------------------------------------------------
00400 !
00401       ZSHIFT = 360. * NINT((ZLONMIN-ZGLBLONMIN-180.+1.E-10)/360.)
00402 
00403 !
00404       ZGLBLONMIN = ZGLBLONMIN + ZSHIFT
00405       ZGLBLONMAX = ZGLBLONMAX + ZSHIFT
00406 
00407 !
00408 !
00409 !*    5.2    index limits on longitude
00410 !            -------------------------
00411 !
00412       ICOL1(1)=MAX(MIN(INT((ZLONMIN-ZGLBLONMIN-ZDLON/2.)/ZDLON+1.),INBCOL),0)+1
00413       ICOL2(1)=MAX(MIN(INT((ZLONMAX-ZGLBLONMIN-ZDLON/2.)/ZDLON+1.),INBCOL),0)
00414 !
00415 !* Does right domain border goes outside the global field longitude range?
00416 !* Does it then goes into the global field domain by the other side?
00417 !* Then a second part of the global field domain must be considered
00418 !
00419       ICOL1(2)=1
00420       ICOL2(2)=MAX(MIN(INT((ZLONMAX-ZGLBLONMIN-ZDLON/2.-360.)/ZDLON+1.),INBCOL),0)      
00421 !
00422 !----------------------------------------------------------------------------
00423 !
00424 !*    6.     Loop on longitude limits
00425 !            ------------------------
00426 !
00427       DO JLOOP=1,2
00428 !
00429         ICOL = ICOL2(JLOOP) - ICOL1(JLOOP) + 1
00430 !
00431         IF (ICOL<1) CYCLE
00432 !
00433 !----------------------------------------------------------------------------
00434 !
00435 !*   11.     Loop on columns
00436 !            ---------------
00437 !
00438         DO JCOL=1,ICOL
00439 !
00440 !*   11.1    Recovers point value
00441 !            --------------------
00442 !
00443           ICOLINDEX = JCOL+ICOL1(JLOOP)-1
00444 
00445 !
00446 !*   11.2    Test with respect to the 'no data' value
00447 !            ----------------------------------------
00448 !
00449           IMASK = IMASK + 1
00450 !          
00451           IF (ABS(ZVALUE(ICOLINDEX)-ZNODATA)<=1.E-10) CYCLE
00452 !
00453           IMASK_GAUSS(IMASK) = 1          
00454 !
00455 !*   11.3    copy of the correct values in a work array
00456 !            ------------------------------------------
00457 !
00458           IWORK = IWORK + 1
00459 !          
00460           ZLAT_WORK  (IWORK) = ZLAT  (JLINE)
00461           ZLON_WORK  (IWORK) = ZLON  (ICOLINDEX)
00462           ZVALUE_WORK(IWORK) = ZVALUE(ICOLINDEX)
00463 ! 
00464         END DO
00465 !
00466 !-------------------------------------------------------------------------------
00467       END DO
00468 !-------------------------------------------------------------------------------
00469     END DO
00470 !-------------------------------------------------------------------------------
00471   END DO
00472 !-------------------------------------------------------------------------------
00473 END DO
00474 !
00475 !-------------------------------------------------------------------------------
00476 !
00477 
00478 DEALLOCATE(ZLAT)
00479 DEALLOCATE(ZLON)
00480 !
00481 DEALLOCATE (ZVALUE)
00482 DEALLOCATE (IVALUE8 )
00483 DEALLOCATE (IVALUE16)
00484 DEALLOCATE (IVALUE32)
00485 DEALLOCATE (IVALUE32R)
00486 DEALLOCATE (IVALUE64)
00487 DEALLOCATE (ZVALUE32)
00488 DEALLOCATE (ZVALUE64)
00489 !
00490  CALL CLOSE_FILE(HPROGRAM,IGLB)
00491 !
00492 !-------------------------------------------------------------------------------
00493 !
00494 !*   12.     Call to the adequate subroutine (point by point treatment)
00495 !            ----------------------------------------------------------
00496 !
00497 IF(IWORK>0)THEN
00498   CALL PT_BY_PT_TREATMENT(ILUOUT,ZLAT_WORK(1:IWORK),ZLON_WORK(1:IWORK),ZVALUE_WORK(1:IWORK),HSUBROUTINE)
00499 ENDIF
00500 !
00501 DEALLOCATE(ZLAT_WORK  )
00502 DEALLOCATE(ZLON_WORK  )
00503 DEALLOCATE(ZVALUE_WORK)
00504 DEALLOCATE(IMASK_GAUSS)
00505 IF (LHOOK) CALL DR_HOOK('READ_DIRECT_GAUSS',1,ZHOOK_HANDLE)
00506 !
00507 !-------------------------------------------------------------------------------
00508 !
00509 END SUBROUTINE READ_DIRECT_GAUSS