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


SUBROUTINE cloud_cv (nx,ny,nz,i4time,time,dirname,runname,              & 1,24
           xs,ys,zs,dx,dy,topo,latgr,longr,                             &
           p_3d,t_3d,rh_3d,                                             &
           nobsng,stn,obstype,xsng,ysng,                                &
           obstime,latsta,lonsta,elevsta,                               &
           kcloud,store_amt,store_hgt,                                  &
           ref_mos_3d,istat_radar,                                    &
           clouds_3d,cloud_ceiling,                                     &
           istatus)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Perform 3D fractional cloud cover analysis using SAO
!  cloud coverage observations, visible (VIS) and infrared (IR)
!  satellite measurements, and radar reflectivity data.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!  02/01/96
!
!  MODIFICATION HISTORY:
!
!  07/12/96  J. Zhang
!            Added remapping of the cloud cover fields onto the
!            ARPS grid.
!  03/14/97  J. Zhang
!            Cleaning up the code  and implemented for the official
!            arps4.2.4 version.
!  03/28/97  J. Zhang
!            Using the lifiting condensation level as the cloud
!            base when inserting radar reflectivity with no SAO
!            cloud base.
!  04/11/97  J. Zhang
!            Included dims.inc for nx,ny,nz.
!  04/15/97  J. Zhang
!            Change the size of the arrays istn, jstn, hstn, and
!            cstn from fixed (40) to adjustable (mx_sng)
!  08/06/97  J. Zhang
!            Change adascld24.inc to adascld25.inc
!  09/04/97  J. Zhang
!            Changed the radar echo thresholds for inserting clouds
!            from radar reflectivities.
!  09/10/97  J. Zhang
!            Calculate lifting condensation level in INICLDGRD,
!            and used by other routines (INSERTIR and INSERTRAD).
!            Change adascld25.inc to adascld26.inc
!  11/17/97  J. Zhang
!            Change the length of "runname" from fixed number
!            of letters (6) to flexible numbers.
!  11/18/97  J. Zhang
!            Added flag 'clddiag' in adascld26.inc for whether to
!            output the special cloud fields.
!  03/26/98  J. Zhang
!            Some modifications based on the official adas 4.3.3.
!  04/27/98  J. Zhang
!            Conform WRTCLDVAR to WRTVAR
!  05/05/98  J. Zhang
!            Abandoned the cloud grid, using the ARPS grid instead.
!  10/25/98  K. Brewster
!            Modified creation of file name for cloud observation
!            diagnostic file.
!  08/21/01  K. Brewster
!            Changed wrtvar calls to wrtvar1 to match new routine 
!            for writing 3-D arrays to be read by arpsplt as an 
!            arbitary array.
!
!-----------------------------------------------------------------------
!
!  INCLUDE: (from adas.inc)
!
!  mx_sng            ! max. possible # of surface obs.
!  max_cld_snd       ! max. possible # of stations
                     ! with cloud coverage reports.
!  refthr1           ! "significant" radar echo at lower levels
!  refthr2           ! "significant" radar echo at upper levels
!  hgtrefthr         ! height criteria for "significant" radar
                     ! echo thresholds
!  clddiag           ! flag for whether to output the special cloud
                     ! fields
!
!  INPUT:
!
!  nx,ny,nz          ! ARPS grid size
!
!  i4time            ! analysis time in seconds from 00:00 UTC
                     ! Jan. 1, 1960
!  time              ! analysis time in seconds from the model
                     ! initial time
!  dirname           ! directory for data dump
!
!  INPUT (for ARPS grid variables)
!   xs     (nx)      ! The x-coord. of the physical and
                     ! computational grid. Defined at p-point.
!   ys     (ny)      ! The y-coord. of the physical and
                     ! computational grid. Defined at p-point.
!   zs    (nx,ny,nz) ! The physical height coordinate defined at
                     ! p-point of the staggered grid.
