PROGRAM arpstrn,18 ! ! !----------------------------------------------------------------------- ! ! Program for creating a terrain file for ARPS from ! USGS 3 arc second data base (covers continetal US and Alaska) ! or 5min global data base from NCAR. ! ! Author: Ming Xue, CAPS. University of Oklahma. ! ! First written: 11/25/1995. ! Last Modified: 12/05/1995. ! ! 11/1/1998 (Ming Xue). ! Significantly rewritten to also handle 5min global data. ! ! The code for accessing USGS FTP server and reading the DEM data ! patches were written by Burt Freeman and P. Patnaik of S-Cubed. ! ! We assume you have ZXPLOT Version 3.0 or later installed. ! Otherwise, link nozxplot.f. ! ! 2001/06/18 (Gene Bassett) ! Cleaned up namelist input of grid and map projections parameters. ! !----------------------------------------------------------------------- ! ! ! INSTRUCTIONS: ! ! A number functions are controled by Makfile. ! ! To compile, do 'make arpstrn' in ARPS root directory. ! ! You can also do the compilation and linking directly in this ! directory, making use of pre-built arps library: ! ! zxpostf90 -I../../include -o arpstrn arpstrn.f -L../../lib -larps ! ! Here we assumed libarps.a has been produced by 'makearps arps'. ! We also assume you have ZXPLOT Version 3.0 or later installed. ! If not, do ! ! f90 -I../../include -o arpstrn arpstrn.f nozxplot.f -L../../lib -larps ! ! then no plot of the analyzed terrain field will be produced. ! ! To execute, do 'arpstrn < arpstrn.input >! arpstrn.output' ! ! When you use the 3 arc second data, a temporary directory ! whose name is specified for dir_trndata in the input file ! will be used to store the original data. The required ! data will be downloaded from anonymous ftp server ! edcftp.cr.usgs.gov unless you already have them in that directory. ! ! To allow automatic login, you need to add ! ! machine edcftp.cr.usgs.gov login anonymous password your_address ! ! in your $HOME/.netrc file. Make .netrc readable to the owner only ! i.e., do 'chmod 600 .netrc'. ! ! To produce a tar file of the entire package, do 'make arpstrn.tar'. ! !----------------------------------------------------------------------- ! ! Variable Declarations. ! !----------------------------------------------------------------------- IMPLICIT NONE INCLUDE 'globcst.inc' INCLUDE 'grid.inc' INTEGER :: nx, ny REAL, allocatable :: x(:) ! The x-coord. of the u grid point (m) REAL, allocatable :: y(:) ! The y-coord. of the v grid point (m) REAL, allocatable :: xh(:,:) ! X-coord. of the terrain (scalar) point. REAL, allocatable :: yh(:,:) ! Y-coord. of the terrain (scalar) point. REAL, allocatable :: xh1d(:) REAL, allocatable :: yh1d(:) REAL, allocatable :: lath(:,:) ! Latitude of each terrain point REAL, allocatable :: lonh(:,:) ! Longitude of each terrain point REAL, allocatable :: hterain(:,:) ! The height of the terrain. REAL, allocatable :: tem (:,:) REAL, allocatable :: tem2 (:,:) REAL, allocatable :: xw (:) REAL, allocatable :: yw (:) INTEGER :: nx_trn,ny_trn REAL, allocatable :: h_trn(:,:) NAMELIST /grid_dims/ nx,ny NAMELIST /jobname/ runname NAMELIST /grid/ dx,dy,ctrlat,ctrlon NAMELIST /projection/ mapproj,trulat1,trulat2,trulon,sclfct INTEGER :: trnanxopt ! Terrain analysis scheme option INTEGER :: trndataopt ! Terrain data set option INTEGER :: nsmth ! Number of times 9-point smoother is applied ! to the terrain field CHARACTER (LEN=120) :: usgs_dem_index_fn CHARACTER (LEN=80) :: fn_trndata CHARACTER (LEN=120) :: dir_trndata REAL :: hctrinc INTEGER :: lat_sample,lon_sample ! Data sampling frequency in seconds REAL :: latd_sample,lond_sample ! Data sampling frequency in degrees NAMELIST /dem_trn/ trnanxopt,trndataopt,nsmth, & lat_sample,lon_sample,dir_trndata,fn_trndata, & usgs_dem_index_fn,hctrinc INTEGER :: ldir_trndata,lfn REAL :: latgrid,longrid INTEGER :: maxmap PARAMETER(maxmap=10) CHARACTER (LEN=132) :: mapfile(maxmap) INTEGER :: lmapfile,nmapfile NAMELIST /map_plot/latgrid,longrid,nmapfile,mapfile COMMON /mappar2/ latgrid,longrid NAMELIST /trn_output/ terndmp INTEGER :: trndatares ! Terrain data resolution in seconds ! !----------------------------------------------------------------------- ! ! LOCAL VARIABLES: ! !----------------------------------------------------------------------- ! REAL :: trulat (2) ! Latitude at which the map projection ! is true (degees N) REAL :: swx,swy,ctrx,ctry ! Temporary variables. REAL :: latmax,latmin,lonmax,lonmin ! max/min lat/lon of the projected grid INTEGER :: swlat_trn,swlon_trn,nelat_trn,nelon_trn ! SW and NE coner lat/lon of the ! the assembled terrain patch. INTEGER :: i,j,ih,jh REAL :: lath1,lonh1,w1,w2,w3,w4,a,b,c,d,h1,h2,h3 REAL :: badvalue REAL :: hmax,hmin,swlat_offset,swlon_offset INTEGER :: inith_set, badvfound LOGICAL :: fexist INTEGER :: imin,imax,jmin,jmax,kmin,kmax, istatus ! !----------------------------------------------------------------------- ! ! TEMPORARY ARRAYS: ! !----------------------------------------------------------------------- ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! !----------------------------------------------------------------------- ! ! Set up the default values for all the variables to be read in ! using the namelist method. In case the user does not specify a ! particular value, this value will be used. ! !----------------------------------------------------------------------- ! nx = 67 ny = 67 runname = 'may20' dx = 1000.0 dy = 1000.0 ctrlat = 35.0 ctrlon = -100.0 mapproj = 0 trulat1 = 30.0 trulat2 = 60.0 trulon = -100.0 sclfct = 1.0 trnanxopt = 1 trndataopt = 4 fn_trndata = 'tbase_global_5min.data' dir_trndata= '/work/official/arpstern.data/' usgs_dem_index_fn = '../src/arpstrn/usgs_dem.index' nsmth = 1 lat_sample = 30 lon_sample = 30 hctrinc = 250.0 latgrid = 10. longrid = 10. nmapfile = 1 mapfile(1) = '/home/mxue/zxplot3/data/us_state.mapdata' mapfile(2) = '/home/mxue/zxplot3/data/world_us_country.mapdata' terndmp = 1 ! !----------------------------------------------------------------------- ! ! Read and Print of Namelist variables and parameters. ! !----------------------------------------------------------------------- ! READ(5,grid_dims,ERR=980,END=990) allocate( allocate( allocate(xh(nx,ny)) allocate(yh(nx,ny)) allocate(xh1d(0:nx)) allocate(yh1d(0:ny)) allocate(lath(0:nx,0:ny)) allocate(lonh(0:nx,0:ny)) allocate(hterain(nx,ny)) allocate(tem (nx,ny)) allocate(tem2 (nx,ny)) allocate(xw (8*nx)) allocate(yw (8*nx)) ! ! Default value of -9999.0 for the flag is used. ! READ (5,jobname,ERR=980,END=990) WRITE(6,'(/a,a)') 'The name of this run is: ', runname CALL gtlfnkey( runname, lfnkey ) READ(5,grid,ERR=980,END=990) WRITE(6,'(/a,f10.3,a)')'Input dx was ',dx,' meters' WRITE(6,'(/a,f10.3,a)')'Input dy was ',dy,' meters' READ(5,projection,ERR=980,END=990) WRITE(6,'(/a,i4)') 'Input mapproj was ',mapproj WRITE(6,'(/a,f10.3,a)') & 'Input trulat1 was ',trulat1,' degree North' WRITE(6,'(/a,f10.3,a)') & 'Input trulat2 was ',trulat2,' degree North' WRITE(6,'(/a,f10.3)') & 'The latitude of the center of the model domain was ',ctrlat WRITE(6,'(/a,f10.3)') & 'The longitude of the center of the model domain was ',ctrlon WRITE(6,'(/a,f10.3,a)') & 'Input trulon was ',trulon,' degree East' WRITE(6,'(/a,e15.5)') & 'Input sclfct was ',sclfct IF ( mapproj == 0 ) THEN trulat1 = ctrlat trulat2 = ctrlat trulon = ctrlon END IF trnanxopt = 1 trndataopt= 2 nsmth = 0 fn_trndata = 'tbase_global_5min.data' usgs_dem_index_fn = 'usgs_dem.index' READ(5,dem_trn,ERR=980,END=990) IF( trndataopt == 1) THEN trndatares = 3600 lon_sample = max(3600,lon_sample) lat_sample = max(3600,lat_sample) ELSE IF( trndataopt == 2) THEN trndatares = 300 lon_sample = max(300,lon_sample) lat_sample = max(300,lat_sample) ELSE IF( trndataopt == 3) THEN trndatares = 30 lon_sample = max(30,lon_sample) lat_sample = max(30,lat_sample) ELSE IF( trndataopt == 4) THEN trndatares = 3 lon_sample = max(3,lon_sample) lat_sample = max(3,lat_sample) END IF WRITE(6,'(/a,i5,a)') & 'The sample internal in longitude dir. was set to ',lon_sample, & ' seconds.' WRITE(6,'(/a,i5,a)') & 'The sample internal in latitude dir. was set to ',lat_sample, & ' seconds.' IF(MOD(lat_sample,trndatares) /= 0 .OR. MOD(lon_sample,trndatares) /= 0) THEN lon_sample = MAX(1,lon_sample/trndatares) * trndatares lat_sample = MAX(1,lat_sample/trndatares) * trndatares WRITE(6,'(/a,i4,a,/a,i6,a,i6/))') & 'lat_sample and lon_sample have to be divisible by ', & trndatares,'.', & 'They were reset to lon_sample=',lon_sample, & ' lat_sample=',lat_sample END IF IF(MOD(3600,lat_sample) /= 0 .OR. MOD(3600,lon_sample) /= 0) THEN WRITE(6,'(/a,/a/))') & '3600 has to be divisible by both lat_sample and lon_sample.', & 'Please reset them in the input file. Job stopped.' STOP END IF latgrid = 0.0 longrid = 0.0 READ(5,map_plot) READ(5,trn_output) WRITE(6,'(/a,i4)') & 'Terrain dumping option set to ',terndmp WRITE(6,'(/a/)')'Finished reading namelist input file.' ldir_trndata = 120 CALL strlnth( dir_trndata, ldir_trndata) IF( dir_trndata(ldir_trndata:ldir_trndata) /= '/') THEN ldir_trndata=ldir_trndata+1 dir_trndata(ldir_trndata:ldir_trndata)='/' END IF ! !----------------------------------------------------------------------- ! ! setting ctrlon in terms of degrees east ! !----------------------------------------------------------------------- ! ! IF(ctrlon.lt.0)THEN ! ctrlon=360+ctrlon ! END IF ! !----------------------------------------------------------------------- ! ! test to see if reset value is within longitudinal limits.. ! !----------------------------------------------------------------------- ! ! IF(ctrlon.lt.0.or.ctrlon.gt.360)THEN ! print *,'ctrlon is incorrectly set in terrain.input, please ! : reset, use degrees east' ! STOP ! END IF ! !----------------------------------------------------------------------- ! ! test to see if the ctrlat is within limits... ! !----------------------------------------------------------------------- ! IF(ctrlat < 0.OR.ctrlat > 90)THEN PRINT *,'ctrlat in terrain.input is too large or too small. ', & 'must be set between 0. AND +90. degree north.' STOP END IF ! !----------------------------------------------------------------------- ! ! setting trulon in terms of degrees east ! !----------------------------------------------------------------------- ! ! IF(trulon.lt.0)THEN ! trulon=360+trulon ! END IF ! !----------------------------------------------------------------------- ! ! test to see if reset value is within longitudinal limits.. ! !----------------------------------------------------------------------- ! ! IF(trulon.lt.0.or.trulon.gt.360)THEN ! print *,'trulon is incorrectly set in terrain.input, please ! & reset, use degrees east' ! STOP ! END IF ! !----------------------------------------------------------------------- ! ! test to see if trulat is within limits... ! !----------------------------------------------------------------------- ! IF(trulat1 < 0.OR.trulat1 > 90)THEN PRINT *,'Input parameter trulat1 is too large or too small.', & 'must be set between 0. AND +90. degree north.' STOP END IF IF(trulat2 < 0.OR.trulat2 > 90)THEN PRINT *,'Input parameter trulat2 is too large or too small.', & 'must be set between 0. AND +90. degree north.' STOP END IF ! !----------------------------------------------------------------------- ! ! Set up map projection ! !----------------------------------------------------------------------- ! trulat(1) = trulat1 trulat(2) = trulat2 CALL setmapr( mapproj, 1.0 , trulat , trulon) ! set up parameters for map projection CALL lltoxy( 1,1, ctrlat,ctrlon, ctrx, ctry ) swx = ctrx - (FLOAT(nx-3)/2.) * dx swy = ctry - (FLOAT(ny-3)/2.) * dy CALL setorig( 1, swx, swy) ! !----------------------------------------------------------------------- ! ! Set the horizontal coordinates of the model grid ! !----------------------------------------------------------------------- ! DO i=1,nx x(i) = dx * (i-2) END DO DO j=1,ny y(j) = dy * (j-2) END DO DO j=1,ny DO i=1,nx xh(i,j)=(i-1.5)*dx yh(i,j)=(j-1.5)*dy END DO END DO DO j=0,ny DO i=0,nx xh1d(i)=(i-1.5)*dx yh1d(j)=(j-1.5)*dy END DO END DO PRINT*,' dx,dy=',dx,dy ! !----------------------------------------------------------------------- ! ! Final out the lat/lon of each scalar (terrain data) point. ! !----------------------------------------------------------------------- ! ! Include an extra zone so that data grid covering ! (lonmax-lonmin)*(latmax-latmin) is large enough area for 2nd order ! interpolation ! CALL xytoll(nx+1,ny+1,xh1d,yh1d,lath,lonh) ! !----------------------------------------------------------------------- ! ! Final out the max/min lat/lon of each scalar (terrain data) point. ! !----------------------------------------------------------------------- CALL a3dmax0(lath,0,nx,0,nx,0,ny,0,ny,1,1,1,1,latmax,latmin) CALL a3dmax0(lonh,0,nx,0,nx,0,ny,0,ny,1,1,1,1,lonmax,lonmin) IF( trndataopt == 3 ) THEN swlat_trn = INT((1000.0+latmin-15.0/3600.0)*0.1)*10-1000 swlon_trn = INT((1000.0+lonmin-15.0/3600.0)*0.1)*10-1000 nelat_trn = INT((1000.0+latmax+15.0/3600.0)*0.1)*10-1000 nelon_trn = INT((1000.0+lonmax+15.0/3600.0)*0.1)*10-1000 ! IF( nelat_trn /= latmax ) nelat_trn = nelat_trn + 10 ! IF( nelon_trn /= lonmax ) nelon_trn = nelon_trn + 10 IF( nelat_trn < latmax+15.0/3600.0 ) nelat_trn = nelat_trn + 10 IF( nelon_trn < lonmax+15.0/3600.0 ) nelon_trn = nelon_trn + 10 swlat_offset = 15.0/3600.0 swlon_offset = 15.0/3600.0 ELSE swlat_trn = INT(1000.0+latmin)-1000 swlon_trn = INT(1000.0+lonmin)-1000 nelat_trn = INT(1000.0+latmax)-1000 nelon_trn = INT(1000.0+lonmax)-1000 IF( nelat_trn /= latmax ) nelat_trn = nelat_trn + 1 IF( nelon_trn /= lonmax ) nelon_trn = nelon_trn + 1 swlat_offset = 0.0 swlon_offset = 0.0 ENDIF swlat_trn=MAX( -90, swlat_trn) nelat_trn=MIN( 90, nelat_trn) swlon_trn=MAX(-180, swlon_trn) nelon_trn=MIN( 180, nelon_trn) PRINT*,'lonmin, lonmax=',lonmin, lonmax PRINT*,'latmin, latmax=',latmin, latmax PRINT*,'sw lat/lon, ne lat/lon=', & swlat_trn,swlon_trn,nelat_trn,nelon_trn IF( trndataopt == 3 ) THEN nx_trn = (3600*(nelon_trn-swlon_trn)-30.0)/lon_sample+1 ny_trn = (3600*(nelat_trn-swlat_trn)-30.0)/lat_sample+1 ELSE nx_trn = (3600*(nelon_trn-swlon_trn))/lon_sample+1 ny_trn = (3600*(nelat_trn-swlat_trn))/lat_sample+1 ENDIF Write(6,'(/2(a,i7),a/)') & 'Allocating array h_trn of size ',nx_trn,'x',ny_trn,'.' allocate(h_trn(nx_trn,ny_trn),STAT=istatus) IF( istatus /= 0 ) THEN Write(6,'(/a/)')'Allocation of array h_trn failed. Program stopped.' STOP END IF badvalue = -9999.0 DO i=1,nx_trn DO j=1,ny_trn h_trn(i,j)=badvalue END DO END DO !----------------------------------------------------------------------- ! ! Fill in array h_trn, by reading in 3 arc second DEM/terrain data. ! !----------------------------------------------------------------------- IF( trndataopt == 1) THEN ! CALL FILLHTRN1DEG(h_trn,nx_trn,ny_trn, & ! swlon_trn,nelon_trn,lon_sample,swlat_trn,nelat_trn,lat_sample,& ! dir_trndata(1:ldir_trndata),badvalue) ELSE IF( trndataopt == 2) THEN CALL fillhtrn5min(h_trn,nx_trn,ny_trn, & swlon_trn,nelon_trn,lon_sample,swlat_trn,nelat_trn,lat_sample, & dir_trndata(1:ldir_trndata),fn_trndata,badvalue) ELSE IF( trndataopt == 3) THEN print*,'nx_trn,ny_trn,nx_trn',nx_trn,ny_trn CALL FILLHTRN30SEC(h_trn,nx_trn,ny_trn, & swlon_trn,nelon_trn,lon_sample,swlat_trn,nelat_trn,lat_sample,& dir_trndata(1:ldir_trndata),badvalue) ELSE IF( trndataopt == 4) THEN lfn = len_trim(usgs_dem_index_fn) CALL fillhtrn3sec(h_trn,nx_trn,ny_trn, & swlon_trn,nelon_trn,lon_sample,swlat_trn,nelat_trn,lat_sample, & dir_trndata(1:ldir_trndata),usgs_dem_index_fn(1:lfn),badvalue) ELSE WRITE(6,'(1x,a/1x,a,i3,a)') 'trndataopt must be from 1 to 4.', & 'The input value was ', trndataopt,', Program stopped.' STOP 991 END IF CALL a3dmax(h_trn,1,nx_trn,1,nx_trn,1,ny_trn,1,ny_trn, & 1,1,1,1, & hmax,hmin,imax,jmax,kmax, imin,jmin,kmin) WRITE(6,'(2(1x,a,g25.12,2(a,i5)))') & 'hmin =',hmin,' at i=',imin,', j=',jmin, & 'hmax =',hmax,' at i=',imax,', j=',jmax WRITE(6,'(/a)') 'Finished reading terrain data.' ! print*,' nx_trn, ny_trn =', nx_trn, ny_trn inith_set = 0 badvfound = 0 DO i=1,nx_trn DO j=1,ny_trn IF( h_trn(i,j) /= badvalue)THEN IF(inith_set == 0 ) THEN hmax = h_trn(i,j) hmin = h_trn(i,j) inith_set = 1 ELSE hmax = MAX(hmax, h_trn(i,j)) hmin = MIN(hmin, h_trn(i,j)) END IF ELSE badvfound = 1 END IF END DO END DO IF( badvfound == 1) THEN WRITE(6,'(/a,/a)') & 'Missing value(s) found in sampled terrain array.', & 'The missing data need to be filled. Job stopped.' STOP END IF IF(inith_set == 0 ) THEN ! If still not set hmax = 0.0 hmin = 0.0 END IF WRITE(6,'(/a,2f10.3)') & 'Min and max in the sampled terrain data array=',hmin, hmax ! !----------------------------------------------------------------------- ! ! Initialize ARPS terrain array hterain from h_trn using bi-linear ! interpolation. ! !----------------------------------------------------------------------- ! PRINT*,'swlon_trn, swlat_trn=',swlon_trn, swlat_trn PRINT*,'lon_sample,lat_sample=',lon_sample,lat_sample lond_sample = lon_sample/3600.0 latd_sample = lat_sample/3600.0 IF( trnanxopt == 1) THEN ! 1st order interpolation DO i=1,nx-1 DO j=1,ny-1 ih=MIN(nx_trn-1, & MAX(1,INT((lonh(i,j)-(swlon_trn+swlon_offset))*3600.0/lon_sample)+1)) jh=MIN(ny_trn-1, & MAX(1,INT((lath(i,j)-(swlat_trn+swlat_offset))*3600.0/lat_sample)+1)) ! print*,'i,j,ih,jh=', i,j,ih,jh,h_trn(ih,jh) IF(h_trn(ih ,jh ) == badvalue .OR. h_trn(ih+1,jh) == badvalue .OR. & h_trn(ih+1,jh+1) == badvalue .OR. & h_trn(ih ,jh+1) == badvalue) THEN hterain(i,j)=badvalue ELSE lonh1=lonh(i,j)-(swlon_trn+swlon_offset)-(ih-1)*lond_sample lath1=lath(i,j)-(swlat_trn+swlat_offset)-(jh-1)*latd_sample w1=(latd_sample-lath1)*(lond_sample-lonh1) w2=(latd_sample-lath1)*lonh1 w3=lath1*lonh1 w4=lath1*(lond_sample-lonh1) hterain(i,j)=(w1*h_trn(ih ,jh )+w2*h_trn(ih+1,jh) & +w3*h_trn(ih+1,jh+1)+w4*h_trn(ih,jh+1)) & /(latd_sample*lond_sample) END IF END DO END DO ELSE ! 2nd order interpolation DO i=1,nx-1 DO j=1,ny-1 ih=MIN(nx_trn-1, & MAX(2,INT((lonh(i,j)-(swlon_trn+swlon_offset))*3600.0/lon_sample)+1)) jh=MIN(ny_trn-1, & MAX(2,INT((lath(i,j)-(swlat_trn+swlat_offset))*3600.0/lat_sample)+1)) IF(h_trn(ih ,jh ) == badvalue .OR. h_trn(ih+1,jh) == badvalue .OR. & h_trn(ih+1,jh+1) == badvalue .OR. & h_trn(ih ,jh+1) == badvalue) THEN hterain(i,j)=badvalue ELSE IF(h_trn(ih-1,jh+1) == badvalue .OR. & h_trn(ih-1,jh) == badvalue .OR. & h_trn(ih-1,jh-1) == badvalue .OR. & h_trn(ih+1,jh-1) == badvalue .OR. & h_trn(ih ,jh-1) == badvalue) THEN ! Use 1st order hterain(i,j)=badvalue lonh1=lonh(i,j)-(swlon_trn+swlon_offset)-(ih-1)*lond_sample lath1=lath(i,j)-(swlat_trn+swlat_offset)-(jh-1)*latd_sample w1=(latd_sample-lath1)*(lond_sample-lonh1) w2=(latd_sample-lath1)*lonh1 w3=lath1*lonh1 w4=lath1*(lond_sample-lonh1) hterain(i,j)=(w1*h_trn(ih ,jh )+w2*h_trn(ih+1,jh) & +w3*h_trn(ih+1,jh+1)+w4*h_trn(ih,jh+1)) & /(latd_sample*lond_sample) ELSE ! now real 2nd order interpolation d=lonh(i,j)-(swlon_trn+swlon_offset)-(ih-1)*lond_sample a=-lond_sample b=0.0 c=+lond_sample w1= (d-b)*(d-c)/((a-b)*(a-c)) w2= (d-a)*(d-c)/((b-a)*(b-c)) w3= (d-a)*(d-b)/((c-a)*(c-b)) h1=w1*h_trn(ih-1,jh-1)+w2*h_trn(ih,jh-1) & +w3*h_trn(ih+1,jh-1) h2=w1*h_trn(ih-1,jh )+w2*h_trn(ih,jh ) & +w3*h_trn(ih+1,jh ) h3=w1*h_trn(ih-1,jh+1)+w2*h_trn(ih,jh+1) & +w3*h_trn(ih+1,jh+1) d=lath(i,j)-(swlat_trn+swlat_offset)-(jh-1)*latd_sample a=-latd_sample b=0.0 c=+latd_sample w1= (d-b)*(d-c)/((a-b)*(a-c)) w2= (d-a)*(d-c)/((b-a)*(b-c)) w3= (d-a)*(d-b)/((c-a)*(c-b)) hterain(i,j)=w1*h1+w2*h2+w3*h3 END IF END IF END DO END DO END IF ! !----------------------------------------------------------------------- ! ! Fill in Great Lakes. The original data set corresponds to the ! bottom of the lakes. ! !----------------------------------------------------------------------- ! DO j=1,ny DO i=1,nx tem(i,j) = lath(i,j) tem2(i,j) = lonh(i,j) END DO END DO CALL fix_lake_eliv(hterain,tem,tem2,nx,ny) CALL a3dmax(hterain,1,nx,1,nx-1,1,ny,1,ny-1,1,1,1,1, & hmax,hmin,imax,jmax,kmax, imin,jmin,kmin) WRITE(6,'(2(1x,a,g25.12,2(a,i5)))') & 'htrnmin =',hmin,' at i=',imin,', j=',jmin, & 'htrnmax =',hmax,' at i=',imax,', j=',jmax !----------------------------------------------------------------------- ! ! Apply smoothing on terrain height ! !----------------------------------------------------------------------- DO i=1,nsmth CALL smth(hterain,nx,1,nx-1,ny,1,ny-1,2,tem) ! call SMTH(hterain,nx,1,nx-1,ny,1,ny-1,1,tem) END DO ! !----------------------------------------------------------------------- ! ! Write out the terrain file on ARPS grid. ! !----------------------------------------------------------------------- ! hmax=hterain(1,1) hmin=hterain(1,1) DO i=1,nx-1 DO j=1,ny-1 hterain(i,j) = MAX(0.0,hterain(i,j)) hmax=MAX(hmax,hterain(i,j)) hmin=MIN(hmin,hterain(i,j)) END DO END DO WRITE(6,'(/a,2f10.3)') & 'Max/min in the analyzed terrain array was ',hmax,hmin IF (terndmp /= 0) THEN CALL writtrn(nx,ny,runname(1:lfnkey)//'.trndata',dx,dy, & mapproj,trulat1,trulat2,trulon,sclfct,ctrlat,ctrlon,hterain) END IF DO j=1,ny DO i=1,nx xh(i,j)=xh(i,j)*0.001 yh(i,j)=yh(i,j)*0.001 ! hterain(i,j)=hterain(i,j)*0.001 END DO END DO !wdt skip graphics STOP !wdt update ! !----------------------------------------------------------------------- ! ! Generate graphical output. ! !----------------------------------------------------------------------- ! CALL xdevic CALL xctrbadv( 1 ) ! Turn on missing value checking for contouring CALL xvtrbadv( 1 ) ! Turn on missing value checking for vector plotting CALL xsetclrs(6) CALL xaxfmt('(I6)') CALL xbadval ( badvalue ) ! Set the missing value flag to -9999.0 xl = (nx-3)*dx * 0.001 yl = (ny-3)*dy * 0.001 xorig = 0.0 yorig = 0.0 CALL xstpjgrd(mapproj,trulat1,trulat2,trulon, & ctrlat,ctrlon,xl,yl,xorig,yorig) CALL plot_trn(hterain,xh,yh,nx,1,nx-1,ny,1,ny-1, & -dx*0.001,(nx-2)*dx*0.001,dx*0.001, & -dy*0.001,(ny-2)*dy*0.001,dy*0.001, hctrinc, tem,xw,yw) DO i=1,nmapfile lmapfile=LEN(mapfile(i)) CALL strlnth(mapfile(i), lmapfile) WRITE(6,'(1x,a,a)') 'Input was ',mapfile(i)(1:lmapfile) INQUIRE(FILE=mapfile(i)(1:lmapfile), EXIST = fexist ) IF( .NOT.fexist) THEN WRITE(6,'(a)') 'Map file '//mapfile(i)(1:lmapfile)// & ' not found. Program stopped in ARPSPLT.' STOP 001 END IF CALL xdrawmap(10,mapfile(i)(1:lmapfile),latgrid,longrid) END DO ! ctrlat = 40.28 ! ctrlon = -111.56 ! CALL lltoxy( 1,1, ctrlat,ctrlon, ctrx, ctry ) ! call xcolor(1) ! call xthick(3) ! call xpenup(ctrx*0.001,ctry*0.001-0.03*(ny-3)*dy*0.001) ! call xpendn(ctrx*0.001,ctry*0.001+0.03*(ny-3)*dy*0.001) ! call xpenup(ctrx*0.001-0.03*(nx-3)*dx*0.001,ctry*0.001) ! call xpendn(ctrx*0.001+0.03*(nx-3)*dx*0.001,ctry*0.001) ! ctrlat = 40.5 ! ctrlon = -111.5 ! CALL lltoxy( 1,1, ctrlat,ctrlon, ctrx, ctry ) ! call xcolor(1) ! call xthick(3) ! call xpenup(ctrx*0.001,ctry*0.001-0.03*(ny-3)*dy*0.001) ! call xpendn(ctrx*0.001,ctry*0.001+0.03*(ny-3)*dy*0.001) ! call xpenup(ctrx*0.001-0.03*(nx-3)*dx*0.001,ctry*0.001) ! call xpendn(ctrx*0.001+0.03*(nx-3)*dx*0.001,ctry*0.001) ! CALL xgrend STOP 980 CONTINUE WRITE(6,'(/1x,a,a)') & 'Error occured when reading namelist input file. Program stopped.' STOP 990 CONTINUE WRITE(6,'(/1x,a,a)') & 'End of file reached when reading namelist input file. ', & 'Program stopped.' STOP END PROGRAM arpstrn SUBROUTINE fillhtrn3sec(h_trn,nx_trn,ny_trn, & 1,3 swlon_trn,nelon_trn,lon_sample, & swlat_trn,nelat_trn,lat_sample,dir_trndata, & usgs_dem_index_fn,badvalue) ! !----------------------------------------------------------------------- ! ! !----------------------------------------------------------------------- ! ! AUTHOR: Ming Xue ! 11/25/95 ! ! MODIFICATION HISTORY: ! ! 2000/02/03 Gene Bassett ! Added subroutine to fix the elevations in the Great Lakes. ! !----------------------------------------------------------------------- ! ! Variable Declarations. ! !----------------------------------------------------------------------- IMPLICIT NONE ! !----------------------------------------------------------------------- ! ! LOCAL VARIABLES: ! !----------------------------------------------------------------------- ! INTEGER :: nlat,nlon ! Number of data points in the 3" ! one degree DEM data block. INTEGER, ALLOCATABLE :: h_block(:,:) ! Array to store 1x1 degree DEM patch INTEGER :: nx_trn,ny_trn REAL :: h_trn(nx_trn,ny_trn) CHARACTER (LEN=80) :: trn_name INTEGER :: lat_sample,lon_sample ! Data sampling frequency in data index INTEGER :: swlat_trn,swlon_trn,nelat_trn,nelon_trn ! SW and NE coner lat/lon of the ! the assembled terrain patch. INTEGER :: istatus,istatus1,istatus2,ii,jj,i,j,ilat,ilon REAL :: badvalue, tmax0,tmin0 CHARACTER (LEN=3) :: dtflag LOGICAL :: existfile CHARACTER (LEN=*) :: dir_trndata,usgs_dem_index_fn INTEGER :: lat_skip, lon_skip,ldir_trndata ! !----------------------------------------------------------------------- ! ! Make sure directory dir_trndata already exists. ! !----------------------------------------------------------------------- ldir_trndata = len_trim(dir_trndata) INQUIRE(FILE=dir_trndata(1:ldir_trndata),EXIST=existfile) IF( .NOT. existfile ) THEN WRITE(6,'(/1x,3a,3(/1x,a))') & 'Directory ',dir_trndata(1:ldir_trndata),' does not exist.', & 'Create the directory or create a link to the data directory.', & 'This directory has to be writable, unless all required DEM data', & 'exists locally.' END IF nlat = 1201 nlon = 1201 ALLOCATE (h_block(nlat,nlon)) DO ilat=swlat_trn,nelat_trn-1 DO ilon=swlon_trn,nelon_trn-1 !----------------------------------------------------------------------- ! ! Find the name of DEM file whose SW corner lat/lon = ilat/ilon. ! !----------------------------------------------------------------------- CALL lookup_trn(ilat,ilon,usgs_dem_index_fn, & trn_name,dtflag,istatus) IF( istatus /= 0) GO TO 310 !----------------------------------------------------------------------- ! ! Acquire file trn_name from anonymous FTP server ! edcftp.cr.usgs.gov if it does not already exist locally in dir_trndata ! !----------------------------------------------------------------------- CALL get_trn(dir_trndata(1:ldir_trndata), & trn_name,dtflag,istatus1) IF(istatus1 /= 0) GO TO 310 ! !----------------------------------------------------------------------- ! ! Read in 1x1 degree DEM data block into array h_block. ! !----------------------------------------------------------------------- ! CALL read_trn(dir_trndata(1:ldir_trndata)//trn_name, & h_block,nlat,nlon,istatus2) IF(istatus2 /= 0) GO TO 310 tmax0=h_block(1,1) tmin0=h_block(1,1) DO i=1,1201 DO j=1,1201 tmax0=MAX(tmax0,FLOAT(h_block(i,j))) tmin0=MIN(tmin0,FLOAT(h_block(i,j))) END DO END DO PRINT*,'max/min in data file ',dir_trndata(1:ldir_trndata), & '=',tmax0,tmin0 ! !----------------------------------------------------------------------- ! ! Transfer selected data points from h_block into h_trn. ! !----------------------------------------------------------------------- ! lat_skip = max(1,lat_sample/3) lon_skip = max(1,lon_sample/3) ii = (nlon-1)/lon_skip*(ilon-swlon_trn) jj = (nlat-1)/lat_skip*(ilat-swlat_trn) DO j=1,(nlat-1)/lat_skip+1 DO i=1,(nlon-1)/lon_skip+1 h_trn(ii+i,jj+j)= & FLOAT(h_block((i-1)*lon_skip+1,(j-1)*lat_skip+1)) END DO END DO CYCLE 310 CONTINUE WRITE(6,'(/1x,a,2i5,a,/1x,a)') & 'DEM file with S-W lat/lon=',ilat,ilon,' was not found or not', & 'read correctly. The DEM array is filled with missing values.' ii = (nlon-1)/lon_skip*(ilon-swlon_trn) jj = (nlat-1)/lat_skip*(ilat-swlat_trn) DO j=1,(nlat-1)/lat_skip+1 DO i=1,(nlon-1)/lon_skip+1 h_trn(ii+i,jj+j)= badvalue END DO END DO END DO END DO DEALLOCATE(h_block) RETURN END SUBROUTINE fillhtrn3sec SUBROUTINE fillhtrn5min(h_trn,nx_trn,ny_trn, & 1,2 swlon_trn,nelon_trn,lon_sample, & swlat_trn,nelat_trn,lat_sample,dir_trndata,fn_trndata, & badvalue) !----------------------------------------------------------------------- ! ! read the TerrainBase data ! This original program modified by LDI ! This promgram used to make the 5min topo input data using NCAR 5min topo ! output is the 5 min topo for ARPS terrain program ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER :: itopo(4320) ! Array for topo along one latitude circle INTEGER :: imin,imax,jmin,jmax,i,j INTEGER :: nx_trn,ny_trn REAL :: h_trn(nx_trn,ny_trn) INTEGER :: swlat_trn,swlon_trn,nelat_trn,nelon_trn ! SW and NE coner lat/lon of the assembled terrain patch. INTEGER :: lon_sample, lat_sample CHARACTER (LEN=80) :: fn_trndata CHARACTER (LEN=120) :: dir_trndata INTEGER :: ldir_trndata,lfn_trndata REAL :: badvalue REAL :: hmax, hmin INTEGER :: inith_set , iskip, jskip, ii LOGICAL existfile imin = swlon_trn*12+1 imax = nelon_trn*12+1 jmax = (90-swlat_trn)*12+1 jmin = (90-nelat_trn)*12+1 PRINT*,'imin,imax,jmin,jmax=',imin,imax,jmin,jmax ldir_trndata = 120 CALL strlnth( dir_trndata, ldir_trndata) lfn_trndata = 80 CALL strlnth( fn_trndata, lfn_trndata) INQUIRE(FILE=dir_trndata(1:ldir_trndata)//fn_trndata(1:lfn_trndata), & EXIST=existfile) IF ( .not. existfile) THEN WRITE(6,'(a,a,/a)') & 'File ',dir_trndata(1:ldir_trndata)//fn_trndata(1:lfn_trndata), & ' not found. Program stopped in subroutine FILLHTRN5MIN.' STOP END IF OPEN(10,FILE=dir_trndata(1:ldir_trndata)// & fn_trndata(1:lfn_trndata),STATUS='old',FORM='formatted') iskip = lon_sample/300 jskip = lat_sample/300 DO j=1,jmax ! jmax =< 2160 READ(10,100)(itopo(i),i=1,4320) IF(j >= jmin.AND. & MOD((jmax-jmin+1)-(j-jmin+1),jskip) == 0)THEN ! Fill in array h_trn DO i=imin, imax, iskip ii = i IF( i < 0) ii=4320+i h_trn((i-imin)/iskip+1, & ((jmax-jmin+1)-(j-jmin+1))/jskip+1)=itopo(ii) END DO END IF END DO 100 FORMAT(20I6) ! CALL XDEVIC IF( .false.) THEN ! Plotting is true nx_trn = (12*(nelon_trn-swlon_trn))/iskip+1 ny_trn = (12*(nelat_trn-swlat_trn))/jskip+1 ! print*,'nx_trn,ny_trn,imax-imin+1,jmax-jmin+1=', ! : nx_trn,ny_trn,imax-imin+1,jmax-jmin+1 inith_set = 0 DO i=1,nx_trn DO j=1,ny_trn IF( h_trn(i,j) /= badvalue)THEN IF(inith_set == 0 ) THEN hmax = h_trn(i,j) hmin = h_trn(i,j) inith_set = 1 ELSE hmax = MAX(hmax, h_trn(i,j)) hmin = MIN(hmin, h_trn(i,j)) END IF END IF END DO END DO IF(inith_set == 0 ) THEN ! If still not set hmax = 0.0 hmin = 0.0 END IF PRINT*,' hmin, hmax =', hmin, hmax ! hmax = h_trn(1,1) ! hmin = h_trn(1,1) ! DO 1203 i=1,nx_trn ! DO 1203 j=1,ny_trn ! hmax = max(hmax, h_trn(i,j)) ! hmin = min(hmin, h_trn(i,j)) ! 1203 CONTINUE ! print*,' hmin, hmax =', hmin, hmax END IF CLOSE(2) RETURN END SUBROUTINE fillhtrn5min SUBROUTINE lookup_trn(swlat,swlon,usgs_dem_index_fn, & 1 trn_name,dtflag,ierr) !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Find a 1x1 degree DEM file whose SW corner is at (swlat,swlon). ! dtflag= 'US' or 'AK', indicating if the data file is in Alaska. ! Note: The longitude W is given as positive numbers in the Index. ! This should be fine as long as this program is used for ! accessing US 3" data only. The code should be modified slightly ! to handle global data. ! ! INPUT : swlat, swlon,usgs_dem_index_fn ! OUTPUT: trn_name, dtflag, ierr ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER :: swlat,swlon CHARACTER (LEN=80) :: trn_name,name1 CHARACTER (LEN=3) :: dtflag INTEGER :: ierr INTEGER :: selat,selon,lat,lon,ll REAL :: alat,alon CHARACTER (LEN=*) :: usgs_dem_index_fn ! OPEN (50,FILE=trim(usgs_dem_index_fn),STATUS='old',IOSTAT=ierr) IF( ierr /= 0) THEN WRITE(6,'(/1x,a,a,a,/1x,a)') 'Opening file ', & trim(usgs_dem_index_fn),' failed. Program stopped.' STOP END IF READ (50,*) ! selat = swlat selon = -(swlon + 1) WRITE(6,'(/1x,2(a,i4))') & 'Searching for a file with the SE corner latitude=',selat, & ' longitude=', selon 100 READ (50,'(a3,a30,2f10.1)',END=300) dtflag,name1, alat, alon lat=nint(alat) lon=nint(alon) IF (lat == selat.AND.lon == selon) THEN trn_name=name1 ll=INDEX(trn_name,'.gz') WRITE(6,'(1x,a,a,a)') 'Found the entry ',trn_name(1:ll+2), & ' with the matching lat/lon.' CLOSE (50) RETURN ELSE GO TO 100 END IF 300 CONTINUE CLOSE (50) PRINT*,'No entry in data base for this latitude and longitude.' ierr = 1 RETURN END SUBROUTINE lookup_trn SUBROUTINE get_trn(dir_trndata,trn_name,dtflag,istatus) 1,3 IMPLICIT NONE CHARACTER (LEN=120) :: dir_trndata CHARACTER (LEN=80) :: trn_name CHARACTER (LEN=3) :: dtflag INTEGER :: istatus,ldir_trndata CHARACTER (LEN=120) :: ch1,ch2,ch3 CHARACTER (LEN=80) :: dr LOGICAL :: existfile,existfile1 INTEGER :: l1 l1=INDEX(trn_name,'.gz') IF( dtflag == 'AK') THEN dr='Alaska/'//CHAR(ICHAR(trn_name(1:1))-32) ELSE dr=trn_name(1:1) dr=CHAR(ICHAR(dr(1:1))-32) END IF ch1='cd '//dr ch2='dir '//trn_name(1:l1+2) ch3='get '//trn_name(1:l1+2) ! ! check to see if dem file pre-exists ! istatus = 1 ldir_trndata=120 CALL strlnth(dir_trndata,ldir_trndata) INQUIRE(FILE=dir_trndata(1:ldir_trndata)//trn_name(1:l1+2), & EXIST=existfile) INQUIRE(FILE=dir_trndata(1:ldir_trndata)//trn_name(1:l1-1), & EXIST=existfile1) IF (existfile) THEN PRINT *,trn_name(1:l1+2),' exists locally' ELSE IF (existfile1 ) THEN PRINT *,trn_name(1:l1-1),' exists locally' ELSE ! ! write the ftp input file ! OPEN (29,FILE='ftp.in') WRITE (29,1) 'binary' WRITE (29,1) 'cd pub/data/DEM/250' WRITE (29,1) ch1 WRITE (29,1) ch2 WRITE (29,1) ch3 WRITE (29,1) 'quit' CLOSE (29) 1 FORMAT(a) ! ! invoke ftp command ! ch1='ftp edcftp.cr.usgs.gov< ftp.in' PRINT *,'Connecting to ftp site to get the file...' CALL unixcmd(ch1) CALL unixcmd( & 'mv '//trn_name(1:l1+2) //' '//dir_trndata(1:ldir_trndata)) PRINT *,'File ',trn_name(1:l1+2), & ' transferred to the local machine now.' END IF istatus=0 ! RETURN END SUBROUTINE get_trn SUBROUTINE read_trn(trn_fullname,h_block,nlat,nlon,istatus) 1,7 IMPLICIT NONE CHARACTER (LEN=128) :: trn_fullname INTEGER :: nlat,nlon ! integer*2 h_block(nlat,nlon) INTEGER :: h_block(nlat,nlon) INTEGER :: istatus CHARACTER (LEN=80) :: ch1,ch2 CHARACTER (LEN=120) :: ch4 DIMENSION dum15(15),dum6(6) CHARACTER (LEN=144) :: head INTEGER :: i,j,ii,ijump,m,n,l1,ltd,lnd,idum REAL :: xjumpinv,tmax0,tmin0,tmax,tmin,dum,dum6,dum15,amx,amn REAL :: selnsec,seltsec LOGICAL :: existfile istatus=1 l1=INDEX(trn_fullname,'.gz') INQUIRE(FILE='tmp1.file', EXIST = existfile) IF(existfile)THEN ch2='/bin/rm tmp1.file' CALL unixcmd(ch2) ENDIF INQUIRE(FILE=trn_fullname(1:l1-1),EXIST=existfile) IF(existfile) THEN ! unzipped version exists ch1='cp '//trn_fullname(1:l1-1)//' tmp1.file' CALL unixcmd(ch1) ELSE ! need to unzip ch1='gunzip -c '//trn_fullname(1:l1+2)//'> tmp1.file' PRINT *,'Unzipping the terrain file..' CALL unixcmd(ch1) PRINT *,'Terrain file unzipping competed..' END IF INQUIRE(FILE='tmp2.file', EXIST = existfile) IF(existfile)THEN ch2='/bin/rm tmp2.file' CALL unixcmd(ch2) ENDIF ch4='dd if=tmp1.file of=tmp2.file ibs=4096 cbs=1024 conv=unblock' PRINT *,'Converting the terrain file..' CALL unixcmd(ch4) PRINT *,'Conversion completed..' INQUIRE(FILE='tmp1.file', EXIST = existfile) IF(existfile)THEN ch2='/bin/rm tmp1.file' CALL unixcmd(ch2) ENDIF ! ! Read in terrain data ! OPEN (29,FILE='tmp2.file') READ (29,11) head,idum,idum,idum,idum,(dum15(i),i=1,15), & idum,idum,idum,(dum6(i),i=1,6),selnsec,seltsec,tmin,tmax,dum, & idum,dum,dum,dum,idum,m 11 FORMAT(a144,4I6,15E24.0,3I6,11E24.0,i6,3E12.0,2I6) PRINT*,'Min and max in the input DEM file header=', & tmin,tmax ltd=seltsec/3600. lnd=selnsec/3600. WRITE (6,'(/1x,a,2i5)') & 'South-east corner latitude and longitude from the file ',ltd,lnd WRITE (6,'(/1x,a)') & 'Reading terrain data and store into the terrain array.' IF( m == 1201) THEN ijump=1 ELSE IF( m == 601) THEN ijump=2 ELSE IF( m == 401) THEN ijump=3 ELSE WRITE(6,'(/1x,a,/1x,i6,a)') & 'The DEM file must have 1201, 601 or 401 data in the lon. dir.' & ,m,' data points were found. Program stopped.' STOP END IF DO i=1,1201,ijump READ (29,2) idum,idum,n,idum,dum,dum,dum,amx,amn, & (h_block(i,j),j=1,n) END DO 2 FORMAT (4I6,5E24.0,146I6,/(170I6)) IF( n /= 1201) THEN WRITE(6,'(/1x,a,/1x,i6,a)') & 'The DEM file must have 1201 data in the lat. dir.' & ,n,' data points were found. Program stopped.' STOP END IF IF( .true. ) THEN tmax0=h_block(1,1) tmin0=h_block(1,1) DO i=1,1201,ijump DO j=1,n tmax0=MAX(tmax0,FLOAT(h_block(i,j))) tmin0=MIN(tmin0,FLOAT(h_block(i,j))) END DO END DO PRINT*,'READTRN: max/min in the data read in=',tmax0,tmin0 END IF ! ! Linearly interpolate terrain data to all 3 second grid points ! when the input data resolution is coarser than 3 second. ! xjumpinv=1.0/ijump DO ii=1,ijump-1 DO i=1,1201-ijump,ijump DO j=1,n h_block(i+ii,j)=h_block(i,j)+(h_block(i+ijump,j) & -h_block(i,j))*ii*xjumpinv END DO END DO END DO IF( .false.) THEN tmax0=h_block(1,1) tmin0=h_block(1,1) DO i=1,1201 DO j=1,n tmax0=MAX(tmax0,FLOAT(h_block(i,j))) tmin0=MIN(tmin0,FLOAT(h_block(i,j))) END DO END DO PRINT*,'max/min in the data read in=',tmax0,tmin0 END IF PRINT*,'Terrain data stored into the terrain array.' ! CLOSE (29) CALL unixcmd('/bin/rm tmp2.file') istatus = 0 ! RETURN END SUBROUTINE read_trn SUBROUTINE fillhtrn30sec(h_trn,nx_trn,ny_trn, & 1,2 swlon_trn,nelon_trn,lon_sample, & swlat_trn,nelat_trn,lat_sample,dir_trndata,badvalue) ! !----------------------------------------------------------------------- ! ! !----------------------------------------------------------------------- ! ! AUTHOR: Ming Xue ! 1/31/2002 (based on fillhtrn3sec) ! ! MODIFICATION HISTORY: ! !----------------------------------------------------------------------- ! ! Variable Declarations. ! !----------------------------------------------------------------------- IMPLICIT NONE ! !----------------------------------------------------------------------- ! ! LOCAL VARIABLES: ! !----------------------------------------------------------------------- ! INTEGER :: nlat,nlon ! Number of data points in the 3" ! one degree DEM data block. INTEGER, ALLOCATABLE :: h_block(:,:) ! Array to store 1x1 degree DEM patch INTEGER :: nx_trn,ny_trn REAL :: h_trn(nx_trn,ny_trn) CHARACTER (LEN=80) :: trn_name INTEGER :: lat_sample,lon_sample ! Data sampling frequency in data index INTEGER :: swlat_trn,swlon_trn,nelat_trn,nelon_trn ! SW and NE coner lat/lon of the ! the assembled terrain patch. INTEGER :: istatus,istatus1,istatus2,ii,jj,i,j,ilat,ilon REAL :: badvalue, tmax0,tmin0 CHARACTER (LEN=3) :: dtflag LOGICAL :: existfile CHARACTER (LEN=*) :: dir_trndata INTEGER :: lat_skip, lon_skip,ldir_trndata ! !----------------------------------------------------------------------- ! ! Make sure directory dir_trndata already exists. ! !----------------------------------------------------------------------- print*,'Inside fillhtrn30sec ' ldir_trndata = len_trim(dir_trndata) ! INQUIRE(FILE=dir_trndata(1:ldir_trndata),EXIST=existfile) ! IF( .NOT. existfile ) THEN ! WRITE(6,'(/1x,3a,3(/1x,a))') & ! 'Directory ',dir_trndata(1:ldir_trndata),' does not exist.', & ! 'Create the directory or create a link to the data directory.', & ! 'This directory has to be writable, unless all required DEM data', & ! 'exists locally.' ! END IF nlat = 1200 nlon = 1200 ALLOCATE(h_block(nlat,nlon)) print*,'done allocating h_block' print*,'swlat_trn,nelat_trn,swlon_trn,nelon_trn=',swlat_trn,nelat_trn,swlon_trn,nelon_trn DO ilat=swlat_trn,nelat_trn-10,10 DO ilon=swlon_trn,nelon_trn-10,10 print*,' ' print*,'SW corner lat, lon of 10x10 degree patch to be read=',ilat, ilon !----------------------------------------------------------------------- ! Find the name of the 10x10 degree file whose SW corner lat/lon = ilat/ilon. !----------------------------------------------------------------------- IF(ilon.lt.0.0.and.ilat.ge.0.0)write(trn_name,'(a,i3.3,a,i3.3,a)') & 'W',ABS(ilon),'N',ABS(ilat),'.30s_ascdat' IF(ilon.lt.0.0.and.ilat.lt.0.0)write(trn_name,'(a,i3.3,a,i3.3,a)') & 'W',ABS(ilon),'S',ABS(ilat),'.30s_ascdat' IF(ilon.ge.0.0.and.ilat.ge.0.0)write(trn_name,'(a,i3.3,a,i3.3,a)') & 'E',ABS(ilon),'N',ABS(ilat),'.30s_ascdat' IF(ilon.ge.0.0.and.ilat.lt.0.0)write(trn_name,'(a,i3.3,a,i3.3,a)') & 'E',ABS(ilon),'S',ABS(ilat),'.30s_ascdat' !----------------------------------------------------------------------- ! ! Acquire file trn_name from CAPS anonymous FTP server ! ftp://ftp.caps.ou.edu/pub/ARPS/ARPS.data/arpstopo30.data if it does ! not already exist locally in dir_trndata ! !----------------------------------------------------------------------- CALL get_30s_trn(trim(dir_trndata),trim(trn_name),istatus1) IF(istatus1 /= 0) GO TO 310 ! !----------------------------------------------------------------------- ! ! Read in 10x10 degree DEM data block into array h_block. ! !----------------------------------------------------------------------- ! print*,'To read data from ', dir_trndata(1:ldir_trndata)//trim(trn_name) CALL read_30s_trn(dir_trndata(1:ldir_trndata)//trim(trn_name), & h_block,nlat,nlon,istatus2) print*,'Done reading data in ', dir_trndata(1:ldir_trndata)//trim(trn_name) DO i=1,nlon DO j=1,nlat IF(h_block(i,j).eq.-9999)h_block(i,j)=0.0 ! in ocean by definition ! of the data set ENDDO ENDDO IF(istatus2 /= 0) GO TO 310 ! !----------------------------------------------------------------------- ! ! Transfer selected data points from h_block into h_trn. ! !----------------------------------------------------------------------- ! lat_skip = max(1,lat_sample/30) lon_skip = max(1,lon_sample/30) ii = nlon/lon_skip*((ilon-swlon_trn)/10) jj = nlat/lat_skip*((ilat-swlat_trn)/10) DO j=1,nlat/lat_skip DO i=1,nlon/lon_skip h_trn(ii+i,jj+j)= & FLOAT(h_block((i-1)*lon_skip+1,(j-1)*lat_skip+1)) END DO END DO print*,'data values transferred from h_block to h_trn' CYCLE 310 CONTINUE WRITE(6,'(/1x,a,2i5,a,/1x,a)') & '30second data file with S-W lat/lon=',ilat,ilon,' was not found or not', & 'read correctly. The data array is filled with missing values.' ii = nlon/lon_skip*((ilon-swlon_trn)/10) jj = nlat/lat_skip*((ilat-swlat_trn)/10) DO j=1,nlat/lat_skip DO i=1,nlon/lon_skip h_trn(ii+i,jj+j)= badvalue END DO END DO END DO END DO DEALLOCATE( h_block ) print*,'end of fillhtrn30sec ' RETURN END SUBROUTINE fillhtrn30sec SUBROUTINE get_30s_trn(dir_trndata,trn_name,istatus) 1,3 IMPLICIT NONE CHARACTER (LEN=*) :: dir_trndata CHARACTER (LEN=*) :: trn_name INTEGER :: istatus,ldir_trndata CHARACTER (LEN=120) :: ch1 LOGICAL :: existfile,existfile1 INTEGER :: nunit ch1='get '//trim(trn_name)//'.gz' ! ! check to see if dem file pre-exists ! istatus = 1 INQUIRE(FILE=trim(dir_trndata)//trim(trn_name),EXIST=existfile) INQUIRE(FILE=trim(dir_trndata)//trim(trn_name)//'.gz',EXIST=existfile1) IF (existfile) THEN PRINT *,trim(trn_name),' exists locally' ELSE IF (existfile1 ) THEN PRINT *,trim(trn_name)//'.gz',' exists locally' ELSE ! PRINT *,trim(trn_name),' or its compressed version not found in ' PRINT *,'in directory ',trim(dir_trndata), & '. Will try to ftp it from ftp.caps.ou.edu.' Print *,'It requires that you have .netrc setup in your home directory' Print *,'for automatic anonymous ftp access to ftp.caps.ou.edu. ' ! write the ftp input file ! call getunit( nunit) OPEN (nunit,FILE='ftp.in') WRITE (nunit,1) 'binary' WRITE (nunit,1) 'cd pub/ARPS/ARPS.data/arpstopo30.data' WRITE (nunit,1) ch1 WRITE (nunit,1) 'quit' CLOSE (nunit) call retunit(nunit) 1 FORMAT(a) ! ! invoke ftp command ! ch1='ftp ftp.caps.ou.edu < ftp.in' PRINT *,'Connecting to ftp site to get the file...' CALL unixcmd(ch1) CALL unixcmd('mv '//trim(trn_name)//'.gz '//trim(dir_trndata)) PRINT *,'File ',trim(trn_name)//'.gz ', & ' transferred to the local machine now.' END IF istatus=0 ! RETURN END SUBROUTINE get_30s_trn SUBROUTINE read_30s_trn(trn_fullname,h_block,nlat,nlon,istatus) 1,4 IMPLICIT NONE CHARACTER (LEN=*) :: trn_fullname INTEGER :: nlat,nlon INTEGER :: h_block(nlat,nlon) INTEGER :: istatus INTEGER :: i,j LOGICAL :: existfile character(len=132) :: ch1 character(len=100) :: filename Doubleprecision :: ll_lon,ll_lat,lon_inc,lat_inc INTEGER :: imissing IF( nlat .ne. 1200 .or. nlon.ne. 1200 ) then print*,'Array size for array h_block, nlat and nlon must be ' print*,'equal to 1200 inside read_30s_trn. ' print*,'Input nlat and nlon =', nlat, nlon istatus = 1 RETURN END IF istatus=1 print*,'inside read_30s_trn, trn_fullname=', trim(trn_fullname) INQUIRE(FILE=trim(trn_fullname),EXIST=existfile) IF(existfile) THEN ! unzipped version exists ch1='cp '//trim(trn_fullname)//' tmp1.file' CALL unixcmd(ch1) ELSE ! need to unzip INQUIRE(FILE=trim(trn_fullname)//'.gz',EXIST=existfile) IF(existfile) then ch1='gunzip -c '//trim(trn_fullname)//'>tmp1.file' PRINT *,'Unzipping the terrain file..' CALL unixcmd(ch1) PRINT *,'Terrain file unzipping competed..' ELSE print*,'File ',trim(trn_fullname),' or its gzipped version not found,' print*,'Terrain data read failed.' istatus = 1 STOP RETURN ENDIF END IF ! ! Read in terrain data ! call read_10x10_topo30s('tmp1.file',h_block,ll_lon, ll_lat, & lon_inc, lat_inc,imissing) write(6,'(4(f20.14),3i7)') ll_lon, ll_lat, lon_inc, lat_inc, imissing ! CALL unixcmd('/bin/rm tmp1.file') istatus = 0 ! RETURN END SUBROUTINE read_30s_trn SUBROUTINE read_10x10_topo30s(filename,it1,ll_lon,ll_lat, & 1 lon_inc,lat_inc,imissing) ! ! Read in 10x10 degrees 30 second encoded ASCII terrain file filename ! and store the values in it1 ! ! Author: Ming Xue (1/31/2002) ! IMPLICIT none character (len=*) :: filename INTEGER :: it1(1200,1200) Doubleprecision :: ll_lon,ll_lat,lon_inc,lat_inc INTEGER :: imissing character(len=1), ALLOCATABLE :: ichar1(:,:) character(len=1), ALLOCATABLE :: ichar2(:,:) INTEGER :: itopomax, itopomin INTEGER :: itopomax1,itopomin1 INTEGER :: i,j,ii real :: topomean1 ALLOCATE(ichar1(1200,1200),ichar2(1200,1200)) open(21,file=trim(filename),status='old',form='formatted') read(21,'(4(f20.14),3i7)')ll_lon,ll_lat,lon_inc,lat_inc, & itopomin,itopomax,imissing do j=1,1200 do i=1,1200,20 read(21,'(40a1)') (ichar1(i-1+ii,j),ichar2(i-1+ii,j),ii=1,20) enddo enddo close(21) do j=1,1200 do i=1,1200 it1(i,j) = (ichar(ichar1(i,j))-32)*110+ ichar(ichar2(i,j))-32 - 999 if( it1(i,j) .eq. -999) it1(i,j) = -9999 enddo enddo itopomin1 = 100000 itopomax1 = -100000 topomean1 = 0.0 do j=1,1200 do i=1,1200 if( it1(i,j).ne.-9999 .and. it1(i,j).gt.itopomax1) itopomax1=it1(i,j) if( it1(i,j).ne.-9999 .and. it1(i,j).lt.itopomin1) itopomin1=it1(i,j) if( it1(i,j).ne.-9999) topomean1 = topomean1 + it1(i,j) enddo enddo topomean1 = topomean1/(1200*1200) if( itopomin1 .eq. 100000 ) itopomin1 = -9999 if( itopomax1 .eq.-100000 ) itopomax1 = -9999 write(6,'(a,2i7,f20.14)') & 'Min., Max and mean of the 10x10 degree block are ', & itopomin1, itopomax1, topomean1 IF( itopomin1 .ne. itopomin1 .or.itopomax1.ne.itopomax ) then print*,'Warning: min or max in data read in do not agree with ' print*,'those in the header. Min., Max in thedata header were ', & itopomin, itopomax ENDIF DEALLOCATE(ichar1,ichar2) END SUBROUTINE read_10x10_topo30s SUBROUTINE plot_trn(z,x,y,m,m1,m2,n,n1,n2,x1,x2,xstep, & 1,2 y1,y2,ystep,zinc,tem,xw,yw) IMPLICIT NONE INTEGER :: m,m1,m2,n,n1,n2 REAL :: x1,x2,xstep,y1,y2,ystep REAL :: z(m,n),x(m,n),y(m,n),cl(100) REAL :: tem(m,n),xw(8*m),yw(8*m) REAL :: zinc,zmin, zmax, amax, amin CHARACTER (LEN=80) :: ch INTEGER :: lch, mode, ncl REAL :: pl, pr, pb, pt, px, py, pxc, pyc, xs, ys ! ! Setup device and define plotting space. ! pl = 0.15 pr = 0.85 pb = 0.15 pt = 0.85 px = pr - pl py = pt - pb pxc = (pr+pl)/2 pyc = (pb+pt)/2 xs = x2-x1 ys = y2-y1 IF( py/px >= ys/xs ) THEN py = ys/xs*px CALL xpspac(pl, pr, pyc-py/2, pyc+py/2 ) ELSE px = xs/ys*py CALL xpspac(pxc-px/2, pxc+px/2, pb, pt) END IF CALL xmap(x1,x2,y1,y2) ! ! Call XCONTA and XCLIMT to plot a contour map with default options. ! cl(1)=0.0 cl(2)=zinc CALL xnctrs(10,100 ) mode=1 PRINT*,'m,m1,m2, n,n1,n2=' , m,m1,m2, n,n1,n2 CALL a3dmax0(z,1,m,m1,m2,1,n,n1,n2,1,1,1,1, amax,amin) WRITE(6,'(1x,2(a,e13.6))') & 'Min. terrain= ', amin,', Max. terrain=',amax CALL xctrclr(46,68) CALL xctrlim(0.0, amax) CALL xctrlim(0.0, 0.0) ! call xcontcopt(2) CALL xcolfil( tem,xw,yw,m,m2-m1+1,n2-n1+1, cl, ncl,mode) CALL xchsiz( 0.025 * (y2-y1)) CALL xcpalet(2,-9999.9, -9999.0) CALL xclfmt('(I4)') CALL xctrclr(1,1) ! CALL XCONTA(Z(m1,n1),X(m1,n1),Y(m1,n1),tem,M,m2-m1+1,n2-n1+1, ! : CL, NCL,MODE) ! zmax=cl(ncl) zmin=cl(1) zinc=cl( MIN(2,ncl) )-cl(1) CALL xchsiz(0.03*(y2-y1)) WRITE(ch,'(''HMIN='',F6.1,'' HMAX='',F6.1,'' INC='',F5.1)') & amin, amax, zinc lch = 80 CALL strlnth(ch,lch) CALL xcolor(1) CALL xcharc((x1+x2)*0.5,y2+0.01*(y2-y1),ch(1:lch)) ! ! Draw a border and plot ticks and labels on the border. ! CALL xaxsca(x1,x2,xstep,y1,y2,ystep) RETURN END SUBROUTINE plot_trn SUBROUTINE smth(a,m,m1,m2,n,n1,n2, ismooth,tem) 1 ! Two-Dimension smooth use nine-points IMPLICIT NONE INTEGER :: m,n,m1,m2,n1,n2 INTEGER :: ismooth INTEGER :: i,j,im,ip,jm,jp REAL :: s REAL :: a(m,n) REAL :: tem(m,n) IF(ismooth == 0) RETURN DO j=1,n DO i=1,m tem(i,j) = a(i,j) END DO END DO IF(ismooth == 1) THEN ! 5 point smoothing PRINT*,'Performing 5-point smoothing on input array' s=0.5 DO j=n1,n2 DO i=m1,m2 im=MAX(m1,i-1) ip=MIN(m2,i+1) jm=MAX(n1,j-1) jp=MIN(n2,j+1) tem(i,j)=a(i,j)*(1.-s) + & ( a(ip,j)+a(im,j)+a(i,jp)+a(i,jm) )*0.25*s END DO END DO ELSE IF(ismooth == 2) THEN ! 9 point smoothing PRINT*,'Performing 9-point smoothing on input array' s=0.5 DO j=n1,n2 DO i=m1,m2 im=MAX(m1,i-1) ip=MIN(m2,i+1) jm=MAX(n1,j-1) jp=MIN(n2,j+1) tem(i,j)=a(i,j)*(1.-s)**2 + & ( a(ip,j)+a(im,j)+a(i,jp)+a(i,jm) )*0.5*s*(1.-s) & + ( a(im,jm)+a(im,jp)+a(ip,jm)+a(ip,jp) ) & *0.25*s**2 END DO END DO ELSE IF(ismooth == 3) THEN ! horizontal smoothing only PRINT*,'Performing horizontal smoothing on input array' s=0.5 DO j=n1,n2 DO i=m1,m2 im=MAX(m1,i-1) ip=MIN(m2,i+1) tem(i,j)=a(i,j)*(1.-s)+(a(ip,j)+a(im,j))*0.5*s END DO END DO ELSE IF(ismooth == 4) THEN ! vertical smoothing only PRINT*,'Performing vertical smoothing on input array' s=0.5 DO j=n1,n2 DO i=m1,m2 jm=MAX(n1,j-1) jp=MIN(n2,j+1) tem(i,j)=a(i,j)*(1.-s)+(a(i,jp)+a(i,jm))*0.5*s END DO END DO END IF DO j=n1,n2 DO i=m1,m2 a(i,j) = tem(i,j) END DO END DO RETURN END SUBROUTINE smth