!########################################################################
!########################################################################
!######### #########
!######### SUBROUTINE PREPSGLOBS #########
!######### #########
!######### Developed by #########
!######### Center for Analysis and Prediction of Storms #########
!######### University of Oklahoma #########
!######### #########
!########################################################################
!########################################################################
SUBROUTINE prepsglobs(mxsng,ntime,srcsng,nsrc_sng,sngfile, & 3,7
stnsng,latsng,lonsng,xsng,ysng,hgtsng, &
obsng,qobsng,qualsng,isrcsng,qsrc,chsrc, &
nx,ny,nz,nvar,anx,xs,ys,zp, &
shght,su,sv,spres,stheta,sqv, &
rmiss,nobsng,istatus)
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! This subroutine reads non-surface single-level data.
! The data are appended to surface data already collected.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Keith Brewster, CAPS
! October, 1997
!
! MODIFICATION HISTORY:
!
! 5/4/98 Developed based on RDRASS to assign height from background
! Can also be used to read satellite winds (John Manobianco).
!
! 1998/07/13 (Gene Bassett) Implemented general format for sgl obs
! and used this for MDCRS data.
!
! 1999/09/16 (Dingchen Hou) Modified the interpretion of MDCRS data.
!
! 1999/11/19 (Gene Bassett, Keith Brewster)
! Modified MDCRS data to use pressure only for deriving other
! observational quantities but not as a pressure observation in
! ADAS proper.
!
! 11/9/2001 (Keith Brewster)
! Added FORTRAN-90 features and rearranged the logic to eliminate
! GO-TOs, added processing for humidity and pressure data,
! and generally make it more suitable for additional data
! sources other than aircraft data.
!
! August 2002 (Eric Kemp)
! Fixed bug involving check of contents of chsng array. Further
! reorganizations/changes/updates.
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: mxsng ! Max possible number of
! single-point observations.
INTEGER, INTENT(IN) :: nvar ! Total number of observed
! variable types.
INTEGER, INTENT(IN) :: ntime ! Maximum number of time levels
! for observations.
INTEGER, INTENT(IN) :: nsrc_sng ! Max number of types of single
! point observations.
CHARACTER(LEN=8), INTENT(IN) :: srcsng(nsrc_sng) ! Observation types
CHARACTER(LEN=132), INTENT(IN) :: sngfile ! Name of SGL input file.
CHARACTER(LEN=5), INTENT(INOUT) :: stnsng(mxsng) ! ID of observations
REAL, INTENT(INOUT) :: latsng(mxsng) ! Observation latitude (deg N)
REAL, INTENT(INOUT) :: lonsng(mxsng) ! Observation longitude (deg E)
REAL, INTENT(INOUT) :: xsng(mxsng) ! Observation x grid coordinate (m)
REAL, INTENT(INOUT) :: ysng(mxsng) ! Observation y grid coordinate (m)
REAL, INTENT(INOUT) :: hgtsng(mxsng) ! Observation height (m MSL)
REAL, INTENT(INOUT) :: obsng(nvar,mxsng) ! Observation data by variable.
REAL, INTENT(INOUT) :: qobsng(nvar,mxsng) ! Observation standard error.
INTEGER, INTENT(INOUT) :: qualsng(nvar,mxsng) ! Observation quality
! indicator.
INTEGER, INTENT(INOUT) :: isrcsng(mxsng) ! Source number for each
! station.
REAL, INTENT(IN) :: qsrc(nvar,mxsng) ! Standard error of observation
! for each source.
CHARACTER(LEN=8), INTENT(INOUT) :: chsrc(mxsng,ntime) ! Source for each
! station.
INTEGER, INTENT(IN) :: nx,ny,nz ! Grid dimensions.
REAL, INTENT(IN) :: anx(nx,ny,nz,nvar) ! Gridded analysis data.
REAL, INTENT(IN) :: xs(nx) ! x-coordinates of grid scalar points (m)
REAL, INTENT(IN) :: ys(ny) ! y-coordinates of grid scalar points (m)
REAL, INTENT(IN) :: zp(nx,ny,nz) ! Height of grid w-points (m MSL)
REAL, INTENT(INOUT) :: shght(nz) ! Dummy array for height
REAL, INTENT(INOUT) :: su(nz) ! Dummy array for u-winds
REAL, INTENT(INOUT) :: sv(nz) ! Dummy array for v-winds
REAL, INTENT(INOUT) :: spres(nz) ! Dummy array for pressure
REAL, INTENT(INOUT) :: stheta(nz) ! Dummy array for pot. temperature
REAL, INTENT(INOUT) :: sqv(nz) ! Dummy array for specific humidity
REAL, INTENT(IN) :: rmiss ! Flag for missing data.
INTEGER, INTENT(INOUT) :: nobsng ! Total number of single-point
! observations stored in arrays
! (nobsng <= maxsng)
INTEGER, INTENT(INOUT) :: istatus ! Status flag
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'phycst.inc'
!-----------------------------------------------------------------------
!
! Internal parameters
!
!-----------------------------------------------------------------------
REAL, PARAMETER :: ktstoms=0.5144
REAL, PARAMETER :: mbtopa=100.
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: jsrc
INTEGER :: nprev
CHARACTER (LEN=132) :: line
INTEGER :: ivar,ksta,nsingle
INTEGER :: ipt,jpt,kgrid
INTEGER :: indom
INTEGER :: nlevs
CHARACTER (LEN=8) :: obs_id
INTEGER :: obs_num
CHARACTER (LEN=8) :: date_str
CHARACTER (LEN=6) :: time_str
INTEGER :: num_lines
CHARACTER (LEN=8) :: obs_type
REAL :: obs_lat,obs_lon,hgt_msl,hgt_agl
REAL :: obs_t,obs_td,obs_wspd,obs_wdir,obs_gust
REAL :: obs_psta,obs_pmsl,obs_palt,obs_vis
REAL :: xsta,ysta,tk,tdk,psta,qv,qvsat
CHARACTER (LEN=16) :: obs_wx
CHARACTER (LEN=6) :: fmt_in
INTEGER :: k,istat
REAL :: weight
REAL :: ddrot,selev
REAL :: altpres ! pressure derived from altimeter reading
INTEGER :: iunit
!-----------------------------------------------------------------------
!
! External functions
!
!-----------------------------------------------------------------------
REAL, EXTERNAL :: alttostpr
REAL, EXTERNAL :: msltostpr
REAL, EXTERNAL :: f_qvsat
REAL, EXTERNAL :: ztopsa
!fpp$ expand (alttostpr)
!!dir$ inline always alttostpr
!*$* inline routine (alttostpr)
!fpp$ expand (msltostpr)
!!dir$ inline always msltostpr
!*$* inline routine (msltostpr)
!fpp$ expand (f_qvsat)
!!dir$ inline always f_qvsat
!*$* inline routine (f_qvsat)
!fpp$ expand (ztopsa)
!!dir$ inline always ztopsa
!*$* inline routine (ztopsa)
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
CALL getunit
(iunit)
nprev = nobsng
WRITE(6,'(A,A)') ' Opening: ',sngfile
WRITE(6,'(A,I6,I6)') ' In PREPSGLOBS , mxsng, nprev = ', &
mxsng,nprev
OPEN(UNIT=iunit,FILE=trim(sngfile),STATUS='old',iostat=istat)
IF ( istat /= 0 ) THEN
WRITE(6,'(A)') ' Error opening file: ',sngfile
istatus = -1
RETURN
END IF
!-----------------------------------------------------------------------
!
! Main data-reading loop
!
!-----------------------------------------------------------------------
ksta = nobsng
DO ! Go line by line in file until end of file is reached
!-----------------------------------------------------------------------
!
! INPUT FORMAT:
!
! first line: obs_id, obs_num, date_str, time_str,
! obs_lat, obs_lon, hgt_msl, hgt_agl,
! obs_type, num_lines
!
! See MDCRS format below.
!
! obs_id station id (8 characters)
! obs_num station id number
! date_str yyyymmdd
! time_str hhmm
! obs_lat latidute (degrees)
! obs_lon longitude (degrees)
! hgt_msl height above mean sea level (m)
! value considered missing if <= rmiss
! hgt_agl height above ground level (m), optional,
! intended for use with surface obs to help with
! mis-matches in terrain
! value considered missing if <= rmiss
! obs_type ADAS observation type (8 characters)
! num_lines number of observation lines to follow
! the header line
!
! currently unused in ADAS:
! obs_id, obs_num, date_str, time_str, hgt_agl
!
!
! currently supported observation lines formatted as follows:
!
! FMT1 20.0 -10.0 215 10.0 100.0 1013.2 1013.2 100. +TSRA
! ______ _____ _____ ___ _____ _____ ______ ______ ____ ________________
!
! FMT1 obs_t, obs_td, obs_wdir, obs_wspd, obs_gust,
! obs_pmsl, obs_palt, obs_vis, obs_wx
!
! obs_t temperature (C)
! value considered missing if <= rmiss
! obs_td dew point (C)
! value considered missing if <= rmiss
! obs_wdir wind direction (degrees clockwise from north)
! value considered missing if < 0
! obs_wspd wind speed (m/s)
! value considered missing if <= rmiss
! obs_wdir wind direction (degrees clockwise from north)
! value considered missing if < 0
! obs_gust wind gust (m/s)
! value considered missing if <= rmiss
! obs_pmsl sea level pressure (mb)
! value considered missing if <= rmiss
! obs_palt altimiter setting (mb)
! value considered missing if <= rmiss
! obs_vis visibility (km)
! value considered missing if < 0
! obs_wx current weather (METAR format)
!
! currently unused in ADAS:
! obs_gust, obs_palt, obs_vis, obs_wx
!
!-----------------------------------------------------------------------
!
! Initially set all non-header line values to missing
!
!-----------------------------------------------------------------------
obs_t = rmiss
obs_td = rmiss
obs_wdir = -1
obs_wspd = rmiss
obs_wdir = -1
obs_gust = rmiss
obs_psta = rmiss
obs_pmsl = rmiss
obs_palt = rmiss
obs_vis = rmiss
obs_wx = ' '
altpres = rmiss
psta = rmiss
!-----------------------------------------------------------------------
!
! Read in the info for one station
! Skip comments
! Comments begin with # or !. Also, skip lines that begin with a space.
!
! Sample format
!XXXXXXXX 00000000 19990601_153600 42.7167 -84.9517 9448 -999.00 MDCRS 1
!-------- -------- -------- ------ -------- --------- ------ ------- -------- --
! A8, 1X, I8,1X,I4,2I2,1X,2I2,2X,1X,F8.4,1X,F9.4, 1X, I6,1X,F7.2,1X,A8,1X,I2
! MDCRS -39.8 -999.0 267 28.3 YYZ ORD FSL00307
!-----------------------------------------------------------------------
READ (iunit,'(A)',IOSTAT=istat) line
IF (istat /= 0) EXIT ! Get out of DO loop
IF (line(1:1) == '#' .OR. line(1:1) == '!' .OR. line(1:1) == ' ') CYCLE
READ(line, &
'(a8,1x,i8,1x,a8,1x,a6,1x,f8.4,1x,f9.4,1x,f6.0,1x,f7.2,1x,a8,1x,i2)', &
IOSTAT=istat) obs_id, obs_num, date_str, time_str, &
obs_lat, obs_lon, hgt_msl, hgt_agl, obs_type, num_lines
IF (istat /= 0) CYCLE
READ(iunit, &
'(2x,a6,1x,f6.1,1x,f6.1,1x,f3.0,1x,f5.1)',IOSTAT=istat) &
fmt_in, obs_t, obs_td, obs_wdir, obs_wspd
IF (istat /= 0) CYCLE
! WRITE(6,'(2F9.2, F7.0, 2F7.1, F5.0, F5.1)') &
! obs_lat, obs_lon, hgt_msl, obs_t, obs_td, obs_wdir, obs_wspd
CALL lltoxy
(1,1,obs_lat,obs_lon,xsta,ysta)
CALL findlc
(nx,ny,xs,ys,xsta,ysta,ipt,jpt,indom)
IF (indom /= 0) CYCLE
!-----------------------------------------------------------------------
!
! If MDCRS data are being processed, we need to convert from
! pressure altitude to pressure and then estimate the height
! based on the background pressure field.
!
!-----------------------------------------------------------------------
IF ( obs_type == 'MDCRS ' ) THEN
altpres = mbtopa*ztopsa(hgt_msl)
!-----------------------------------------------------------------------
!
! Interpolate background field (in the horizontal)
! for the whole vertical column.
!
!-----------------------------------------------------------------------
CALL colint
(nx,ny,nz,nvar, &
xs,ys,zp,xsta,ysta,ipt,jpt,anx, &
su,sv,stheta,spres,shght,sqv,selev, &
nlevs)
!-----------------------------------------------------------------------
!
! Interpolate hgts in the vertical from background.
! Interpolation is linear in log-p.
!
!-----------------------------------------------------------------------
kgrid = 0
hgt_msl = rmiss
DO k=3,nlevs-1
IF (spres(k) < altpres) THEN
kgrid = k
EXIT
END IF
END DO
IF (kgrid > 0) THEN
weight = (LOG(altpres)-LOG(spres(kgrid)))/ &
(LOG(spres(kgrid-1))-LOG(spres(kgrid)))
hgt_msl = (1.-weight)*shght(kgrid) &
+ weight*shght(kgrid-1)
ELSE
CYCLE
END IF
END IF ! IF ( obs_type == 'MDCRS ' ) THEN
!-----------------------------------------------------------------------
!
! Use this datapoint if we have a valid height for it.
!
!-----------------------------------------------------------------------
ksta = ksta + 1
IF (ksta > mxsng) THEN
WRITE(6,'(a,i6,a)') &
' ERROR: number of single level stations,',mxsng, &
'exceeded in PREPSGLOBS. Increase mxsng and retry.'
istatus = -2
STOP
END IF
DO ivar=1,nvar
obsng(ivar,ksta)=rmiss
qobsng(ivar,ksta)=999.
qualsng(ivar,ksta)=-99
END DO
stnsng(ksta) = obs_id(1:5)
latsng(ksta) = obs_lat
lonsng(ksta) = obs_lon
xsng(ksta) = xsta
ysng(ksta) = ysta
chsrc(ksta,1) = obs_type
DO jsrc=1,nsrc_sng
IF (chsrc(ksta,1) == srcsng(jsrc)) THEN
isrcsng(ksta)=jsrc
EXIT
END IF
END DO
jsrc=isrcsng(ksta)
if ( jsrc == 0 ) then
write(6,*) &
'Unable to find data source ',chsrc(ksta,1),' in input file.'
write(6,*)
return
endif
!-----------------------------------------------------------------------
!
! Set obs height
!
!-----------------------------------------------------------------------
hgtsng(ksta) = hgt_msl
!-----------------------------------------------------------------------
!
! Station pressure (mb)
! For now we'll convert msl pressure to station pressure
! using the current temperature.
!
!-----------------------------------------------------------------------
IF (obs_psta > rmiss ) THEN
psta=mbtopa*obs_psta
obsng(3,ksta)=psta
qobsng(3,ksta)=qsrc(3,jsrc)
qualsng(3,ksta)=100
ELSE IF (obs_palt > rmiss ) THEN
psta=mbtopa*alttostpr(obs_palt,hgt_msl)
obsng(3,ksta)=psta
qobsng(3,ksta)=qsrc(3,jsrc)
qualsng(3,ksta)=100
ELSE IF (obs_pmsl > rmiss .AND. &
obs_t > rmiss .AND. &
hgt_msl < 500. ) THEN
tk=obs_t + 273.15
psta=mbtopa*msltostpr(obs_pmsl,tk,hgt_msl)
obsng(3,ksta)=psta
qobsng(3,ksta)=qsrc(3,jsrc)
qualsng(3,ksta)=100
ELSE IF (altpres > rmiss) THEN ! MDCRS
psta=altpres
ELSE
psta=mbtopa*alttostpr(1013.,hgt_msl)
END IF
!-----------------------------------------------------------------------
!
! Set winds.
!
!-----------------------------------------------------------------------
IF (obs_wdir >= 0. .AND. obs_wspd >= 0.) THEN
CALL ddrotuv
(1,lonsng(ksta),obs_wdir,obs_wspd,ddrot, &
obsng(1,ksta),obsng(2,ksta))
qualsng(1,ksta)=100
qualsng(2,ksta)=100
qobsng(1,ksta)=qsrc(1,jsrc)
qobsng(2,ksta)=qsrc(2,jsrc)
END IF
!-----------------------------------------------------------------------
!
! Potential temperature (K)
!
!-----------------------------------------------------------------------
IF (obs_t > rmiss .AND. psta > rmiss) THEN
tk=obs_t + 273.15
obsng(4,ksta)=tk*((p0/psta)**rddcp)
qualsng(4,ksta)=100
qobsng(4,ksta)=qsrc(4,jsrc)
END IF
!-----------------------------------------------------------------------
!
! Specific humidity (kg/kg)
!
!-----------------------------------------------------------------------
IF (obs_td > rmiss .AND. obs_t > rmiss .AND. &
psta > rmiss ) THEN
tk=obs_t + 273.15
tdk=obs_td + 273.15
qv = f_qvsat
( psta,tdk )
qvsat = f_qvsat
( psta, tk )
obsng(5,ksta)=max((0.05*qvsat),min(qv,qvsat))
qobsng(5,ksta)=qsrc(5,jsrc)
qualsng(5,ksta)=100
END IF
END DO
!-----------------------------------------------------------------------
!
! Update observation counts, close up and exit.
!
!-----------------------------------------------------------------------
nobsng = ksta
nsingle = nobsng - nprev
WRITE(6,'(a,i6,i6,i6)') ' PREPSGLOBS: nsingle,nprev,nobsng', &
nsingle,nprev,nobsng
istatus=0
CLOSE(iunit)
CALL retunit(iunit)
RETURN
END SUBROUTINE prepsglobs