!   temp_3d(nx,ny,nz)! the temperature field
!
!   topo (nx,ny)     ! The height of the terrain (equivalent
!   dx, dy           ! grid spacing
!
!  INPUT for SAO obs.
!
!   stn (mx_sng)         ! station name of single-lvel data
!   obstype (mx_sng)     ! names of sfc sources
!   obstime (mx_sng)     ! time for the observation.
!   latsta (mx_sng)      ! latitude of single-level data
!   lonsta (mx_sng)      ! longitude of single-level data
!   elevsta (mx_sng)     ! height of single-level data
!   xsng (mx_sng)        ! x location of single-level data
!   ysng (mx_sng)        ! y location of single-level data
!
!   kcloud (mx_sng)      ! number of obs. cloud layers.
!   store_amt (mx_sng,5) ! cloud coverage (ea. layer,
                         ! ea. station).
!   store_hgt (mx_sng,5) ! height of obs. cloud layers.
!
!  LOCAL
!
!   cf_modelfg (nx,ny,nz) ! first guess cloud cover field
!   rh_modelfg (nx,ny,nz) ! first guess relative humidity field
!   t_sfc_k (nx,ny)       ! surface temperature field
!
!  OUTPUT:
!
!  istatus                ! The flag indicating process status.
!  clouds_3d (nx,ny,nz)   ! final gridded cloud cover analysis
!  cloud_ceiling (nx,ny)  ! cloud ceiling (M AGL)
!
!  LOCAL:
!  n_cld_snd         number of cloud soundings created
!  cld_snd (max_cld_snd,nz)   Cld snding obtained from SAO data.
!  wt_snd (max_cld_snd,nz)    weights assigned to cloud sounding
!                                obtained from SAO data.
!  cvr_max (nx,ny)           ! final column maximum cloud cover
!  cvr_tot (nx,ny)           ! final column total cloud cover
!  cloud_top (nx,ny)         ! cloud top (M ASL)
!
!  LOCAL for SAO:
!
!  ista_snd (max_cld_snd)    index of cloud sounding stations
!  i_snd (max_cld_snd)       i-locn of each cld snd stn in ADAS grid
!  j_snd (max_cld_snd)       j-locn of each cld snd stn in ADAS grid
!
!
!  LOCAL for gridded cloud cover analysis
!
!  cldcv (nx,ny,nz)     3D gridded fractional cloud cover analysis.
!                        (when input, it's the first guess field)
!  wtcldcv (nx,ny,nz)   wts given to gridded fracn cld cvr anx.
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!  Include files:
!
  INCLUDE 'adas.inc'  ! ADAS parameters.
!
!-----------------------------------------------------------------------
!
!  INPUT: general
  INTEGER :: nx,ny,nz          ! ARPS grid size
  INTEGER :: i4time            ! analysis time in seconds from
                             ! 00:00 UTC Jan. 1, 1960
  REAL :: time                 ! analysis time in seconds from the
                             ! model initiali time
  CHARACTER (LEN=*) :: dirname     ! directory for data dump
  CHARACTER (LEN=*) :: runname     ! a string identify the run
!
!  INPUT: model grid
!
  REAL :: dx,dy                ! ADAS grid spacing

  REAL :: xs    (nx)           ! The x-coord. of the physical and
                               ! computational grid. Defined at p-point.
  REAL :: ys    (ny)           ! The y-coord. of the physical and
                               ! computational grid. Defined at p-point.
  REAL :: zs (nx,ny,nz)        ! The physical height coordinate defined at
                               ! p-point of the staggered grid.
  REAL :: t_3d(nx,ny,nz)       ! temperature (K)
  REAL :: p_3d(nx,ny,nz)
  REAL :: rh_3d(nx,ny,nz)
  REAL :: topo (nx,ny)         ! The height of the terrain (equivalent
!
!  INPUT for SAO obs.
!
  INTEGER :: nobsng
  CHARACTER (LEN=5) :: stn (mx_sng)    ! station name of single-lvel data
  CHARACTER (LEN=8) :: obstype (mx_sng)! names of sfc sources
  INTEGER :: obstime (mx_sng)    ! time for the observation.
  REAL :: xsng (mx_sng)          ! x location of single-level data
  REAL :: ysng (mx_sng)          ! y location of single-level data
  REAL :: latsta (mx_sng)        ! latitude of single-level data
  REAL :: lonsta (mx_sng)        ! longitude of single-level data
  REAL :: elevsta (mx_sng)       ! height of single-level data
!
  INTEGER :: kcloud (mx_sng)          ! number of cloud layers.
  CHARACTER (LEN=4) :: store_amt (mx_sng,5) ! cld coverage (ea.lyr, ea. stn).
  REAL :: store_hgt (mx_sng,5)        ! height of cloud layers.
!
!  INPUT: for radar
  INTEGER :: istat_radar          ! Valid radar reflectivity data?
  REAL :: ref_mos_3d(nx,ny,nz)  ! 3D radar reflectivity on model grid
                                  ! may be modified by sate VIS data
!
!  OUTPUT:
  INTEGER :: istatus              ! Flag for process status
  REAL :: clouds_3d(nx,ny,nz)     ! Final cloud cover field
  REAL :: cloud_ceiling (nx,ny)   ! cloud ceiling (M AGL)
!
!  LOCAL: for first guess fields
  REAL :: cf_modelfg (nx,ny,nz)   ! first guess cloud cover field
  REAL :: rh_modelfg (nx,ny,nz)   ! first guess relative humidity fld
  REAL :: z_lcl (nx,ny)           ! lifting condensation level(MSL)
!
!  LOCAL: for surface arrays
  REAL :: latgr (nx,ny)           ! latitude at each grid point
  REAL :: longr (nx,ny)           ! longitude at each grid point
  REAL :: pres_sfc_pa(nx,ny)      ! sfc pressure (Pascal)
  REAL :: t_gnd_k(nx,ny)          ! ground skin temp.
  REAL :: t_sfc_k (nx,ny)         ! surface temperature field
  REAL :: cvr_snow (nx,ny)        ! surface snow coverage
  REAL :: rland_frac (nx,ny)      ! land coverage fraction
!
!  LOCAL: for SAO cloud sounding
  INTEGER :: ista_snd (max_cld_snd)   ! seq. index of cld snd stn
  INTEGER :: i_snd (max_cld_snd)      ! i-loctn of cld snd
  INTEGER :: j_snd (max_cld_snd)      ! j-loctn of cld snd
  INTEGER :: n_cld_snd                ! # of cloud snds created
  REAL :: cld_snd (max_cld_snd,nz)    ! SAO cld snd
  REAL :: wt_snd (max_cld_snd,nz)     ! wgt for SAO cld snd
!
!  LOCAL for gridded cloud cover analysis
  REAL :: cldcv (nx,ny,nz)       ! 3D gridded frac cld cv analysis.
                               ! (it's also bkgrnd field when input)
  REAL :: wtcldcv (nx,ny,nz)     ! wts assgned to cld cvr analysis
                               ! (it's also bkgrnd field when input)
!  LOCAL: for solar positions
  REAL :: solar_alt(nx,ny)       ! solar altitude angle
  REAL :: solar_ha(nx,ny)        ! solar hour angle
  REAL :: solar_dec              ! solar declination angle
!
!  LOCAL: for satellite insertion
  INTEGER :: io_vis              ! Valid satellite VIS albedo data?
  REAL :: albedo(nx,ny)          ! vis. albedo derived from sat.vis.data
  REAL :: cloud_frac_vis_a(nx,ny)! cldcvr derived from vis. albedo
  INTEGER :: istat_vis           ! status of inserting VIS data

  INTEGER :: io_ir               ! Valid satellite bright. temp. data?
  REAL :: tb8_k(nx,ny)           ! Obs. sate. band8 bright. temp.
  REAL :: tb8_cold_k(nx,ny)      ! Cold filtered band8 bright. temp.
  REAL :: cldtop_m_tb8(nx,ny)    ! Sat. cld top ht (m) from band 8 data
  REAL :: cldtop_m (nx,ny)       ! cldtop height
  REAL :: cloud_top (nx,ny)      ! cloud top (M ASL)
  INTEGER :: istatus_ir          ! status of inserting IR data
!
  REAL :: sfc_sao_buffer         ! No clearing cloud by sat. below
                                 ! this ht.(m AGL) (hence letting
                                 ! SAOs dominate)
  PARAMETER (sfc_sao_buffer = 800.) ! meters, keep lower SAO cld from
                                    ! cleared out by sate. ir data
!
!  LOCAL: for radar data insertion
  REAL :: dbz_max_2d(nx,ny)       ! column max. radar refl. (dbZ)
  REAL :: cloud_base (nx,ny)      ! cloud base heights from SAO+sate
  REAL :: cloud_base_buf(nx,ny)   ! lowest cloud base heights within
                                  ! a searching radius
  LOGICAL :: l_unresolved(nx,ny)  ! no SAO+sate cld, yet radar echo is
                                  ! above the threshold
  REAL :: vis_rad_thdbz
  PARAMETER (vis_rad_thdbz=10.)! threshold define cloudy refl.
  REAL :: vis_rad_thcvr
  PARAMETER (vis_rad_thcvr=0.2)! VIS cld cvr threshold,
                               ! below this thresh. may cause
                               ! radar echo being cleared out.
!
!  LOCAL: intermidiate products
  REAL :: cvr_max (nx,ny)         ! column maximum cloud cover
  REAL :: cvr_tot (nx,ny)         ! final column total cloud cover
  REAL :: cvr_1d (nz)             ! cloud cover array for 1 grid col.
!
!  LOCAL: for post-process
  REAL :: thresh_cvr_base,thresh_cvr_top,thresh_cvr_ceiling
  PARAMETER (thresh_cvr_base = 0.1)
  PARAMETER (thresh_cvr_top  = 0.1)
  PARAMETER (thresh_cvr_ceiling = 0.65)

  REAL :: default_top,default_base,default_ceiling
  PARAMETER (default_base     = 0.0)
  PARAMETER (default_top      = 0.0)
  PARAMETER (default_ceiling  = 0.0)

!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: k1,l,j1,j2,ibeg
  LOGICAL :: l_stn_clouds       ! Using SAO stns' cloud obs?
  PARAMETER (l_stn_clouds = .true.)
  LOGICAL :: cldprt
!
  REAL :: default_clear_cover
  PARAMETER (default_clear_cover=0.01)
!
  INTEGER :: istatus_sao,istatus_fg,istatus_barnes                      &
          ,istatus_rad,istatus_vis
  INTEGER :: i,j,k,imid,jmid
  REAL :: grid_spacing_m
  REAL :: albmin,albmax,vcfmin,vcfmax

  CHARACTER (LEN=6) :: varid
  CHARACTER (LEN=20) :: varname
  CHARACTER (LEN=20) :: varunits

  INTEGER :: nstn,istn(mx_sng),jstn(mx_sng)
  REAL :: hstn(mx_sng)
  CHARACTER (LEN=5) :: cstn(mx_sng)

  INTEGER :: istat_col

  CHARACTER (LEN=6) :: satnam
  CHARACTER (LEN=80) :: fname
  REAL :: latsat,lonsat
  INTEGER :: itime,isource,ifield,lrunnam,istatwrt
!
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
  WRITE(6,*)' Welcome to the ADAS Cloud Analysis'
  cldprt=(clddiag == 1)
  ibeg=MAX(1,(nx-10))
  istatus=0
  imid=nx/2
  jmid=ny/2
!
!-----------------------------------------------------------------------
!
!  Initialize cloud cover fields on the analysis grid
!
!-----------------------------------------------------------------------
!
  PRINT*,'Call background fields routine'
  CALL inicldgrd(nx,ny,nz,zs,                                           &
          bgqcopt,default_clear_cover,                                  &
          topo,t_3d,p_3d,rh_3d,cf_modelfg,t_sfc_k,pres_sfc_pa,          &
          cldcv,wtcldcv,z_ref_lcl,z_lcl,rh_modelfg,                     &
          r_missing,istatus_fg)
!
  IF (cldprt) THEN
    WRITE(6,'(/a)') ' ==== CLOUD_CV cloud cover first guess===='
    WRITE(6,632) (i,i=ibeg,nx)
    WRITE(6,633) (k,(cf_modelfg(i,jmid,k),i=ibeg,nx)                    &
                ,k=nz,1,-1)
  END IF
  632   FORMAT(/1X,3X,11(1X,i4,1X))
  633   FORMAT(1X,i3,11F6.1)
!
  IF (istatus_fg /= 1)THEN
    WRITE(6,*)' Error in background field: Aborting cloud analysis'
    GO TO 999
  END IF
!
  IF (cloudopt == 2) THEN   ! Using radar data only
    PRINT*,'## NOTE ##:  Using radar data only. LCL is used.'
    GO TO 330
  END IF
!
!-----------------------------------------------------------------------
!
!  Create cloud sounding from the SAO cloud observations.
!
!-----------------------------------------------------------------------
!
  WRITE(6,*)
  WRITE(6,*)' Call Ingest/Insert SAO routines'
  WRITE(6,*)

  n_cld_snd = 0
  IF (nobsng >= 1) THEN
!
    CALL insert_sao1 (nx,ny,nz,dx,dy,xs,ys,zs,topo,t_sfc_k              &
              ,cldcv,wtcldcv,t_3d,rh_modelfg                            &
              ,nobsng,stn,obstype,xsng,ysng,ista_snd                    &
              ,obstime,latsta,lonsta,elevsta                            &
              ,kcloud,store_amt,store_hgt                               &
              ,l_stn_clouds,n_cld_snd,cld_snd,wt_snd                    &
              ,i_snd,j_snd                                              &
              ,istatus_sao)
!
    IF(istatus_sao /= 1) THEN
      WRITE(6,*)' Error inserting SAO data: Aborting cloud analysis'
      GO TO 999
    END IF
  ELSE
    WRITE(6,'(a,a,/a)')                                                 &
     ' !!!WARNING!!! No surface cloud obs. available.',                 &
                     ' Skipping SAOs insertion'
  END IF
!
!-----------------------------------------------------------------------
!
!  Initialize clouds_3d array
!
!-----------------------------------------------------------------------
!
  DO k=1,nz
    DO j=1,ny
      DO i=1,nx
        clouds_3d(i,j,k)=0.0
      END DO
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Do grid analysis on SAO data using Barnes interpolation.
!
!-----------------------------------------------------------------------
!
  WRITE(6,*)
  WRITE(6,*)' Analyzing SAO cloud soundings'
!
  grid_spacing_m = dx

  CALL barnes_r5 (nx,ny,nz,cldcv,clouds_3d,wtcldcv,cf_modelfg           &
          ,l_stn_clouds,default_clear_cover,cld_snd,wt_snd              &
          ,grid_spacing_m,i_snd,j_snd,n_cld_snd                         &
          ,istatus_barnes)
!
  IF(cldprt) THEN
    WRITE(6,'(/a)') ' ==== CLOUD_CV cloud cover barnes===='
    WRITE(6,632) (i,i=ibeg,nx)
    WRITE(6,633) (k,(clouds_3d(i,jmid,k),i=ibeg,nx)                     &
                ,k=nz,1,-1)
  END IF
!632  format(/1x,3x,11(1x,i4,1x))
!633  format(1x,i3,11f6.1)

  IF (istatus_barnes /= 1) THEN
    WRITE(6,*)' Error in Barnes interp, Aborting cld analysis...'
    GO TO 999
  END IF
!
!-----------------------------------------------------------------------
!
!  Find all stations within the model domain and print the cloud
!  soundings at these station points after the Barnes interpolation.
!
!-----------------------------------------------------------------------
!
  k=0
  DO i=1,n_cld_snd
    IF(i_snd(i) >= 1.AND.i_snd(i) <= nx                                 &
          .AND. j_snd(i) <= ny.AND.j_snd(i) >= 1) THEN
      k=k+1
      cstn(k)=stn(ista_snd(i))
      istn(k)=i_snd(i)
      jstn(k)=j_snd(i)
      hstn(k)=0.001*elevsta(ista_snd(i))
    END IF
  END DO
  nstn=k
!
  IF (cld_files == 1) THEN
    CALL gtlfnkey( runname, lrunnam )
    WRITE(fname,'(a,a)') runname(1:lrunnam),'.cld_brns_snd'
    OPEN (UNIT=14,FILE=trim(fname),STATUS='unknown')

    WRITE(14,404) nobsng,nstn,n_cld_snd
    404     FORMAT(1X,' Total/in-domain # of stations:',2I5/            &
            ' Cloud observations used for deriving cloud soundings:',i3/)

    i = nstn/24

    IF(i < 1) THEN

      WRITE(14,405) (cstn(k),k=1,nstn)
      405         FORMAT(1X,' hgt(m)',1X,24A5)
      WRITE(14,407) (istn(k),k=1,nstn)
      WRITE(14,407) (jstn(k),k=1,nstn)
      407         FORMAT(1X,7X,24I5)
      WRITE(14,408) (hstn(k),k=1,nstn)
      408       FORMAT(1X,7X,24F5.2)
      DO k1=1,nz
        WRITE(14,406) zs(istn(1),jstn(1),k1)                            &
                   ,(clouds_3d(istn(l),jstn(l),k1),l=1,nstn)
        406         FORMAT(1X,f7.1,24F5.2)
      END DO !k1
    ELSE

      DO k=1,i
        j1=(k-1)*24+1
        j2=k*24
        WRITE(14,405) (cstn(l),l=j1,j2)
        WRITE(14,407) (istn(l),l=j1,j2)
        WRITE(14,407) (jstn(l),l=j1,j2)
        WRITE(14,408) (hstn(l),l=j1,j2)

        DO k1=1,nz
          WRITE(14,'(1x,f7.1,24f5.2)') zs(istn(j1),jstn(j1),k1)         &
                   ,(clouds_3d(istn(l),jstn(l),k1),l=j1,j2)
        END DO !k1
      END DO !k

      j=i*24+1
      WRITE(14,405) (cstn(l),l=j,nstn)
      WRITE(14,407) (istn(l),l=j,nstn)
      WRITE(14,407) (jstn(l),l=j,nstn)
      WRITE(14,408) (hstn(l),l=j,nstn)
      DO k1=1,nz
        WRITE(14,406) zs(istn(j),jstn(j),k1)                            &
                   ,(clouds_3d(istn(l),jstn(l),k1),l=j,nstn)
      END DO !k1
    END IF
    CLOSE(14)
  END IF
!
  IF (cld_files == 1) THEN
    WRITE(6,*)  'Writing 3D cloud fraction after inserting SAOs.'
    varid='cldsao'
    varname='Clouds after SAO'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,nz,clouds_3d,varid,varname,varunits,             &
                 time,runname,dirname,istatwrt)
  END IF
!
!-----------------------------------------------------------------------
!
!  Read in the surface snow coverage data.
!  Currently, the snow cover field is simply set to zero
!
!-----------------------------------------------------------------------
!
!  varname='snwcvr'
!  CALL READVAR(nx,ny,1, varname,time,cvr_snow, runname)

  DO j = 1,ny
    DO i = 1,nx
      cvr_snow(i,j) = 0.0
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Read in the land (water) coverage fraction data.
!  Currently, this is simply set to 1.
!
!-----------------------------------------------------------------------
!
!  varname='lndfrc'
!  CALL READVAR(nx,ny,1, varname,time,rland_frac, runname)

  DO j = 1,ny
    DO i = 1,nx
      rland_frac(i,j) = 1.0
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Calculate solar altitude
!
!-----------------------------------------------------------------------
!
  WRITE(6,*)  'Calculating solar position parameters.'
!
  DO j = 1,ny
    DO i = 1,nx
      CALL solar_pos(latgr(i,j),longr(i,j)                              &
               ,i4time,solar_alt(i,j),solar_dec,solar_ha(i,j))
    END DO
  END DO
  imid = nx/2
  jmid = ny/2
  PRINT*,' pt(',imid,',',jmid,'): Solar alt=',solar_alt(imid,jmid),     &
         '  declin=',solar_dec,'  hour_angle=',solar_ha(imid,jmid)
!
!-----------------------------------------------------------------------
!
!  READ IN SATELLITE VISIBLE DATA
!
!-----------------------------------------------------------------------
!
  ifield=1
  isource=1

  WRITE(6,*)  'Getting satellite visible data remapped on the',         &
              ' model grid'
!
  CALL rdsatfld(nx,ny,1,vis_fname,satnam,latsat,lonsat,                 &
                itime,isource,varname,albedo,io_vis)
!
  IF (cld_files == 1) THEN
    varid='albedo'
    varname='Albedo'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,1 ,albedo, varid,varname,varunits,               &
                 time,runname,dirname,istatwrt)
  END IF

  IF(io_vis == 0) THEN
    WRITE(6,'(a)')  ' Read successful, calling get_vis'
    CALL get_vis (solar_alt,nx,ny                                       &
                  ,cloud_frac_vis_a,albedo,r_missing,istat_vis)

    albmax = -999.0
    albmin =  999.0
    vcfmax = -999.0
    vcfmin =  999.0

    DO j=1,ny
      DO i=1,nx
        IF(albedo(i,j) >= 0.) THEN
            albmax=MAX(albmax,albedo(i,j))
            albmin=MIN(albmin,albedo(i,j))
        END IF
        IF(cloud_frac_vis_a(i,j) >= 0.) THEN
          vcfmax=MAX(vcfmax,cloud_frac_vis_a(i,j))
          vcfmin=MIN(vcfmin,cloud_frac_vis_a(i,j))
        END IF
      END DO
    END DO
    WRITE(6,'(a,a)') 'Visible Satellite Data: ',vis_fname
    WRITE(6,'(a,f10.4,a,f10.4)')                                        &
         ' min albedo:',albmin,'  max albedo:',albmax
    WRITE(6,'(a,f10.4,a,f10.4)')                                        &
         ' min vis cf:',vcfmin,'  max vis cf:',vcfmax

  ELSE
    WRITE(6,'(a,a,/a)')  ' ###Problem reading ',vis_fname,              &
                         ' Skipping vis processing'
  END IF
!
  IF (cld_files == 1) THEN
    varid ='cldalb'
    varname='Cloud from Albedo'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,1,cloud_frac_vis_a,varid,varname,varunits,       &
                 time,runname,dirname,istatwrt)
  END IF
!
!-----------------------------------------------------------------------
!
!  Insert satellite IR data
!
!-----------------------------------------------------------------------
!
  ifield=1
  isource=1

  WRITE(6,*) 'Inserting satellite IR data.'
  WRITE(6,*) 'Getting satellite IR data remapped on the model',         &
             ' grid'
!
  CALL rdsatfld(nx,ny,1,ir_fname,satnam,latsat,lonsat,                  &
                itime,isource,varname,tb8_k,io_ir)
!
  IF (cld_files == 1) THEN
    varid='cttemp'
    varname='Cloud Top Temperature'
    varunits='Degrees K'
    CALL wrtvar1(nx,ny,1, tb8_k,varid,varname,varunits,                 &
                 time,runname,dirname,istatwrt)
  END IF
!
  IF(io_ir == 0) THEN
    WRITE(6,'(a)')  ' Read successful, calling insert_ir'
    CALL insert_ir (nx,ny,nz,latgr,longr,rland_frac,cvr_snow,           &
                    topo,zs,z_lcl,t_3d,p_3d,                            &
                    t_sfc_k,t_gnd_k,clouds_3d,                          &
                    solar_alt,solar_ha,solar_dec,                       &
                    tb8_k,tb8_cold_k,cldtop_m_tb8,cldtop_m,             &
                    grid_spacing_m,sfc_sao_buffer,                      &
                    clouds_3d,istatus_ir)
  ELSE
    WRITE(6,'(a,a,/a)')                                                 &
        ' !!!WARNING!!! Problem using satellite IR  data',              &
                     ' Skipping IR insertion'
  END IF
!
  IF (cld_files == 1) THEN
    WRITE(6,*)  'Writing cloud fraction after inserting IR data.'
    varid='cld_ir'
    varname='Clouds after IR Data'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,nz,clouds_3d,varid,varname,varunits,             &
                 time,runname,dirname,istatwrt)
  END IF
!
!-----------------------------------------------------------------------
!
!  Getting the 2-D maximum radar reflectivity field
!
!-----------------------------------------------------------------------
!
  DO i=1,nx
    DO j=1,ny
      dbz_max_2d(i,j) = r_missing
      DO k=1,nz
        dbz_max_2d(i,j) = MAX(dbz_max_2d(i,j),ref_mos_3d(i,j,k))
      END DO
    END DO
  END DO
!
!-----------------------------------------------------------------------
!
!  Insert radar data
!
!-----------------------------------------------------------------------
!
  330   CONTINUE
  IF (istat_radar == 1) THEN

    WRITE(6,*) 'Inserting radar reflectivity data.'
    CALL insert_radar(nx,ny,nz,clddiag,topo,zs,t_3d,z_lcl               &
                ,refthr1,refthr2,hgtrefthr                              &
                ,ref_mos_3d,clouds_3d                                 &
                ,cloud_base,cloud_base_buf,l_unresolved                 &
                ,istatus_rad)
!
    IF (istatus_rad /= 1) THEN
      WRITE(6,*)' Error inserting radar data,'                          &
                 ,' Aborting cld analysis'
      GO TO 999
    END IF
  ELSE
    WRITE(6,'(a,a,/a)')  ' !!!WARNING!!! Problem using radar data',     &
                     ' Skipping RADAR insertion'
  END IF
!
  IF (cld_files == 1) THEN
    WRITE(6,*)  'Writing cloud fraction after inserting radar data.'
    varid='cldrad'
    varname='Clouds after Radar'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,nz,clouds_3d,varid,varname,varunits,             &
                 time,runname,dirname,istatwrt)
  END IF
