! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE RDNMCGRB2 ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## SUBROUTINE rdnmcgrb2(gribfile,grbflen, gribtime, & 1,6 gridesc, iproj_grb, gthin, & ni_grb,nj_grb,np_grb, nk_grb,zk_grb, npeq,nit, & pi_grb,pj_grb,ipole, di_grb,dj_grb, & latsw,lonsw, latne,lonne, & latrot,lonrot,angrot, & latstr,lonstr,facstr, & lattru1,lattru2,lontrue, & scanmode, iscan,jscan,kscan, & ires,iearth,icomp, & jpenta,kpenta,mpenta,ispect,icoeff, & xp_grb,yp_grb, xo_grb,yo_grb,zo_grb, & nxgrb,nygrb,nzgrb,var_lev3d,var_grb3d, & var_grb2d,ibms,rcdata, iret) !----------------------------------------------------------------------- ! ! PURPOSE: ! ! This subroutine is to read and select given variables with GRIB ! grid ID and level type from NMC GRIB files. ! ! The decoder of GRIB is from NMC, ftp:nic.fb4.noaa.gov/pub ! !----------------------------------------------------------------------- ! ! AUTHOR: Yuhe Liu ! 01/02/1996 Initialized. ! ! MODIFICATIONS: ! ! 09/24/1998 (Dennis A. Moon, Chief Scientist, SSESCO) ! Added sorting in vertical levels to assure that the level changes ! monotonically decreasing. ! ! November 1999 (Eric Kemp) ! Added several arguments to subroutine call. ! ! 9 January 2001 (Eric Kemp) ! Added proper Y2K bug fix conforming with ARPS 5.0. ! !----------------------------------------------------------------------- ! ! INPUT: ! ! gribfile GRIB file name ! grbflen Length of GRIB file name ! gribtime Time of GRIB data ! ! OUTPUT: ! ! iproj_grb Map projection number of GRIB data ! trlon_grb True longitude of GRIB data (degrees E) ! latnot_grb(2) True latitude(s) of GRIB data (degrees N) ! swlat_grb Latitude of first grid point at southwest conner ! swlon_grb Longitude of first grid point at southwest conner ! ! dx_grb x-direction grid length ! dy_grb y-direction grid length ! ! iret Return flag ! !----------------------------------------------------------------------- ! ! Variable Declarations. ! !----------------------------------------------------------------------- USE gribcst2 IMPLICIT NONE INTEGER :: nxgrb,nygrb,nzgrb INTEGER :: var_lev3d(nzgrb,n3dvs,n3dlvt) ! Levels (hybrid) for each 3-D variable REAL :: var_grb3d(nxgrb,nygrb,nzgrb,n3dvs,n3dlvt) ! GRIB 3-D variables REAL :: var_grb2d(nxgrb,nygrb,n2dvs,n2dlvt) ! GRIB variables LOGICAL :: ibms(nxgrb*nygrb) ! BMS logical array for data bit map REAL :: rcdata(nxgrb*nygrb) ! temporary data array INTEGER :: grbflen CHARACTER (LEN=80) :: gribfile CHARACTER (LEN=13) :: gribtime CHARACTER (LEN=1) :: opnmod !----------------------------------------------------------------------- ! ! GRIB grid information ! !----------------------------------------------------------------------- CHARACTER (LEN=42) :: gridesc ! Grid description INTEGER :: gdsflg ! GDS indicator INTEGER :: iproj_grb ! Map projection indicator INTEGER :: gthin ! Indicator of whether the grid is "thinned" INTEGER :: ni_grb ! Number of points along x-axis INTEGER :: nj_grb ! Number of points along y-axis INTEGER :: np_grb ! Total number of horizontal grid points INTEGER :: nk_grb ! Number of vertical parameters REAL :: zk_grb(nzgrb) ! Vertical coordinate parameters INTEGER :: npeq ! Number of lat circles from pole to equator INTEGER :: nit(nzgrb) ! Number of x-points for thinned grid REAL :: pi_grb ! x-coordinate of pole point REAL :: pj_grb ! y-coordinate of pole point INTEGER :: ipole ! Projection center flag REAL :: di_grb ! x-direction increment or grid length REAL :: dj_grb ! y-direction increment or grid length REAL :: latsw ! Latitude of South West corner point REAL :: lonsw ! Longitude of South West corner point REAL :: latne ! Latitude of North East corner point REAL :: lonne ! Longitude of North East corner point REAL :: lattru1 ! Latitude (1st) at which projection is true REAL :: lattru2 ! Latitude (2nd) at which projection is true REAL :: lontrue ! Longitude at which projection is true REAL :: latrot ! Latitude of southern pole of rotation REAL :: lonrot ! Longitude of southern pole of rotation REAL :: angrot ! Angle of rotation REAL :: latstr ! Latitude of the pole of stretching REAL :: lonstr ! Longitude of the pole of stretching REAL :: facstr ! Stretching factor INTEGER :: scanmode ! Scanning indicator INTEGER :: iscan ! x-direction scanning indicator INTEGER :: jscan ! y-direction scanning indicator INTEGER :: kscan ! FORTRAN index scanning indicator INTEGER :: ires ! Resolution direction increments indicator INTEGER :: iearth ! Earth shape indicator: spherical or oblate? INTEGER :: icomp ! (u,v) components decomposition indicator INTEGER :: jpenta ! J-Pentagonal resolution parameter INTEGER :: kpenta ! K-Pentagonal resolution parameter INTEGER :: mpenta ! M-Pentagonal resolution parameter INTEGER :: ispect ! Spectral representation type INTEGER :: icoeff ! Spectral coefficient storage mode REAL :: xp_grb ! X coordinate of sub-satellite point REAL :: yp_grb ! Y coordinate of sub-satellite point REAL :: xo_grb ! X coordinate of image sector origin REAL :: yo_grb ! Y coordinate of image sector origin REAL :: zo_grb ! Camera altitude from center of Earth INTEGER :: iret ! Return flag !----------------------------------------------------------------------- ! ! Temporary arrays to read GRIB file ! !----------------------------------------------------------------------- INTEGER :: nrecs ! number of records INTEGER :: fsize ! Size of GRIB file INTEGER :: grbunit ! I/O unit of GRIB file !----------------------------------------------------------------------- ! ! Misc internal variables ! !----------------------------------------------------------------------- INTEGER :: i,j,k,l,m,n, ij, ki, kj, ilev INTEGER :: iyr,imo,iday,ihr,fhr, myr INTEGER :: ileft, iright, iincr INTEGER :: jleft, jright, jincr INTEGER :: chklev, mlvtp INTEGER :: iendn,itypec,wdlen, nwrd LOGICAL :: grdflg ! flag for grid information LOGICAL :: fexist !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! !----------------------------------------------------------------------- ! ! Find the type of endian, type of character set and length of ! machine word ! ! iendn - Integer for big-endian or little-endian ! = 0 big-endian ! = 1 little-endian ! = 2 cannot compute ! itypec - Integer for type of character set ! = 0 ascii character set ! = 1 ebcdic character set ! = 2 not ascii or ebcdic ! wdlen - Integer for words size of computer in bytes ! = 4 for 32 bit (4 bytes) computers ! = 8 for 64 bit (8 bytes) computers ! !----------------------------------------------------------------------- CALL w3fi04(iendn,itypec,wdlen) IF ( iendn == 2 ) THEN WRITE(6,'(a)') 'Unknown endian type. Stopped in rdnmcgrb2' STOP END IF IF ( itypec == 2 ) THEN WRITE(6,'(a)') 'Unknown character set. Stopped in rdnmcgrb2' STOP END IF !----------------------------------------------------------------------- ! ! initialize the var_lev3d array so we can sort the records by ! level values as we read them. We can't assume monotonic ordering ! of the levels ! !----------------------------------------------------------------------- DO k=1, nzgrb DO n=1, n3dvs DO m=1, n3dlvt var_lev3d(k,n,m)= -999999 END DO END DO END DO !----------------------------------------------------------------------- ! ! Open the GRIB file ! !----------------------------------------------------------------------- READ (gribtime,'(i4,3i2,1x,i2)') iyr,imo,iday,ihr,fhr ! myr = iyr - 1900 !arpscntl Y2K RLC per GMB/Donghai ! myr = MOD( iyr, 100 ) !EMK...Proper Y2K bug fix found in ARPS 5.0 package myr = MOD( iyr, 100 ) IF (myr == 0) THEN myr = 100 END IF INQUIRE(FILE=gribfile(1:grbflen), EXIST = fexist ) IF ( .NOT.fexist ) THEN WRITE(6,'(a)') 'GRIB file '//gribfile(1:grbflen)// & ' not found. Program stopped in RDNMCGRB2.' STOP END IF PRINT *, ' Opening GRIB file, gribfile= ',gribfile opnmod = 'r' CALL gopen ( grbunit, gribfile, grbflen, opnmod, iret ) IF ( iret /= 0 ) THEN WRITE(6,'(a,a,/,a,i4)') & 'Error in opening file ',gribfile, & 'C function gopen return status: ',iret RETURN END IF !----------------------------------------------------------------------- ! ! Get the size of the GRIB file ! !----------------------------------------------------------------------- fsize = 0 CALL gseek( grbunit, fsize, 2, iret ) WRITE (6,'(a,i16,a)') 'The size of GRIB file is ',fsize,' bytes' !----------------------------------------------------------------------- ! ! Scan the GRIB file to count records ! !----------------------------------------------------------------------- nrecs = 0 CALL grbscan( grbunit, fsize, nprods, rcstart, rcbytes, nrecs ) IF ( nrecs > nprods ) THEN WRITE (6,'(a/a,i6,a,i6/a/a)') & 'The actual number of products exceeded the expected number.', & 'Number of assumed products: ', nprods, & 'Number of actual products: ', nrecs, & 'Program stopped in RDNMCGRB2. Please change NPRODS in ', & 'file gribcst.inc and re-run the program.' CALL gclose( grbunit, iret ) STOP ELSE IF ( nrecs <= 0 ) THEN WRITE (6,'(a,a,a)') & 'No GRIB message found in file ',gribfile, & 'Program stopped in RDNMCGRB2.' CALL gclose( grbunit, iret ) STOP END IF !----------------------------------------------------------------------- ! ! Read the GRIB file and fill in the variable arrays ! !----------------------------------------------------------------------- DO n=1,n2dvars DO m=1,n2dlvtps var_nr2d(n,m) = 0 END DO END DO DO m=1,n3dlvtps DO n=1,n3dvars var_nr3d(n,m) = 0 END DO END DO grdflg = .false. WRITE(6,*)'Unpacking ',nrecs,' records...' DO l=1,nrecs DO i=1,ipdsz ipds(i) = 0 END DO DO i=1,igdsz igds(i) = 0 END DO CALL gseek( grbunit, rcstart(l), 0, iret ) CALL gread( grbunit, mgrib, rcbytes(l), iret ) IF ( iendn == 1 ) THEN ! little endian machine nwrd = (rcbytes(l)+3)/4 CALL swap4byte( mgrib, nwrd ) END IF CALL w3fi63( mgrib, ipds, igds, ibms, rcdata, mptrs, iret ) IF ( ipds(3) /= gridtyp ) THEN ! write (6,'(a,i6,a/a,i6,a,i6)') 'Grid id of record, ',L, ! : 'was inconsistant with expected,', ! : 'ipds(3)=',ipds(3), ' gridtyp=',gridtyp CYCLE END IF DO m=1,n3dlvtps IF ( ipds(6) == levtyp3d(m) ) THEN chklev = 1 mlvtp = m GO TO 30 ELSE chklev = 0 END IF END DO DO m=1,n2dlvtps IF ( ipds(6) == levtyp2d(m) ) THEN chklev = 2 mlvtp = m EXIT ELSE chklev = 0 END IF END DO 30 CONTINUE IF ( chklev == 0 ) THEN ! write (6,'(a,i4,a/a,i4)') ! : 'Type of level of record, ',L, ! : ' was inconsistant with expected,', ! : ' ipds(6) =',ipds(6) CYCLE END IF IF ( ipds(8) /= myr .OR.ipds(9) /= imo.OR. & ipds(10) /= iday.OR.ipds(11) /= ihr.OR. & ipds(14) /= fhr ) THEN !arpscntl RLC format WRITE (6,'(a,i6,a/a,I3.2,3i2.2,i2.2/2a)') & 'Time of record, ',l, 'was inconsistant with expected,', & ' pds time = ',(ipds(j),j=8,11),ipds(14), & ' gribtime = ', TRIM(gribtime) WRITE (6,'(A,I3.2,3i2.2,i2.2)') "Gribtime: ", myr, imo, iday, ihr, fhr CYCLE END IF gdsflg = IAND(ipds(4),128)/128 IF ( .NOT. grdflg ) THEN CALL grbgrid(gridtyp, gdsflg, igds, & gridesc, iproj_grb, gthin, & ni_grb,nj_grb,np_grb, nk_grb,zk_grb, npeq,nit, & pi_grb,pj_grb,ipole, di_grb,dj_grb, & latsw,lonsw, latne,lonne, & latrot,lonrot,angrot, & latstr,lonstr,facstr, & lattru1,lattru2,lontrue, & scanmode, iscan,jscan,kscan, & ires,iearth,icomp, & jpenta,kpenta,mpenta,ispect,icoeff, & xp_grb,yp_grb, xo_grb,yo_grb,zo_grb) WRITE (6,'(a)') gridesc grdflg = .true. END IF IF ( igds(1) /= mproj_grb ) THEN ! write (6,'(a,i3)') ! : 'Map projection was not consistant, igds(1) = ', igds(1) CYCLE END IF IF ( igds(2) /= nxgrb .OR. igds(3) /= nygrb ) THEN WRITE (6,'(a/a,i4,2x,a,i4/a,i4,2x,a,i4/a)') & 'Horizontal dimension was not consistant,', & ' igds(2) = ', igds(2), ' igds(3) = ', igds(3), & ' nxgrb = ', nxgrb , ' nygrb = ', nygrb, & 'Program stopped in RDNMCGRB2.' STOP END IF IF ( iscan == 0 ) THEN ileft = 1 iright = nxgrb iincr = 1 ELSE ileft = nxgrb iright = 1 iincr = -1 END IF IF ( jscan /= 0 ) THEN jleft = 1 jright = nygrb jincr = 1 ELSE jleft = nygrb jright = 1 jincr = -1 END IF IF ( kscan == 0 ) THEN ki = 1 kj = nxgrb ELSE IF ( kscan == 1 ) THEN ki = nygrb kj = 1 ELSE ! write (6,'(a,i3,a,i6)') ! : 'Unknown scanning mode, kScan = ', kScan CYCLE END IF IF ( chklev == 1 ) THEN ! 3-D variable DO n=1,n3dvars DO m=1,n3dlvtps IF ( ipds(5) == var_id3d(n,m) ) THEN var_nr3d(n,m) = var_nr3d(n,m) + 1 !----------------------------------------------------------------------- ! ! Insert the level and data values into the var_lev3d and var_grb3d ! arrays in order of decreasing level value, ! ! For example if the level type is pressure levels the levels ! will be sorted in order of decreasing pressure ! ! ilev is the level at which to insert the current data ! !----------------------------------------------------------------------- ilev= 0 DO k=1,nzgrb IF ( ipds(7) > var_lev3d(k,n,m) ) THEN ilev = k EXIT END IF END DO 120 CONTINUE IF ( ilev == 0 ) THEN PRINT*,'couldnt locate level ',ipds(7) PRINT*,'for var ID#',var_id3d(n,m) STOP END IF ! slide all the following levels down one to make room DO k=nzgrb, ilev+1, -1 var_lev3d(k,n,m)= var_lev3d(k-1,n,m) DO j=jleft,jright,jincr DO i=ileft,iright,iincr ij = ki*iincr*(i-ileft) + kj*jincr*(j-jleft) + 1 var_grb3d(i,j,k,n,m)= var_grb3d(i,j,k-1,n,m) END DO END DO END DO ! now insert the data at the appropriate level var_lev3d(ilev,n,m) = ipds(7) DO j=jleft,jright,jincr DO i=ileft,iright,iincr ij = ki*iincr*(i-ileft) + kj*jincr*(j-jleft) + 1 var_grb3d(i,j,ilev,n,m) = rcdata(ij) END DO END DO END IF END DO END DO ELSE IF ( chklev == 2 ) THEN ! 2-D variable DO n=1,n2dvars DO m=1,n2dlvtps IF ( ipds(5) == var_id2d(n,m) ) THEN var_nr2d(n,m) = var_nr2d(n,m) + 1 DO i=ileft,iright,iincr DO j=jleft,jright,jincr ij = ki*iincr*(i-ileft) + kj*jincr*(j-jleft) + 1 var_grb2d(i,j,n,m) = rcdata(ij) END DO END DO END IF END DO END DO END IF END DO !----------------------------------------------------------------------- ! ! Set good status ! !----------------------------------------------------------------------- iret = 0 CALL gclose( grbunit, iret ) RETURN END SUBROUTINE rdnmcgrb2