PROGRAM hdf2grads ! !################################################################## !################################################################## !###### ###### !###### PROGRAM HDF2GRADS ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Program to read history data dump from ARPS HDF 4 format and ! clean-up the dimensions inside the file and create a control file ! for GrADS. ! !----------------------------------------------------------------------- ! ! AUTHOR: Yunheng Wang ! 11/3/2003 ! ! MODIFICATION HISTORY: ! !----------------------------------------------------------------------- ! ! Variable Declarations: ! !----------------------------------------------------------------------- ! IMPLICIT NONE INTEGER :: nx,ny,nz,nzsoil ! Grid dimensions. INTEGER :: nstyps ! Maximum number of soil types. CHARACTER(LEN=5), PARAMETER :: dim_name(5) = & (/ 'x_dim','y_dim','z_dim','s_dim','n_dim' /) CHARACTER(LEN=3), PARAMETER :: mon_name(12) = & (/ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', & 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' /) INTEGER :: year, month, day, hour, minute, second REAL :: time ! INTEGER, PARAMETER :: nhisfile_max=200 ! CHARACTER (LEN=132) :: grdbasfn,hisfile(nhisfile_max) ! INTEGER :: hinfmt,nhisfile ! INTEGER :: lengbf,lenfil ! CHARACTER(LEN=80) :: dirname ! NAMELIST /output/ dirname CHARACTER(LEN=132) :: infilename, outfilename !----------------------------------------------------------------------- ! ! Misc. Local variables ! !----------------------------------------------------------------------- INTEGER :: nf, sindex, aindex INTEGER :: sd_id, sds_id, dim_id INTEGER :: nsds, nattr ! File attributes INTEGER :: srank, stype, snattr ! SD set attributes INTEGER :: sdim_size(4) CHARACTER(LEN=20) :: sname CHARACTER(LEN=20) :: aname INTEGER :: atype,clen,ulen CHARACTER(LEN=80) :: comments,units INTEGER :: ireturn INTEGER :: n, nvar, nlevel LOGICAL :: fexist = .TRUE. INTEGER :: funit, snamelen CHARACTER(LEN=80) :: vartag(200), timestr CHARACTER(LEN=20) :: fmtstr ! !----------------------------------------------------------------------- ! ! Include files: ! !----------------------------------------------------------------------- ! INCLUDE 'hdf.f90' INTEGER :: sfstart, sfend INTEGER :: sffinfo, sfginfo INTEGER :: sfselect, sfendacc INTEGER :: sfdimid, sfsdmname INTEGER :: sffattr, sfgainfo, sfrcatt, sfrnatt ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! WRITE(6,'(/9(/5x,a)/)') & ! '###############################################################', & ! '###############################################################', & ! '### ###', & ! '### Welcome to HDF2GRADS ###', & ! '### This program converts the history dump data ###', & ! '### sets generated by ARPS, between various formats. ###', & ! '### ###', & ! '###############################################################', & ! '###############################################################' ! !----------------------------------------------------------------------- ! ! Get the names of the input data files. ! !----------------------------------------------------------------------- ! ! CALL get_input_file_names(hinfmt,grdbasfn,hisfile,nhisfile) WRITE(6,ADVANCE='NO',FMT='(a)') ' Enter HDF file name: ' READ(5,*) infilename INQUIRE(FILE=trim(infilename), EXIST = fexist ) IF( .NOT. fexist ) THEN WRITE(6,*) 'ERROR: File "',TRIM(infilename),'" does not exist.' STOP END IF !----------------------------------------------------------------------- ! ! Set the control parameters for output: ! !----------------------------------------------------------------------- ! ! READ (5,output) !----------------------------------------------------------------------- ! ! Get dimensions from grid and base file ! !----------------------------------------------------------------------- ! lengbf = len_trim(grdbasfn) ! CALL get_dims_from_data(hinfmt,grdbasfn(1:lengbf), & ! nx,ny,nz,nzsoil,nstyps, ireturn) !----------------------------------------------------------------------- ! ! Beginning to process HDF files ! !----------------------------------------------------------------------- nf = 1 ! DO nf = 1,nhisfile ! loop over each file sd_id = sfstart(infilename,DFACC_WRITE) IF (sd_id <= 0) THEN WRITE (6,*) 'ERROR: cannot open file "',TRIM(infilename),'"' STOP ENDIF ! ! get dimension information ! aindex = sffattr(sd_id, 'nx') ireturn = sfrnatt(sd_id, aindex, nx) aindex = sffattr(sd_id, 'ny') ireturn = sfrnatt(sd_id, aindex, ny) aindex = sffattr(sd_id, 'nz') ireturn = sfrnatt(sd_id, aindex, nz) aindex = sffattr(sd_id, 'nzsoil') ireturn = sfrnatt(sd_id, aindex, nzsoil) aindex = sffattr(sd_id, 'nstyp') ireturn = sfrnatt(sd_id, aindex, nstyps) WRITE(6,'(/a,3(a,I3),2(a,I3))') & ' Dimensions read in from data are:', & ' nx =',nx,', ny =', ny,', nz =',nz, & ' nzsoil =',nzsoil,', nstyps =',nstyps aindex = sffattr(sd_id, 'year') ireturn = sfrnatt(sd_id, aindex, year) aindex = sffattr(sd_id, 'month') ireturn = sfrnatt(sd_id, aindex, month) aindex = sffattr(sd_id, 'day') ireturn = sfrnatt(sd_id, aindex, day) aindex = sffattr(sd_id, 'hour') ireturn = sfrnatt(sd_id, aindex, hour) aindex = sffattr(sd_id, 'minute') ireturn = sfrnatt(sd_id, aindex, minute) aindex = sffattr(sd_id, 'second') ireturn = sfrnatt(sd_id, aindex, second) aindex = sffattr(sd_id, 'time') ireturn = sfrnatt(sd_id, aindex, time) ! WRITE(timestr,'(a,I2.2,a1,I2.2,a1,a3,I4.4,F2.0,a2)') & ! '1 LINEAR ',hour,':',minute,'Z', & ! mon_name(month),year,time,'HR' WRITE(6,'(a,I4.4,a,I2.2,a,I2.2,a,I2.2,a,I2.2,a,I2.2,a,I5.5,a)') & ' Data valid at ', & year,'-',month,'-',day,'_', & hour,':',minute,':',second,'+',INT(time),' seconds.' ireturn = sffinfo(sd_id,nsds,nattr) nvar = 0 DO sindex = 1,nsds ! loop over each dataset in the file sds_id = sfselect(sd_id,sindex-1) ireturn = sfginfo (sds_id,sname,srank,sdim_size,stype,snattr) !WRITE(6,*) ' ', sname, ' Changed' ! ! 1st dimension ! dim_id = sfdimid(sds_id,0) IF(sdim_size(1) == nx) ireturn = sfsdmname(dim_id,dim_name(1)) ! ! 2nd dimension ! dim_id = sfdimid(sds_id,1) IF(sdim_size(2) == ny) ireturn = sfsdmname(dim_id,dim_name(2)) ! ! 3rd dimension ! dim_id = sfdimid(sds_id,2) IF(sdim_size(3) == nz) THEN ireturn = sfsdmname(dim_id,dim_name(3)) ELSE IF(sdim_size(3) == nzsoil) THEN ireturn = sfsdmname(dim_id,dim_name(4)) ELSE IF(sdim_size(3) == nstyps) THEN ireturn = sfsdmname(dim_id,dim_name(5)) END IF ! ! 4th dimension ! dim_id = sfdimid(sds_id,3) IF(sdim_size(4) == nstyps) THEN ireturn = sfsdmname(dim_id,dim_name(5)) END IF ! ! Prepare variable tag for GrADS control file ! aindex = sffattr(sds_id,'comment') ireturn = sfgainfo(sds_id,aindex,aname,atype,clen) ireturn = sfrcatt(sds_id,aindex,comments) aindex = sffattr(sds_id,'units') ireturn = sfgainfo(sds_id,aindex,aname,atype,ulen) ireturn = sfrcatt(sds_id,aindex,units) snamelen = LEN_TRIM(sname) snamelen = 2*snamelen + 2 WRITE(fmtstr,'(a,I2,a)') '(3a,',22-snamelen,'x,I4,5a)' IF(srank == 2) THEN nlevel = 0 IF(sdim_size(1) == nx .AND. sdim_size(2) == ny) THEN nvar = nvar + 1 WRITE(vartag(nvar),FMT=fmtstr) TRIM(sname),'=>', & TRIM(sname),nlevel,' 99 ', & comments(1:clen),' (',units(1:ulen),')' END IF ELSE IF(srank == 3) THEN nlevel = sdim_size(3) IF(sdim_size(1) == nx .AND. sdim_size(2) == ny .AND. & sdim_size(3) == nz) THEN nvar = nvar + 1 WRITE(vartag(nvar),FMT=fmtstr) TRIM(sname),'=>', & TRIM(sname),nlevel,' 99 ', & comments(1:clen),' (',units(1:ulen),')' END IF ELSE IF(srank == 4) THEN END IF ireturn = sfendacc(sds_id) END DO ireturn = sfend(sd_id) ! ! Write a GrADS control file ! WRITE(outfilename,'(a,a)') TRIM(infilename),'.ctl' WRITE(6,'(/a,a)') ' Output GrADS control file is: ',TRIM(outfilename) funit = 30 + nf OPEN(funit, FILE=TRIM(outfilename), FORM='FORMATTED', & IOSTAT = ireturn, STATUS = 'UNKNOWN') IF (ireturn /= 0) THEN WRITE(6,'(1x,3a,I)') 'ERROR: Cannot create file: ', & TRIM(outfilename),' IOSTAT = ',ireturn STOP END IF WRITE(funit,'(a)') & '*', & '* Template of GrADS control file for ARPS HDF format history dumps', & '*', & '* Usage:', & '*', & '* 1. Use gradshdf instead of grads', & '* 2. ga-> xdfopen this_control_file', & '* 3. ga-> set mproj off', & '* Then works as usual GrADS data files', & '* 4. Change this control file', & '* 4.1 Specify dataset: DSET HDF_file_name', & '* 4.2 Add a variable: VARS current_value + 1', & '* var_name=>SDS_name Vertical_level 99 comments', & '* 4.3 Remove a variable: VARS current_value - 1', & '* remove the variable line', & '* 5. A perl script in scripts/ directory is recommended.', & '* 5.1 cd ARPS root directory', & '* 5.2 source scripts/link_data', & '* 5.3 cd your working directory', & '* 5.3 useg -hdf this_control_file', & '*', & '* Limitations:', & '* ', & '* 1. Does not work with 16bit mapped HDF data', & '* 2. No map projection, "set mproj off" before start to display any data', & '* 3. Only works with 2D & 3D atmospheric variables', & '*', & '* Note:', & '* If expects more accurant plots of ARPS data, please use "ARPSCVT" to', & '* convert HDF files to GrADS binary format.', & '*', & '*' WRITE(funit,'(a,a)') 'DSET ', TRIM(infilename) WRITE(funit,'(a)' ) 'TITLE GrADS control file for ARPS HDF format dumps' WRITE(funit,'(a,a,I4,a)') 'XDEF ',dim_name(1), nx,' linear 1 1' WRITE(funit,'(a,a,I4,a)') 'YDEF ',dim_name(2), ny,' linear 1 1' WRITE(funit,'(a,a,I4,a)') 'ZDEF ',dim_name(3), nz,' linear 1 1' ! WRITE(funit,'(a,a)') 'TDEF ',TRIM(timestr) WRITE(funit,'(/a,I4)' ) 'VARS ',nvar DO n = 1, nvar WRITE(funit,'(a)') TRIM(vartag(n)) END DO WRITE(funit,'(a)') 'ENDVARS' CLOSE(funit) ! END DO WRITE(6,*) WRITE(6,'(a)') ' Recommended command sequence to show GrADS plots:',& ' - go to ARPS root directory', & ' - "source scripts/link_data"', & ' - come back to current data directory' WRITE(6,'(a,a,a/)') ' - "useg -hdf ',TRIM(outfilename),'"' WRITE(6,*) ' ==== HDF2GRADS terminated normally ====' END PROGRAM hdf2grads