!
  IF (cloudopt == 2) GO TO 340   ! Using radar data only
!
!-----------------------------------------------------------------------
!
!  Inserting the satellite visible data
!
!-----------------------------------------------------------------------
!
  IF (io_vis == 0) THEN
    WRITE(6,*) 'Inserting satellite VIS data.'
    CALL insert_vis (nx,ny,nz,zs,topo,clouds_3d                         &
                   ,albedo,cloud_frac_vis_a                             &
                   ,vis_rad_thcvr,vis_rad_thdbz                         &
                   ,istat_radar,ref_mos_3d,refthr2,dbz_max_2d         &
                   ,r_missing,sfc_sao_buffer,istatus_vis)
!
    IF (istatus_vis /= 1) THEN
      WRITE(6,*)' Error inserting VIS data, Aborting cld analysis.'
      GO TO 999
    END IF
  ELSE
    WRITE(6,'(a,a,/a)')                                                 &
            '  !!!WARNING!!! Problem using satellite VIS data',         &
                     ' Skipping VIS data insertion'
  END IF
!
  IF (cld_files == 1) THEN
    WRITE(6,*)  'Writing cloud fraction after inserting VIS data.'
    varid='cldvis'
    varname='Clouds after Vis'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,nz,clouds_3d,varid,varname,varunits,             &
                 time,runname,dirname,istatwrt)
  END IF
