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


SUBROUTINE barnes_r5 (nx,ny,nz,TO,t,wt_p,cf_modelfg,                    &
           l_stn_clouds,default_clear_cover,cld_snd,wt_snd,             &
           spcng,i_snd,j_snd,n_cld_snd,                                 &
           istatus)
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Horizontally interpolate the SAO cloud soundings to ADAS grid.
!  The interpolation scheme is Barnes-type, the weight given to a
!  data point is:
!
!  wt(m) = [(100.0*bias)/(1.533*dgrd(m)**2 + 1.0)]**(5.0/2.0)
!  wt(m) ~ 34367.237 /(dgrd(m)**5)
!
!  where
!
!    m  is the index of a data point
!    bias=1.0        ! it can be a function of data location
!    dgrd(m) is the distance from the mth data point to
!          the grid point, in terms of the number of grid spacings.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:  (Jian Zhang)
!  07/95   Based on the LAPS cloud analysis code
!
!  MODIFICATION HISTORY:
!  02/06/96  J. Zhang
!            Modified for ADAS. Added documents.
!  05/10/96  J. Zhang
!            Added the interpolation for the station grid column
!            (skipped during the first step).
!  03/14/97  J. Zhang
!            Clean up the code and implemented for the offcial
!            arps4.2.4 version
!  07/30/97  J. Zhang
!            Added minimum weight threshold for Barnes interpolation.
!            This can avoid the interpolations at the grid points
!            where there is no station nearby.
!  08/06/97  J. Zhang
!            Change adascld24.inc to adascld25.inc.
!            Set weight_modelfg=1.0 for the cases when there is
!            no SAO cloud soundings.
!  09/09/97  J. Zhang
!            Using the different influence cutoff radius for
!            cloud soundingd with different cloud coverage
!  09/10/97  J. Zhang
!            Awoke the procedure which uses background RH field to
!            derive cloud cover field when there is no SAO cloud
!            sounding.
!            Change adascld25.inc to adascld26.inc.
!  11/18/97  J. Zhang
!            Moved "max_obs" to adascld26.inc.
!  11/19/97  J. Zhang
!            Added test for the case when ncnt > max_obs.
!
!-----------------------------------------------------------------------
!
!  INPUT:
!
!
!  OUTPUT:
!
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE

  INCLUDE 'adas.inc'
!
!   INPUT from adas.inc:
!   real r_missing      ! missing value flag
!   real range_cld      ! cutoff radius for interpolation
!   integer max_cld_snd ! max. possible # of cloudy soundings
!   integer max_obs     ! max. possible # of cldy data points in 3D
                        ! domain (should be about max_cld_snd*nz)
!   integer i_perimeter ! an extension of the ADAS domain for
                        ! searching SAOs.
!
! INPUT:
!
  INTEGER :: nx,ny,nz           ! grid size
  INTEGER :: n_cld_snd          ! actual # of cld snd

  REAL :: TO(nx,ny,nz)          ! 1st guess of gridded cloud cover
  REAL :: cf_modelfg(nx,ny,nz)  ! 1st guess for cloud cover field
  REAL :: wt_p(nx,ny,nz)        ! weights for first guess field

  LOGICAL :: l_stn_clouds       ! using SAO stns'cld sndings?
  REAL :: default_clear_cover   ! defaule cld value for clear sky

  REAL :: cld_snd(max_cld_snd,nz) ! obs. cloud cover sounding
  REAL :: wt_snd(max_cld_snd,nz)  ! weights for obs. cld sounding

  INTEGER :: i_snd(max_cld_snd)   ! i-loc of cloud sounding stn
  INTEGER :: j_snd(max_cld_snd)   ! j-loc of cloud sounding stn
!
! OUTPUT:
! 
  REAL :: t(nx,ny,nz)       ! the gridded analysis of cld cvr
  INTEGER :: istatus
!
! LOCAL:
!
  INTEGER :: nx_lut,ny_lut      ! dims for look up tbl of intp wgt.
  INTEGER :: ix_low,ix_high,iy_low,iy_high

  INTEGER :: n_fnorm
!
  INTEGER :: iskip        ! # of grid pts skipped when performing
                         ! Barnes intp. (for time-saving)
  INTEGER :: lowi_lut(nx) ! index for skipped grid points.
  INTEGER :: lowj_lut(ny) ! index for skipped grid points.
!
  REAL, allocatable :: fnorm(:)    ! normalized weights
!
  INTEGER :: iob(max_obs)   ! i-loc of each cld data pt. in ADAS grid
  INTEGER :: job(max_obs)   ! j-loc of each cld data pt. in ADAS grid
  INTEGER :: kob(max_obs)   ! k-lvl of each cld data pt. in ADAS grid
  INTEGER :: nob(max_obs)   ! sequential index of each cldy data pt.

  REAL, allocatable :: iiilut(:,:)
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: nlast (nz)        ! the index for the cloud sounding data
                             ! point at each level.
  LOGICAL :: l_analyze (nz)
!
  REAL :: weight_modelfg       ! the weight given to the 1st guess
                             ! cloud cover field
  REAL :: rden_ratio,radm2,rfac
  PARAMETER ( rfac=10.0, radm2=1.533/rfac**2)
!   parameter ( radm2=1.533)
!
  REAL :: exp_dist_wt          ! power of distance in weight
  PARAMETER( exp_dist_wt = 5.0)

  REAL :: spcng                ! grid spacing in m

  REAL :: rr,rr_max
  INTEGER :: iii,iii_max

  INTEGER :: iiizero,ncnt
  REAL :: bias_iii             ! a bias may be a func of locatns

  LOGICAL :: cldprt
  INTEGER :: i,j,k,n,nobs,nstart,nstop,ii,jj,nn,n1,jmid,ibeg
  REAL :: weight,sum,sumwt

  INTEGER :: il,ih,jl,jh,km1
  REAL :: z1,z2,z3,z4,fraci,fracj
  INTEGER :: astat
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  nx_lut = nx + i_perimeter - 1
  ny_lut = ny + i_perimeter - 1
  ix_low = 1  - i_perimeter
  ix_high= nx + i_perimeter
  iy_low = 1  - i_perimeter
  iy_high= ny + i_perimeter
  n_fnorm = 1.6 * ((nx_lut*nx_lut)+(ny_lut*ny_lut))

  allocate (fnorm(n_fnorm),stat=astat)
  IF (astat /= 0) THEN
    WRITE (6,'(a)') "BARNES_R5: ERROR allocating fnorm, exiting"
    STOP
  END IF
  allocate (iiilut(-nx_lut:nx_lut,-ny_lut:ny_lut),stat=astat)
  IF (astat /= 0) THEN
    WRITE (6,'(a)') "BARNES_R5: ERROR allocating fnorm, exiting"
    STOP
  END IF

  cldprt=(clddiag == 1)
  jmid=ny/2
  ibeg=MAX(1,nx-10)
  WRITE(6,'(1x,a)') ' Barnes_r5 called'

  istatus = 0
  IF(cldprt) THEN
    WRITE(6,'(a,i8)') ' # of cloud soundings = ',n_cld_snd
    WRITE(6,'(/a)') ' ==== BARNES cloud cover first guess===='
    WRITE(6,'(/1X,3X,11(1X,i4,1X))') (i,i=nx-10,nx)
    WRITE(6,'(1X,i3,11F6.1)')                                           &
         (k,(cf_modelfg(i,jmid,k),i=ibeg,nx),k=nz,1,-1)
  END IF
!
!-----------------------------------------------------------------------
!
!  Obtain and/or iterate for value of iskip
!
!-----------------------------------------------------------------------
!
  iskip = nint(20000. / spcng)           ! # of grid pts skipped
                                          ! during calcul'n
  iskip = MAX(iskip,1)

  100   rden_ratio = ((FLOAT(nx)-1.)/FLOAT(iskip))

  IF( ABS(rden_ratio - nint(rden_ratio)) > 0.001) THEN
    WRITE(6,*)' Bad value of iskip'
    IF(iskip > 1)THEN
      iskip = iskip - 1
      GO TO 100
    ELSE IF( iskip == 1) THEN
      WRITE(6,*)' Code error - stop'
      STOP
    END IF
  ELSE
    WRITE(6,*)' Good value of iskip = ',iskip
  END IF
!
!-----------------------------------------------------------------------
!
!  Create an array (lookup table) of weights as function of the
!  distance iii (in the unit of grid spacings)
!
!-----------------------------------------------------------------------
!
  IF( l_stn_clouds) PRINT*, ' # of cloud soundings = ',n_cld_snd

  iiizero = 0

  DO iii = 1,n_fnorm
    bias_iii = 1E0    ! It can be func of location iii later

    fnorm(iii) = (100.*bias_iii/FLOAT(iii)) ** (exp_dist_wt/2.0)
    IF( fnorm(iii) == 0. .AND. iiizero == 0) THEN
      iiizero = iii
      WRITE(6,*)' WARNING: fnorm array reached zero, iii=',iiizero
    END IF
  END DO  ! III

  WRITE(6,*)' Min possible weight = ',fnorm(n_fnorm)
  WRITE(6,*)' Max possible weight = ',fnorm(1)

  IF (n_cld_snd <= 0) THEN
    weight_modelfg = 1.0
  ELSE
    weight_modelfg = 0.0
  END IF
!
!-----------------------------------------------------------------------
!
!  Count the number of cloudy data points on each cloud height
!  level, and mark each cloudy data point with iob- and job-index.
!
!-----------------------------------------------------------------------
!
  ncnt=0        ! # of cloudy data points on each cloud grid level

  DO k = 1, nz

    IF (.NOT. l_stn_clouds) THEN   ! using gridded non-model 1st
                                   ! guess field
      nlast(k) = ncnt
      DO j=1,ny
        DO i=1,nx
          IF( TO(i,j,k) == r_missing) GO TO 223
          ncnt=ncnt+1
          iob(ncnt)=i
          job(ncnt)=j
          kob(ncnt)=k
          nlast(k) = ncnt
          223         CONTINUE
        END DO ! i
      END DO ! j

    ELSE ! l_stn_clouds = .TRUE.,  use cloud soundings
      nlast(k) = ncnt

      IF (n_cld_snd >= 1) THEN
        DO n = 1,n_cld_snd
          IF(cld_snd(n,k) < default_clear_cover) GO TO 233
!
!-----------------------------------------------------------------------
!
!  Test if out of the bounds of the ADAS_plus domain
!
!-----------------------------------------------------------------------
!
          IF(i_snd(n) < ix_low .OR. i_snd(n) > ix_high) GO TO 233
          IF(j_snd(n) < iy_low .OR. i_snd(n) > iy_high) GO TO 233

          ncnt=ncnt+1
          IF (ncnt > max_obs) THEN
            PRINT*,'# of cldy grid pts exceeds the max. # allowed'
            PRINT*,'# of cldy grid pts:',ncnt,' # allowed:',max_obs
            PRINT*,'Plz increase MAX_OBS in adas.inc.'
            PRINT*,' Aborting...'
            STOP
          END IF
          iob(ncnt)=i_snd(n)
          job(ncnt)=j_snd(n)
          kob(ncnt)=k
          nob(ncnt)=n
          nlast(k) = ncnt
          233           CONTINUE
        END DO ! n
      END IF

    END IF ! l_stn_clouds

    IF( k > 1) THEN
      km1 = k - 1
      l_analyze(k) = .false.

      IF(.NOT. l_stn_clouds) THEN
        DO j=1,ny
          DO i=1,nx
            IF( TO(i,j,k) /= TO(i,j,km1)) THEN
              l_analyze(k) = .true.
              GO TO 250
            END IF
          END DO ! i
        END DO ! j

      ELSE
        DO n=1,n_cld_snd
          IF( cld_snd(n,k) /= cld_snd(n,km1)) THEN
            l_analyze(k) = .true.
            goto 250
          END IF
        END DO ! n

      END IF ! l_stn_clouds

      250       CONTINUE

    ELSE ! k .eq. 1
      l_analyze(k) = .true.
    END IF

  END DO ! K

  IF(ncnt == 0) THEN
    PRINT*, 'No SAO cloud sounding data for Barnes'
    PRINT*, 'Using the background cloud cover field'

    DO k=2,nz-2
      DO j=1,ny
        DO i=1,nx
          t(i,j,k) = cf_modelfg(i,j,k)
        END DO
      END DO
    END DO
    istatus = 1
    RETURN
  ELSE
    WRITE(6,*)' Ncnt = ',ncnt
  END IF
