!######################################################################## !######################################################################## !###### ###### !###### PROGRAM VERIFGRID ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !######################################################################## !######################################################################## PROGRAM verifgrid,38 !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Reads in two verification files, performs horizontal grid ! interpolation if desired by the user, and outputs bias and RMSE ! scores. ! ! AUTHOR: Eric Kemp, November 1999 ! ! MODIFICATION HISTORY ! Eric Kemp, 31 March 2000 ! Added lat/lon coordinates of corners for NCL plotting. Also replaced ! some modules with FORTRAN 77 include files, modified character ! variable declarations, and corrected bug in wind differences ! calculations. ! ! Eric Kemp, 7 July 2000 ! Added allocation statement for arrays iloc and jloc when grids match. ! !----------------------------------------------------------------------- ! ! Use modules ! !----------------------------------------------------------------------- ! USE extdims2 USE verif !----------------------------------------------------------------------- ! ! Variable declarations ! !----------------------------------------------------------------------- IMPLICIT NONE INCLUDE 'globcst.inc' INTEGER :: fdate(6),adate(6) INTEGER,ALLOCATABLE :: ftimesec(:),atimesec(:),timesec(:) INTEGER :: fmapproj,amapproj REAL :: fscale,ascale REAL :: ftrulat(2),ftrulon,atrulat(2),atrulon REAL :: fdx,fdy,adx,ady REAL :: fscswlat,fscswlon,ascswlat,ascswlon REAL :: fmapswlat,fmapswlon,amapswlat,amapswlon REAL :: fmapnwlat,fmapnwlon,amapnwlat,amapnwlon REAL :: fmapselat,fmapselon,amapselat,amapselon REAL :: fmapnelat,fmapnelon,amapnelat,amapnelon REAL :: corner_lat(2,2), corner_lon(2,2) REAL :: imapswlat,imapswlon,imapnwlat,imapnwlon, & imapselat,imapselon,imapnelat,imapnelon CHARACTER*4 :: fmodel,fgrid,amodel,agrid, fid_p, aid_p, fid_sfc, aid_sfc CHARACTER*16 :: fname_p, fname_sfc, aname_p, aname_sfc CHARACTER*3 :: funit_p, funit_sfc, aunit_p, aunit_sfc LOGICAL :: comcoord REAL,ALLOCATABLE :: fx_ext(:),ax_ext(:),fxs(:),axs(:) REAL,ALLOCATABLE :: fy_ext(:),ay_ext(:),fys(:),ays(:) REAL :: fx0,ax0,fy0,ay0 REAL,ALLOCATABLE :: flat_ext(:,:),alat_ext(:,:) REAL,ALLOCATABLE :: flon_ext(:,:),alon_ext(:,:) REAL,ALLOCATABLE :: dxfld(:),dyfld(:),rdxfld(:),rdyfld(:) REAL,ALLOCATABLE,DIMENSION(:,:) :: slopey, alphay, betay REAL,ALLOCATABLE :: ftem(:,:),item(:,:),atem(:,:),dtem(:,:) REAL :: avgitem,avgatem INTEGER :: itemcount,atemcount INTEGER,ALLOCATABLE :: iloc(:,:),jloc(:,:) REAL,ALLOCATABLE :: fx2d(:,:),fy2d(:,:) REAL,ALLOCATABLE :: ax2d(:,:),ay2d(:,:) REAL,ALLOCATABLE, DIMENSION(:,:,:,:) :: & fvar_sfc, ivar_sfc, avar_sfc, diff_sfc REAL,ALLOCATABLE, DIMENSION(:,:,:,:,:) :: & fvar_p, ivar_p, avar_p, diff_p REAL,ALLOCATABLE :: fvar2d(:,:) REAL :: vtrulat(2),vscale REAL,ALLOCATABLE :: vxs(:),vys(:) REAL,ALLOCATABLE :: vx(:),vy(:) REAL,ALLOCATABLE :: vx2d(:,:),vy2d(:,:) !----------------------------------------------------------------------- ! ! Functions ! !----------------------------------------------------------------------- REAL,EXTERNAL :: pntint2d2 !fpp$ expand (pntint2d2) !dir$ inline always pntint2d2 !----------------------------------------------------------------------- ! ! Miscellaneous variables ! !----------------------------------------------------------------------- REAL,PARAMETER :: missing = -9999. INTEGER,PARAMETER :: imissing = -9999 INTEGER :: i,j,k,l,ii,jj,kk,ll,m,n INTEGER :: fn_datasets,an_datasets INTEGER :: maxntime INTEGER :: imin,imax,jmin,jmax INTEGER :: aimin,aimax,ajmin,ajmax REAL :: maxy2d,miny2d,maxx2d,minx2d REAL :: maxay2d,minay2d,maxax2d,minax2d REAL :: vxctr,vyctr REAL :: vxmin,vxmax,vymin,vymax INTEGER,ALLOCATABLE :: counter_p(:,:,:), counter_sfc(:,:) REAL,ALLOCATABLE, DIMENSION(:,:,:) :: bias_p, rms_p REAL,ALLOCATABLE, DIMENSION(:,:) :: bias_sfc, rms_sfc REAL :: vctrx,vctry,vswx,vswy INTEGER :: status INTEGER :: fistart,fiend,fjstart,fjend INTEGER :: fimid,fjmid REAL :: fxmid,fymid REAL :: axpnt,aypnt INTEGER :: mastercounter CHARACTER*72 :: line72= & '------------------------------------------------------------------------' INTEGER :: fflag_p,fflag_sfc INTEGER :: aflag_p,aflag_sfc INTEGER :: vflag_p,vflag_sfc !----------------------------------------------------------------------- ! ! Namelists ! !----------------------------------------------------------------------- INTEGER :: fnx,fny,fntime, fextdopt CHARACTER*256 :: ffilename NAMELIST /forecast/ fnx,fny,fntime,fextdopt,ffilename INTEGER :: anx,any,antime, aextdopt CHARACTER*256 :: afilename NAMELIST /analysis/ anx,any,antime,aextdopt,afilename INTEGER :: korder NAMELIST /interp/ korder INTEGER :: vmapproj, vnx,vny, vbuffer, vimin,vimax,vjmin,vjmax REAL :: vdx,vdy,vctrlat,vctrlon, vtrulat1,vtrulat2,vtrulon,vsclfct NAMELIST /verification/ vdx,vdy,vctrlat,vctrlon,vmapproj,vtrulat1,vtrulat2, & vtrulon,vsclfct,vnx,vny,vbuffer,vimin,vimax,vjmin, & vjmax CHARACTER*256 :: statsfile,hfilename,hdiffile INTEGER :: if_diff=0 NAMELIST /stats/ statsfile,hfilename,hdiffile, if_diff !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ fmodel='' fgrid='' amodel='' agrid='' WRITE(6,'(//5x,a)') & &'###################################################################' WRITE(6,'(5x,a,/5x,a)') & &'# #',& &'# Welcome to VERIFGRID, a program that reads in verification #' WRITE(6,'(5x,a)') & &'# HDF files from CVT2VERIF and calculates statistics in text #' WRITE(6,'(5x,a)') & &'# and HDF format. #',& &'# #',& &'###################################################################' WRITE(6,*) !----------------------------------------------------------------------- ! ! Read in namelists ! !----------------------------------------------------------------------- PRINT *, 'Reading NAMELIST forecast' READ(5,forecast) PRINT *, 'Reading NAMELIST analysis' READ(5,analysis) PRINT *, 'Reading NAMELIST interp' READ(5,interp) PRINT *, 'Reading NAMELIST verification' READ(5,verification) PRINT *, 'Reading NAMELIST stats' READ(5,stats) !----------------------------------------------------------------------- ! ! Read forecast data. ! !----------------------------------------------------------------------- ALLOCATE (ftimesec(fntime), & fvar_p(fnx,fny,nlevel,fntime,nvar_sfc), & fvar_sfc(fnx,fny,fntime,nvar_sfc), & STAT=status) IF (status /= 0) CALL alloc_fail (status, 'f1') CALL rdverif ( fnx,fny,nlevel,fntime,nvar_p,nvar_sfc, & ffilename,fmodel,fgrid,fdate,ftimesec,pressure, & fmapproj, fscale, ftrulat(1),ftrulat(2),ftrulon, & fdx,fdy, fscswlat,fscswlon, & fmapswlat,fmapswlon,fmapnwlat,fmapnwlon, & fmapselat,fmapselon,fmapnelat,fmapnelon, & fflag_p,fvar_p, fid_p, fname_p, funit_p, & fflag_sfc,fvar_sfc, fid_sfc, fname_sfc, funit_sfc ) CALL setmapr(fmapproj,fscale,ftrulat,ftrulon) CALL lltoxy(1,1,fscswlat,fscswlon,fx0,fy0) CALL setorig(1,fx0,fy0) ALLOCATE (fx_ext(fnx), fxs(fnx), fy_ext(fny), fys(fny), & flat_ext(fnx,fny), flon_ext(fnx,fny), STAT=status) IF (status /= 0) CALL alloc_fail (status, 'f2') DO i = 1,fnx fx_ext(i) = (i-1)*fdx END DO DO j = 1,fny fy_ext(j) = (j-1)*fdy END DO fxs = fx_ext fys = fy_ext CALL xytoll(fnx,fny,fxs,fys,flat_ext,flon_ext) !----------------------------------------------------------------------- ! ! Read analysis data ! !----------------------------------------------------------------------- ALLOCATE (atimesec(antime),& avar_p(anx,any,nlevel,antime,nvar_sfc), & avar_sfc(anx,any,antime,nvar_sfc), & STAT=status) IF (status /= 0) CALL alloc_fail (status, 'a1') avar_sfc(:,:,:,:) = missing CALL rdverif ( anx,any,nlevel,antime,nvar_p,nvar_sfc, & afilename,amodel,agrid,adate,atimesec,pressure, & amapproj, ascale, atrulat(1),atrulat(2),atrulon, & adx,ady,ascswlat,ascswlon, & amapswlat,amapswlon,amapnwlat,amapnwlon, & amapselat,amapselon,amapnelat,amapnelon, & aflag_p,avar_p, aid_p, aname_p, aunit_p, & aflag_sfc,avar_sfc, aid_sfc, aname_sfc, aunit_sfc ) CALL setmapr(amapproj,ascale,atrulat,atrulon) CALL lltoxy(1,1,ascswlat,ascswlon,ax0,ay0) CALL setorig(1,ax0,ay0) ALLOCATE (ax_ext(anx), axs(anx), ay_ext(any), ays(any), & alat_ext(anx,any), alon_ext(anx,any), STAT=status) IF (status /= 0) CALL alloc_fail (status, 'a2') DO i = 1,anx ax_ext(i) = (i-1)*adx END DO DO j = 1,any ay_ext(j) = (j-1)*ady END DO axs = ax_ext ays = ay_ext CALL xytoll(anx,any,axs,ays,alat_ext,alon_ext) !----------------------------------------------------------------------- ! ! Determine if start dates for forecast and analysis datasets match. ! !----------------------------------------------------------------------- DO i=1,6 IF (fdate(i) /= adate(i)) THEN PRINT *, 'FATAL: Forecast and analysis start dates do not match' PRINT *, 'fdate= ', fdate PRINT *, 'adate= ', adate STOP END IF END DO !----------------------------------------------------------------------- ! ! Determine if grids match. ! !----------------------------------------------------------------------- PRINT *, 'Checking to see if grids match' ALLOCATE (fx2d(fnx,fny), fy2d(fnx,fny), & ax2d(anx,any), ay2d(anx,any), STAT=status) IF (status /= 0) CALL alloc_fail (status, 'fa') IF (fmapproj == amapproj .AND. fscale == ascale .AND. & ftrulat(1) == atrulat(1) .AND. ftrulat(2) == atrulat(2) .AND. & ftrulon == atrulon .AND. fdx == adx .AND. fdy == ady .AND. & fnx == anx .AND. fny == any .AND. fscswlat == ascswlat .AND. & fscswlon == ascswlon ) THEN comcoord = .TRUE. WRITE(6,*)' Grids share a common coordinate system' DO j = 1,any ax2d(:,j) = axs(:) END DO DO i = 1,anx ay2d(i,:) = ays(:) END DO ELSE comcoord = .FALSE. WRITE(6,*)'Grid coordinate systems differ, converting lat/lon' CALL setmapr(fmapproj,fscale,ftrulat,ftrulon) CALL setorig(1,fx0,fy0) CALL lltoxy(anx,any,alat_ext,alon_ext,ax2d,ay2d) CALL lltoxy(fnx,fny,flat_ext,flon_ext,fx2d,fy2d) ENDIF !----------------------------------------------------------------------- ! ! If grids are different, horizontally interpolate the forecast ! to the analysis. ! !----------------------------------------------------------------------- ALLOCATE (ivar_p(anx,any,nlevel,fntime,nvar_p), & ivar_sfc(anx,any,fntime,nvar_sfc), STAT=status) IF (status /= 0) CALL alloc_fail (status, 'ivar') ivar_p(:,:,:,:,:) = missing ivar_sfc(:,:,:,:) = missing CALL FLUSH (6) IF (.NOT.comcoord) THEN ALLOCATE (dxfld(fnx), dyfld(fny), rdxfld(fnx), rdyfld(fny), & slopey(fnx,fny), alphay(fnx,fny), betay(fnx,fny), & ftem(fnx,fny), item(anx,any), atem(anx,any), dtem(anx,any), & iloc(anx,any), jloc(anx,any), fvar2d(fnx,fny), STAT=status) IF (status /= 0) CALL alloc_fail (status, 'x') item(:,:) = missing atem(:,:) = missing dtem(:,:) = missing iloc(:,:) = imissing jloc(:,:) = imissing PRINT *, 'Calling setdxdy' CALL setdxdy(fnx,fny,1,fnx-1,1,fny-1,fxs,fxs,dxfld,dyfld, & rdxfld,rdyfld) PRINT *, 'Calling setijloc2' CALL setijloc2(fnx,fny,anx,any,iloc,jloc,fx2d,fy2d,ax2d,ay2d) PRINT *, 'Interpolating sfc vars' DO l = 1,nvar_sfc DO k = 1,fntime CALL setdrvy2(fnx,fny,1,2,fnx-1,2,fny-1,1,1,dyfld, & rdyfld,fvar_sfc(1,1,k,l),slopey,alphay,betay) DO n = 2,any-1 DO m = 2,anx-1 IF (iloc(m,n) /= imissing .AND. jloc(m,n) /= imissing) THEN i = iloc(m,n) j = jloc(m,n) IF (fvar_sfc(i,j,k,l) /= missing .AND. & fvar_sfc(i-1,j,k,l) /= missing .AND. & fvar_sfc(i+1,j,k,l) /= missing .AND. & fvar_sfc(i,j-1,k,l) /= missing .AND. & fvar_sfc(i,j+1,k,l) /= missing) THEN ivar_sfc(m,n,k,l) = pntint2d2(fnx,fny,3,fnx-3,3,fny-2, & korder,fxs,fys,ax2d(m,n), & ay2d(m,n),i,j, & fvar_sfc(1,1,k,l), & dxfld,dyfld,rdxfld,rdyfld,& slopey,alphay,betay) ENDIF ENDIF END DO END DO END DO END DO PRINT *, 'Interpolating pressure vars' DO l = 1,nvar_p DO k = 1,fntime DO kk = 1,nlevel CALL setdrvy2(fnx,fny,1,2,fnx-1,2,fny-1,1,1,dyfld, & rdyfld,fvar_p(1,1,kk,k,l),slopey,alphay,betay) DO n = 2,any-1 DO m = 2,anx-1 IF (iloc(m,n) /= imissing .AND. jloc(m,n) /= imissing) THEN i = iloc(m,n) j = jloc(m,n) IF (fvar_p(i,j,kk,k,l) /= missing .AND. & fvar_p(i-1,j,kk,k,l) /= missing .AND. & fvar_p(i+1,j,kk,k,l) /= missing .AND. & fvar_p(i,j-1,kk,k,l) /= missing .AND. & fvar_p(i,j+1,kk,k,l) /= missing) THEN ivar_p(m,n,kk,k,l) = pntint2d2(fnx,fny,3,fnx-3,3,fny-3, & korder,fxs,fys,ax2d(m,n), & ay2d(m,n),i,j, & fvar_p(1,1,kk,k,l), & dxfld,dyfld,rdxfld,rdyfld,& slopey,alphay,betay) END IF END IF END DO !m END DO !n END DO !kk END DO !k END DO !l ELSE ALLOCATE (iloc(anx,any), jloc(anx,any), STAT=status) ! EMK 7/7/00 ivar_p = fvar_p ivar_sfc = fvar_sfc ENDIF !----------------------------------------------------------------------- ! ! Set limits of verification domain. ! !----------------------------------------------------------------------- IF (vbuffer >= 0) THEN vimin = 1+vbuffer vjmin = 1+vbuffer vimax = vnx-vbuffer vjmax = vny-vbuffer ENDIF IF (vimin < 1) THEN vimin = 1 WRITE(6,*)'ERROR: vimin < 1. Resetting vimin to ',vimin ENDIF IF (vjmin < 1) THEN vjmin = 1 WRITE(6,*)'ERROR: vjmin < 1. Resetting vjmin to ',vjmin ENDIF IF (vimax > vnx) THEN vimax = vnx WRITE(6,*)'ERROR: vimax > vnx. Resetting vimax to ',vimax ENDIF IF (vjmax > vny) THEN vjmax = vny WRITE(6,*)'ERROR: vjmax > vny. Resetting vjmax to ',vjmax ENDIF vtrulat(1) = vtrulat1 vtrulat(2) = vtrulat2 vscale = vsclfct ALLOCATE (vxs(vnx),vys(vny), vx(vnx),vy(vny), vx2d(vnx,vny),vy2d(vnx,vny), & STAT=status) IF (status /= 0) CALL alloc_fail (status, 'z') iloc(:,:) = imissing jloc(:,:) = imissing CALL setmapr(vmapproj,vscale,vtrulat,vtrulon) CALL lltoxy(1,1,vctrlat,vctrlon,vctrx,vctry) vswx = vctrx - (FLOAT(vnx-3)/2.) * (vdx*vsclfct) vswy = vctry - (FLOAT(vny-3)/2.) * (vdy*vsclfct) CALL setorig (1,vswx,vswy) DO i = 1,vnx vx(i) = (i-2)*vdx END DO DO j = 1,vny vy(j) = (j-2)*vdy END DO DO i = 1,vnx-1 vxs(i) = 0.5*(vx(i)+vx(i+1)) END DO vxs(vnx) = (2.*vx(vnx))-vx(vnx-1) DO j = 1,vny-1 vys(j) = 0.5*(vy(j)+vy(j+1)) END DO vys(vny) = (2.*vy(vny))-vy(vny-1) DO j = 1,vny vx2d(:,j) = vxs(:) END DO DO i = 1,vnx vy2d(i,:) = vys(:) END DO CALL lltoxy(anx,any,alat_ext,alon_ext,ax2d,ay2d) CALL setijloc2(vnx,vny,anx,any,iloc,jloc,vx2d,vy2d,ax2d,ay2d) CALL xytoll ( 1, 1, vx2d(vimin,vjmin), vy2d(vimin,vjmin), & corner_lat(1,1), corner_lon(1,1) ) CALL xytoll ( 1, 1, vx2d(vimin,vjmax), vy2d(vimin,vjmax), & corner_lat(1,2), corner_lon(1,2) ) CALL xytoll ( 1, 1, vx2d(vimax,vjmin), vy2d(vimax,vjmin), & corner_lat(2,1), corner_lon(2,1) ) CALL xytoll ( 1, 1, vx2d(vimax,vjmax), vy2d(vimax,vjmax), & corner_lat(2,2), corner_lon(2,2) ) !----------------------------------------------------------------------- ! ! Calculate differences for each variable ! !----------------------------------------------------------------------- maxntime = MIN(fntime,antime) WRITE(6,*)'maxntime = ',maxntime ALLOCATE (timesec(maxntime), & diff_p(anx,any,nlevel,maxntime,nvar_sfc_stats), & diff_sfc(anx,any,maxntime,nvar_sfc_stats), & STAT=status) IF (status /= 0) CALL alloc_fail (status, 'd') diff_sfc(:,:,:,:) = missing diff_p(:,:,:,:,:) = missing m = 0 DO k = 1,fntime DO kk = 1,antime IF (ftimesec(k) == atimesec(kk)) THEN m = m + 1 timesec(m) = ftimesec(k) END IF END DO END DO maxntime = m PRINT *, 'Times in fcst file (', m, '):', ftimesec(1:fntime) PRINT *, 'Times in anl file (', m, '):', atimesec(1:antime) PRINT *, 'Times in both files (', m, '):', timesec(1:m) PRINT *, 'Computing differences of pressure vars' DO l = 1,nvar_p DO k = 1, fntime DO kk = 1,antime DO m = 1,maxntime IF (timesec(m) == ftimesec(k) .AND. & timesec(m) == atimesec(kk)) THEN mastercounter = 0 DO ll = 1,nlevel DO j = 1,any-1 DO i = 1,anx-1 IF (iloc(i,j) /= imissing .AND. iloc(i,j) >= vimin & .AND. iloc(i,j) <= vimax .AND. & jloc(i,j) /= imissing .AND. jloc(i,j) >= vjmin & .AND. jloc(i,j) <= vjmax) THEN mastercounter = mastercounter + 1 IF (ivar_p(i,j,ll,k,l) /= missing .AND. & avar_p(i,j,ll,kk,l) /= missing) THEN diff_p(i,j,ll,m,l) = ivar_p(i,j,ll,k,l) - & avar_p(i,j,ll,kk,l) ENDIF ENDIF END DO !i END DO !j END DO !ll ENDIF END DO !m END DO !kk END DO !k END DO !l PRINT *, 'Computing differences of sfc vars' DO l = 1,nvar_sfc DO k = 1, fntime DO kk = 1,antime DO m = 1,maxntime IF (timesec(m) == ftimesec(k) .AND. & timesec(m) == atimesec(kk)) THEN mastercounter = 0 DO j = 2,any-1 DO i = 2,anx-1 IF (iloc(i,j) /= imissing .AND. iloc(i,j) >= vimin & .AND. iloc(i,j) <= vimax .AND. & jloc(i,j) /= imissing .AND. jloc(i,j) >= vjmin & .AND. jloc(i,j) <= vjmax) THEN mastercounter = mastercounter + 1 IF (ivar_sfc(i,j,k,l) /= missing .AND. & avar_sfc(i,j,kk,l) /= missing) THEN diff_sfc(i,j,m,l) = ivar_sfc(i,j,k,l) - avar_sfc(i,j,kk,l) ENDIF ENDIF END DO !i END DO !j ENDIF END DO !m END DO !kk END DO !k END DO !l !----------------------------------------------------------------------- ! ! Calculate differences for total winds ! !----------------------------------------------------------------------- PRINT *, 'Computing differences of total winds at sfc' n = 0 ! index of sfc DO k = 1,fntime DO kk = 1,antime DO m = 1,maxntime IF (timesec(m) == ftimesec(k) .AND. & timesec(m) == atimesec(kk)) THEN DO j = 1,any-1 DO i = 1,anx-1 IF (iloc(i,j) /= imissing .AND. iloc(i,j) >= vimin .AND. & iloc(i,j) <= vimax .AND. jloc(i,j) /= imissing .AND. & jloc(i,j) >= vjmin .AND. jloc(i,j) <= vjmax) THEN IF (avar_sfc(i,j,kk,id_u) /= missing .AND. & avar_sfc(i,j,kk,id_v) /= missing .AND. & ivar_sfc(i,j,k,id_u) /= missing .AND. & ivar_sfc(i,j,k,id_u) /= missing) THEN diff_sfc(i,j,m,id_wspd) = & SQRT( ivar_sfc(i,j,k,id_u)**2 + ivar_sfc(i,j,k,id_v)**2 ) - & SQRT( avar_sfc(i,j,kk,id_u)**2 + avar_sfc(i,j,kk,id_v)**2 ) END IF END IF END DO END DO END IF END DO END DO END DO PRINT *, 'Computing differences of total winds at pressure levels' DO k = 1,fntime DO kk = 1,antime DO m = 1,maxntime IF (timesec(m) == ftimesec(k) .AND. & timesec(m) == atimesec(kk)) THEN DO n=1,nlevel DO j = 1,any-1 DO i = 1,anx-1 IF (iloc(i,j) /= imissing .AND. iloc(i,j) >= vimin .AND. & iloc(i,j) <= vimax .AND. jloc(i,j) /= imissing .AND. & jloc(i,j) >= vjmin .AND. jloc(i,j) <= vjmax) THEN IF (avar_p(i,j,n,kk,id_u) /= missing .AND. & avar_p(i,j,n,kk,id_v) /= missing .AND. & ivar_p(i,j,n,k,id_u) /= missing .AND. & ivar_p(i,j,n,k,id_u) /= missing) THEN diff_p(i,j,n,m,id_wspd) = & SQRT( ivar_p(i,j,n,k,id_u)**2 + ivar_p(i,j,n,k,id_v)**2 ) - & SQRT( avar_p(i,j,n,kk,id_u)**2 + avar_p(i,j,n,kk,id_v)**2 ) END IF END IF END DO END DO END DO END IF END DO END DO END DO !----------------------------------------------------------------------- ! ! Calculate statistics ! !----------------------------------------------------------------------- ALLOCATE ( bias_p(nlevel,maxntime,nvar_p_stats), & rms_p(nlevel,maxntime,nvar_p_stats), & bias_sfc(maxntime,nvar_sfc_stats), & rms_sfc(maxntime,nvar_sfc_stats), & counter_sfc(maxntime,nvar_sfc_stats), & counter_p(nlevel,maxntime,nvar_p_stats), & STAT=status) IF (status /= 0) CALL alloc_fail (status, 'stats') bias_p(:,:,:) = 0.0 rms_p(:,:,:) = 0.0 bias_sfc(:,:) = 0.0 rms_sfc(:,:) = 0.0 counter_sfc(:,:) = 0 counter_p(:,:,:)= 0 ! 5D vars PRINT *, 'Computing statistics on pressure levels' DO l = 1,nvar_p DO k = 1,maxntime DO m = 1,nlevel DO j = 1,any DO i = 1,anx IF (diff_p(i,j,m,k,l) /= missing) THEN bias_p(m,k,l) = bias_p(m,k,l) + diff_p(i,j,m,k,l) rms_p(m,k,l) = rms_p(m,k,l) + diff_p(i,j,m,k,l)**2 counter_p(m,k,l) = counter_p(m,k,l) + 1 ENDIF END DO END DO IF (counter_p(m,k,l) > 0) THEN bias_p(m,k,l) = bias_p(m,k,l)/counter_p(m,k,l) rms_p(m,k,l) = SQRT( rms_p(m,k,l)/counter_p(m,k,l) ) ELSE bias_p(m,k,l) = missing rms_p(m,k,l) = missing ENDIF END DO !m END DO !k END DO !l ! 4D vars PRINT *, 'Computing statistics at sfc' DO l = 1,nvar_sfc DO k = 1,maxntime DO j = 1,any DO i = 1,anx IF (diff_sfc(i,j,k,l) /= missing) THEN bias_sfc(k,l) = bias_sfc(k,l) + diff_sfc(i,j,k,l) rms_sfc(k,l) = rms_sfc(k,l) + diff_sfc(i,j,k,l)**2 counter_sfc(k,l) = counter_sfc(k,l) + 1 ENDIF END DO END DO IF (counter_sfc(k,l) > 0) THEN bias_sfc(k,l) = bias_sfc(k,l)/counter_sfc(k,l) rms_sfc(k,l) = SQRT( rms_sfc(k,l)/counter_sfc(k,l) ) ELSE bias_sfc(k,l) = missing rms_sfc(k,l) = missing ENDIF END DO !k END DO !l PRINT *, 'Computing wind statistics at p' DO k = 1,maxntime DO m = 1,nlevel DO j = 1,any DO i = 1,anx IF (diff_p(i,j,m,k,id_wspd) /= missing) THEN bias_p(m,k,id_wspd) = bias_p(m,k,id_wspd) + diff_p(i,j,m,k,id_wspd) rms_p(m,k,id_wspd) = rms_p(m,k,id_wspd) + diff_p(i,j,m,k,id_wspd)**2 rms_p(m,k,id_wvec) = rms_p(m,k,id_wvec) + & diff_p(i,j,m,k,id_u)**2 + diff_p(i,j,m,k,id_v)**2 counter_p(m,k,id_wspd) = counter_p(m,k,id_wspd) + 1 ENDIF END DO END DO counter_p(m,k,id_wvec) = counter_p(m,k,id_wspd) IF (counter_p(m,k,id_wspd) > 0) THEN bias_p(m,k,id_wspd) = bias_p(m,k,id_wspd)/counter_p(m,k,id_wspd) rms_p(m,k,id_wspd) = SQRT( rms_p(m,k,id_wspd)/counter_p(m,k,id_wspd) ) rms_p(m,k,id_wvec) = SQRT( rms_p(m,k,id_wvec)/counter_p(m,k,id_wvec) ) ELSE bias_p(m,k,id_wspd) = missing rms_p(m,k,id_wspd) = missing rms_p(m,k,id_wvec) = missing ENDIF END DO END DO PRINT *, 'Computing wind statistics at sfc' DO k = 1,maxntime DO j = 1,any DO i = 1,anx IF (diff_sfc(i,j,k,id_wspd) /= missing) THEN bias_sfc(k,id_wspd) = bias_sfc(k,id_wspd) + diff_sfc(i,j,k,id_wspd) rms_sfc(k,id_wspd) = rms_sfc(k,id_wspd) + diff_sfc(i,j,k,id_wspd)**2 rms_sfc(k,id_wvec) = rms_sfc(k,id_wvec) + & diff_sfc(i,j,k,id_u)**2 + diff_sfc(i,j,k,id_v)**2 counter_sfc(k,id_wspd) = counter_sfc(k,id_wspd) + 1 ENDIF END DO END DO counter_sfc(k,id_wvec) = counter_sfc(k,id_wspd) IF (counter_sfc(k,id_wspd) > 0) THEN bias_sfc(k,id_wspd) = bias_sfc(k,id_wspd)/counter_sfc(k,id_wspd) rms_sfc(k,id_wspd) = SQRT( rms_sfc(k,id_wspd)/counter_sfc(k,id_wspd) ) rms_sfc(k,id_wvec) = SQRT( rms_sfc(k,id_wvec)/counter_sfc(k,id_wvec) ) ELSE bias_sfc(k,id_wspd) = missing rms_sfc(k,id_wspd) = missing rms_sfc(k,id_wvec) = missing ENDIF END DO !----------------------------------------------------------------------- ! ! Output statistics ! !----------------------------------------------------------------------- PRINT *, 'Writing text output to ', TRIM(statsfile) OPEN(UNIT=13,FILE=statsfile,STATUS="REPLACE") WRITE(13,600) 'Forecast initialized ',fdate(1),'-',fdate(2), & '-',fdate(3),'.',fdate(4),':',fdate(5),':',fdate(6) WRITE(13,610) 'Forecast model/grid:', TRIM(fmodel), TRIM(fgrid) WRITE(13,625) NINT((fnx+1)*fdx/1000.0), NINT((fny+1)*fdx/1000.0), & fdx/1000.0, fnx,fny WRITE(13,*) WRITE(13,610) 'Analysis model/grid:', TRIM(amodel), TRIM(agrid) WRITE(13,625) NINT((anx+1)*adx/1000.0), NINT((any+1)*adx/1000.0), & adx/1000.0, anx,any WRITE(13,*) WRITE(13,*) 'Verification Region:' WRITE(13,625) NINT((vnx+1)*vdx/1000.0), NINT((vny+1)*vdx/1000.0), & vdx/1000.0, vnx,vny WRITE(13,650) 'NW/NE', & corner_lat(1,2),corner_lon(1,2),corner_lat(2,2),corner_lon(2,2) WRITE(13,650) 'SW/SE', & corner_lat(1,1),corner_lon(1,1),corner_lat(2,1),corner_lon(2,1) WRITE(13,*) 'Buffer: vimin/max, vjmin/max: ', vimin, vimax, vjmin, vjmax WRITE(13,*) 'Number of grid points in verif region: ', mastercounter WRITE(13,*) DO l = 1,nvar_sfc_stats WRITE(13,'(A)') TRIM(line72) WRITE(13,810) TRIM(varname_sfc(l)), TRIM(varunit_sfc(l)) WRITE(13,*) 'Time(hr) Grid Points Bias RMS Error' DO k = 1,maxntime WRITE(13,700) timesec(k)/3600, counter_sfc(k,l), & bias_sfc(k,l), rms_sfc(k,l) END DO END DO DO l = 1,nvar_p_stats DO m = 1,nlevel WRITE(13,'(A)') TRIM(line72) WRITE(13,810) TRIM(varname_p(l)), TRIM(varunit_p(l)) WRITE(13,*) 'Level = ', pressure(m) / 100.0, ' mb' WRITE(13,*) 'Time(hr) Grid Points Bias RMS Error' DO k = 1,maxntime WRITE(13,700) timesec(k)/3600, counter_p(m,k,l), & bias_p(m,k,l), rms_p(m,k,l) END DO END DO END DO PRINT *, 'Writing statistics to HDF file ', TRIM(hfilename) CALL wrt_verif_stats_diff (hfilename, if_diff, hdiffile, fdate, & amodel,agrid,adx,anx,any, & fmodel,fgrid,fdx, & vdx, vdy, vnx, vny, vmapproj, & vtrulat1, vtrulat2, vtrulon, vsclfct, vctrlat, vctrlon, & corner_lat, corner_lon, & nlevel, maxntime, nvar_p_stats, nvar_sfc_stats, & timesec, pressure, missing, mastercounter, & counter_p, bias_p, rms_p, diff_p, & counter_sfc, bias_sfc, rms_sfc, diff_sfc, & varid_p, varname_p, varunit_p, & varid_sfc, varname_sfc, varunit_sfc) WRITE(6,*)'Program verifgrid successfully completed.' 600 FORMAT (/1x,a21,i4.4,a1,i2.2,a1,i2.2,a1,i2.2,a1,i2.2,a1,i2.2) 610 FORMAT (1X,A,1X,A,' / ',A) 625 FORMAT (' Domain:',I5, ' x', I5, ' km, dx=', F5.1, & ' km (',I4,' x',I4,')' ) 650 FORMAT (1X,A,' corner lat/lon:', 2F10.3, 2X, 2F10.3) 700 FORMAT (1x,i8,2x,i11,2x,f8.2,3x,f8.2) 800 FORMAT (1x,i8,2x,i11,4x,f8.2,4x,f8.2,10x,f8.2) 810 FORMAT ( 1X,A," (",A,")" ) END PROGRAM verifgrid