!
  340   CONTINUE
!
!-----------------------------------------------------------------------
!
!  Calculate the column maximum and column total cloud cover.
!
!-----------------------------------------------------------------------
!
  DO i=1,nx
    DO j=1,ny
      DO k=1,nz
        cvr_1d (k) = clouds_3d(i,j,k)
      END DO
      CALL col_max_tot (nz,cvr_1d,cvr_max(i,j),cvr_tot(i,j)             &
                        ,istat_col)
    END DO
  END DO
  IF (cld_files == 1) THEN
    WRITE(6,*)  'Writing column total cloud cover.'
    varid='totcvr'
    varname='Total Column Cloud Cover'
    varunits='Fraction'
    CALL wrtvar1(nx,ny,1,cvr_tot,varid,varname,varunits,                &
                 time,runname,dirname,istatwrt)
  END IF
!
!-----------------------------------------------------------------------
!
!  Compare the final cloud analysis with radar reflectivity
!
!-----------------------------------------------------------------------
!
  IF (istat_radar == 1) THEN
    CALL compare_radar(nx,ny,nz,ref_mos_3d,dbz_max_2d                 &
                 ,cvr_max,refthr2,cloud_frac_vis_a                      &
                 ,vis_rad_thcvr,vis_rad_thdbz,r_missing)
  END IF
