!########################################################################
!########################################################################
!###### ######
!###### 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