!
!-----------------------------------------------------------------------
!
!  Create a lookup table for fnorm(iii): the weights as a function
!  of i- and j- distances.
!
!-----------------------------------------------------------------------
!
  rr_max = (nx_lut-1)**2 + (ny_lut-1)**2
  iii_max = radm2*100.*rr_max + 1.
  PRINT*,' radm2*100,iii_max,n_fnorm: ',radm2*100.,iii_max,n_fnorm

  IF( iii_max > n_fnorm) THEN
    PRINT*,' iii_max is too large, increase n_fnorm',iii_max            &
          ,n_fnorm
    istatus = 0
    RETURN
  END IF
!
  DO i = -nx_lut,nx_lut
    DO j = -ny_lut,ny_lut
      rr=i*i+j*j
      iii=radm2*100.*rr+1.
      IF( iii > n_fnorm) iii=n_fnorm
      iiilut(i,j) = fnorm(iii)            ! lookup table for weights
                                          ! fnorm as a function of
                                          ! distance iii.
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Loop through each cloud height level.
!
!-----------------------------------------------------------------------
!
  DO k = 1, nz

    IF(k == 1)THEN
      nstart = 1
    ELSE
      nstart = nlast(k-1) + 1
    END IF

    nstop = nlast(k)
    nobs = nstop-nstart+1       ! # of obs. in one level

    IF (nobs <= 0) THEN  ! No Obs; Set level to model 1st guess
!
      IF(cldprt) WRITE(6,'(a,4i5,a)') ' lvl,nstart,nstop,nobs=',        &
           k,nstart,nstop,nobs,' No Obs; Set level to model fg'
      DO j=1,ny
        DO i=1,nx
          t(i,j,k) = cf_modelfg(i,j,k)
        END DO ! i
      END DO ! j

    ELSE IF( weight_modelfg > 1.0E-15 .OR. l_analyze(k) ) THEN

      IF(cldprt) WRITE(6,'(a,4i5)') ' lvl,nstart,nstop,nobs=',          &
        k,nstart,nstop,nobs
!
!-----------------------------------------------------------------------
!
!    Analyze every iskip-th  grid point
!
!-----------------------------------------------------------------------
!
      DO j=1,ny,iskip
        DO i=1,nx,iskip
          sum=0.
          sumwt=0.
          IF(.NOT. l_stn_clouds)THEN
            DO n=nstart,nstop
              ii=iob(n)
              jj=job(n)
              iii = (i-ii)*(i-ii) + (j-jj)*(j-jj)
              rr = FLOAT (iii)
              rr = spcng*SQRT (rr)
              IF (rr <= range_cld) THEN
!
!-----------------------------------------------------------------------
!
!c              gridded obs are being weighted
!
!-----------------------------------------------------------------------
!
                weight = iiilut(i-ii,j-jj) * wt_p(ii,jj,k)
                sum=weight*TO(ii,jj,k)+sum
                sumwt=sumwt+weight
              END IF
            END DO  ! n
          ELSE
            DO n=nstart,nstop
              ii=iob(n)
              jj=job(n)
              nn=nob(n)
              iii = (i-ii)*(i-ii) + (j-jj)*(j-jj)
              rr = FLOAT (iii)
              rr = spcng*SQRT (rr)
              IF (rr <= range_cld) THEN
!
!-----------------------------------------------------------------------
!
!c              Station obs are being weighted
!
!-----------------------------------------------------------------------
!
                weight = iiilut(i-ii,j-jj) * wt_snd(nn,k)
                sum=weight*cld_snd(nn,k)+sum
                sumwt=sumwt+weight
              END IF
            END DO ! n
          END IF

          sum   = sum   + weight_modelfg * cf_modelfg(i,j,k)
          sumwt = sumwt + weight_modelfg

          IF (ABS(sumwt) <= 1.0E-15) THEN
!9/3/97        t(i,j,k) = r_missing
!              istatus = 0
!              print*,'(00): ',i,j,k,' tot sum:',sum,'  tot sumwt:'
!     :                ,sumwt,'  t:',t(i,j,k)
            t(i,j,k) = 0.01
          ELSE
            t(i,j,k)=sum/sumwt
          END IF

        END DO ! i
      END DO ! j
!
!-----------------------------------------------------------------------
!
!      Bilinearly interpolate to fill in rest of domain
!
!-----------------------------------------------------------------------
!
      DO i = 1,nx
        lowi_lut(i) = (i-1)/iskip*iskip + 1
        IF( i == nx) lowi_lut(i) = lowi_lut(i) - iskip
      END DO ! i

      DO j = 1,ny
        lowj_lut(j) = (j-1)/iskip*iskip + 1
        IF( j == ny) lowj_lut(j) = lowj_lut(j) - iskip
      END DO ! i

      DO j=1,ny
        jl = lowj_lut(j)
        jh = jl + iskip
        fracj = FLOAT(j-jl)/FLOAT(iskip)

        DO i=1,nx
          il = lowi_lut(i)
          ih = il + iskip
          fraci = FLOAT(i-il)/FLOAT(iskip)

          z1=t(il,jl,k)
          z2=t(ih,jl,k)
          z3=t(ih,jh,k)
          z4=t(il,jh,k)

          t(i,j,k) =  z1+(z2-z1)*fraci+(z4-z1)*fracj                    &
                    - (z2+z4-z3-z1)*fraci*fracj
        END DO ! i
      END DO ! j

      IF (l_stn_clouds .AND. n_cld_snd >= 1) THEN
!
!-----------------------------------------------------------------------
!
!  Reinterpolate at the station grid points which were skipped
!  previously.
!
!-----------------------------------------------------------------------
!
        DO n1=1,n_cld_snd
          i = i_snd(n1)
          j = j_snd(n1)
          IF(i < 1.OR.i > nx.OR.j < 1.OR.j > ny) GO TO 252
          IF( (i-1) /= (i-1)/iskip*iskip .OR. (j-1) /= (j-1)/iskip*iskip) THEN
            sum=0.
            sumwt=0.
            DO n=nstart,nstop
              ii=iob(n)
              jj=job(n)
              nn=nob(n)
              iii = (i-ii)*(i-ii) + (j-jj)*(j-jj)
              rr = FLOAT (iii)
              rr = spcng*SQRT (rr)
              IF (rr <= range_cld) THEN
!
!-----------------------------------------------------------------------
!
!c                Station obs are being weighted
!
!-----------------------------------------------------------------------
!
                weight = iiilut(i-ii,j-jj) * wt_snd(nn,k)
                sum=weight*cld_snd(nn,k)+sum
                sumwt=sumwt+weight
              END IF
            END DO ! n

            sum = sum + weight_modelfg * cf_modelfg(i,j,k)
            sumwt = sumwt + weight_modelfg

            IF (ABS(sumwt) <= 1.0E-15) THEN
!                  t(i,j,k) = r_missing
!                  istatus = 0
!                  print*,'(00*): ',i,j,k,' tot sum:',sum,
!     :                 '  tot sumwt:',sumwt,'  t:',t(i,j,k)
              t(i,j,k) = 0.01
            ELSE
              t(i,j,k)=sum/sumwt
            END IF

          END IF  ! Stn (i,j) was skipped during the 1st-pass intp.
          252           CONTINUE

        END DO ! n1
      END IF  ! l_stn_clouds = .true. and n_cld_snd >0

    ELSE       ! no 1st guess and obs. is identical to lower lvl
!
!-----------------------------------------------------------------------
!
!c        Obs are identical; Copy analysis from 1 level below
!
!-----------------------------------------------------------------------
!
      IF(cldprt) WRITE(6,'(a,4i5,a)') ' lvl,nstart,nstop,nobs=',        &
        k,nstart,nstop,nobs,' Identical Obs; Copy from 1 lvl down'

      km1 = k - 1

      DO j=1,ny
        DO i=1,nx
          t(i,j,k) = t(i,j,km1)
        END DO ! i
      END DO ! j

    END IF

  END DO ! K

  istatus = 1
!
  deallocate (fnorm,stat=astat)
  deallocate (iiilut,stat=astat)
  RETURN
END SUBROUTINE barnes_r5
!
!##################################################################
!##################################################################
!######                                                      ######
!######               SUBROUTINE HGT_TO_ZK                   ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE hgt_to_zk (z,zk,nk,zs_1d,istatus) 2
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  To find the k-position of a given height in the model grid
!  If the height is above the model highest level, the largest
!  level index (nk) will be returned. If the height is below
!  the lowest model level, the lowestlevel index (1) will be
!  returned.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!  05/01/96
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  INPUT:
  REAL :: z         ! the height (m) to be coverted to k-index
  INTEGER :: nk     ! number of vertical levels in model grid
  REAL :: zs_1d(nk) ! the physical height of each model level
!
!  OUTPUT:
  INTEGER :: istatus
  REAL :: zk        ! the k-position of the ht. in the model grid
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: k,nkm1
  REAL :: height_above,thickness,frac
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  zk = FLOAT(nk-1)
  height_above = zs_1d(nk-1)

  IF( z > height_above) THEN
    nkm1=nk-1
!        write(6,*)
!        write(6,601) z,zk,nkm1,zs_1d(nkm1)
!601     format(' Warning: above model domain in HGT_TO_ZK'/
!     :        1x,' z=',f9.0,' zk=',f6.2,' nk=',i2,'  zs(nk)=',f9.0)
!        write(6,*) 'Top level index will be assigned to ZK.'
    istatus=0
!
    GO TO 999
  END IF

  DO k = nk-2,1,-1

    IF( height_above >= z .AND. zs_1d(k) <= z) THEN
      thickness = height_above - zs_1d(k)
      frac = (z - zs_1d(k))/thickness
      zk = FLOAT(k) + frac
      istatus=1
      GO TO 999
    END IF

    height_above = zs_1d(k)
  END DO ! K

  zk = 1.0

!      write(6,*)
!      write(6,602) z,zk,zs_1d(1)
!602   format(' Warning: below model level_1 in HGT_TO_ZK'/
!     :      1x,' z=',f9.0,' zk=',f6.2,' k=1  zs(1)=',f9.0)
!      write(6,*) 'Bottom level index will be assigned to ZK.'
  istatus=0

  999   CONTINUE
  RETURN
END SUBROUTINE hgt_to_zk



SUBROUTINE wmix (p,t,dd,w,nl) 1
!
!            07-jun-84       source code from wang
!                            (not on u. of w. source tape)
!
!            dd      - dewpoint depression
  DIMENSION p(*), t(*), dd(*), w(*)
  DO i = 1, nl
    td = t(i) - dd(i)
    IF (td > 253.0) GO TO 110
    es = vpice(td)
    GO TO 120
    110     es = satvap(td)
    120     w(i) = 622.0 * es / p(i)
  END DO
  RETURN
END SUBROUTINE wmix
!
!##################################################################
!##################################################################
!######                                                      ######
!######              FUNCTION WSAT                           ######
!######                                                      ######
!##################################################################
!##################################################################
!


  FUNCTION wsat(p, t),1