!
!-----------------------------------------------------------------------
!
!  Get Cloud Bases and Tops
!
!-----------------------------------------------------------------------
!
  WRITE(6,*)' Calculating Cloud Ceiling, Base and Top'
!
  DO j = 1,ny-1
    DO i = 1,nx-1
      cloud_base(i,j) = default_base
      cloud_ceiling(i,j) = default_ceiling
      cloud_top(i,j)  = default_top
!
!-----------------------------------------------------------------------
!
!  Test for Cloud Base (MSL)
!
!-----------------------------------------------------------------------
!
      IF (cvr_max(i,j) >= thresh_cvr_base) THEN
        DO k = nz-1,1,-1
          IF(clouds_3d(i,j,k) < thresh_cvr_base .AND.                   &
                clouds_3d(i,j,k+1) >= thresh_cvr_base) THEN
            cloud_base(i,j) = 0.5 * (zs(i,j,k) + zs(i,j,k+1))
          END IF
        END DO ! k
      END IF ! Clouds exist in this column
!
!-----------------------------------------------------------------------
!
!  Test for Cloud Top (MSL)
!
!-----------------------------------------------------------------------
!
      IF (cvr_max(i,j) >= thresh_cvr_top) THEN
        DO k = 1,nz-1
          IF(clouds_3d(i,j,k) > thresh_cvr_top .AND.                    &
                clouds_3d(i,j,k+1) <= thresh_cvr_top) THEN
            cloud_top(i,j) = 0.5 * (zs(i,j,k) + zs(i,j,k+1))
          END IF
        END DO ! k
      END IF ! Clouds exist in this column
