!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE PREPSGLOBS                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE prepsglobs(mxsng,ntime,srcsng,nsrc_sng,sngfile,              & 1,6
           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.
!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  INTEGER :: nvar,mxsng,ntime
!
  INTEGER :: jsrc
  INTEGER :: nsrc_sng
  CHARACTER (LEN=132) :: sngfile, line
  CHARACTER (LEN=8) :: srcsng(nsrc_sng)
  CHARACTER (LEN=8) :: chsrc(mxsng,ntime)
  CHARACTER (LEN=5) :: stnsng(mxsng)
  REAL :: latsng(mxsng)
  REAL :: lonsng(mxsng)
  REAL :: xsng(mxsng)
  REAL :: ysng(mxsng)
  REAL :: hgtsng(mxsng)
  REAL :: obsng(nvar,mxsng)
  REAL :: qobsng(nvar,mxsng)
  INTEGER :: qualsng(nvar,mxsng)
  REAL :: qsrc(nvar,mxsng)
  INTEGER :: isrcsng(mxsng)
  REAL :: rmiss
  INTEGER :: nprev
  INTEGER :: nobsng
  INTEGER :: istatus

  INTEGER :: nx,ny,nz
  REAL :: anx(nx,ny,nz,nvar)
  REAL :: xs(nx),ys(ny)
  REAL :: zp(nx,ny,nz)

  REAL :: shght(nz)
  REAL :: su(nz)
  REAL :: sv(nz)
  REAL :: spres(nz)
  REAL :: stheta(nz)
  REAL :: sqv(nz)

  REAL :: ktstoms,mbtopa
  PARAMETER (ktstoms=0.5144,mbtopa=100.)
!
!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------
!
  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,iline,istat
  REAL :: weight
  REAL :: ddrot,selev

  REAL :: altpres   ! presure derived from altimeter reading
!
!-----------------------------------------------------------------------
!
!  Functions
!
!-----------------------------------------------------------------------
!
  REAL :: alttostpr
  REAL :: msltostpr
  REAL :: f_qvsat
  REAL :: 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)

!
!-----------------------------------------------------------------------
!
!  Include files:
!
!-----------------------------------------------------------------------
!
  INCLUDE 'phycst.inc'

!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  nprev=nobsng
  WRITE(6,'(a,a)') ' Opening: ',sngfile
  WRITE(6,'(a,i6,i6)') ' In PREPSGLOBS , mxsng, nprev = ',              &
                         mxsng,nprev
  OPEN(12,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 iline=1,999999

!
!-----------------------------------------------------------------------
!
!  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 (12,'(A)',iostat=istat) line
    IF (istat /= 0) EXIT
    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(12,                                                            &
      '(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) THEN
!
!-----------------------------------------------------------------------
!
!  Station pressure (mb)
!  Pressure altitude is assumed here.
!
!-----------------------------------------------------------------------
!
      IF ( obs_type == 'MDCRS   ' ) THEN
!
!-----------------------------------------------------------------------
!
!  Need to convert from pressure altitude to pressure and set
!  true height based on the background pressure field.
!
!-----------------------------------------------------------------------
!
        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)
        END IF
      END IF
!
!-----------------------------------------------------------------------
!
!  Use this datapoint if we have a valid height for it.
!
!-----------------------------------------------------------------------
!
  IF (chsrc(ksta,1) == 'MDCRS   ') THEN

        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)
!
!-----------------------------------------------------------------------
!
!  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
          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 IF
    END IF
  END DO

  nobsng = ksta
  nsingle = nobsng - nprev
  WRITE(6,'(a,i6,i6,i6)') ' PREPSGLOBS: nsingle,nprev,nobsng',          &
                           nsingle,nprev,nobsng
  istatus=0
  CLOSE(12)
  RETURN
END SUBROUTINE prepsglobs