!
!         1 4-may-84 added from csu vas code
!                            (not on u. of w. source tape)
!
! jz 4/29/98 to avoid warning message when compile on origin
  DIMENSION p(1),t(1),dd(1),w(1)
  dd(1)  = 0.0
! jz 4/29/98 end
  CALL wmix(p,t,dd,w,1)
  wsat=w(1)
!      wsat=w
!
!         1 4-may-84 return added
!
  RETURN
  END FUNCTION wsat
!
!##################################################################
!##################################################################
!######                                                      ######
!######              FUNCTION VPICE                          ######
!######                                                      ######
!##################################################################
!##################################################################
!


  FUNCTION vpice(temp)
!
!            07-jun-84       source code from wong
!                            (not on u. of w. source tape)
  REAL(KIND=8) :: c(6)
  REAL(KIND=8) :: t
!
  DATA c/ 0.7859063157D+00,  0.3579242320D-01,                          &
       -0.1292820828D-03,  0.5937519208D-06,                            &
        0.4482949133D-09,  0.2176664827D-10/
!
  t = temp - 273.16
  vplog = c(1) + t * (c(2) + t * (c(3) + t * (c(4) + t * (c(5) +        &
               t *  c(6)))))
  vpice = 10.0 ** vplog
  RETURN
  END FUNCTION vpice
!
!##################################################################
!##################################################################
!######                                                      ######
!######              FUNCTION SATVAP                         ######
!######                                                      ######
!##################################################################
!##################################################################
!


  FUNCTION satvap(temp)
!
!            07-jun-84       source code from wang
!                            (not on u. of w. source tape)
!
  REAL(KIND=8) :: c(10)
  REAL(KIND=8) :: s, t
!
  DATA c/ 0.9999968760D-00, -0.9082695004D-02,                          &
        0.7873616869D-04, -0.6111795727D-06,                            &
        0.4388418740D-08, -0.2988388486D-10,                            &
        0.2187442495D-12, -0.1789232111D-14,                            &
        0.1111201803D-16, -0.3099457145D-19/
  t = temp - 273.16
  s = 6.1078000000D+00 / (c(1) + t * (c(2) + t * (c(3) +                &
                               t * (c(4) + t * (c(5) +                  &
                               t * (c(6) + t * (c(7) +                  &
                               t * (c(8) + t * (c(9) +                  &
                               t * c(10)))))))))) ** 8
  satvap = s
  RETURN
  END FUNCTION satvap


SUBROUTINE precw(p,w,u,np)
!
!            02-may-84       sequence numbers removed
!
  DIMENSION p(*),w(*),u(*)
  DATA f/1961.33/
  w1=w(1)
  p1=p(1)
  s=0.
  u(1)=s
!
!            07-jun-84       correction of tape read error
!  do 100 i=2,n
  DO i = 2, np
    w2=w(i)
    p2=p(i)
    dp=ABS(p2-p1)
    s=s+(w1+w2)*dp/f
    u(i)=s
    w1=w2
    p1=p2
  END DO
  RETURN
END SUBROUTINE precw
!
!##################################################################
!##################################################################
!######                                                      ######
!######              FUNCTION VSKINT                         ######
!######                                                      ######
!##################################################################
!##################################################################
!


  FUNCTION vskint(tbb,jcof,juse,jact)
!
! * obtain sfc-skin-temp from vas brightness temperatures
!     jcof=0 for empirical coefficients
!     jcof=1 for climatological(theoretical) coeffs.
!
!     juse=0 to use 'day'(2-chan) or 'night'(3-chan) eqn.
!        according to solar zenith angle
! *******  currently forced out; will use day only if chan 12 missing.
!     juse=1 to use 'day' eqn.
!     juse=2 to use 'night' eqn.
!
!     jact=0 if nothing done
!     jact=1 if 'day' eqn. actually used
!     jact=2 if 'night' eqn. actually used
  COMMON/nav/vlat,vlon,vzen,szen,il,ie,iras,ipic,itime,jtime,jday
  COMMON/tsurfc/tscc(4,2)
  COMMON/tsurfe/tsce(4,2)
  DIMENSION tsc(4,2),tx(3),ic(3),tbb(*)
  DATA ic/7,8,12/,nx/3/,vmisg/999999./
  DO i=1,nx
    j=ic(i)
    tx(i)=tbb(j)
  END DO
  jact=0
  ts=tx(2)
  IF(tx(1) == vmisg) GO TO 180
  IF(tx(2) == vmisg) GO TO 180
  IF(jcof /= 0) GO TO 110
  DO j=1,2
    DO i=1,4
      tsc(i,j)=tsce(i,j)
    END DO
  END DO
  GO TO 130
  110 DO j=1,2
    DO i=1,4
      tsc(i,j)=tscc(i,j)
    END DO
  END DO
  130 j=juse
  IF(j /= 0) GO TO 150
  j=2                       !changed 1 --> 2
!  if(szen.ge.90.) j=2       !deleted line
  150 IF(j == 1) GO TO 160
  IF(tx(3) == vmisg) j=1
  IF(tx(3) < tx(2)-4.) j=1 !changed tx(2) --> tx(2)-4.
  160 jact=j
  ts=tsc(4,j)
  DO i=1,nx
    ts=ts+tx(i)*tsc(i,j)
  END DO
  IF(ts == 0.) ts=vmisg
  180 vskint=ts
  RETURN
  END FUNCTION vskint
!
!##################################################################
!##################################################################
!######                                                      ######
!######               SUBROUTINE PCP_MXR                     ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!


SUBROUTINE pcp_mxr (nx,ny,nz,t_3d,p_3d ,ref_3d                          & 1
           ,cldpcp_type_3d                                              &
           ,qr_3d,qs_3d,qh_3d,istatus )

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Perform 3D precipitation mixing ratio (in g/kg) analysis using
!  radar reflectivity data. For rain water, using Kessler (1969)
!  formula:
!            qr(g/kg) = a*(rho*arg)**b                  (1)
!
!  Here arg = Z (mm**6/m**3), and dBZ = 10log10 (arg).
!  Coeffcients a=17300.0, and b=7/4.
!  rho represents the air density.
!
!  For snow and hail, using Rogers and Yau (1989) formula:
!
!            qs(g/kg) = c*(rho*arg)**d                  (2)
!
!  where, c=38000.0,  d=2.2
!
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!  06/13/96
!
!  MODIFICATION HISTORY:
!  07/30/97 (J. Zhang)
!           Added precipitation type in the argument list so that
!           mixing ratios of different precip. types can be computed.
!  09/04/97 (J. Zhang)
!            Changed the radar echo thresholds for inserting precip.
!            from radar reflectivities.
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  INPUT:
  INTEGER :: nx,ny,nz              ! Model grid size
!
  REAL :: ref_3d(nx,ny,nz)  ! radar reflectivity (dBZ)
  REAL :: t_3d(nx,ny,nz)  ! Temperature (deg. Kelvin)
  REAL :: p_3d(nx,ny,nz)  ! Pressure (Pascal)

  INTEGER :: cldpcp_type_3d(nx,ny,nz) ! cloud/precip type field
!
!  OUTPUT:
  INTEGER :: istatus
!
  REAL :: qr_3d(nx,ny,nz)     ! rain mixing ratio in (g/kg)
  REAL :: qs_3d(nx,ny,nz)     ! snow/sleet/frz-rain mixing ratio
                            ! in (g/kg)
  REAL :: qh_3d(nx,ny,nz)     ! hail mixing ratio in (g/kg)
!
!  LOCAL:
  REAL :: a,b,c,d                  ! Coef. for Z-qr relation.
  PARAMETER (a=17300.0, b=7.0/4.0)
  PARAMETER (c=38000.0, d=2.2)
  REAL :: rair                     ! Gas constant (J/deg/kg)
  PARAMETER (rair = 287.04)
  REAL :: thresh_ref
  PARAMETER (thresh_ref = 0.0)
  INTEGER :: pcptype
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: i,j,k, iarg
  REAL :: arg,rhobar,br,dr
  PARAMETER (br=1.0/b, dr=1.0/d)
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
!-----------------------------------------------------------------------
!
  istatus=0
!
!-----------------------------------------------------------------------
!
!  Compute the precip mixing ratio in g/kg from radar reflectivity
!  factor following Kessler (1969) or Rogers and Yau (1989).
!
!-----------------------------------------------------------------------
!
  DO k = 1,nz-1
    DO j = 1,ny-1
      DO i = 1,nx-1
        IF (ref_3d(i,j,k) >= thresh_ref) THEN    ! valid radar refl.
          rhobar = p_3d(i,j,k)/rair/t_3d(i,j,k)
          arg = 10.0**(0.1*ref_3d(i,j,k))
          iarg = cldpcp_type_3d(i,j,k)
          pcptype = iarg/16              ! precip. type

          IF (pcptype == 0) THEN       ! no precip
            PRINT*,'+++ NOTE: radar echo though no precip. +++'
          ELSE IF (pcptype == 1.OR.pcptype == 3) THEN   ! rain or Z R
            qr_3d(i,j,k) = (arg/a)**br/rhobar
          ELSE IF (pcptype == 2) THEN                   ! snow
            qs_3d(i,j,k) = (arg/c)**dr/rhobar
          ELSE IF (pcptype == 4.OR.pcptype == 5) THEN   ! hail or sleet
            qh_3d(i,j,k) = (arg/c)**dr/rhobar
          ELSE                                          ! unknown
            PRINT*,'+++ NOTE: unknown precip type. +++'
          END IF
        ELSE
          qr_3d(i,j,k) = 0.
          qs_3d(i,j,k) = 0.
          qh_3d(i,j,k) = 0.
        END IF
      END DO ! k
    END DO ! i
  END DO ! j
!
!-----------------------------------------------------------------------
!
  istatus = 1
!
  RETURN
END SUBROUTINE pcp_mxr

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


SUBROUTINE pcp_mxr_ferrier (nx,ny,nz,t_3d,p_3d ,ref_3d                  & 1
           ,cldpcp_type_3d                                              &
           ,qr_3d,qs_3d,qh_3d,istatus )

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Perform 3D precipitation mixing ratio (in g/kg) analysis using
!  radar reflectivity data. For rain water, using Ferrier et al (1995)
!  formulation:
!
!
!     For rain water:
!
!          18
!        10   * 720                              1.75
!  Zer = --------------------------- * (rho * qr)
!          1.75      0.75       1.75
!        pi     * N0r     * rhor
!
!
!     For dry snow (t <= 0 C):
!
!
!          18           2                     0.25
!        10  * 720 * |K|                * rhos
!                       ice                                    1.75
!  Zes = ----------------------------------------- * (rho * qs)     t <= 0 C
!          1.75         2          0.75       2
!        pi        * |K|      * N0s     * rhoi
!                     water
!
!
!     For wet snow (t >= 0 C):
!
!
!              18
!            10   * 720                                 1.75
!  Zes =     ----------------------------   * (rho * qs)            t >  0 C
!              1.75      0.75       1.75
!            pi     * N0s     * rhos
!
!
!     For hail water:
!
!
!          /   18                       \ 0.95
!         /  10   * 720                  \              1.6625
!  Zeh = |   ---------------------------- | * (rho * qh)
!         \    1.75      0.75       1.75 /
!          \ pi     * N0h     * rhoh    /
!
!  Here Zx (mm**6/m**3, x=r,s,h), and dBZ = 10log10 (Zx).
!  rho represents the air density, rhor,rhos,rhoh are the density of
!  rain, snow and hail respectively. Other variables are all constants
!  for this scheme, see below.
!
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Donghai Wang and Eric Kemp)
!  07/20/2000
!
!  MODIFICATION HISTORY:
!
!  11/09/2000 Keith Brewster
!  Moved some parameters with real-valued exponentiation to be
!  computed at runtime due to compiler complaint.
!
!  04/07/2003 Keith Brewster
!  Restructured code to make more tractable.and consistent with 
!  the reflec_ferrier subroutine.
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  INPUT:
  INTEGER :: nx,ny,nz              ! Model grid size