!
!-----------------------------------------------------------------------
!
!  Test for Cloud Ceiling (AGL)
!
!-----------------------------------------------------------------------
!
      IF (cvr_max(i,j) >= thresh_cvr_ceiling) THEN
        DO k = nz-1,1,-1
          IF(clouds_3d(i,j,k) < thresh_cvr_ceiling .AND.                &
                clouds_3d(i,j,k+1) >= thresh_cvr_ceiling) THEN
            cloud_ceiling(i,j) = 0.5 * (zs(i,j,k)+zs(i,j,k+1))          &
                                     - topo(i,j)
          END IF
        END DO ! k
      END IF ! Clouds exist in this column

    END DO ! i
  END DO ! j
!
!-----------------------------------------------------------------------
!
!  Set the boundary values
!
!-----------------------------------------------------------------------
!
  DO i = 1,nx-1
    cloud_base(i,ny) = cloud_base(i,ny-1)
    cloud_ceiling(i,ny) = cloud_ceiling(i,ny-1)
    cloud_top(i,ny)  = cloud_top(i,ny-1)
  END DO ! i
!
  DO j = 1,ny
    cloud_base(nx,j) = cloud_base(nx-1,j)
    cloud_ceiling(nx,j) = cloud_ceiling(nx-1,j)
    cloud_top(nx,j)  = cloud_top(nx-1,j)
  END DO ! i
!
  IF (cld_files == 1) THEN
    varid='cldbas'
    varname='Cloudbase'
    varunits='Meters'
    CALL wrtvar1(nx,ny,1,cloud_base,varid,varname,varunits,             &
                 time,runname,dirname,istatwrt)
    varid='cldtop'
    varname='Cloud Top Height'
    varunits='Meters'
    CALL wrtvar1(nx,ny,1,cloud_top,varid,varname,varunits,              &
                 time,runname,dirname,istatwrt)
    varname='ceilng'
    varname='Cloud Ceiling'
    varunits='Meters'
    CALL wrtvar1(nx,ny,1,cloud_ceiling,varid,varname,varunits,          &
                 time,runname,dirname,istatwrt)
  END IF
!
!-----------------------------------------------------------------------

  istatus=1

  999   CONTINUE
!
!-----------------------------------------------------------------------
!
  RETURN
END SUBROUTINE cloud_cv




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


SUBROUTINE col_max_tot (nz,cvr,cvr_max,cvr_tot,istatus) 1
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  To find the number of cloud decks in one column of grid.
!
!-----------------------------------------------------------------------
!
!  AUTHOR: (Jian Zhang)
!  06/01/96.
!
!  MODIFICATION HISTORY:
!  04/11/97  J. Zhang
!            Included adascld24.inc for ncloud
!  08/06/97  J. Zhang
!            Change adascld24.inc to adascld26.inc
!  05/05/98  J. Zhang
!            Abandon cloud grid. Using only ARPS grid.
!
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  INPUT:
  INTEGER :: nz
!
!  INPUT:
  REAL :: cvr(nz)     ! Cloud cover in one column of grid.
!
!  OUTPUT:
  INTEGER :: istatus
  REAL :: cvr_max         ! column maximum cldcvr
  REAL :: cvr_tot         ! column integrated cldcvr
!
!  LOCAL:
  INTEGER :: nlyr         ! number of cloud decks (layers) in the column.
  INTEGER :: ilyr(nz) ! Layer index for each cloud lvl (needs)

  REAL :: a(nz)       ! max. cloud cover of each cloud layer
  REAL :: f(nz)       ! Apparnt "x-sectn" of cldlyrs seen from above
  INTEGER :: ik(nz)   ! Height level representative of cloud layers
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: k,n
  REAL :: cvr_thresh,sumf
  PARAMETER (cvr_thresh = 0.1)
!
!-----------------------------------------------------------------------
!
!  Convert from cld cvr to discreet cloud layer indices (cvr to a)
!
!  Find the maximum cloud cover "a" in each cloud deck, and
!  the level index "ik" associated with the maximum cloud cover.
!
!-----------------------------------------------------------------------
!
  istatus=0
  nlyr = 0
  IF(cvr(nz) > cvr_thresh) THEN    ! cld_top at upper bndry
    nlyr = nlyr + 1
    a(nlyr) = cvr(nz)
    ik(nlyr) = nz
  END IF

  DO k = nz-1,1,-1
    IF(cvr(k) >= cvr_thresh .AND. cvr(k+1) < cvr_thresh) THEN
      nlyr = nlyr + 1        ! at top of a new cld layer
      a(nlyr) = cvr(k)
      ik(nlyr) = k
    ELSE IF(nlyr >= 1) THEN
      IF(cvr(k) > a(nlyr)) THEN
        a(nlyr) = cvr(k)   ! Max cldcvr within a layer
        ik(nlyr) = k       ! the lvl index for the max. cldcv
      END IF
    END IF

    IF(cvr(k) >= cvr_thresh) THEN      ! Still within layer
      ilyr(k) = nlyr
    ELSE                                 ! Below layer
      ilyr(k) = 0
    END IF

  END DO ! k