!
  REAL :: ref_3d(nx,ny,nz)  ! radar reflectivity (dBZ)
  REAL :: t_3d(nx,ny,nz)  ! Temperature (deg. Kelvin)
  REAL :: p_3d(nx,ny,nz)  ! Pressure (Pascal)

  INTEGER:: cldpcp_type_3d(nx,ny,nz) ! cloud/precip type field
!
!  OUTPUT:
  INTEGER :: istatus
!
  REAL :: qr_3d(nx,ny,nz)     ! rain mixing ratio in (g/kg)
  REAL :: qs_3d(nx,ny,nz)     ! snow/sleet/frz-rain mixing ratio
                            ! in (g/kg)
  REAL :: qh_3d(nx,ny,nz)     ! hail mixing ratio in (g/kg)
!

  REAL,PARAMETER :: ki2 = 0.176 ! Dielectric factor for ice if other
                                !   than melted drop diameters are used.
  REAL,PARAMETER :: kw2=0.93 ! Dielectric factor for water.

  REAL,PARAMETER :: m3todBZ=1.0E+18 ! Conversion factor from m**3 to
                                    !   mm**6 m**-3.
  REAL,PARAMETER :: Zefact=720.0 ! Multiplier for Ze components.
  REAL,PARAMETER :: lg10div=0.10 ! Log10 multiplier (1/10)

  REAL,PARAMETER :: pi=3.1415926 ! Pi.
  REAL,PARAMETER :: N0r=8.0E+06 ! Intercept parameter in 1/(m^4) for rain.
  REAL,PARAMETER :: N0s=3.0E+06 ! Intercept parameter in 1/(m^4) for snow.
  REAL,PARAMETER :: N0h=4.0E+04 ! Intercept parameter in 1/(m^4) for hail.

  REAL,PARAMETER :: N0xpowf=3.0/7.0 ! Power to which N0r,N0s & N0h are
                                    !   raised.
  REAL,PARAMETER :: K2powf=4.0/7.0  ! Power to which K-squared 
                                    !  of ice, water are raised
  REAL,PARAMETER :: zkpowf=4.0/7.0  ! Power to which Zk is raised
  REAL,PARAMETER :: zepowf=4.0/7.0  ! Power to which Ze is raised
  REAL,PARAMETER :: zehpowf=(4.0/7.0)*1.0526  ! Power to which Zeh is raised

  REAL,PARAMETER :: rhoi=917.  ! Density of ice (kg m**-3)
  REAL,PARAMETER :: rhor=1000. ! Density of rain (kg m**-3)
  REAL,PARAMETER :: rhos=100.  ! Density of snow (kg m**-3)
  REAL,PARAMETER :: rhoh=913.  ! Density of hail (kg m**-3)

  REAL,PARAMETER :: rhoipowf=8.0/7.0  ! Power to which rhoi is raised.
  REAL,PARAMETER :: rhospowf=1.0/7.0  ! Power to which rhos is raised.
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  REAL :: thresh_ref
  PARAMETER (thresh_ref = 0.0)
  INTEGER :: i,j,k, iarg
  INTEGER :: pcptype
  REAL :: zkconst,zerf,zesnegf,zesposf,zehf,rfract
  REAL :: ze,zer,zeh,zes,rho,tc
!
!-----------------------------------------------------------------------
!
! Include Files
!
!-----------------------------------------------------------------------
!
  INCLUDE 'phycst.inc'
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
!-----------------------------------------------------------------------
!
!  Intiailize constant factors in the Ze terms for rain, snow and hail,
!  respectively, in Ferrier.
!
!  These are the inverse of those presented in the reflec_ferrier function.
!
!-----------------------------------------------------------------------
!
  istatus=0

  zkconst = (Zefact*m3todBZ) ** zkpowf

  zerf=1000.*(pi * (N0r**N0xpowf) * rhor )/zkconst

  zesnegf=1000.*(pi*(kw2**k2powf)*(N0s**N0xpowf)*(rhoi**rhoipowf)) /    &
          ( zkconst * (ki2**k2powf) * (rhos**rhospowf) )
          
  zesposf=1000.*( pi * (N0s**N0xpowf) * rhos) / zkconst
 
  zehf=1000.*( pi * (N0h**N0xpowf) * rhoh) / zkconst

!-----------------------------------------------------------------------
!
!  Compute the precip mixing ratio in g/kg from radar reflectivity
!  factor following Ferrier et al (1995).
!
!-----------------------------------------------------------------------
!
  DO k = 2,nz-1
    DO j = 1,ny-1
      DO i = 1,nx-1
        IF (ref_3d(i,j,k) >= thresh_ref) THEN    ! valid radar refl.
          rho = p_3d(i,j,k)/(rd*t_3d(i,j,k))
          ze = 10.0**(0.1*ref_3d(i,j,k))
          iarg = cldpcp_type_3d(i,j,k)
          pcptype = iarg/16              ! precip. type
          tc = t_3d(i,j,k) - 273.15

          IF (pcptype == 1) THEN   ! rain
            qr_3d(i,j,k) = zerf * (ze**zepowf) / rho
          ELSE IF (pcptype == 2) THEN                   ! snow
            IF (tc <= 0.0) THEN     !dry snow
              qs_3d(i,j,k) = zesnegf * (ze**zepowf) / rho
            ELSE IF (tc < 5.0) THEN     !wet snow
              rfract=0.20*tc
              zer=rfract*ze
              zes=(1.-rfract)*ze
              qs_3d(i,j,k) = zesposf * (zes**zepowf) / rho
              qr_3d(i,j,k) = zerf * (zer**zepowf) / rho
            ELSE
              qr_3d(i,j,k) = zerf * (ze**zepowf) / rho
            END IF
          ELSE IF (pcptype == 3) THEN   ! ZR
            qr_3d(i,j,k) = zerf * (ze**zepowf) / rho
          ELSE IF (pcptype == 4) THEN   ! sleet
            IF (tc <= 0.0) THEN     ! hail category
              qh_3d(i,j,k) = zehf * (ze**zehpowf) / rho
            ELSE IF( tc < 10. ) THEN
              rfract=0.10*tc
              zer=rfract*ze
              zeh=(1.-rfract)*ze
              qr_3d(i,j,k) = zerf * (zer**zepowf) / rho
              qh_3d(i,j,k) = zehf * (zeh**zehpowf) / rho
            ELSE
              qr_3d(i,j,k) = zerf * (ze**zepowf) / rho
            END IF
          ELSE IF (pcptype == 5) THEN   ! hail
            qh_3d(i,j,k) = zehf * (ze**zehpowf) / rho
          ELSE                                          ! unknown
            IF (tc <= 0.0) THEN     !dry snow
              qs_3d(i,j,k) = zesnegf * (ze**zepowf) / rho
            ELSE IF ( tc < 5.0 ) THEN     !wet snow
              rfract=0.20*tc
              zer=rfract*ze
              zes=(1.-rfract)*ze
              qs_3d(i,j,k) = zesposf * (zes**zepowf) / rho
              qr_3d(i,j,k) = zerf * (zer**zepowf) / rho
            ELSE ! rain
              qr_3d(i,j,k) = zerf * (ze**zepowf) / rho
            END IF
          END IF
        ELSE
          qr_3d(i,j,k) = 0.
          qs_3d(i,j,k) = 0.
          qh_3d(i,j,k) = 0.
        END IF
      END DO ! k
    END DO ! i
  END DO ! j
  PRINT*,'Finish Ferrier ...'
!
!-----------------------------------------------------------------------
!
  istatus = 1
!
  RETURN
END SUBROUTINE pcp_mxr_ferrier
!
!##################################################################
!##################################################################
!######                                                      ######
!######               SUBROUTINE REFMOSAIC                   ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!

SUBROUTINE refmosaic(nradfil,nx,ny,nz,mx_rad,                           & 3,1
           xs,ys,zs,radfname,ref_mos_3d,rhinf,rvinf,                    &
           refl,tem1,tem2,istatus)
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  This routine patches together reflectivity fields observed from
!  multiple radars to create one 3D radar reflectivity field.
!  It also fills the data gaps between the radar beams and elevations).
!  These gaps are possible because that the real-time radar data
!  processing only put data to the grid point nearest to the radar gate.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!  06/04/96.
!
!  MODIFICATION HISTORY:
!  11/01/01 (Keith Brewster)  
!  Created refmosaic from rad_patch_fill saving lots of memory when
!  there are more than a couple of radars.
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
  INTEGER :: nradfil              ! # of radars currently available
  INTEGER :: nx,ny,nz             ! model grid size
  INTEGER :: mx_rad
  REAL :: xs(nx)                  ! x-coor at scalar points
  REAL :: ys(ny)                  ! y-coor at scalar points
  REAL :: zs(nx,ny,nz)            ! z-coor at scalar points
  CHARACTER (LEN=132) radfname(mx_rad)
  REAL :: rhinf
  REAL :: rvinf
!
!  OUTPUT:
!
  REAL :: ref_mos_3d (nx,ny,nz) ! combined radar refl. field
  INTEGER :: istatus
!
!  Temporary working array
!
  REAL :: refl(nx,ny,nz)
  REAL :: tem1(nx,ny,nz)
  REAL :: tem2(nx,ny,nz)
!
!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: i,j,k,irad
  INTEGER :: im1,ip1,jm1,jp1,km1,kp1
  INTEGER :: isrcrad,istat_rad
  REAL    :: latrad,lonrad,elvrad
  REAL    :: x_m1,x_p1,y_m1,y_p1,hgt_km1,hgt_kp1,frac
  REAL    :: refl_ip1,refl_im1,refl_jm1,refl_jp1,refl_km1,refl_kp1
  LOGICAL :: got_im1,got_ip1,got_jm1,got_jp1,got_km1,got_kp1
  INTEGER :: strhopt_rad,mapproj_rad
  REAL    :: dx_rad,dy_rad,dz_rad,dzmin_rad
  REAL    :: ctrlat_rad,ctrlon_rad,tlat1_rad,tlat2_rad,tlon_rad
  REAL    :: sclfct_rad
  CHARACTER (LEN=5) stnrad
  CHARACTER (LEN=128) warn_string 
!
!-----------------------------------------------------------------------
!
!  Include files
!
!-----------------------------------------------------------------------
!
   INCLUDE 'grid.inc'
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  istatus=0

  warn_string = 'WARNING: Radar data are not used ' //                  &
                   'due to grid or map projection inconsistencies'

  WRITE(6,'(a)')                                                        &
    ' Mosaiking reflectivity from multiple radar observations'
!
!-----------------------------------------------------------------------
!
!  Combining the multiple radar obs. to produce one set of
!  3D reflectivity field.
!
!-----------------------------------------------------------------------
!
  DO irad = 1,nradfil
    CALL read1rad(nx,ny,nz,radfname(irad),                              &
                  strhopt_rad,mapproj_rad,dx_rad,dy_rad,dz_rad,         &
                  dzmin_rad,ctrlat_rad,ctrlon_rad,                      &
                  tlat1_rad,tlat2_rad,tlon_rad,sclfct_rad,              &
                  isrcrad,stnrad,latrad,lonrad,elvrad,                  &
                  tem1,refl,tem2,tem2,                                  &
                  istat_rad)