!
!-----------------------------------------------------------------------
!
!  Convert cloud layer fractions to "cross-section" seen from
!  satellite.  This solves for the "f" array given the "a" array
!
!-----------------------------------------------------------------------
!
  IF(nlyr == 0) THEN
    istatus=1
    cvr_max=0.0
    cvr_tot=0.0
    RETURN
  END IF

  a(1) = MIN(  f(1) = a(1)
  sumf = f(1)
  cvr_max=a(1)
  cvr_tot=a(1)

  IF(nlyr >= 2) THEN
    DO n = 2,nlyr
      a(n) = MIN(      cvr_max = MAX(      f(n) = a(n) * (1.0 - sumf) ! fraction of radiation reaches
                                 ! top of atm from each cld layer
      sumf = sumf + f(n)         ! fraction of radiation blked
                                 ! /attened by all cld lyrs above
    END DO ! n
!
!-----------------------------------------------------------------------
!
!  Calculate column integrated cloud cover as if the cloud
!  particles are uniformly (fusely) distributed in the atmosphere.
!
!-----------------------------------------------------------------------
!
    cvr_tot =sumf
!
  END IF ! nlyr
!
!-----------------------------------------------------------------------
!
  istatus=1
  RETURN
END SUBROUTINE col_max_tot





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


SUBROUTINE compare_radar (nx,ny,nz,ref_mos_3d,dbz_max_2d              & 1
           ,cvr_max,ref_base,cf_vis_a                                   &
           ,vis_rad_thcvr,vis_rad_thdbz,r_missing)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!  This routine compares the cloud and radar fields and flags
!  remaining differences that weren't caught in earlier processing
!  This routine does not alter any arrays or pass anything back,
!  it is diagnostic only.
!
!-----------------------------------------------------------------------
!
!  AUTHOR:   Jian Zhang
!  07/15/96  Based on the LAPS cloud analysis code of 9/1995
!
!  MODIFICATION HISTORY:
!
!
!-----------------------------------------------------------------------
!
!
!-----------------------------------------------------------------------
!
!  Variable Declarations.
!
!-----------------------------------------------------------------------
!
  IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
!  INPUT:
  INTEGER :: nx,ny,nz            ! Model grid size(dbz)
  REAL :: ref_mos_3d(nx,ny,nz) ! radar reflectivity remapped on grid
  REAL :: dbz_max_2d(nx,ny)      ! Column max. radar reflectivity (dbz)
  REAL :: cvr_max(nx,ny)         ! column maximum cloud cover
  REAL :: cf_vis_a(nx,ny)  ! sate. visible albedo derived cldcvr
  REAL :: ref_base       ! thrshld define signif. radar echo
  REAL :: vis_rad_thcvr  ! thrshld define signif. vis cldcvr (0.2)
  REAL :: vis_rad_thdbz  ! thrshld define signif. cldy radar ehco (10dbz)
  REAL :: r_missing      ! flag for missing or bad data
!
!  OUTPUT:
!  None
!
!-----------------------------------------------------------------------
!
!  Misc local variables
!
!-----------------------------------------------------------------------
!
  INTEGER :: i,j
!
!-----------------------------------------------------------------------
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
  WRITE(6,*) 'Comparing clouds and radar (_RDR)'
  WRITE(6,*) 'vis_rad_thcvr = ',vis_rad_thcvr
  WRITE(6,*) 'vis_rad_thdbz = ',vis_rad_thdbz

  DO i = 1,nx
    DO j = 1,ny
      IF(cvr_max(i,j) < vis_rad_thcvr .AND. dbz_max_2d(i,j) > ref_base) THEN
!
!-----------------------------------------------------------------------
!
!  We have a discrepancy between the VIS and radar
!
!-----------------------------------------------------------------------
!
        IF(cvr_max(i,j) == cf_vis_a(i,j)) THEN ! CVR = VIS

          IF(dbz_max_2d(i,j) < vis_rad_thdbz) THEN
            WRITE(6,1) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            1             FORMAT(' VIS_RDR: cvr_mx/dbz/vis <',2I4,f5.2,f8.1,f5.2)
          ELSE
            WRITE(6,11) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            11            FORMAT(' VIS_RDR: cvr_mx/dbz/vis >',2I4,f5.2,f8.1,f5.2)
          END IF  ! dbz_max_2d < vis_rad_thdbz

        ELSE IF (cvr_max(i,j) < cf_vis_a(i,j)) THEN
!
!-----------------------------------------------------------------------
!
!  Don't blame the VIS            CVR < VIS
!
!-----------------------------------------------------------------------
!
          IF(dbz_max_2d(i,j) < vis_rad_thdbz) THEN
!
!-----------------------------------------------------------------------
!
!  We can potentially block out the radar
!
!-----------------------------------------------------------------------
!
            WRITE(6,2) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            2            FORMAT(' CLD_RDR: cvr_mx/dbz/vis <',2I4,f5.2,f8.1,f5.2)
          ELSE ! Radar is too strong to block out
            WRITE(6,3) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            3            FORMAT(' CLD_RDR: cvr_mx/dbz/vis >',2I4,f5.2,f8.1,f5.2)
          END IF   ! dbz_max_2d < vis_rad_thdbz

        ELSE IF (cvr_max(i,j) > cf_vis_a(i,j)) THEN
!
!-----------------------------------------------------------------------
!
!  Don't know if VIS lowered cloud cover        CVR > VIS
!  At least if difference is less than VIS "cushion"
!
!-----------------------------------------------------------------------
!
          IF(dbz_max_2d(i,j) < vis_rad_thdbz) THEN
!
!-----------------------------------------------------------------------
!
!  We can potentially block out the radar
!
!-----------------------------------------------------------------------
!
            WRITE(6,4) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            4            FORMAT(' ???_RDR: cvr_mx/dbz/vis <',2I4,f5.2,f8.1,f5.2)
          ELSE ! Radar is too strong to block out
            WRITE(6,5) i,j,cvr_max(i,j),dbz_max_2d(i,j),cf_vis_a(i,j)
            5            FORMAT(' ???_RDR: cvr_mx/dbz/vis >',2I4,f5.2,f8.1,f5.2)
          END IF   ! dbz_max_2d < vis_rad_thdbz
        END IF  ! cvr_max(i,j) = cf_vis_a(i,j)
      END IF  ! cvr_max < vis_rad_thcvr & dbz_max_2d > ref_base
    END DO ! j
  END DO ! i

  RETURN
END SUBROUTINE compare_radar