!
!-----------------------------------------------------------------------
!
!  For successful read of radar data.
!
!  Check IF the radar data are remapped on the same grid as
!  the one we are using for ADAS.
!
!-----------------------------------------------------------------------
!
    IF (istat_rad == 1 ) THEN
      WRITE(6,'(a,a)') ' Successfully read radar datafile ',radfname(irad)
      IF (ABS(strhopt_rad-strhopt) > 1.0E-4 .OR.                        &
              mapproj_rad /= mapproj) THEN
        WRITE(6,*) warn_string
        WRITE(6,*)                                                      &
          'RADAR: strhopt=',strhopt_rad, '  mapproj=',mapproj_rad
        WRITE(6,*) 'ADAS: strhopt=',strhopt, '  mapproj=',mapproj
        CYCLE
      END IF
!
      IF (ABS(dx_rad-dx) > 1.0E-4 .OR. ABS(dy_rad-dy) > 1.0E-4 .OR.     &
          ABS(dz_rad-dz) > 1.0E-4 .OR.                                  &
          ABS(dzmin_rad-dzmin) > 1.0E-4) THEN
        WRITE(6,*) warn_string
        WRITE(6,*) 'RADAR: dx=',dx_rad, ' dy=',dy_rad,' dz=',dz_rad
        WRITE(6,*) 'ADAS: dx=',dx, ' dy=',dy,' dz=',dz
        CYCLE
      END IF
!
      IF (mapproj /= 0) THEN
        IF (ABS(ctrlat_rad-ctrlat) > 1.0E-4 .OR.                        &
              ABS(ctrlon_rad-ctrlon) > 1.0E-4) THEN
          WRITE(6,*) warn_string
          WRITE(6,*) 'RADAR: ctrlat=',ctrlat_rad,' ctrlon=',ctrlon_rad
          WRITE(6,*) 'ADAS: ctrlat=',ctrlat, ' ctrlon=',ctrlon
          CYCLE
        END IF
!
        IF(ABS(sclfct_rad-sclfct) > 1.0E-4) THEN
          WRITE(6,*) warn_string
          WRITE(6,*) 'RADAR: sclfct=',sclfct_rad
          WRITE(6,*) 'ADAS: sclfct=',sclfct
          CYCLE
        END IF
      END IF
!
      IF (mapproj == 1 .OR. mapproj == 3) THEN
        IF (ABS(tlat1_rad-trulat1) > 1.0E-4 .OR.                        &
              ABS(tlon_rad-trulon) > 1.0E-4) THEN
          WRITE(6,*) warn_string
          WRITE(6,*) 'RADAR: trulat1=',tlat1_rad, ' trulon=',tlon_rad
          WRITE(6,*) 'ADAS: trulat1=',trulat1, ' trulon=',trulon
          CYCLE
        END IF
      ELSE IF (mapproj == 2) THEN
        IF (ABS(tlat1_rad-trulat1) > 1.0E-4 .OR.                        &
            ABS(tlat2_rad-trulat2) > 1.0E-4 &
            .OR. ABS(tlon_rad-trulon) > 1.0E-4) THEN
          WRITE(6,*) warn_string
          WRITE(6,*) 'RADAR: trulat1=',tlat1_rad,                       &
                   ' trulat2=',tlat2_rad,' trulon=',tlon_rad
          WRITE(6,*) 'ADAS: trulat1=',trulat1,                          &
                   ' trulat2=',trulat2,' trulon=',trulon
          CYCLE
        END IF
      END IF
!
!-----------------------------------------------------------------------
!
!     For now, mosaic by taking the maximum value
!
!-----------------------------------------------------------------------
!
      WRITE(6,'(a,a,a)') ' Bringing radar ',stnrad,' into mosaic '

! OpenMP changed loop order to j,k,i:
!$OMP PARALLEL DO PRIVATE (j,k,i,irad)
      DO j=1,ny
        DO k=1,nz-1
          DO i=1,nx
            ref_mos_3d(i,j,k) = MAX(ref_mos_3d(i,j,k),refl(i,j,k))
          END DO
        END DO
      END DO
    END IF ! read ok
  END DO  !irad

!
!-----------------------------------------------------------------------
!
!  Vertical interpolation to fill the gaps between different
!  elevations.
!
!-----------------------------------------------------------------------
!
! WRITE(6,'(a)') ' Vertically interpolating radar refl.'
!! OpenMP changed loop order to j,i,k:
!!$OMP PARALLEL DO PRIVATE(j,i,k,kp1,got_kp1,refl_kp1,hgt_kp1,km1,got_km1,refl_km1,hgt_km1,frac)
! DO j=1,ny
!   DO i=1,nx
!     DO k=2,nz-2
!       tem1(i,j,k) = ref_mos_3d(i,j,k)
!       IF(ref_mos_3d(i,j,k) < -10.) THEN
!         got_kp1=.FALSE.
!         DO kp1=k+1,nz-1
!           IF (zs(i,j,kp1) > (zs(i,j,k)+rvinf)) EXIT
!           IF (ref_mos_3d(i,j,kp1) >= -10.) THEN
!             refl_kp1 = ref_mos_3d(i,j,kp1)
!             hgt_kp1 = zs(i,j,kp1)
!             got_kp1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         got_km1=.FALSE.
!         DO km1=k-1,2,-1
!           IF(zs(i,j,km1) < (zs(i,j,k)-rvinf)) EXIT
!           IF(ref_mos_3d(i,j,km1) >= -10) THEN
!             refl_km1 = ref_mos_3d(i,j,km1)
!             hgt_km1 = zs(i,j,km1)
!             got_km1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         IF(got_km1 .AND. got_kp1 .AND.                             &
!            (hgt_kp1-hgt_km1) < rvinf ) THEN
!           frac = (zs(i,j,k)-hgt_km1)/(hgt_kp1-hgt_km1)
!           tem1(i,j,k) = refl_kp1*frac + refl_km1*(1.-frac)
!         END IF
!       END IF
!     END DO
!   END DO
! END DO

!
!-----------------------------------------------------------------------
!
!  Horizontal interpolation to further fill gaps between
!  the beams.
!
!-----------------------------------------------------------------------
!
! WRITE(6,'(a)') ' Horizontally interpolating radar refl.'

! DO k=1,nz-1
!   DO i=2,nx-2
!     DO j=2,ny-2
!       ref_mos_3d(i,j,k)=tem1(i,j,k)
!       IF(tem1(i,j,k) < -10.) THEN 
!         got_ip1=.FALSE.
!         DO ip1=i+1,nx-1
!           IF (xs(ip1) > (xs(i)+rhinf)) EXIT
!           IF(tem1(ip1,j,k) >= -10.) THEN
!             refl_ip1=tem1(ip1,j,k)
!             x_p1=xs(ip1)
!             got_ip1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         got_im1=.FALSE.
!         DO im1=i-1,1,-1
!           IF (xs(im1) < (xs(i)-rhinf)) EXIT
!           IF(tem1(im1,j,k) >= -10.) THEN
!             refl_im1=tem1(im1,j,k)
!             x_m1=xs(im1)
!             got_im1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         got_jp1=.FALSE.
!         DO jp1=j+1,ny-1
!           IF (ys(jp1) > (ys(j)+rhinf)) EXIT
!           IF(tem1(i,jp1,k) >= -10.) THEN
!             refl_jp1=tem1(i,jp1,k)
!             y_p1=ys(jp1)
!             got_jp1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         got_jm1=.FALSE.
!         DO jm1=j-1,1,-1
!           IF (ys(jm1) < (ys(j)-rhinf)) EXIT
!           IF(tem1(i,jm1,k) >= -10.) THEN
!             refl_jm1=tem1(i,jm1,k)
!             y_m1=ys(jm1)
!             got_jm1=.TRUE.
!             EXIT
!           END IF
!         END DO

!         IF(got_im1 .AND. got_ip1 .AND. (x_p1-x_m1) < rhinf .AND.  &
!            got_jm1 .AND. got_jp1 .AND. (y_p1-y_m1) < rhinf ) THEN
!           frac = (xs(i)-x_m1)/(x_p1-x_m1)
!           ref_mos_3d(i,j,k) = refl_ip1*frac + refl_im1*(1-frac)
!           frac = (ys(j)-y_m1)/(y_p1-y_m1)
!           ref_mos_3d(i,j,k) = (refl_jp1*frac + refl_jm1*(1-frac)    &
!                                    + ref_mos_3d(i,j,k))*0.5
!         ELSE IF (got_im1 .AND. got_ip1 .AND.                      &
!                  (x_p1-x_m1) < rhinf) THEN
!           frac = (xs(i)-x_m1)/(x_p1-x_m1)
!           ref_mos_3d(i,j,k) = refl_ip1*frac + refl_im1*(1-frac)
!         ELSE IF (got_jm1 .AND. got_jp1 .AND.                      &
!                  (y_p1-y_m1) < rhinf) THEN
!           frac = (ys(j)-y_m1)/(y_p1-y_m1)
!           ref_mos_3d(i,j,k) = refl_jp1*frac + refl_jm1*(1-frac)
!         END IF
!       END IF
!     END DO
!   END DO
! END DO

!
!-----------------------------------------------------------------------
!
! Done.
!
!-----------------------------------------------------------------------
!
  istatus=1

  RETURN
END SUBROUTINE refmosaic
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE READRAD                    ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE readrad(nx,ny,nz,isrcrad,stnrad                              &,4
           ,latrad,lonrad,elvrad                                        &
           ,gridvel,gridref,gridnyq,gridtim                             &
           ,istatus)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Reads radar data remapped on the ARPS grid.
!  This routine requires the remapping to occur on the same grid
!  as the analysis.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:  Jian Zhang
!  05/1996  Read the remapped radar data which was written by the
!           corresponding output routine "wrtrad" in remaplib.f.
!
!  MODIFICATION HISTORY:
!  03/19/97  J. Zhang
!            Added a line of error message when there is trouble
!            reading a radar file.
!  04/03/97  J. Zhang
!            Added the option of reading the data file created
!            from "WTRADCOL".  Added output for the remapping
!            parameters in the radar file (e.g., strhopt,mapproj,
!            dx,dy,dz,dzmin,ctrlat,ctrlon,tlat1,tlat2,tlon,scale)
!  04/07/97  J. Zhang
!            Added  the QC for the case when i,j,k outside the model
!            domain
!  04/09/97  J. Zhang
!            Added the Initializations for gridref, girdvel...
!  04/11/97  J. Zhang
!            Include dims.inc for nx,ny,nz
!  04/14/97  J. Zhang
!            Added message output for the case when actual # of
!            radar files exceeds the maximum allowed number in the
!            ADAS include file.  When that happens, the program will
!            stop.
!  03/31/98  J. Zhang
!            Deleted the option for reading the radar data file
!            created from "WRTRAD".
!
!-----------------------------------------------------------------------
!
!  INCLUDE:  (from dims.inc and adas.inc)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!    mx_rad     maximum number of radars
!
!    nradfil    number of radar files
!    radfname   file name for radar datasets
!
!  OUTPUT:
!
!    isrcrad  index of radar source
!    stnrad   radar site name    character*4
!    latrad   latitude of radar  (degrees N)
!    lonrad   longitude of radar (degrees E)
!    elvrad   elevation of feed horn of radar (m MSL)
!
!    gridvel  radial velocity on ARPS grid
!    gridref  reflectivity on ARPS grid
!    gridnyq  nyquist velocity on ARPS grid
!    gridtim  observation time at ARPS grid
!
!    istatus  status indicator
!
!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  Include files:
!
  INCLUDE 'adas.inc'     ! ADAS parameters
!
!-----------------------------------------------------------------------
!
!  INPUT:
  INTEGER :: nx,ny,nz    ! the ARPS grid size
!
!  LOCAL:
! 
  REAL :: readk(nz)
  REAL :: readhgt(nz)
  REAL :: readref(nz)
  REAL :: readvel(nz)
  REAL :: readnyq(nz)
  REAL :: readtim(nz)
!
  INTEGER :: kntref(nz)
  INTEGER :: kntvel(nz)
  INTEGER :: iradvr
  INTEGER :: nradvr
!
!  OUTPUT:
  INTEGER :: istatus
!
!  OUTPUT:  ARPS radar arrays
  REAL :: gridvel(nx,ny,nz,mx_rad)
  REAL :: gridref(nx,ny,nz,mx_rad)
  REAL :: gridnyq(nx,ny,nz,mx_rad)
  REAL :: gridtim(nx,ny,nz,mx_rad)
!
!  OUTPUT:  Radar site variables
  INTEGER :: isrcrad(0:mx_rad)
  CHARACTER (LEN=5) :: stnrad(mx_rad)
  REAL :: latrad(mx_rad)
  REAL :: lonrad(mx_rad)
  REAL :: elvrad(mx_rad)
!
!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------
!
  CHARACTER (LEN=4) :: stn
  CHARACTER (LEN=80) :: runname
  CHARACTER (LEN=132) :: fname
  INTEGER :: ireftim,itime,vcpnum,idummy
  INTEGER :: iradfmt,strhopt,mapprin
  INTEGER :: nchanl,ierr
  INTEGER :: iyr, imon, idy, ihr, imin, isec
  INTEGER :: i,j,k,krad,kk,ipt,klev

  REAL :: dxin,dyin,dzin,dzminin,ctrlatin
  REAL :: ctrlonin,tlat1in,tlat2in,tlonin,scalin,rdummy
  REAL :: xrd,yrd,gridlat,gridlon,elev
!
!-----------------------------------------------------------------------
!
!  Common block that stores remapping parameters for the radar
!  data file.
!
!-----------------------------------------------------------------------
!
  COMMON/remapfactrs_rad/strhopt,mapprin
  COMMON/remapfactrs_rad2/dxin,dyin,dzin,dzminin,                       &
           ctrlatin,ctrlonin,tlat1in,tlat2in,tlonin,scalin
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
  istatus=0
  IF (nradfil > mx_rad) THEN
    WRITE(6,'(a,i3,a,i3/a)')                                            &
        ' ERROR: nradfil ',nradfil,' exceeds mx_rad dimension',         &
        mx_rad,' please increase MX_RAD in the .inc file'
    PRINT*,' ABORTING from READRAD......'
    STOP
  END IF
  IF(nradfil < 1) THEN
    WRITE(6,*) 'No radar data available. Returning from READRAD...'
    RETURN
  END IF
!
!-----------------------------------------------------------------------
!
!  Initializations
!
!-----------------------------------------------------------------------
!
! OpenMP changed loop order to j,krad,k,i:
!$OMP PARALLEL DO PRIVATE(j,krad,k,i)
  DO j=1,ny
    DO krad = 1, mx_rad
      DO k=1,nz
        DO i=1,nx
          gridref(i,j,k,krad)=-9999.
          gridvel(i,j,k,krad)=-9999.
          gridnyq(i,j,k,krad)=-9999.
          gridtim(i,j,k,krad)=-9999.
        END DO
      END DO
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Loop through all radars
!
!-----------------------------------------------------------------------
!
  DO krad = 1, nradfil

    fname=radfname(krad)
    CALL asnctl ('NEWLOCAL', 1, ierr)
    CALL asnfile(fname, '-F f77 -N ieee', ierr)

    CALL getunit( nchanl )
    OPEN(UNIT=nchanl,FILE=trim(fname),ERR=399,                          &
         FORM='unformatted',STATUS='old')
!
!-----------------------------------------------------------------------
!
!  Read radar description variables
!
!-----------------------------------------------------------------------
!
    istatus=1
    isrcrad(krad)=1
!
    READ(nchanl) stn
    stnrad(krad)=stn
    READ(nchanl) ireftim,itime,vcpnum,idummy,idummy,                    &
               idummy,idummy,idummy,idummy,idummy
!
    CALL abss2ctim(itime, iyr, imon, idy, ihr, imin, isec )
    iyr=MOD(iyr,100)
    WRITE(6,'(/a,i2.2,a,i2.2,a,i2.2,1X,i2.2,a,i2.2,a)')                 &
       'Reading remapped raw radar data for: ',                         &
       imon,'/',idy,'/',iyr,ihr,':',imin,' UTC'
!
    READ(nchanl) runname
    READ(nchanl) iradfmt,strhopt,mapprin,idummy,idummy,                 &
               idummy,idummy,idummy,idummy,idummy

    READ(nchanl) dxin,dyin,dzin,dzminin,ctrlatin,                       &
           ctrlonin,tlat1in,tlat2in,tlonin,scalin,                      &
           latrad(krad),lonrad(krad),elvrad(krad),                      &
           rdummy,rdummy
!
    DO k=1,nz
      kntref(k) = 0
      kntvel(k) = 0
    END DO

    READ(nchanl) nradvr,iradvr
!
    DO ipt=1,(nx*ny)

      READ(nchanl,END=51) i,j,xrd,yrd,                                  &
                     gridlat,gridlon,elev,klev
      READ(nchanl,END=52) (readk(kk),kk=1,klev)
      READ(nchanl,END=52) (readhgt(kk),kk=1,klev)
      READ(nchanl,END=52) (readref(kk),kk=1,klev)
      READ(nchanl,END=52) (readvel(kk),kk=1,klev)
      READ(nchanl,END=52) (readnyq(kk),kk=1,klev)
      READ(nchanl,END=52) (readtim(kk),kk=1,klev)

      IF(i <= nx.AND.i >= 1 .AND. j <= ny.AND.j >= 1) THEN
        DO kk=1,klev
          k=nint(readk(kk))
          IF(k <= nz.AND.k >= 1) THEN
            gridref(i,j,k,krad)=readref(kk)
            gridvel(i,j,k,krad)=readvel(kk)
            gridnyq(i,j,k,krad)=readnyq(kk)
            gridtim(i,j,k,krad)=readtim(kk)
            IF (gridref(i,j,k,krad) > -200. .AND. gridref(i,j,k,krad) < 200.) &
                kntref(k)=kntref(k)+1
            IF (gridvel(i,j,k,krad) > -200. .AND. gridvel(i,j,k,krad) < 200.) &
                kntvel(k)=kntvel(k)+1
          END IF  ! 1 < k < nz
        END DO  ! kk = 1, klev
      END IF  ! 1 < i < nx  & 1 < j < ny

    END DO  ! ipt = 1, nx*ny

    51      CONTINUE
    ipt=ipt-1
    WRITE(6,'(a,i6,a)') ' End of file reached after reading',           &
                       ipt,' columns'
    GO TO 55
    52      CONTINUE
    WRITE(6,'(a,i6,a)') ' End of file reached while reading',           &
                       ipt,' column'
    55      CONTINUE
!
!-----------------------------------------------------------------------
!
!  Write statistics
!
!-----------------------------------------------------------------------
!
    WRITE(6,'(a)') '  k   n ref    n vel'
    DO k=1,nz
      WRITE(6,'(i3,2i10)') k,kntref(k),kntvel(k)
    END DO
!
    CLOSE(nchanl)
    CALL retunit( nchanl )

    GO TO 400

    399     CONTINUE
    PRINT*,'Error reading the radar file:',fname

    400     CONTINUE
  END DO  ! KRAD = 1, nradfil

  RETURN
END SUBROUTINE readrad
!
!##################################################################
!##################################################################
!######                                                      ######
!######             SUBROUTINE READ1RAD                      ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE read1rad(nx,ny,nz,radfname,                                  & 1,35
                  strhopt_rad,mapproj_rad,dx_rad,dy_rad,dz_rad,         &
                  dzmin_rad,ctrlat_rad,ctrlon_rad,                      &
                  tlat1_rad,tlat2_rad,tlon_rad,sclfct_rad,              &
                  isrcrad,stnrad,latrad,lonrad,elvrad,                  &
                  gridvel,gridref,gridnyq,gridtim,                      &
                  istatus)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Reads radar data remapped on the ARPS grid.
!  This routine requires the remapping to occur on the same grid
!  as the analysis.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:  Jian Zhang
!  05/1996  Read the remapped radar data which was written by the
!           corresponding output routine "wrtrad" in remaplib.f.
!
!  MODIFICATION HISTORY:
!  03/19/97  J. Zhang
!            Added a line of error message when there is trouble
!            reading a radar file.
!  04/03/97  J. Zhang
!            Added the option of reading the data file created
!            from "WTRADCOL".  Added output for the remapping
!            parameters in the radar file (e.g., strhopt,mapproj,
!            dx,dy,dz,dzmin,ctrlat,ctrlon,tlat1,tlat2,tlon,scale)
!  04/07/97  J. Zhang
!            Added  the QC for the case when i,j,k outside the model
!            domain
!  04/09/97  J. Zhang
!            Added the Initializations for gridref, girdvel...
!  04/11/97  J. Zhang
!            Include dims.inc for nx,ny,nz
!  04/14/97  J. Zhang
!            Added message output for the case when actual # of
!            radar files exceeds the maximum allowed number in the
!            ADAS include file.  When that happens, the program will
!            stop.
!  03/31/98  J. Zhang
!            Deleted the option for reading the radar data file
!            created from "WRTRAD".
!  11/01/01  K. Brewster
!            Modified readrad to read1rad to read only one radar file 
!            at a time to save memory.
!  02/02/04  K. Thomas
!	     Change so a missing HDF4 isn't a fatal error.
!  02/18/04  K. Thomas
!	     Allocated I/O unit not returned when binary file doesn't exit.
!	     This update fixes the problem.
!
!-----------------------------------------------------------------------
!
!  INPUT:
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!    radfname   file name for radar datasets
!
!  OUTPUT:
!
!    isrcrad  index of radar source
!    stnrad   radar site name    character*4
!    latrad   latitude of radar  (degrees N)
!    lonrad   longitude of radar (degrees E)
!    elvrad   elevation of feed horn of radar (m MSL)
!
!    gridvel  radial velocity on ARPS grid
!    gridref  reflectivity on ARPS grid
!    gridnyq  nyquist velocity on ARPS grid
!    gridtim  observation time at ARPS grid
!
!    istatus  status indicator
!
!
!-----------------------------------------------------------------------
!
!  Variable Declarations:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
  INTEGER :: nx,ny,nz    ! the ARPS grid size
  CHARACTER (LEN=132) :: radfname
  INTEGER :: strhopt_rad,mapproj_rad
  REAL    :: dx_rad,dy_rad,dz_rad,dzmin_rad
  REAL    :: ctrlat_rad,ctrlon_rad,tlat1_rad,tlat2_rad,tlon_rad
  REAL    :: sclfct_rad
!
!  OUTPUT:  Radar site variables
!
  INTEGER :: isrcrad
  CHARACTER (LEN=5) :: stnrad
  REAL :: latrad
  REAL :: lonrad
  REAL :: elvrad
!
!  OUTPUT:  ARPS radar arrays
!
  REAL :: gridvel(nx,ny,nz)
  REAL :: gridref(nx,ny,nz)
  REAL :: gridnyq(nx,ny,nz)
  REAL :: gridtim(nx,ny,nz)
  INTEGER :: istatus
!
!-----------------------------------------------------------------------
!
!  Misc. local variables
!
!-----------------------------------------------------------------------
!
  REAL :: readk(nz)
  REAL :: readhgt(nz)
  REAL :: readref(nz)
  REAL :: readvel(nz)
  REAL :: readnyq(nz)
  REAL :: readtim(nz)
!
  INTEGER, ALLOCATABLE :: kntref(:)
  INTEGER, ALLOCATABLE :: kntvel(:)
!
  INTEGER :: mxradvr,nradvr
  PARAMETER(mxradvr=10)
  INTEGER :: iradvr(mxradvr)

  CHARACTER (LEN=4) :: stn
  CHARACTER (LEN=80) :: runname
  INTEGER :: ireftim,itime,vcpnum,idummy
  INTEGER :: iradfmt,strhopt,mapprin
  INTEGER :: nchanl,ierr
  INTEGER :: iyr, imon, idy, ihr, imin, isec
  INTEGER :: i,j,k,krad,kk,ipt,klev

  REAL :: xrd,yrd,gridlat,gridlon,elev,rdummy
!
!-----------------------------------------------------------------------
!
! hdf arrays
!
!-----------------------------------------------------------------------
!
  INTEGER (KIND=selected_int_kind(4)), ALLOCATABLE :: itmp(:,:,:)
  REAL, ALLOCATABLE :: hmax(:), hmin(:) ! Temporary array
  INTEGER :: lens,dmpfmt,sd_id,isource
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  istatus=0
!
!-----------------------------------------------------------------------
!
!  Initializations
!
!-----------------------------------------------------------------------
!
  ALLOCATE(kntref(nz))
  ALLOCATE(kntvel(nz))
!
! OpenMP changed loop order to j,k,i:
!$OMP PARALLEL DO PRIVATE(j,k,i)
  DO j=1,ny
    DO k=1,nz
      DO i=1,nx
        gridref(i,j,k)=-9999.
        gridvel(i,j,k)=-9999.
        gridnyq(i,j,k)=-9999.
        gridtim(i,j,k)=-9999.
      END DO
    END DO
  END DO
!
  DO k=1,nz
    kntref(k)=0
    kntvel(k)=0
  END DO
!
!-----------------------------------------------------------------------
!
! Open file
!
!-----------------------------------------------------------------------
!
  CALL asnctl ('NEWLOCAL', 1, ierr)
  CALL asnfile(radfname, '-F f77 -N ieee', ierr)

  lens=LEN(trim(radfname))
  IF(radfname(lens-3:lens)=='hdf4')THEN
    dmpfmt=2
  ELSE
    dmpfmt=1
  ENDIF
  print*,'radfname=',TRIM(radfname),'dmpfmt=',dmpfmt

  IF(dmpfmt==1)THEN
  CALL getunit( nchanl )
  OPEN(UNIT=nchanl,FILE=trim(radfname),ERR=399,                         &
         FORM='unformatted',STATUS='old')
!
!-----------------------------------------------------------------------
!
!  Read radar description variables
!
!-----------------------------------------------------------------------
!
  istatus=1
  isrcrad=1
!
  READ(nchanl) stn
  stnrad=stn
  READ(nchanl) ireftim,itime,vcpnum,idummy,idummy,                      &
               idummy,idummy,idummy,idummy,idummy
!
  CALL abss2ctim(itime, iyr, imon, idy, ihr, imin, isec )
  iyr=MOD(iyr,100)
  WRITE(6,'(/a,i2.2,a,i2.2,a,i2.2,1X,i2.2,a,i2.2,a)')                   &
       'Reading remapped raw radar data for: ',                         &
       imon,'/',idy,'/',iyr,ihr,':',imin,' UTC'
!
  READ(nchanl) runname
  READ(nchanl) iradfmt,strhopt_rad,mapproj_rad,idummy,idummy,           &
               idummy,idummy,idummy,idummy,idummy

  READ(nchanl) dx_rad,dy_rad,dz_rad,dzmin_rad,ctrlat_rad,               &
           ctrlon_rad,tlat1_rad,tlat2_rad,tlon_rad,sclfct_rad,          &
           latrad,lonrad,elvrad,                                        &
           rdummy,rdummy
!
  READ(nchanl) nradvr,iradvr
!
  DO ipt=1,(nx*ny)

    READ(nchanl,END=51) i,j,xrd,yrd,                                    &
                   gridlat,gridlon,elev,klev
    READ(nchanl,END=52) (readk(kk),kk=1,klev)
    READ(nchanl,END=52) (readhgt(kk),kk=1,klev)
    READ(nchanl,END=52) (readref(kk),kk=1,klev)
    READ(nchanl,END=52) (readvel(kk),kk=1,klev)
    READ(nchanl,END=52) (readnyq(kk),kk=1,klev)
    READ(nchanl,END=52) (readtim(kk),kk=1,klev)

    IF(i <= nx.AND.i >= 1 .AND. j <= ny.AND.j >= 1) THEN
      DO kk=1,klev
        k=nint(readk(kk))
        IF(k <= nz.AND.k >= 1) THEN
          gridref(i,j,k)=readref(kk)
          gridvel(i,j,k)=readvel(kk)
          gridnyq(i,j,k)=readnyq(kk)
          gridtim(i,j,k)=readtim(kk)
          IF (gridref(i,j,k) > -200. .AND. gridref(i,j,k) < 200.)      &
              kntref(k)=kntref(k)+1
          IF (gridvel(i,j,k) > -200. .AND. gridvel(i,j,k) < 200.)      &
              kntvel(k)=kntvel(k)+1
        END IF  ! 1 < k < nz
      END DO  ! kk = 1, klev
    END IF  ! 1 < i < nx  & 1 < j < ny

  END DO  ! ipt = 1, nx*ny

  51      CONTINUE
  ipt=ipt-1
    WRITE(6,'(a,i6,a)') ' End of file reached after reading',          &
                       ipt,' columns'
    GO TO 55
    52      CONTINUE
    WRITE(6,'(a,i6,a)') ' End of file reached while reading',          &
                       ipt,' column'
    55      CONTINUE
!
!-----------------------------------------------------------------------
!
!  Write statistics
!
!-----------------------------------------------------------------------
!
    print*,'finishing reading binary radar file'
    CLOSE(nchanl)
    CALL retunit( nchanl )

    GO TO 400

    399     CONTINUE
    PRINT*,'Error reading the radar file:',radfname
    CALL retunit( nchanl )

    400     CONTINUE
  ELSE !HDF4 file 

    ALLOCATE (itmp(nx,ny,nz),stat=istatus)
    IF (istatus /= 0) THEN
      WRITE (6,*) "READ1RAD: ERROR allocating itmp, returning"
      STOP
    END IF
    ALLOCATE (hmax(nz),stat=istatus)
    IF (istatus /= 0) THEN
      WRITE (6,*) "READ1RAD: ERROR allocating hmax, returning"
      STOP
    END IF
    ALLOCATE (hmin(nz),stat=istatus)
    IF (istatus /= 0) THEN
      WRITE (6,*) "READ1RAD: ERROR allocating hmin, returning"
      STOP
    END IF

    CALL hdfopen(trim(radfname), 1, sd_id)
    IF (sd_id < 0) THEN
      WRITE (6,*) "READ1RAD: ERROR opening ",                           &
                trim(radfname)," for reading."
      istatus = 0
      goto 700
    END IF
    CALL hdfrdc(sd_id, 4, 'radid', stn, istatus)
    stnrad=stn
    CALL hdfrdi(sd_id, 'ireftim', ireftim, istatus)
    CALL hdfrdi(sd_id, 'itime', itime, istatus)
    CALL hdfrdi(sd_id, 'vcpnum', vcpnum, istatus)
    CALL hdfrdi(sd_id, 'isource', isource, istatus)
    CALL hdfrdc(sd_id, 40, 'runname', runname, istatus)
    CALL hdfrdi(sd_id, 'iradfmt', iradfmt, istatus)
    CALL hdfrdi(sd_id, 'strhopt', strhopt_rad, istatus)
    CALL hdfrdi(sd_id, 'mapproj', mapproj_rad, istatus)
    CALL hdfrdr(sd_id, 'dx', dx_rad, istatus)
    CALL hdfrdr(sd_id, 'dy', dy_rad, istatus)
    CALL hdfrdr(sd_id, 'dz', dz_rad, istatus)
    CALL hdfrdr(sd_id, 'dzmin', dzmin_rad, istatus)
    CALL hdfrdr(sd_id, 'ctrlat', ctrlat_rad, istatus)
    CALL hdfrdr(sd_id, 'ctrlon', ctrlon_rad, istatus)
    CALL hdfrdr(sd_id, 'trulat1', tlat1_rad, istatus)
    CALL hdfrdr(sd_id, 'trulat2', tlat2_rad, istatus)
    CALL hdfrdr(sd_id, 'trulon', tlon_rad, istatus)
    CALL hdfrdr(sd_id, 'sclfct', sclfct_rad, istatus)
    CALL hdfrdr(sd_id, 'latrad', latrad, istatus)
    CALL hdfrdr(sd_id, 'lonrad', lonrad, istatus)
    CALL hdfrdr(sd_id, 'elvrad', elvrad, istatus)
    CALL hdfrdi(sd_id, 'nradvr', nradvr, istatus)
    CALL hdfrd1di(sd_id,'iradvr', mxradvr,iradvr,istatus)
    PRINT *, ' Got nradvr,iradvr: ',nradvr,iradvr
    CALL abss2ctim(itime, iyr, imon, idy, ihr, imin, isec )
    iyr=MOD(iyr,100)
    WRITE(6,'(/a,i2.2,a,i2.2,a,i2.2,1X,i2.2,a,i2.2,a)')                 &
       'Reading remapped raw radar data for: ',                         &
       imon,'/',idy,'/',iyr,ihr,':',imin,' UTC'

    CALL hdfrd3d(sd_id,"gridref",nx,ny,nz,gridref,istatus,itmp,hmax,hmin)
    IF (istatus /= 0) GO TO 115
    CALL hdfrd3d(sd_id,"gridvel",nx,ny,nz,gridvel,istatus,itmp,hmax,hmin)
    IF (istatus /= 0) GO TO 115
    CALL hdfrd3d(sd_id,"gridnyq",nx,ny,nz,gridnyq,istatus,itmp,hmax,hmin)
    IF (istatus /= 0) GO TO 115
    CALL hdfrd3d(sd_id,"gridtim",nx,ny,nz,gridtim,istatus,itmp,hmax,hmin)
    IF (istatus /= 0) GO TO 115
    CALL hdfclose(sd_id,istatus)
    DO j=1,ny
      DO k=1,nz
        DO i=1,nx
          IF (gridref(i,j,k) > -200. .AND. gridref(i,j,k) < 200.)     &
            kntref(k)=kntref(k)+1
          IF (gridvel(i,j,k) > -200. .AND. gridvel(i,j,k) < 200.)     &
            kntvel(k)=kntvel(k)+1
        END DO
      END DO
    END DO

    istatus=1
    print*,'finishing reading hdf'

    700 CONTINUE

    DEALLOCATE(hmin)
    DEALLOCATE(hmax)
    DEALLOCATE(itmp)
  END IF
  IF (istatus == 1) THEN
    WRITE(6,'(a)') '  k   n ref    n vel'
    DO k=1,nz
      WRITE(6,'(i3,2i10)') k,kntref(k),kntvel(k)
    END DO
  END IF

  DEALLOCATE(kntref)
  DEALLOCATE(kntvel)

  RETURN
!
!  Destination for hdf read error
!

  115   CONTINUE
  WRITE(6,'(/a/)') ' Error reading data in HDFREAD'

  istatus=-11

  DEALLOCATE(hmin)
  DEALLOCATE(hmax)
  DEALLOCATE(itmp)
  DEALLOCATE(kntref)
  DEALLOCATE(kntvel)

  RETURN

END SUBROUTINE read1rad
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE GET_VIS                    ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!
!


SUBROUTINE process_vis(solar_alt,nx,ny,                                 & 1
           cloud_frac_vis_a,albedo,r_missing,istatus)
!
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Read satellite visible imagery data from LAPS ".lvd" file.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!   04/1996   Based on the LAPS cloud analysis code of 1995.
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!  INPUT:
  INTEGER :: nx,ny
  REAL :: solar_alt(nx,ny)
  REAL :: r_missing
!
!  OUTPUT:
!
  REAL :: albedo(nx,ny)
  REAL :: cloud_frac_vis_a(nx,ny)
!
!  LOCAL
!
  INTEGER :: ihist_alb(-10:20)
  INTEGER :: ihist_frac_sat(-10:20)
  INTEGER :: ih_cf_sat(-10:20)
!
!-----------------------------------------------------------------------
!
!  Misc. variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: i,j,iscr_alb
  INTEGER :: ibeg,iend,jbeg,jend
  INTEGER :: n_missing_albedo
  REAL :: albedo_to_cf,cloud_frac_vis
  REAL :: frac,term1,term2
  INTEGER :: istatus,iscr_frac_sat
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
!-----------------------------------------------------------------------
!
!  Initialize all histogram arrays.
!
!-----------------------------------------------------------------------
!
  DO i=-10,20
    ihist_alb(i) = 0
    ihist_frac_sat(i) = 0
    ih_cf_sat(i) = 0
  END DO
!
!-----------------------------------------------------------------------
!
!  Read the interpolated satellite albedo data.
!  These data were created by laps2arps.f (based on ter2arps)
!  by interpolating OLAPS (vortex95) grid satellite data onto
!  the ARPS grid.
!
!-----------------------------------------------------------------------
!
  ibeg=MAX(1,nx/2-5)
  iend=MIN(nx,nx/2+5)
  jbeg=MAX(1,ny/2-5)
  jend=MIN(ny,ny/2+5)
!
  WRITE(6,'(a)') ' Satellite albedo value examples in the mid-domain:'

  WRITE(6,'(/4x,11(2x,i2,2x))') (i,i=ibeg,iend)
  WRITE(6,'(1x,i3,11f6.2)')                                             &
       (j,(albedo(i,j),i=ibeg,iend),j=jend,jbeg,-1)
!
  n_missing_albedo = 0
!
!-----------------------------------------------------------------------
!
!  Horizontal array loop
!
!-----------------------------------------------------------------------
!
  DO j = 1,ny
    DO i = 1,nx
!
!-----------------------------------------------------------------------
!
!  We now only use the VIS data if the solar alt exceeds 15 deg
!
!-----------------------------------------------------------------------
!
      IF (solar_alt(i,j) > 15.0 .AND. albedo(i,j) > 0.) THEN
!
!-----------------------------------------------------------------------
!
!  Translate the albedo into cloud fraction
!  Store histogram information for satellite data
!
!-----------------------------------------------------------------------
!
        iscr_alb  = nint(albedo(i,j)*10.)
        iscr_alb  = MIN(MAX(iscr_alb,-10),20)
        ihist_alb(iscr_alb) = ihist_alb(iscr_alb) + 1

        cloud_frac_vis = albedo_to_cf(albedo(i,j))
!
!-----------------------------------------------------------------------
!
!  Fudge the frac at low solar elevation angles
!  Note the ramp extrapolates down to 9 deg to account for slight
!  errors in determining the solar elevation
!
!-----------------------------------------------------------------------
!
        IF(solar_alt(i,j) < 20. .AND. solar_alt(i,j) >= 9.) THEN
          frac = (20. - solar_alt(i,j)) / 10.
          term1 = .13 * frac
          term2 = 1. + term1
          cloud_frac_vis = (cloud_frac_vis + term1) * term2
        END IF

        iscr_frac_sat = nint(cloud_frac_vis*10.)
        iscr_frac_sat = MIN(MAX(iscr_frac_sat,-10),20)
        ihist_frac_sat(iscr_frac_sat) =                                 &
                   ihist_frac_sat(iscr_frac_sat) + 1
!
!-----------------------------------------------------------------------
!
!  Make sure satellite cloud fraction is between 0 and 1
!
!-----------------------------------------------------------------------
!
        cloud_frac_vis=max(min(cloud_frac_vis,1.0),0.0)
        cloud_frac_vis_a(i,j) = cloud_frac_vis

        iscr_frac_sat = nint(cloud_frac_vis*10.)
        iscr_frac_sat = MIN(MAX(iscr_frac_sat,-10),20)
        ih_cf_sat(iscr_frac_sat) =                                      &
                   ih_cf_sat(iscr_frac_sat) + 1

      ELSE   ! albedo(i,j) = r_missing
        n_missing_albedo =  n_missing_albedo + 1
        cloud_frac_vis_a(i,j) = r_missing
      END IF  ! albedo(i,j).ne.r_missing

    END DO ! i
  END DO ! j

  WRITE(6,'(/a,i8/)')' N_MISSING_ALBEDO =',n_missing_albedo

  IF(n_missing_albedo == nx*ny) THEN ! Return with status = 0
    WRITE(6,'(a)')' All albedos were missing, return from process_vis'
    istatus = 0
    RETURN
  END IF

  WRITE(6,'(a)')'       HISTOGRAMS'
  WRITE(6,'(a)')'  I   Alb  CFsat  CFsato'
  DO i = -5,15
    WRITE(6,'(i4,i5,i7,i8)')                                          &
      i,ihist_alb(i),ihist_frac_sat(i),ih_cf_sat(i)
  END DO ! i
!
  WRITE(6,'(a)') ' ==== process_vis: Albedo derived cld cvr'
  WRITE(6,'(/4x,11(2x,i2,2x))') (i,i=ibeg,iend)
  WRITE(6,'(1X,i3,11f6.2)')                                           &
       (j,(cloud_frac_vis_a(i,j),i=ibeg,iend),j=jend,jbeg,-1)
  istatus = 1

  RETURN
END SUBROUTINE process_vis

!
!##################################################################
!##################################################################
!######                                                      ######
!######                FUNCTION ALBEDO_TO_CF                 ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


FUNCTION albedo_to_cf( albedo )
!
!-----------------------------------------------------------------------
!
!  This version assumes 0.15 land albedo and 0.80 total cloud albedo.
!  Albedo fields are now calibrated before this call using the new
!  visible calibration files.
!
!  cloud_frac_vis = (albedo - 0.15) / (0.80 - 0.15)
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
  REAL, INTENT(IN) :: albedo
  REAL :: albedo_to_cf
!
! Local Variables
!
  REAL, PARAMETER :: land_albedo=0.15
  REAL, PARAMETER :: max_albedo=0.80
  REAL, PARAMETER :: alb_denom=(1./(max_albedo-land_albedo))
  REAL :: cf_vis
  
  cf_vis = (albedo-land_albedo)*alb_denom

  albedo_to_cf = MIN(MAX(cf_vis,0.),1.0)

  RETURN
END FUNCTION albedo_to_cf
!
!##################################################################
!##################################################################
!######                                                      ######
!######              SUBROUTINE SPREAD2                      ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE spread2 (cld_snd,wt_snd,i_snd,j_snd,n_cld_snd                & 10
           ,max_cld_snd,nz,iadas,jadas,k,cover,wt)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  This subroutine inserts the cloud sounding into the analysis arrays
!  at one point location.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:
!  07/95
!
!  MODIFICATION HISTORY:
!  03/20/96. (Jian Zhang)
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER :: nz           ! number of cloud analysis levels
  INTEGER :: max_cld_snd  ! max. possible # of cloud soundings
                        ! in the domain

  INTEGER :: n_cld_snd    ! sequential index of cloud sounding sta.

  INTEGER :: iadas        ! i-loc of cld sounding stn in ADAS grid
  INTEGER :: jadas        ! j-loc of cld sounding stn in ADAS grid
  INTEGER :: k            ! the level where obs. cloud locates

  INTEGER :: i_snd (max_cld_snd)    ! array for i-location of
                                  ! cloud sounding stations
  INTEGER :: j_snd (max_cld_snd)    ! array for j-location of
                                  ! cloud sounding stations

  REAL :: cld_snd(max_cld_snd,nz)   ! cloud cover sounding array
  REAL :: wt_snd(max_cld_snd,nz)    ! weight array for cloud sounding

  REAL :: cover                     ! obs. cloud coverage
  REAL :: wt                        ! weight for the cloud cover obs.

  cld_snd(n_cld_snd,k) = cover
  wt_snd(n_cld_snd,k) = wt
  i_snd(n_cld_snd) = iadas
  j_snd(n_cld_snd) = jadas

  RETURN
END SUBROUTINE spread2
!
!##################################################################
!##################################################################
!######                                                      ######
!######              FUNCTION T_GROUND_K                     ######
!######                                                      ######
!##################################################################
!##################################################################
!


  FUNCTION t_ground_k (t_sfc_k,solar_alt,solar_ha                       &
                ,solar_dec,rlat,cvr_snow,r_missing_data,i,j,nx,ny)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  Calculate the ground skin temperature as a function of
!  the surface air temperature and solar positions.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:  (Jian Zhang)
!          Based on the LAPS cloud analysis code of 09/95
!
!  MODIFICATION HISTORY:
!  04/29/96  J. Zhang
!            Added ARPS format documents.
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Variable Declarition
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!  INPUT:
  INTEGER :: i,j,nx,ny
  REAL :: t_sfc_k            ! surface air temperature
  REAL :: solar_alt          ! solar altitude angle
  REAL :: solar_ha           ! solar hour angle
  REAL :: solar_dec          ! solar declination angle
  REAL :: rlat               ! latitude of the grid point
  REAL :: cvr_snow           ! ground snow cover at the grid point
  REAL :: r_missing_data     ! flag for data hole
!
!  OUTPUT:
  REAL :: t_ground_k         ! ground skin temperature
!
!  LOCAL:
  INTEGER :: imid,jmid
  REAL :: high_alt,low_alt,corr_low,corr_high,corr_ramp
  REAL :: t_ground_fullcorr,t_snow_k,corr_negonly
  REAL :: solar_transit_alt,corr
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
  imid=(nx/2)+1
  jmid=(ny/2)+1
  solar_transit_alt = 90. - ABS(rlat - solar_dec)

  IF(solar_ha < 0.) THEN ! morning
    high_alt = solar_transit_alt * .66
    low_alt  = solar_transit_alt * .36
!       low_alt  = high_alt - 11.
  ELSE                     ! afternoon
    high_alt = solar_transit_alt * .79
    low_alt  = solar_transit_alt * .49
!       low_alt  = high_alt - 11.
  END IF

  corr_high = 4.
  corr_low = -4.
  corr_ramp = (corr_high - corr_low) / (high_alt - low_alt)
!
!-----------------------------------------------------------------------
!
!  Warmer at day, colder at night
!
!-----------------------------------------------------------------------
!
  IF(solar_alt < low_alt)THEN
    corr = corr_low

  ELSE IF(solar_alt > high_alt)THEN
    corr = corr_high

  ELSE ! ramp the function
    corr = corr_low + (solar_alt - low_alt) * corr_ramp

  END IF

  IF(i == imid .AND. j == jmid) THEN
    WRITE(6,'(1x,a,2i4,a)') 'Sample solar position parms for point (',  &
          i,j,')'
    WRITE(6,'(1x,a,a)') '  hangle  altitude transalt  ratio  ',         &
                   ' highalt   lowalt  correctn'
    WRITE(6,'(1X,7F9.2)') solar_ha,solar_alt,solar_transit_alt,         &
          solar_alt/solar_transit_alt,high_alt,low_alt,corr
  END IF

  corr_negonly = MIN(corr,0.0)            ! Only colder at night

  IF(cvr_snow /= r_missing_data) THEN
    t_ground_fullcorr = t_sfc_k + corr  ! Warmer at day, colder at night
    t_snow_k = t_sfc_k + corr_negonly   ! Only colder at night
    t_snow_k = MIN(t_snow_k,273.15)     ! Snow can't be above 0C
    t_ground_k = t_ground_fullcorr * (1.-cvr_snow)                      &
                          + t_snow_k * cvr_snow
  ELSE
    t_ground_k = t_sfc_k + corr_negonly ! Only colder at night
  END IF

  RETURN
  END FUNCTION t_ground_k