!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE INSERT_SAO1 ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
!
SUBROUTINE insert_sao1(nx,ny,nz,dx,dy,xs,ys,zs,topo,t_sfc_k, & 1,24
cldcv,wtcldcv,t_modelfg,cf_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)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Ingest the SAO cloud coverage observations.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 02/96. Based on the LAPS cloud analysis code by Steve Albers,
! 1995.
!
! MODIFICATION HISTORY:
!
! 02/06/96 J. Zhang
! Modified for ADAS grid. Added documents.
! 03/14/97 J. Zhang
! Clean up the code and implemented for the official
! arps4.2.4 version
! 04/15/97 J. Zhang
! Added error message output for the case when the
! actual # of cloud soundings (N_CLD_SND) exceeds the
! maximum allowed # (MAX_CLD_SND) defined in
! adascld24.inc.
! 08/06/97 J. Zhang
! Change adascld24.inc to adascld25.inc
! 09/09/97 J. Zhang
! Assign a weight to a SAO cloud sounding base on
! the cloud coverage amount.
! 09/11/97 J. Zhang
! Change adascld25.inc to adascld26.inc
! 02/17/98 Keith Brewster
! Changed logic to skip cloud layers with below zero
! height -- missing, in other words.
! 05/05/98 J. Zhang
! Abandoned the cloud grid, using the ARPS grid instead.
! 05/01/98 Keith Brewster
! Removed abort for missing data, instead data are
! checked for missing at every step.
!
!-----------------------------------------------------------------------
!
! INCLUDE: (from adas.inc)
!
! mx_sng ! max. possible # of surface obs.
! max_cld_snd ! max. possible # of stations
! with cloud coverage reports.
!
! INPUT:
!
! nx,ny,nz ! Number of ADAS grid pts.in 3 directions.
!
! l_stn_clouds ! Using SAO stations' cloud obs?
!
!c 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.
! topo (nx,ny) ! The height of the terrain (equivalent
!
! First guess fields
!
! cf_modelfg (nx,ny,nz) ! first guess cloud cover field
! t_modelfg (nx,ny,nz) ! first guess temperature field
! t_sfc_k (nx,ny) ! surface temperature field
!
! cldcv (nx,ny,nz) 3D gridded fractional cloud cover analysis.
! (when input, it's the first guess field)
! wtcldcv (nx,ny,nz) weights assigned to gridded fractional
! cloud cover analysis. (when input, it's
! the weights for first guess field)
!
! Single-level (e.g., surface) station variables
!
! 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.
!
! OUTPUT:
!
! istatus The flag indicating process status.
!
! 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.
! i_snd (max_cld_snd) i-location of each cloud sounding
! station in ADAS grid
! j_snd (max_cld_snd) j-location of each cloud sounding
! station in ADAS grid
!
! LOCAL:
!
! name_array (max_cld_snd) station names (first letter) for
! each cloud sounding
! ista_snd (max_cld_snd) index of cloud sounding stations
! cvr_snd (max_cld_snd) column integrated cloud cover
! cloud_top(nx,ny) Analyzed cloud top heights (m ASL).
! cloud_base(nx,ny) Analyzed cloud base heights (m ASL).
! cloud_ceiling(nx,ny) Analyzed cloud ceiling heights (m ASL).
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'adas.inc'
!
!-----------------------------------------------------------------------
!
! INCLUDE: (from adas.inc)
!
! integer mx_sng ! max. possible # of surface obs.
! integer max_cld_snd ! max. possible # of stations
! with cloud coverage reports.
!
! INPUT:
INTEGER :: nx,ny,nz
REAL :: dx,dy ! ADAS grid spacing
LOGICAL :: l_stn_clouds ! Using SAO stns' cloud obs? (or bkgrnd)
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 :: topo (nx,ny) ! The height of the terrain (equivalent
!
! First guess fields
!
REAL :: cf_modelfg (nx,ny,nz) ! first guess cloud cover field
REAL :: t_modelfg (nx,ny,nz) ! first guess temperature field
REAL :: t_sfc_k (nx,ny) ! surface temperature field
!
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)
!
! Surface cloud coverage reports
!
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.
!
! OUTPUT:
!
INTEGER :: istatus ! Flag for process status
!
INTEGER :: n_cld_snd ! # of cloud snds created
REAL :: cld_snd (max_cld_snd,nz) ! Cld snd obtained from SAO data.
REAL :: wt_snd (max_cld_snd,nz) ! wgt for SAO cld snd
INTEGER :: i_snd (max_cld_snd) ! i-lctn of cld snd stn in ADAS grid
INTEGER :: j_snd (max_cld_snd) ! j-lctn of cld snd stn in ADAS grid
!
! LOCAL:
!
CHARACTER (LEN=1) :: name_array (nx,ny) ! Cld snd stn name (1st letter)
INTEGER :: ista_snd (max_cld_snd) ! index of cld snd stns
REAL :: cvr_snd (max_cld_snd) ! column integrated cloud cover
!
!-----------------------------------------------------------------------
!
! Empirical factors (parameters) for cloud cover analysis
!
!-----------------------------------------------------------------------
!
!c Using SAO stations slightly outside the ARPS domain.
INTEGER :: ix_low,ix_high,iy_low,iy_high
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
REAL :: ht_defined ! the reachable height of the SAOs
REAL :: ht_base,ht_top ! base and top heights of a cloud layer
INTEGER :: n_analyzed ! # of stations analyzed in this routine
INTEGER :: i,k,l
REAL :: ri(mx_sng),rj(mx_sng)
! i-,j-lctns of each stn in ADAS grid
INTEGER :: iloc,jloc ! i- and j-index of each sta.
INTEGER :: igrd,jgrd ! i- and j-index of each sta. in grid
REAL :: cover ! cloud fractional cover values
REAL :: cld_thk
INTEGER :: k_ceil
LOGICAL :: l_out_of_bounds,l_dry,cldprt
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
istatus = 0
WRITE(6,*)
IF (nobsng < 1) THEN
PRINT*,'## No SAO data available. Returning from INSERT_SAO...'
istatus = 1
RETURN
END IF
WRITE(6,*) 'Inserting SAO data from ',nobsng,' stations.'
cldprt=(clddiag == 1)
!
ix_low = 1 - i_perimeter
ix_high = nx + i_perimeter
iy_low = 1 - i_perimeter
iy_high = ny + i_perimeter
!
!-----------------------------------------------------------------------
!
! Initialize the cloud sounding array.
!
!-----------------------------------------------------------------------
!
DO i=1,max_cld_snd
DO k=1,nz
cld_snd(i,k) = 0.0
wt_snd(i,k) = 0.0
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Initially assign a unreal number for the sensor's reachable
! height.
!
!-----------------------------------------------------------------------
!
ht_defined = 99999.
n_analyzed = 0
!
!-----------------------------------------------------------------------
!
! Loop through the stations
!
!-----------------------------------------------------------------------
!
DO i=1,nobsng
IF( obstype(i)(1:4) == 'meso') GO TO 125
IF( obstype(i)(1:4) == 'armmn') GO TO 125
IF( obstype(i)(1:4) == 'isws') GO TO 125
IF( obstype(i)(1:4) == 'coagmet') GO TO 125
IF( obstype(i)(1:4) == 'hplains') GO TO 125
IF( obstype(i)(1:4) == 'wpdn') GO TO 125
!
!-----------------------------------------------------------------------
!
! Place station at proper ADAS grid point.
!
!-----------------------------------------------------------------------
!
ri(i) = 1. + (xsng(i) - xs(1))/dx
rj(i) = 1. + (ysng(i) - ys(1))/dy
iloc = nint(ri(i))
jloc = nint(rj(i))
IF( iloc < ix_low .OR. iloc > ix_high &
.OR. jloc < iy_low .OR. jloc > iy_high) THEN
! write(6,*) 'Station is outside domain ',stn(i)
GO TO 125
END IF
IF( kcloud(i) == 0) THEN ! Kick out AMOS stations not
! reporting clouds this time
! write(6,*)' No cloud layers - probably AMOS -',
! : ' goto end of loop ',stn(i),obstype(i)
GO TO 125
END IF
n_analyzed = n_analyzed + 1
n_cld_snd = n_cld_snd + 1
IF(n_cld_snd > max_cld_snd) THEN
PRINT*,'##ERROR: actual # of cldsnd=',n_cld_snd, &
' exceeds max. # allowed =',max_cld_snd
PRINT*,'Please increase MAX_CLD_SND in the .inc file.'
PRINT*,'ABORTING from INSERT_SAO......'
STOP
END IF
ista_snd(n_cld_snd) = i
IF(obstype(i)(5:5) /= ' ' .AND. obstype(i)(4:7) /= 'AMOS') THEN
!
!-----------------------------------------------------------------------
!
! Automated Station (12000' limit)
!
!-----------------------------------------------------------------------
!
ht_defined = elevsta(i) + 12000./3.281
ELSE
ht_defined = 99999.
END IF
IF(cldprt) THEN
WRITE(6,1,ERR=110) stn(i),latsta(i),lonsta(i) &
,iloc,jloc,kcloud(i) &
,obstype(i),ht_defined
1 FORMAT(1X,a5,' lat=',f7.2,' lon=',f7.2,' i=',i3,' j=',i3 &
,' kld=',i1,' obsty=',a8,' h_def=',f8.0)
110 WRITE(6,2,ERR=3) &
(store_amt(i,l),store_hgt(i,l),l=1,kcloud(i))
2 FORMAT(1X,5(a4,f8.0))
3 CONTINUE
END IF
IF( iloc < 1 .OR. iloc > (nx-1) .OR. jloc < 1 .OR. jloc > (ny-1) ) THEN
l_out_of_bounds = .true.
igrd=MIN(MAX(iloc,1),(nx-1))
jgrd=MIN(MAX(jloc,1),(ny-1))
ELSE
l_out_of_bounds = .false.
igrd=iloc
jgrd=jloc
name_array(iloc,jloc )=stn(i)(1:1)
name_array(iloc,MIN(jloc+1,ny)) =stn(i)(1:1)
name_array(iloc,MAX(jloc-1,1 ))=stn(i)(1:1)
END IF
cvr_snd (n_cld_snd) = 0. ! column intg. cloud cover.
!
!-----------------------------------------------------------------------
!
! For each station, loop through each cloud layer observed
! by the SAO.
!
!-----------------------------------------------------------------------
!
DO l = 1,kcloud(i)
cover = 0.
IF (store_hgt(i,l) < 0.0 .AND. store_amt(i,l) /= ' CLR' ) THEN
! ht_base = cld_base(l)
! print*,' stn',i,' level',l,' cld.ht.=',store_hgt(i,l)
! : ,' adj. cld. ht.=',ht_base
! ht_base = elevsta(i) + ht_base
CYCLE
ELSE
ht_base = elevsta(i) + store_hgt(i,l)
END IF
IF( ht_base > ht_defined+1.) THEN
IF( store_amt(i,l) /= ' CLR') THEN ! Clouds
WRITE(6,*)' Error, inconsistent SAO data, cloud base is' &
//' reported to be too high for this sensor type'
WRITE(6,*) ht_base,ht_defined,obstype(i)
WRITE(6,*)' Please check cloud layer heights in the LSO' &
//' file to see that they are compatable with the'
WRITE(6,*)' types of sensors used.'
istatus = 0
RETURN
ELSE ! CLR
WRITE(6,*)' Note, CLR sky cloud base does not' &
//' reflect this sensor type'
WRITE(6,*) ht_base,ht_defined,obstype(i)
END IF ! Clouds
END IF !"ht_base > ht_defined+1"
!
!-----------------------------------------------------------------------
!
! CLOUDS ARE NOW IN MSL
! Fill in clear for entire column for SAO or up to ht_base for AWOS
!
!-----------------------------------------------------------------------
!
IF( store_amt(i,l) == ' CLR') THEN
cover=.01
DO k=1,nz
IF( zs(igrd,jgrd,k) <= ht_base &
.AND. zs(igrd,jgrd,k) <= ht_defined ) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
END DO
END IF
!
!-----------------------------------------------------------------------
!
! Assign cloud cover values for entire column for SAO
! or up to ht_base for AWOS. First check if there is dry
! layer or inversion.
!
!-----------------------------------------------------------------------
!
IF( store_amt(i,l) == '-SCT' ) THEN
cover=.15 ! .2
ht_top=ht_base+cld_thk(ht_base-elevsta(i),cover)
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF ! ht_base < zs < ht_top
END DO ! k = 1, nz
END IF
IF( store_amt(i,l) == ' SCT') THEN
cover=.25 ! .3
ht_top=ht_base+cld_thk(ht_base-elevsta(i),cover)
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
IF( store_amt(i,l) == '-BKN' ) THEN
cover=.4 ! .5
ht_top=ht_base+cld_thk(ht_base-elevsta(i),cover)
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry)THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
IF( store_amt(i,l) == ' BKN' ) THEN
cover=.7
ht_top = ht_base + cld_thk(ht_base-elevsta(i),cover) ! 1500.
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
IF( store_amt(i,l) == '-OVC') THEN
cover=.6 ! .9
ht_top=ht_base+cld_thk(ht_base-elevsta(i),cover)
DO k=1,nz
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
IF( store_amt(i,l) == ' OVC') THEN
cover=1.01
ht_top = ht_base + cld_thk(ht_base-elevsta(i),cover) ! 1500.
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry)THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
IF( store_amt(i,l) == ' X ') THEN
cover=1.01
ht_top = ht_base + cld_thk(ht_base-elevsta(i),cover) ! 1500.
DO k=2,nz-2
IF(zs(igrd,jgrd,k) >= ht_base .AND. zs(igrd,jgrd,k) <= ht_top) THEN
!
!-----------------------------------------------------------------------
!
! Check if inversion or dry layer exist.
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,0,l_dry)
IF(.NOT. l_dry) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
ELSE IF(zs(igrd,jgrd,k) < ht_base) THEN
!
!-----------------------------------------------------------------------
!
! Initialize the modify sounding routine
!
!-----------------------------------------------------------------------
!
CALL modify_sounding
(cf_modelfg,t_modelfg,topo &
,t_sfc_k,igrd,jgrd,k,nx,ny,nz,zs &
,ht_base,ht_top,1,l_dry)
END IF
END DO
END IF
cvr_snd(n_cld_snd) = 1. - ((1. - cvr_snd(n_cld_snd)) * cover)
END DO
!
!-----------------------------------------------------------------------
!
! Locate the highest ceiling
!
!-----------------------------------------------------------------------
k_ceil = nz-2
IF( l_stn_clouds) THEN
DO k=nz-2,2,-1
IF( wt_snd(n_cld_snd,k) == 1.00 .AND. cld_snd(n_cld_snd,k) > 0.5) THEN
k_ceil = k
GO TO 1001
END IF
END DO
ELSE
DO k=nz-2,2,-1
IF( wtcldcv(igrd,jgrd,k) == 1.00 .AND. cldcv(igrd,jgrd,k) > 0.5 ) THEN
k_ceil = k
GO TO 1001
END IF
END DO
END IF
!
!-----------------------------------------------------------------------
!
! Fill in other clear layers outside of clouds, below the ceiling,
! and within defined height range of sensor.
!
!-----------------------------------------------------------------------
!
1001 cover = .01
IF( l_stn_clouds) THEN
DO k=2,k_ceil
IF( wt_snd(n_cld_snd,k) /= 1.00 &
.AND. zs(igrd,jgrd,k) <= ht_defined ) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
END DO
ELSE
DO k=2,k_ceil
IF( wtcldcv(igrd,jgrd,k) /= 1.00 &
.AND. zs(igrd,jgrd,k) <= ht_defined ) THEN
CALL spread2
(cld_snd,wt_snd,i_snd,j_snd,n_cld_snd &
,max_cld_snd,nz,iloc,jloc,k,cover,1.)
END IF
END DO
END IF
125 CONTINUE
END DO ! I=1,NOBSNG
!
!-----------------------------------------------------------------------
!
WRITE(6,*)' Num stations analyzed/cloud soundings = ' &
,n_analyzed,n_cld_snd
!
!-----------------------------------------------------------------------
!
istatus = 1
! 999 CONTINUE
RETURN
END SUBROUTINE insert_sao1
!
!
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE MODIFY_SOUNDING ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
!
SUBROUTINE modify_sounding (cf_modelfg,t_modelfg,topo, & 14
t_sfc_k,i_in,j_in,k,ni,nj,nk,zs, &
ht_base,ht_top,init,l_dry)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Check if there is dry layer or inversion (If there is one,
! ( the observed cloud layer will be cleared out).
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 03/96 Based on the LAPS cloud analysis code, 1995
!
! MODIFICATION HISTORY:
!
! 02/06/96 J. Zhang
! Modified for ADAS grid. Added documents.
!
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
! INPUT:
INTEGER :: init ! flag value indicating if the layer is
! within the cloud.
INTEGER :: ni,nj ! horizontal grid domain size
INTEGER :: nk ! # of cloud analysis levels
INTEGER :: i_in,j_in ! i- and j- location in ADAS grid
INTEGER :: k ! the cloud height level
REAL :: cf_modelfg (ni,nj,nk) ! first guess cloud cover field
REAL :: t_modelfg (ni,nj,nk) ! first guess temperature field
REAL :: t_sfc_k (ni,nj) ! surface temperature field
REAL :: topo(ni,nj) ! height of the terrain
!
REAL :: zs(ni,nj,nk) ! cloud analysis heights
REAL :: ht_base,ht_top
!
!-----------------------------------------------------------------------
!
!c OUTPUT:
LOGICAL :: l_dry ! if there is inversion or dry layer?
!
!-----------------------------------------------------------------------
!
!c LOCAL:
INTEGER :: i,j
REAL :: cf_model_base,t_model_base,t_subcloud
REAL :: t_dry_adiabat,t_inversion_strength
LOGICAL :: l_wait_for_base,l_cf,l_inversion
SAVE l_wait_for_base,cf_model_base,t_model_base, &
l_inversion,t_subcloud
!-----------------------------------------------------------------------
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
l_dry = .false.
l_cf = .false.
!
!-----------------------------------------------------------------------
!
! Find ARPS grid point nearest the SAO if it is out of bounds
!
!-----------------------------------------------------------------------
!
i = MAX(MIN(i_in,ni-1),1)
j = MAX(MIN(j_in,nj-1),1)
IF (init == 1) THEN ! (below base )
! reset to wait for the beginning of the layer
l_wait_for_base = .true.
l_inversion = .false.
t_subcloud = t_modelfg(i,j,k)
RETURN
ELSE ! init = 0 (inside cloud layer)
! For k=1 and init=0, l_wait_base=.F., and there will be NO
! t_subcloud available.
IF(l_wait_for_base .OR. k <= 2) THEN
!
!-----------------------------------------------------------------------
!
! Set reference (just within cloud base)
!
!-----------------------------------------------------------------------
!
l_wait_for_base = .false.
cf_model_base = cf_modelfg(i,j,k)
t_model_base = t_modelfg(i,j,k)
! write(6,21) t_subcloud
!21 format( /' model T_subcloud = ',f7.2)
! write(6,1)
!1 format(1x,21x,' cf_fg',' t_fg ',' dt_inv'
! : ,' lcf',' linv',' i j k ',' cldht')
END IF
!
!-----------------------------------------------------------------------
!
! Determine if the layer is dry or it has inversion.
! (in either case, the cloud will be cleared out)
!
!-----------------------------------------------------------------------
!
IF(.true.) THEN ! Set inversion strength flag
!
t_dry_adiabat = t_sfc_k(i,j) &
-.0098 * (zs(i,j,k) - topo(i,j))
t_inversion_strength = t_modelfg(i,j,k) - t_dry_adiabat
IF( ( (t_modelfg(i,j,k) > t_model_base) &
.OR. &
(k >= 2 .AND. t_modelfg(i,j,k) > t_subcloud) ) &
.AND. &
(t_modelfg(i,j,k) > 283.15) & ! temp check
.AND. &
(t_inversion_strength > 4.) & ! delta theta chk
) THEN
!
l_inversion = .true. ! Inversion exists
! write(6,2) cf_modelfg(i,j,k),t_modelfg(i,j,k)
! : ,t_inversion_strength,l_cf,l_inversion
! : ,i,j,k,nint(zs(i,j,k))
!
!2 format(' Inversion detected = ',3f7.2,2l4,3i4,i6)
ELSE IF (cf_modelfg(i,j,k) < cf_model_base - 0.3 & ! cf search
.AND. zs(i,j,k) - ht_base >= 500.) THEN
!
l_cf = .true. ! Dry layer exists
! write(6,3) cf_modelfg(i,j,k),t_modelfg(i,j,k)
! : ,t_inversion_strength,l_cf,l_inversion
! : ,i,j,k,nint(zs(i,j,k))
!
!3 format(' Dry layer detected = ',3f7.2,2l4,3i4,i6)
ELSE ! neither dry nor inversion
!
!-----------------------------------------------------------------------
!
! If l_inversion and l_cf are not reset to .false. here, the WHOLE
! cloud layer above a SINGLE level will be cleared out IF that one
! level has inversion.
! This is effective through the "save" statement at the beginning
! of this subroutine.
!
!-----------------------------------------------------------------------
!
! write(6,4) cf_modelfg(i,j,k),t_modelfg(i,j,k)
! : ,t_inversion_strength,l_cf,l_inversion
! : ,i,j,k,nint(zs(i,j,k))
!
!4 format(' model RH/T in cloud =',3f7.2,2l4,3i4,i6)
END IF ! inversion check
IF( l_cf.OR.l_inversion ) THEN
l_dry = .true.
END IF
END IF ! .true. for dry-inversion check.
END IF ! INIT=1
!
!-----------------------------------------------------------------------
!
RETURN
END SUBROUTINE modify_sounding
!
!##################################################################
!##################################################################
!###### ######
!###### FUNCTION CLD_THK ######
!###### ######
!##################################################################
!##################################################################
!
FUNCTION cld_thk (ht_base,cover)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Obtain thickness of a cloud layer. The thickness is simply
! set to 1 km for cloud below 7 km and 1.5km for those above
! 7 km.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 03/96
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! INPUT:
! ht_base ! the height of cloud base
! cover ! the cloud amount of the layer
!
! OUTPUT:
! cld_thk ! the thickness of the cloud layer
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
REAL :: ht_base,cover,cld_thk
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IF(ht_base > 7000.)THEN
cld_thk = 1500.
ELSE IF(ht_base > 1000.) THEN
cld_thk = 1000.0+(ht_base-1000.)/12.
ELSE
cld_thk = MIN(1000.0,ht_base)
END IF
IF(cover > 0.01 .AND. cover < 0.5)THEN
cld_thk = MIN(1000.,cld_thk)
END IF
RETURN
END FUNCTION cld_thk
!
!##################################################################
!##################################################################
!###### ######
!###### FUNCTION CLD_BASE ######
!###### ######
!##################################################################
!##################################################################
!
FUNCTION cld_base (k)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Obtain the base height of a cloud layer.
! The base height is currently an artificial function of
! the reported cloud layer index.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 04/17/96
!
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! INPUT:
! k ! the index of the reported cloud layer
!
! OUTPUT:
! cld_base ! the base height of the cloud layer
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
REAL :: cld_base
INTEGER :: k
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IF(k == 1) cld_base = 500.
IF(k == 2) cld_base = 2000.
IF(k == 3) cld_base = 6000.
IF(k == 4) cld_base = 8000.
IF(k == 5) cld_base = 10000.
RETURN
END FUNCTION cld_base
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE INSERT_RADAR ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE insert_radar(nx,ny,nz,clddiag,topo,zs,temp_3d,z_lcl & 1
,ref_base1,ref_base2,hgt_thresh_ref &
,grid_ref,cldcv &
,cloud_base,cloud_base_buf,l_unresolved &
,istatus)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Insert radar data into cloud grid
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 05/1996
!
! MODIFICATION HISTORY:
!
! 05/08/96 J. Zhang
! Modified for the ARPSDAS format. Added full
! documentation.
! 07/26/96 J. Zhang
! Added quality check to avoid out-bounds cloud.
! 03/27/97 J. Zhang
! Updated for the official version of arps4.2.4
! 03/28/97 J. Zhang
! Using the lifting condensation level as the cloud base
! when there is no SAO cloud base.
! 09/01/97 J. Zhang
! Document cleanup for ADASCLD version 25.
! Using the lifting condensation level as the cloud base
! when the radar echo top is below the analyzed SAO cloud
! base
! 09/10/97 J. Zhang
! Put lcl in the input argument list.
! 04/20/98 J. Zhang
! Based on the arps4.3.3 version, abandon the cloud grid.
! Using arps grid.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
IMPLICIT NONE
!-----------------------------------------------------------------------
!
INTEGER :: nx,ny,nz
! INPUT/OUTPUT:
REAL :: cldcv(nx,ny,nz)
! INPUT:
INTEGER :: clddiag
REAL :: temp_3d(nx,ny,nz)
REAL :: zs(nx,ny,nz)
REAL :: topo(nx,ny)
REAL :: z_lcl(nx,ny) ! lifting condensation level
REAL :: grid_ref(nx,ny,nz)
REAL :: ref_base1 ! "significant" radar echo at lower levels
REAL :: ref_base2 ! "significant" radar echo at upper levels
REAL :: hgt_thresh_ref ! height criteria for "significant" radar
! echo thresholds
! OUTPUT:
INTEGER :: istatus
REAL :: cloud_base(nx,ny)
REAL :: cloud_base_buf(nx,ny) ! Lowest SAO/IR base within search radius
!
! LOCAL:
REAL :: radar_cover
PARAMETER(radar_cover=1.0)
REAL :: thresh_cvr ! lower radar echo threshold for cloud filling
PARAMETER (thresh_cvr = 0.2)
LOGICAL :: l_below_base
LOGICAL :: l_unresolved(nx,ny)
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
LOGICAL :: cldprt
REAL :: unlimited_ceiling,ref_thresh
REAL :: zs_1d(nz)
INTEGER :: i,j,k,kp1
INTEGER :: icount_below,isearch_base,insert_count_tot
INTEGER :: icount_radar_lvl,insert_count_lvl
INTEGER :: i_out_bnd,i_lowecho
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
WRITE(6,*) 'Inserting radar reflectivity '
cldprt=(clddiag == 1)
!
!-----------------------------------------------------------------------
!
! Calculate Cloud Bases
!
!-----------------------------------------------------------------------
!
unlimited_ceiling = 200000.
DO j = 1,ny-1
DO i = 1,nx-1
cloud_base(i,j) = unlimited_ceiling
!
DO k = nz-1,1,-1
IF(cldcv(i,j,k) < thresh_cvr .AND. cldcv(i,j,k+1) >= thresh_cvr) THEN
cloud_base(i,j) = 0.5 * (zs(i,j,k) + zs(i,j,k+1))
END IF
END DO ! k
!
IF (cloud_base(i,j) > z_lcl(i,j)) THEN
cloud_base(i,j) = z_lcl(i,j) ! using lcl
END IF
cloud_base_buf(i,j) = cloud_base(i,j)
l_unresolved(i,j) = .false.
END DO ! i
END DO ! j
icount_below = 0 ! tot # of rdr echo pts below cloud base
isearch_base = 0 ! # of neighb cloud bases being succes. found
insert_count_tot = 0 ! tot # of data pts inserted the radar_cover
!
!-----------------------------------------------------------------------
!
! Essentially, this go downward to detect radar tops in time
! to search for a new cloud base
!
!-----------------------------------------------------------------------
!
i_out_bnd=0
i_lowecho=0
DO i = 1,nx-1
DO j = 1,ny-1
DO k=1,nz
zs_1d(k) = zs(i,j,k)
END DO
icount_radar_lvl = 0 ! # of lvls with refl > ref_thresh
insert_count_lvl = 0 ! # of cloud lvls inserted radar_cover
DO k = nz-1,1,-1
kp1 = MIN(k+1,nz)
!
!-----------------------------------------------------------------------
!
! Define the "significant" reflectivity value based on height (to
! eliminate ground clutters and/or other non-weather radar echoes).
!
!-----------------------------------------------------------------------
!
IF ((zs(i,j,k)-topo(i,j)) <= hgt_thresh_ref) THEN
ref_thresh = ref_base1
ELSE
ref_thresh = ref_base2
END IF
IF(grid_ref(i,j,k) > ref_thresh) THEN
icount_radar_lvl = icount_radar_lvl + 1
l_below_base = .false.
!
!-----------------------------------------------------------------------
!
! Test if we are at echo top
!
!-----------------------------------------------------------------------
!
IF(k == nz-1 .OR. grid_ref(i,j,kp1) < ref_thresh) THEN
!
!-----------------------------------------------------------------------
!
! Test if we are below the cloud base.
!
!-----------------------------------------------------------------------
!
IF(zs(i,j,k) < cloud_base_buf(i,j)) THEN
!
!-----------------------------------------------------------------------
!
! Radar Echo Top is below the analyzed cloud base.
! Using the lifting condensation level as the modified cloud base
! if it is lower than the current buffer value.
!
!-----------------------------------------------------------------------
!
cloud_base_buf(i,j)=MIN(z_lcl(i,j),cloud_base_buf(i,j))
IF(cloud_base_buf(i,j) < zs(i,j,k)) THEN
isearch_base = isearch_base + 1
IF(isearch_base < 50) THEN ! limit log output
WRITE(6,71) i,j,k,zs(i,j,k),cloud_base(i,j) &
,cloud_base_buf(i,j)
71 FORMAT(' Rdr Top < Bse*gp=',3I3,' zs=',f7.0 &
& ,' cld_b=',f7.0,'lcl=',f7.0,' Resolved')
END IF
ELSE ! Probably Unresolved base
WRITE(6,72) i,j,k,zs(i,j,k),cloud_base(i,j) &
,cloud_base_buf(i,j)
72 FORMAT(1X,' **** Prob Unresolved ****'/ &
& 1X,'Rdr Top < Bse*gp=',3I3,' zs=',f7.0 &
& ,' cld_b=',f7.0,' lcl=',f7.0)
IF(cloud_base_buf(i,j) == unlimited_ceiling) THEN
l_unresolved(i,j) = .true.
PRINT*,'Error, no LCL found for grid,',i,j, &
' aborting from INSERTRAD...'
STOP
END IF ! cloud_base(i,j).eq.unlimited_ceiling
GO TO 600
END IF ! cloud_base_buf(i,j) .lt. zs(i,j,k)
END IF ! Blw Cld Base: zs.lt.cloud_base_buf(i,j)
END IF ! At Echo Top: ref(k)>thr & (k.eq.nz .or. ref(kp1)<thr
!
!-----------------------------------------------------------------------
!
! Loop through range of cloud grid levels for this model level
!
!-----------------------------------------------------------------------
!
IF(zs(i,j,k) > cloud_base_buf(i,j)) THEN
! Insert radar if we are above cloud base
cldcv(i,j,k) = radar_cover
insert_count_lvl = insert_count_lvl + 1
insert_count_tot = insert_count_tot + 1
ELSE ! Radar Echo below cloud base
l_below_base = .true.
END IF
IF(l_below_base) THEN
icount_below = icount_below + 1
IF(icount_below <= 50) THEN
WRITE(6,81) i,j,k,zs(i,j,k) &
,cloud_base_buf(i,j)
81 FORMAT(1X,'Rdr < Bse* g.p.:',3I3 &
,' zs(i,j,k)=',f7.0,' cld_base=',f7.0)
END IF
GO TO 600
END IF ! l_below_base =.true.
ELSE ! grid_ref(i,j,k) <= ref_thresh
IF(cldcv(i,j,k) > 0.4.AND.i_lowecho <= 25) THEN
i_lowecho=i_lowecho+1
IF(cldprt) WRITE(6,642) grid_ref(i,j,k),cldcv(i,j,k),i,j,k
642 FORMAT(1X,' Rdr echo', f8.1,'<< Cld cvr',f6.2,' at',3I3)
END IF
GO TO 600
END IF ! grid_ref(i,j,k) > ref_thresh ?
IF (cldprt .AND. MOD(insert_count_tot,100) == 0) THEN
WRITE(6,591) k,icount_radar_lvl &
,insert_count_lvl,insert_count_tot
591 FORMAT(1X,'Inserted radar** k=',i3/ &
' n_rdrl=',i5,' n_insl=',i5,' n_instot=',i5)
END IF
600 CONTINUE
END DO ! k
END DO ! j
END DO ! i
WRITE(6,*)' Total cloud grid points modified by radar = ' &
,insert_count_tot
istatus=1
RETURN
END SUBROUTINE insert_radar
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE INSERT_VIS ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE insert_vis (nx,ny,nz,zs,topo,clouds_3d & 1
,albedo,cld_frac_vis_a &
,vis_rad_thcvr,vis_rad_thdbz &
,istat_radar,radar_ref_3d,ref_base,dbz_max_2d &
,r_missing,sfc_sao_buffer,istatus)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! To process satellite data for clouds and to modify the
! 3d cloud cover array.
! Currently Band 8 (11.2 micron) brightness temps are used with a
! dummy call for the CO2 slicing method.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 04/26/96 (Based on LAPS code of 09/95)
!
! MODIFICATION HISTORY:
!
! 04/26/96 (J. Zhang)
! Modified for the ARPSDAS format.
! Added full documentation.
! 09/02/97 (J. Zhang)
! Added if statements to avoid putting in the reflectivity
! threshold values in the data holes.
! 04/20/98 (J. Zhang)
! Abandoned the cloud analysis grid, using the ARPS grid
! instead.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
INTEGER :: nx,ny,nz
! INPUT/OUTPUT:
REAL :: clouds_3d(nx,ny,nz) ! cloud cover analysis
!
! INPUT:
REAL :: r_missing
REAL :: zs(nx,ny,nz)
REAL :: topo(nx,ny)
!
! INPUT: parameters
REAL :: vis_rad_thcvr ! =0.2, defined in cloud_cv.f
REAL :: vis_rad_thdbz ! =10dbz, defined in cloud_cv.f
REAL :: sfc_sao_buffer ! =800m, defined in cloud_cv.f
!
! INPUT: satellite visible channel data
REAL :: albedo(nx,ny)
REAL :: cld_frac_vis_a(nx,ny)
!
! INPUT: radar data
INTEGER :: istat_radar
REAL :: dbz_max_2d(nx,ny)
REAL :: radar_ref_3d(nx,ny,nz)
REAL :: ref_base
!
! OUTPUT:
INTEGER :: istatus
!
! LOCAL:
INTEGER :: ih_alb(-10:20)
INTEGER :: ih_cf_sat(-10:20) ! Histogram for VIS cf array
INTEGER :: ih_cfin(-10:20) ! Histogram for input cf array
INTEGER :: ih_cfout(-10:20) ! Histogram for output cf array
INTEGER :: ih_cfin_out(-10:20,-10:20) ! Histogram for the comparison
! between input cloud cover
! array and modified cf array.
INTEGER :: ih_cfin_sat(-10:20,-10:20) ! Histogram for the comparison
! between input cloud cover
! array and sat. VIS cf array.
INTEGER :: ih_cmaxin_sat(-10:20,-10:20)
INTEGER :: ih_cmaxout_sat(-10:20,-10:20)
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
REAL :: viscorfrc
PARAMETER (viscorfrc=0.29)
INTEGER :: i,j,k,kl
INTEGER :: n_missing_albedo,n_vis_mod
INTEGER :: i_sat,i_in,i_out,i_cmaxin,i_cmaxout
REAL :: diffin,diffout,diffin_sum,diffout_sum &
,diffin_sumsq,diffout_sumsq
REAL :: cld_frac_vis,cld_frac_in,cld_frac_out
REAL :: cushion
REAL :: cmaxin,cmaxout
INTEGER :: iblank_radar,iset_vis
REAL :: r_present
LOGICAL :: l_prt
!
!-----------------------------------------------------------------------
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
istatus=0
!
!-----------------------------------------------------------------------
!
! Initialize all histogram arrays.
!
!-----------------------------------------------------------------------
!
DO i=-10,20
ih_alb(i) = 0
ih_cf_sat(i) = 0
ih_cfin(i) = 0
ih_cfout(i) = 0
DO j=-10,20
ih_cfin_out(i,j) = 0
ih_cfin_sat(i,j) = 0
ih_cmaxin_sat(i,j) = 0
ih_cmaxout_sat(i,j) = 0
END DO
END DO
!
n_missing_albedo = 0
n_vis_mod = 0 ! # of data points modified by VIS data
diffin_sum = 0. ! sum of diff. between column max. INPUT cld
! fraction and the satellite vis cld frac'n.
diffout_sum = 0. ! sum of diff. between column max. OUTPUT cld
! fraction and the satellite vis cld frac'n.
diffin_sumsq = 0.
diffout_sumsq = 0.
!
!-----------------------------------------------------------------------
!
! Horizontal array loop
!
!-----------------------------------------------------------------------
!
l_prt = .false.
DO i = 1,nx-1
DO j = 1,ny-1
!
kl = nint(albedo(i,j)*10.)
kl = MIN(MAX(kl,-10),20)
ih_alb(kl) = ih_alb(kl) + 1
IF(cld_frac_vis_a(i,j) /= r_missing) THEN
cld_frac_vis = cld_frac_vis_a(i,j)
i_sat = nint(cld_frac_vis*10.)
i_sat = MIN(MAX(i_sat,-10),20)
ih_cf_sat(i_sat) = ih_cf_sat(i_sat) + 1 ! # of data points
! in a VIS cf value catagory
!
!-----------------------------------------------------------------------
!
! Make sure satellite cloud fraction is between 0 and 1
!
!-----------------------------------------------------------------------
!
IF(cld_frac_vis < 0.0) cld_frac_vis = 0.0
IF(cld_frac_vis > 1.0) cld_frac_vis = 1.0
i_sat = nint(cld_frac_vis*10.)
cmaxin = 0.
cmaxout = 0.
iblank_radar = 0
iset_vis = 0
DO k = 1,nz-1
! l_out(1)=k.eq.19.and.i.le.17.and.i.ge.2
! : .and.j.le.43.and.j.ge.36
! l_out(3)=k.eq.26.and.i.le.10.and.i.ge.6
! : .and.j.le.26.and.j.ge.30
! l_prt=l_out(1).or.l_out(3)
cld_frac_in = MIN(clouds_3d(i,j,k),1.0) ! save input cf value
!
!-----------------------------------------------------------------------
!
! Modify the cloud field with the vis input - allow .3 vis err?
! The scheme:
! Above the sao buffer layer, the previoud cloud analysis is
! retained if it is within cld_frac_vis + 0.3.
! Below the layer, the cloud analysis must be smaller than
! cld_frac_vis. If not, reset it to cld_frac_vis.
!
!-----------------------------------------------------------------------
!
IF(zs(i,j,k) > topo(i,j)+sfc_sao_buffer) THEN
cushion = 0.3 ! Allow 0.3 error in VIS cld cvr.
ELSE
cushion = 0.0 ! VIS cld cover is the max. allowed.
END IF
IF(cld_frac_vis < viscorfrc .AND. &
((clouds_3d(i,j,k)-cld_frac_vis) > cushion)) THEN
cld_frac_out = cld_frac_vis ! VIS cf value
!
IF(l_prt) THEN
WRITE(6,621) i,j,k,clouds_3d(i,j,k) &
,radar_ref_3d(i,j,k),dbz_max_2d(i,j) &
,cld_frac_vis_a(i,j) &
,cld_frac_out
621 FORMAT(1X,3I3,' oldcld=',f5.2,' ref=',f8.1,' dbz_m=',f8.1 &
,' viscld=',f5.2,' newcld=',f5.2)
END IF
!
!-----------------------------------------------------------------------
!
! Determine if we need to reconcile VIS with radar
!
!-----------------------------------------------------------------------
!
IF(istat_radar == 1 .AND. dbz_max_2d(i,j) /= r_missing &
.AND. dbz_max_2d(i,j) > ref_base) THEN
! Valid radar echo
IF(cld_frac_out < vis_rad_thcvr) THEN
IF(dbz_max_2d(i,j) < vis_rad_thdbz) THEN
! Blank out Radar, Normal VIS Clearing
iblank_radar = 1
ELSE ! dbz_max_2d(i,j) >= vis_rad_thdbz
cld_frac_out = vis_rad_thcvr ! use radar cf
iset_vis = 1
END IF
END IF
END IF
IF(cld_frac_in - cld_frac_out > .01) THEN
n_vis_mod = n_vis_mod + 1
END IF
clouds_3d(i,j,k) = cld_frac_out ! Modify the output
ELSE ! clouds_3d - cld_frac_vis .le. cushion
cld_frac_out = cld_frac_in ! previous cloud analysis
END IF ! clouds_3d - cld_frac_vis .gt. cushion
!
!-----------------------------------------------------------------------
!
! Update Histograms
!
!-----------------------------------------------------------------------
!
i_in = nint(cld_frac_in*10.)
ih_cfin(i_in) = ih_cfin(i_in) + 1
i_out = nint(cld_frac_out*10.)
ih_cfout(i_out) = ih_cfout(i_out) + 1
ih_cfin_sat(i_in,i_sat) &
= ih_cfin_sat(i_in,i_sat) + 1
ih_cfin_out(i_in,i_out) &
= ih_cfin_out(i_in,i_out) + 1
cmaxin = MAX(cmaxin,cld_frac_in) !col.max of inp cldcvr
cmaxout = MAX(cmaxout,cld_frac_out) !col.max of outp cldcvr
END DO ! k
!
!-----------------------------------------------------------------------
!
! Reconcile VIS with radar
!
!-----------------------------------------------------------------------
!
IF(iblank_radar == 1) THEN ! NO VIS / WEAK ECHO
!
!-----------------------------------------------------------------------
!
! Blank out radar column for this grid point
!
!-----------------------------------------------------------------------
!
IF(cmaxout <= vis_rad_thcvr) THEN
WRITE(6,1) i,j,cmaxout,dbz_max_2d(i,j),cld_frac_vis
1 FORMAT(' VIS_RDR - Blank out radar: cvr/dbz/vis << ' &
,2I3,f8.2,f8.1,f8.2)
ELSE ! Some of the column remains above the VIS threshold
! We are "saved" by the VIS cushion
! May not show up in comparisons
WRITE(6,2) i,j,cmaxout,dbz_max_2d(i,j),cld_frac_vis
2 FORMAT(' VIS_RDR - Blank out radar: cvr/dbz/vis-s >> ' &
,2I3,f8.2,f8.1,f8.2)
END IF
IF (dbz_max_2d(i,j) > ref_base) dbz_max_2d(i,j) = ref_base
DO kl = 1,nz
IF (radar_ref_3d(i,j,kl) > ref_base) radar_ref_3d(i,j,kl) = ref_base
END DO ! kl
ELSE IF (iset_vis == 1) THEN ! NO VIS / STRONG ECHO
!
!-----------------------------------------------------------------------
!
! Cloud cvr has been reset to threshold value above VIS
!
!-----------------------------------------------------------------------
!
IF(cmaxout <= vis_rad_thcvr) THEN
WRITE(6,3) i,j,cmaxout,dbz_max_2d(i,j),cld_frac_vis &
,vis_rad_thcvr
3 FORMAT(' VIS_RDR - Reset vis: cvr/dbz/vis/thr << ' &
,2I4,f5.2,f8.1,2F5.2)
ELSE ! Some of the column remains above the VIS threshold
! We are "saved" by the VIS cushion
! May not show up in comparisons
! Is resetting the VIS perhaps not necessary?
WRITE(6,4)i,j,cmaxout,dbz_max_2d(i,j),cld_frac_vis &
,vis_rad_thcvr
4 FORMAT(' VIS_RDR - Reset vis: cvr/dbz/vis/thr-s >> ' &
,2I4,f8.2,f8.1,2F8.2)
END IF
END IF ! iblank_radar=1
IF(j == ny/2 .AND. cmaxin-cmaxout > 0.1) THEN
WRITE(6,12) i,j,cmaxin,cmaxout
12 FORMAT(1X,'Vismod',2I3,' colcfi=',f5.2,' colcfo=',f5.2)
END IF
i_cmaxin = nint(cmaxin*10.)
i_cmaxout = nint(cmaxout*10.)
ih_cmaxin_sat(i_cmaxin,i_sat) &
= ih_cmaxin_sat(i_cmaxin,i_sat) + 1
ih_cmaxout_sat(i_cmaxout,i_sat) &
= ih_cmaxout_sat(i_cmaxout,i_sat) + 1
diffin = cmaxin - cld_frac_vis
diffout = cmaxout - cld_frac_vis
diffin_sum = diffin_sum + diffin
diffout_sum = diffout_sum + diffout
diffin_sumsq = diffin_sumsq + diffin**2
diffout_sumsq = diffout_sumsq + diffout**2
ELSE ! cld_frac_vis_a(i,j) = r_missing
n_missing_albedo = n_missing_albedo + 1
END IF ! cld_frac_vis_a(i,j) .ne. r_missing
END DO ! i
END DO ! j
WRITE(6,*)
WRITE(6,*)' N_MISSING_ALBEDO = ',n_missing_albedo
WRITE(6,*)' N_VIS_MOD = ',n_vis_mod
WRITE(6,*)
WRITE(6,*)' HISTOGRAMS'
WRITE(6,*)' I Alb CFsat CFin CFout'
DO i = -5,15
WRITE(6,11)i,ih_alb(i),ih_cf_sat(i),ih_cfin(i),ih_cfout(i)
11 FORMAT(1X,i3,4I7)
END DO
WRITE(6,*)
WRITE(6,*)' Input vs. Satellite Cloud Fraction Histogram'
WRITE(6,*)
WRITE(6,*)' X-axis: input cld frac, Y-axis: Satellite cld frac'
WRITE(6,20) (i,i=0,10)
20 FORMAT(1X,3X,11I6)
DO j = 0,10
WRITE(6,21) j,(ih_cfin_sat(i,j),i=0,10)
21 FORMAT(1X,i3,11I6)
END DO
WRITE(6,*)
WRITE(6,*)' Input vs. Output Cloud Fraction Histogram'
WRITE(6,*)
WRITE(6,*)' X-axis: input cld frac, Y-axis: output cld fraction'
WRITE(6,20) (i,i=0,10)
DO j = 0,10
WRITE(6,21) j,(ih_cfin_out(i,j),i=0,10)
END DO
WRITE(6,*)
WRITE(6,*)' Column Max Input vs. Satellite Fraction Histogram'
WRITE(6,*)
WRITE(6,*)' X-axis: column max.input cf, Y-axis: col.max.sat.cf.'
WRITE(6,20) (i,i=0,10)
DO j = 0,10
WRITE(6,21) j,(ih_cmaxin_sat(i,j),i=0,10)
END DO
WRITE(6,*)
WRITE(6,*)' Column Max Output vs. Satellite Fraction Histogram'
WRITE(6,*)
WRITE(6,*)' X-axis: column max.output cf, Y-axis: col.max.sat.cf.'
WRITE(6,20) (i,i=0,10)
DO j = 0,10
WRITE(6,21) j,(ih_cmaxout_sat(i,j),i=0,10)
END DO
r_present = nx*ny - n_missing_albedo
IF(r_present > 0.) THEN ! write stats
WRITE(6,31)diffin_sum/r_present,SQRT(diffin_sumsq/r_present)
31 FORMAT(' VIS STATS: Mean/RMS input residual = ',2F8.3)
WRITE(6,41) diffout_sum/r_present,SQRT(diffout_sumsq/r_present)
41 FORMAT(' VIS STATS: Mean/RMS output residual = ',2F8.3)
END IF
WRITE(6,*)
istatus = 1
RETURN
END SUBROUTINE insert_vis
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE INSERT_IR ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE insert_ir (nx,ny,nz,rlat,rlon,rland_frac,cvr_snow & 1,5
,topo,zs,z_lcl,temp_3d,p_3d &
,t_sfc_k,t_gnd_k,cldcv_sao &
,solar_alt,solar_ha,solar_dec &
,tb8_k,tb8_cold_k,cldtop_m_tb8,cldtop_m &
,grid_spacing_m,sfc_sao_buffer &
,cldcv,istatus)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! To process satellite data for clouds and to modify the
! 3d cloud cover array.
! Currently Band 8 (11.2 micron) brightness temps are used.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 04/1996 Based on the LAPS cloud analysis code (Steve Albers,
! 09/1995)
!
! MODIFICATION HISTORY:
!
! 04/26/96 J. Zhang
! Modified for the ARPSDAS format.
! Added full documentation.
! 07/19/96 J. Zhang
! Added the quality check part to deal with the tall
! and steep cloud towers.
! 07/24/96 J. Zhang
! Added the quality check for cases when the cloud top
! is higher than the model top boundary
! 11/01/96 J. Zhang
! Added the rawinsonde data for determing the cloud
! top height for the low clouds.
! 03/18/97 J. Zhang
! Cleanup the code and implemented for the official
! arps4.2.4 version
! 08/06/97 J. Zhang
! Change adascld24.inc to adascld25.inc
! 09/09/97 J. Zhang
! Fixed a bug when calling COMPARE_RAD. Further cleanup.
! 09/10/97 J. Zhang
! Lifting condensation level is now an input argument.
! Change adascld25.inc to adascld26.inc
! 04/20/98 J. Zhang
! Abandoned the cloud analysis grid, using the ARPS grid
! instead.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! Include files:
INCLUDE 'phycst.inc'
INCLUDE 'adas.inc'
!
!-----------------------------------------------------------------------
!
INTEGER :: nx,ny,nz ! ARPS grid size
! INCLUDE: ( from adas.inc)
! real r_missing
!
! INPUT/OUTPUT:
REAL :: cldcv(nx,ny,nz) ! 3D cldcv analx after useing sat.data
!
! INPUT: general
REAL :: grid_spacing_m
!
! INPUT: for model grid geometry
REAL :: topo(nx,ny)
REAL :: rlat(nx,ny),rlon(nx,ny) ! Lat. and lon. of the grid pt.
REAL :: zs(nx,ny,nz) ! Phys. ht (m) at model grid point.
REAL :: z_lcl(nx,ny) ! Lifting condensation level (MSL)
REAL :: temp_3d(nx,ny,nz) ! temp. analysis on model grid
REAL :: p_3d(nx,ny,nz) ! pres. analysis on model grid
!
! INPUT: for model grid sfc characteristic fields
REAL :: rland_frac(nx,ny) ! land coverage fraction at a g.p.
REAL :: cvr_snow(nx,ny) ! snow coverage at a grid point.
REAL :: solar_alt(nx,ny) ! solar altitude angle
REAL :: solar_ha(nx,ny) ! solar hour angle
REAL :: solar_dec
!
! INPUT: for model grid analysis fields
REAL :: t_sfc_k(nx,ny) ! sfc air temp.
!
! INPUT: for SAO
REAL :: sfc_sao_buffer ! No clearing cloud by sat. below
! this ht.(m AGL) (hence letting
! SAOs dominate)
REAL :: cldcv_sao(nx,ny,nz) ! 3D Cloud cover array
!
! OUTPUT:
INTEGER :: istatus
REAL :: t_gnd_k(nx,ny) ! ground skin temp.
REAL :: tb8_k(nx,ny) ! Obs. sate. band8 bright. temp.
REAL :: tb8_cold_k(nx,ny) ! Cold filtered band8 bright. temp.
REAL :: cldtop_m(nx,ny) ! Adj. Sat. cloud top height (m)
REAL :: cldtop_m_tb8(nx,ny) ! Sat. cld top ht (m) from band 8 data
!
! Local: factors and parameters
REAL :: sfc_ir_buffer !No adding cld by sat. below this ht.
! (m AGL) (hence letting SAOs dominate)
PARAMETER (sfc_ir_buffer = 3000.)
REAL :: thk_def !Def. cld thkness inserted by sat.data
PARAMETER (thk_def = 1500.)
REAL :: thr_sao_cvr ! cldcvr thres. in evaluating presence
! of SAO cld layers
PARAMETER (thr_sao_cvr = 0.1)
REAL :: thresh2 ! Thres.for IR cloud detection
PARAMETER (thresh2 = 3.5) ! (Tsfc - T_IR) Were 5K and 15K also
!
! LOCAL: for band 8 brightness temp.
REAL :: tb8_est ! estimated tb8 temp. by using
! cld cvr analysis
! LOCAL: for interpolations
REAL :: zs_1d(nz)
REAL :: t_1d(nz) ! 3D temperature analysis on model grid
REAL :: p_1d(nz) ! pres. analysis on model grid
!
! LOCAL: for Controling search box for SAO analyzed data
INTEGER :: idelt(3)
INTEGER :: jdelt(3)
!
! LOCAL: for satellite cloud presence and cloud top height
LOGICAL :: l_tb8,l_cloud_present
REAL :: cldtop_m_old
INTEGER :: nlyr ! for iterative adj. of cld cvr field
!
! FUNCTIONS:
REAL :: t_ground_k
REAL :: temp_to_rad
REAL :: rad_to_temp
REAL :: band8_cover
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k,i_sao,j_sao
INTEGER :: il,ih,jl,jh,ii,jj
INTEGER :: n_no_sao1,n_no_sao2,n_no_sao3
INTEGER :: i_reset_base
REAL :: htbase,htbase_init,ht_sao_base,ht_cloud
PARAMETER (ht_cloud = 2000.0)
INTEGER :: i_delt,idelt_max,idelt_index,jdelt_index
REAL :: sat_cover,temp_thresh,cldcv_above &
,cover,cover_new,buffer
REAL :: tmin
INTEGER*4 nidelt,njdelt
DATA nidelt/3/,njdelt/3/
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
! Print some band 8 brightness temp. samples.
!
!-----------------------------------------------------------------------
!
WRITE(6,*) 'Insert satellite IR data routines called.'
WRITE(6,*)
!
il=MAX(1,nx/2-5)
ih=MIN(nx,nx/2+5)
jl=MAX(1,ny/2-5)
jh=MIN(ny,ny/2+5)
WRITE(6,*) ' Band 8 brightness temp values in the mid-domain:'
WRITE(6,601) (i,i=il,ih)
601 FORMAT(/1X,3X,11(2X,i2,2X))
WRITE(6,603) (j,(tb8_k(i,j),i=il,ih),j=jh,jl,-1)
603 FORMAT(1X,i3,11F6.1)
!
!-----------------------------------------------------------------------
!
! Define a box for searching SAO cloud base
!
!-----------------------------------------------------------------------
!
idelt_max = nint(50000. / grid_spacing_m)
idelt(1) = -idelt_max
idelt(2) = 0
idelt(3) = +idelt_max
jdelt(1) = 0
jdelt(2) = +idelt_max
jdelt(3) = -idelt_max
!
!-----------------------------------------------------------------------
!
! First guess conversion from cloud height grid to ADAS grid
! This has to err slightly on the high side
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
!
! QC check on band 8 (11.2 mm) brightness temps
!
!-----------------------------------------------------------------------
!
DO j = 1,ny
DO i = 1,nx
IF( tb8_k(i,j) < 173. .OR. tb8_k(i,j) > 350.) tb8_k(i,j)=-999.
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Calculate cold filtered temperatures
!
!-----------------------------------------------------------------------
!
i_delt = MAX(1,nint(grid_spacing_m/10000.))
DO j = 1,ny
jl = MAX(1 ,j-i_delt)
jh = MIN(ny,j+i_delt)
DO i = 1,nx
il = MAX(1 ,i-i_delt)
ih = MIN(nx,i+i_delt)
tb8_cold_k(i,j) = 1.0E15
DO jj = jl,jh,i_delt
DO ii = il,ih,i_delt
IF (tb8_k(ii,jj) > 0.) &
tb8_cold_k(i,j) = MIN(tb8_cold_k(i,j),tb8_k(ii,jj))
END DO ! ii
END DO ! jj
IF(tb8_cold_k(i,j) > 350.) tb8_cold_k(i,j) = -999.
END DO ! i
END DO ! j
!
!-----------------------------------------------------------------------
!
! Calculate ground temperature (for now equate to sfc air temp)
!
!-----------------------------------------------------------------------
!
WRITE(6,*) 'Computing ground skin temperature'
DO j = 1,ny-1
DO i = 1,nx-1
IF ( rland_frac(i,j) >= 0.5) THEN
t_gnd_k(i,j) = t_ground_k(t_sfc_k(i,j),solar_alt(i,j) &
,solar_ha(i,j),solar_dec &
,rlat(i,j),cvr_snow(i,j) &
,r_missing,i,j,nx,ny)
ELSE ! water environment
t_gnd_k(i,j) = t_sfc_k(i,j)
END IF
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Check number of points thrown out as a function of offset to check
! for IR navigation errors. This is only a diagnostic process,
! does not change anything.
!
!-----------------------------------------------------------------------
!
CALL correlation
(t_gnd_k,tb8_k,thresh2,nx,ny)
!
!-----------------------------------------------------------------------
!
! Initializes routine
!
!-----------------------------------------------------------------------
!
n_no_sao1 = 0 ! # of g.p with sat.cld but no SAO cld at the grid pt
n_no_sao2 = 0 ! # of g.p with sat.cld but no SAO cld in the box
n_no_sao3 = 0 ! # of pts with sat.cldtop lower than SAO cld base.
i_reset_base = 1 ! # of pts that sate. ceiling being resetted
!
!-----------------------------------------------------------------------
!
WRITE(6,*) 'Find cloud_top for each grid point.'
DO j=1,ny-1
DO i=1,nx-1
IF(tb8_k(i,j) > 0.) THEN
DO k=1,nz
zs_1d(k) = zs(i,j,k)
t_1d(k) = temp_3d(i,j,k)
p_1d(k) = p_3d(i,j,k)
END DO
tmin=temp_3d(i,j,2)
DO k=2,nz-1
tmin=MIN(tmin,temp_3d(i,j,k))
END DO
!
!-----------------------------------------------------------------------
!
! Calculate cloud top height from Band 8 method
!
!-----------------------------------------------------------------------
!
CALL cloud_top
(nx,ny,nz, &
i,j,zs_1d,t_1d,p_1d,z_ref_lcl,z_lcl(i,j), &
topo(i,j),tmin,r_missing, &
tb8_k(i,j),t_gnd_k(i,j),thresh2, &
cldtop_m_tb8(i,j),cldtop_m(i,j), &
l_tb8,l_cloud_present,sat_cover)
!
!-----------------------------------------------------------------------
!
! Modify those levels where the satellite shows warmer than the
! calculated brightness temp from the analysis of SAO/Pireps
!
!-----------------------------------------------------------------------
!
DO k = nz-1,1,-1
IF (cldcv(i,j,k) > 0.04) THEN ! Efficiency test
!
!-----------------------------------------------------------------------
!
! Estimate the brightness temperature using the cloud cover
! field.
!
!-----------------------------------------------------------------------
!
IF (cldcv(i,j,k) /= r_missing) THEN
tb8_est = temp_to_rad(temp_3d(i,j,k)) &
* cldcv(i,j,k) + temp_to_rad(t_gnd_k(i,j)) &
* (1.-cldcv(i,j,k))
tb8_est = rad_to_temp(tb8_est) ! estimated tb8 temp.
! tb8_est_a = temp_3d(i,j,k) * cldcv(i,j,k)
! : + t_gnd_k(i,j) * (1.-cldcv(i,j,k))
ELSE
tb8_est = t_gnd_k(i,j)
END IF
!
!-----------------------------------------------------------------------
!
! Test if clouds detected by SAO/PIREP should have been
! detected by the satellite (if satellite is warmer than analysis)
!
!-----------------------------------------------------------------------
!
IF (tb8_k(i,j) > tb8_est) THEN !seems too much SAO cld
! Don't touch points within buffer of surface
IF (zs(i,j,k)-topo(i,j) > sfc_sao_buffer) THEN
! Does satellite still imply at least some cloud?
IF(t_gnd_k(i,j)-tb8_k(i,j) > thresh2) THEN ! Some cloud
IF(cldcv(i,j,k) > 0.9) THEN
cldcv(i,j,k)=.01 ! Lower top of solid cld
ELSE ! Cover < 0.9, correct it
cldcv(i,j,k) = band8_cover( tb8_k(i,j) &
,t_gnd_k(i,j),temp_3d(i,j,k))
cldcv(i,j,k) = MAX(0.0,MIN(1.0,cldcv(i,j,k)))
END IF
ELSE !tg-tb<8 Band 8 nearly matches grnd, clear it
!
!-----------------------------------------------------------------------
!
! Insure that "black (or grey) stratus" is not present
!
!-----------------------------------------------------------------------
!
temp_thresh = MIN(t_gnd_k(i,j),t_sfc_k(i,j)-10.0)
IF(temp_3d(i,j,k) < temp_thresh)THEN
cldcv(i,j,k)=.01 ! not in inversion, clear it out
END IF
END IF ! tg-tb>8 IR signature present
END IF ! cldht-topo.gt.sfc_sao_buffer is .true.
END IF ! tb8_k(i,j).gt.tb8_est
END IF ! Current Cloud Cover is significant (> .04)
END DO ! k (for clearing clouds)
!
!-----------------------------------------------------------------------
!
! Insert satellite clouds
!
!-----------------------------------------------------------------------
!
IF(l_cloud_present) THEN ! Insert satellite clouds
!
!-----------------------------------------------------------------------
!
! Set initial satellite cloud base.
!
!-----------------------------------------------------------------------
!
htbase_init=cldtop_m(i,j) - thk_def
htbase = htbase_init
!
!-----------------------------------------------------------------------
!
! Locate lowest SAO cloud base
!
!-----------------------------------------------------------------------
!
ht_sao_base = 1E30
cldcv_above = cldcv_sao(i,j,nz-1)
DO k=nz-2,1,-1
IF (cldcv_sao(i,j,k) <= thr_sao_cvr &
.AND. cldcv_above > thr_sao_cvr) THEN
ht_sao_base = zs(i,j,k+1)
END IF
cldcv_above = cldcv_sao(i,j,k)
END DO ! k
i_sao = i
j_sao = j
!jz IF (ht_sao_base.eq.1e30) THEN ! Srch for nearby SAO cld lyrs
IF (ht_sao_base >= 1E20) THEN ! Srch for nearby SAO cld lyrs
! because the sat.says cld
! and the SAO doesn't
n_no_sao1 = n_no_sao1 + 1 ! Sat.cld but no SAO cld at same pt.
DO jdelt_index = 1,njdelt
jj = j + jdelt(jdelt_index) ! jdelt: 0,5,-5
DO idelt_index = 1,nidelt
ii = i + idelt(idelt_index) ! idelt: -5,0,5
IF(ii >= 1.AND.ii <= nx-1 .AND. jj >= 1.AND.jj <= ny-1) THEN
cldcv_above = cldcv_sao(ii,jj,nz-1)
DO k = nz-2,1,-1
IF (cldcv_sao(ii,jj,k) <= thr_sao_cvr &
.AND. cldcv_above > thr_sao_cvr) THEN
ht_sao_base = zs(i,j,k+1)
END IF
cldcv_above = cldcv_sao(ii,jj,k)
END DO ! k
!jz if(ht_sao_base .ne. 1e30)then
IF(ht_sao_base < 1E20)THEN
i_sao = ii
j_sao = jj
goto 201
END IF
END IF ! In bounds
END DO ! IDELT_INDEX
END DO ! JDELT_INDEX
END IF ! ht_sao_base.eq.1e30
!jz201 IF (HT_SAO_BASE .EQ. 1E30) THEN ! Sat. cld but no SAO cld
201 IF (ht_sao_base >= 1E20) THEN ! Sat. cld but no SAO cld
n_no_sao2 = n_no_sao2 + 1 ! even in neighbor points.
cover=sat_cover
htbase_init = ht_sao_base
IF(tb8_k(i,j)-t_gnd_k(i,j) < -21.) THEN ! We more likely
! have a cloud
buffer = 2100.
ELSE
buffer = sfc_ir_buffer ! Weed out IR tops < ~5000m AGL
END IF
!
!-----------------------------------------------------------------------
!
! Calculate new cloud top and cover
!
!-----------------------------------------------------------------------
!
cldtop_m_old = cldtop_m(i,j)
!
CALL cloud_top
(nx,ny,nz, &
i,j,zs_1d,t_1d,p_1d,z_ref_lcl,z_lcl(i,j), &
topo(i,j),tmin,r_missing, &
tb8_cold_k(i,j),t_gnd_k(i,j),thresh2, &
cldtop_m_tb8(i,j),cldtop_m(i,j), &
l_tb8,l_cloud_present,sat_cover)
!
!-----------------------------------------------------------------------
!
! Change to cover
!
!-----------------------------------------------------------------------
!
cover=band8_cover(tb8_k(i,j),t_gnd_k(i,j),tb8_cold_k(i,j))
htbase = MAX(topo(i,j)+buffer, cldtop_m(i,j)-thk_def )
i_reset_base = i_reset_base +1
IF (htbase > cldtop_m(i,j)) THEN
n_no_sao3 = n_no_sao3 + 1 ! Sat.cld, but no SAO cld,
! & sat.cld is too low.
ELSE IF(i_reset_base/50*50 == i_reset_base) THEN
WRITE(6,611) i,j
611 FORMAT(/1X,' Correction at point(',2I2 &
,') because there is low sat.cld,' &
,' but no SAO cld.')
WRITE(6,612,ERR=212) tb8_k(i,j),tb8_cold_k(i,j) &
,cldtop_m_old,cldtop_m(i,j),cover
612 FORMAT(1X,'tb=',f8.1,' tb_cold=',f8.1, &
' ctop=',f9.0,' ctop_cold=',f9.0,' cvr=',f5.2/)
212 END IF
ELSE IF (ht_sao_base > cldtop_m(i,j)) THEN ! Sat.cld, nut no
! SAO cld at same pt. Do have
! SAO cld in nearby pt. AND
! Sat.top is below ceiling
cover=sat_cover
htbase_init = ht_sao_base ! using SAO cld base
htbase = htbase_init
cldtop_m_old = cldtop_m(i,j)
cldtop_m(i,j) = htbase_init + thk_def ! correct sat. cldtop
!
!-----------------------------------------------------------------------
!
! Find a thinner value for cloud cover consistent with the new
! higher cloud top and the known brightness temperature.
! Note that cover is not really used here as an input
!
!-----------------------------------------------------------------------
!
CALL correct_cover
(cover,cover_new &
,cldtop_m_old,cldtop_m(i,j),i,j,nx,ny,nz &
,zs_1d,t_1d,tb8_k(i,j),t_gnd_k(i,j) &
,istatus)
!
IF (istatus /= 1) THEN
WRITE(6,*)' Error in correct_cover'
RETURN
END IF
cover = cover_new
ELSE ! Normal use of satellite data
! There is a ht_sao_base below cldtop_m in the area
! near the grid pt.
cover=sat_cover
!
!-----------------------------------------------------------------------
!
! Locate SAO cloud base below satellite cloud top, modify
! satellite cloud base. Highest SAO ceiling within default
! thickness range of satellite layer is used.
!
!-----------------------------------------------------------------------
!
DO k=nz-1,1,-1
IF (zs(i,j,k) >= htbase_init .AND. &
zs(i,j,k) <= cldtop_m(i,j)) THEN
IF (cldcv_sao(i_sao,j_sao,k) <= thr_sao_cvr .AND. &
cldcv_sao(i_sao,j_sao,k+1) > thr_sao_cvr) THEN
!c We have an SAO base
htbase = zs(i,j,k+1)
!c If SAO (hence satellite) base is above the satellite
!c cloud top, lower the satellite base by one grid level
IF (htbase > cldtop_m(i,j)) htbase = zs(i,j,k)
GO TO 301
END IF ! We have an SAO base
END IF ! in satellite layer
END DO ! k
END IF ! HT_SAO_BASE .EQ. 1E30
! No SAO cloud base in the area near the grid pt.
301 IF (htbase /= htbase_init .AND. &
i_reset_base/50*50 == i_reset_base) THEN
WRITE(6,*)' Satellite ceiling reset by SAO.'
WRITE(6,660) i,j,htbase,htbase_init,cldtop_m(i,j)
660 FORMAT(1X,'i/j=',2I3,' htbase_new/old=',2F7.0, &
' cldtop_ir=',f7.0)
END IF
!
!-----------------------------------------------------------------------
!
! Add satellite cloud to array
!
!-----------------------------------------------------------------------
!
DO k=nz,1,-1
IF (zs(i,j,k) >= htbase .AND. &
zs(i,j,k) <= cldtop_m(i,j)) & ! in satellite layer
cldcv(i,j,k)=cover
END DO
END IF ! l_cloud_present (Cloudy)
END IF ! non-missing IR data
END DO ! i=1,nx
END DO ! j=1,ny
!
istatus = 1
!
!-----------------------------------------------------------------------
!
! Write stats on Band 8 (11.2mm) methods
!
!-----------------------------------------------------------------------
!
WRITE(6,*)' n_no_sao (1/2/3) = ',n_no_sao1,n_no_sao2,n_no_sao3
CALL compare_rad
(nx,ny,nz,clddiag,r_missing,zs,temp_3d &
,cldcv,t_sfc_k,t_gnd_k,tb8_k &
,cvr_snow,nlyr)
!
!-----------------------------------------------------------------------
! 999 RETURN
END SUBROUTINE insert_ir
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE CORRELATION ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE correlation(t,tb8_k,thresh,ni,nj) 1
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! Checking the navigation of the IR satellite data
! It's only a diagnostic procedure.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Dan Birkenheuer?)
! 09/95.
!
! MODIFICATION HISTORY:
!
! 04/29/96 J. Zhang
! Modified for the ARPSDAS format.
! Added full documentation.
!
! 05/01/98 Keith Brewster
! Added check for missing data.
!
!-----------------------------------------------------------------------
!
! Variable Declaration
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
! INPUT:
INTEGER :: ni,nj ! Model grid size
REAL :: t(ni,nj) ! ground skin temperature
REAL :: tb8_k(ni,nj) ! satellite IR band 8 brightness temperature
REAL :: thresh ! threshold define the bias criteria
!
! LOCAL:
INTEGER :: ibox
PARAMETER (ibox = 3)
INTEGER*4 i_corr_array(-ibox:ibox,-ibox:ibox)
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: min_count,ioff,joff,i,j,ii,jj,icount &
,ioff_min,joff_min
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
WRITE(6,*)
WRITE(6,*)' Checking Navigation of IR satellite, thresh = ' &
,thresh
min_count = 999999
DO joff = -ibox,ibox
DO ioff = -ibox,ibox
icount = 0
DO j = 1,nj-1
jj = MAX(MIN(j+joff,nj-1),1)
DO i = 1,ni-1
ii = MAX(MIN(i+ioff,ni-1),1)
IF(tb8_k(ii,jj) > 0. .AND. (t(i,j) - tb8_k(ii,jj)) > thresh) &
icount = icount+1 ! Clouds Indicated
END DO ! i
END DO ! j
IF(icount < min_count)THEN
min_count = icount
ioff_min = ioff
joff_min = joff
END IF
i_corr_array(ioff,joff) = icount
END DO ! IOFF
END DO ! JOFF
WRITE(6,99)
99 FORMAT(//1X,' Number of cloudy points indicated' &
,' by offseting tb8:')
WRITE(6,100) (i,i=-ibox,ibox)
100 FORMAT(1X,'joff:ioff',7I5)
DO j = ibox,-ibox,-1
WRITE(6,101) j,(i_corr_array(i,j),i=-ibox,ibox)
101 FORMAT(1X,1X,i2,5X,7I5)
END DO
WRITE(6,*)
WRITE(6,201) min_count,ioff_min,joff_min
201 FORMAT(' Min. of',i5,' pts flagged with an offset of',2I4/)
RETURN
END SUBROUTINE correlation
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE CLOUD_TOP ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE cloud_top(nx,ny,nz, & 2
i,j,zs_1d,t_1d,p_1d,z_ref_lcl,z_lcl, &
topo,tmin,r_missing, &
tb8_k,t_gnd_k,thresh2, &
cldtop_m_tb8,cldtop_m, &
l_tb8,l_cloud_present,sat_cover)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! This routine computes the cloud top height given a band 8
! brightness temperature and 3D fields of temp and height.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 04/96 Based on the LAPS cloud analysis code (09/95 Dan Birkenheuer)
!
! MODIFICATION HISTORY:
!
! 04/26/96 (J. Zhang)
! Modified for the ARPSDAS format.
! Added full documentation.
!
! 11/01/96 (J. Zhang)
! Added a scheme for calculation of cloud top height of low clouds
! (e.g., persistent stratocumulus), where temperature inversion
! may exist and the simple matching scheme may fail.
! Reference:
! Macpherson et al., 1996: The impact of MOPS moisture data in
! the U.K. Meteorological Office mesoscale data assimilation
! scheme. MWR, vol. 124, 1746-1766
!
! 09/10/97 (J. Zhang)
! Lifting condensation level is input through calling
! argument.
!
!-----------------------------------------------------------------------
!
! Variable Declarition
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! For tb8 method
!
!-----------------------------------------------------------------------
!
! INPUT:
INTEGER :: nx,ny,nz ! The model grid size
!
! INPUT: Vertical 1D arrays
REAL :: zs_1d(nz) ! physical height (m) at scalar points
REAL :: t_1d(nz) ! 3D temperature analysis on model grid
REAL :: p_1d(nz) ! pres. analysis on model grid
!
! INPUT: At grid point (i,j)
INTEGER :: i,j ! grid point location indices
REAL :: z_lcl ! Lifting condensation level at i,j
REAL :: tb8_k ! band 8 beightness temperature(K)
REAL :: t_gnd_k ! gound temperature
REAL :: topo ! terrain height at the grid point
!
! INPUT: Constants
REAL :: tmin
REAL :: r_missing ! missing data flag value
REAL :: thresh2 ! Input from parent routine (=8K)
REAL :: z_ref_lcl ! ref. level for computing LCL
!
! OUTPUT:
LOGICAL :: l_cloud_present ! "cloudy" indicated by sate. IR data?
LOGICAL :: l_tb8 ! "cloudy" indicated by band 8 data?
REAL :: cldtop_m_tb8 ! cld top height(m) obtained from tb8_k
REAL :: cldtop_m ! cld top height(m) obtained from IR data
REAL :: sat_cover ! cloud fraction obtained from IR data
!
! LOCAL:
REAL :: gamma_s ! ref. moist adiabatic lapse rate
!
! LOCAL: For the conceptual model for the cloud top
REAL :: t_base,p_base_pa,zbase,ztop,dzinc,zht
PARAMETER(dzinc=100.0)
REAL :: p,press,temp,eso,dlvdt,des,dtz,rl,es
REAL :: tb8_loc
INTEGER :: nlevel,nlm1
!
! CONSTANTS:
REAL :: gamma_d ! dry adiabatic lapse rate (K/m)
PARAMETER (gamma_d = 9.8/1004.0)
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: kl,j1
REAL :: arg,frac_k,frac_z,z_ref,t_ref
!
!-----------------------------------------------------------------------
!
! Include files.
!
INCLUDE 'phycst.inc'
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
! Define constants
!
!-----------------------------------------------------------------------
!
dlvdt=-2.3693E+3 ! J/kg/K
eso=610.78 ! pa
!
!-----------------------------------------------------------------------
!
! This section finds the cloud top using Band 8 data
!
!-----------------------------------------------------------------------
!
cldtop_m_tb8 = r_missing ! or zeros
l_tb8 = .false.
!
IF (tb8_k - t_gnd_k < -thresh2) THEN ! probably clds
l_tb8 = .true.
IF (tb8_k < 253.15) GO TO 300 ! Using scan&match method
!
!-----------------------------------------------------------------------
!
! When Tb >= -20 deg C, find the cloud top height using a
! conceptual model presented in Macpherson et al. (1996).
!
!-----------------------------------------------------------------------
!
zbase = z_lcl
IF (zbase >= zs_1d(nz-1)) GO TO 300
! Using scanning & matching method
!
!-----------------------------------------------------------------------
!
! Find the model pressure and temperature at the lifting
! condensation level.
!
!-----------------------------------------------------------------------
!
DO kl = 2,nz-1
z_ref = z_ref_lcl + topo
IF (z_ref <= zs_1d(kl)) THEN
frac_z = (z_ref-zs_1d(kl-1))/(zs_1d(kl)-zs_1d(kl-1))
t_ref = t_1d(kl-1) + frac_z * (t_1d(kl) - t_1d(kl-1))
GO TO 50
END IF
END DO ! kl
PRINT*,'Error for Tbase,aborting....'
STOP
50 CONTINUE
t_base = t_ref - (z_lcl -z_ref)*gamma_d
!
DO kl = 2,nz-1
IF (zbase <= zs_1d(kl)) THEN
frac_z = (zbase-zs_1d(kl-1))/(zs_1d(kl)-zs_1d(kl-1))
arg = ALOG(p_1d(kl-1)) &
+ frac_z * (ALOG(p_1d(kl))-ALOG(p_1d(kl-1)))
p_base_pa = EXP(arg)
GO TO 100
END IF
END DO ! kl
PRINT*,'Error for Zbase,aborting....'
STOP
100 CONTINUE
IF (t_base <= tb8_k) GO TO 300
! Using scanning & matching method
!
!-----------------------------------------------------------------------
!
! Find the cloud top height, which is the level where the temp.
! reaches the satellite brightness temperature throught the moist
! adiabatic cooling process.
!
!-----------------------------------------------------------------------
!
temp = t_base ! temp = t_base_k
press = p_base_pa
gamma_s = 0.004 ! K/m
nlevel = (temp -tb8_k)/gamma_s/dzinc ! a guess for cloud top
IF(nlevel < 0) THEN
PRINT*,'Error in zlevel. aborting....'
PRINT*,' nlevel=',nlevel,' temp=',temp,' gam=',gamma_s, &
' dzinc=',dzinc,' tb8=',tb8_k
STOP
END IF
nlm1 = nlevel
IF(nlm1 < 1) nlm1=1
zht = zbase
!
DO j1=1,nlm1
rl = lathv+(273.15-temp)*dlvdt ! Lv as func of Temp.
arg = rl*(temp-273.15)/273.15/temp/rv
es = eso*EXP(arg) ! satur. vapor press.
arg = -g*dzinc/rd/temp
p = press*EXP(arg) ! hydrosta. press.decrease
!
!-----------------------------------------------------------------------
!
! Calculate saturated adiabatic lapse rate
!
!-----------------------------------------------------------------------
!
des = es*rl/temp/temp/rv
dtz = -g*((1.0+0.621*es*rl/(press*rd*temp))/ &
(cp+0.621*rl*des/press))
IF(ABS(dtz) < 1.0E-15) THEN
PRINT*,' Zero dt/dz:',dtz,' g=',g,' es=',es,' press=',press
PRINT*,'temp=',temp,' cp=',cp,' rl=',rl,' des=',des
STOP
END IF
zht = zht+dzinc ! moist adiabatic ascent every 100m
temp = temp+dtz*dzinc
IF(temp <= tb8_k) THEN ! Cloud top is found
ztop = zht + (tb8_k-temp)/dtz
GO TO 150
END IF
press = p
END DO ! j=1,nlm1
ztop = zht + (tb8_k-temp)/dtz
150 CONTINUE
!
!-----------------------------------------------------------------------
!
! Apply quality check to the cloud top height.
!
!-----------------------------------------------------------------------
!
IF(ztop <= zs_1d(1)) THEN
PRINT*,' Error, ztop for cloud top model is out of' &
,' bound at grid pt(',i,j,').'
PRINT*,' ztop=',ztop,' topo=',topo, &
' z_bottom=',zs_1d(1)
PRINT*,'aborting...'
STOP
END IF
!
IF(ztop > zs_1d(nz-1)) THEN
PRINT*,' Warning, ztop for cloud top model is out of' &
,' bound at grid pt(',i,j,').'
PRINT*,' ztop=',ztop,' topo=',topo &
,' z_top=',zs_1d(nz-1)
PRINT*,' ztop is set to the highest model level'
cldtop_m_tb8 = zs_1d(nz-1)
GO TO 900
END IF
cldtop_m_tb8 = ztop
GO TO 900
!
300 CONTINUE
!
!-----------------------------------------------------------------------
!
! When Tb < -20 deg C, use the scheme that finds the cloud top
! height by scanning the model temperature profile for a value
! matching tb8.
!
!-----------------------------------------------------------------------
!
tb8_loc=tb8_k
IF(tb8_k <= tmin) THEN
PRINT*,' Warning: cloud top colder than tmin in column'
WRITE(6,*) ' i j tb8_k t_top'
WRITE(6,600) i,j,tb8_k,t_1d(nz-1)
600 FORMAT(1X,2I3,2F8.2)
PRINT*,' Cloud top temperature is set to tmin'
tb8_loc=tmin
END IF
!
DO kl = nz-2,1,-1
!
!-----------------------------------------------------------------------
!
! Find the lowest temp. crossing point in the model temperature
! profile.
!
!-----------------------------------------------------------------------
!
IF( (t_1d(kl)-tb8_loc) * (t_1d(kl+1)-tb8_loc) <= 0.) THEN ! Crossing Pt
frac_k = (tb8_loc - t_1d(kl)) &
/ (t_1d(kl+1) - t_1d(kl))
arg = zs_1d(kl) + frac_k * (zs_1d(kl+1)-zs_1d(kl))
IF(arg >= topo) THEN
cldtop_m_tb8 = arg
ELSE
WRITE(6,*)' Warning: Cloud Top Below Ground - flagged'
WRITE(6,601)
601 FORMAT(1X,' i j kl tb8_loc t_abv t_blw frac' &
,' hgt_m topo ctop_8 ')
WRITE (6,602) i,j,kl,tb8_loc,t_1d(kl+1) &
,t_1d(kl),frac_k,arg,topo,cldtop_m_tb8
602 FORMAT(1X,3I3,3F7.2,f5.2,3F8.0)
END IF
END IF ! Crossing point found
END DO ! kl
ELSE ! No clouds according to SATELLITE (Band 8 - 11.2mm)
l_tb8 = .false.
END IF ! tb8_k-t_gnd_k .lt. -thresh2
!
!-----------------------------------------------------------------------
!
! Set variables
!
!-----------------------------------------------------------------------
!
900 CONTINUE
l_cloud_present = l_tb8
cldtop_m = cldtop_m_tb8
sat_cover = 1.0
RETURN
END SUBROUTINE cloud_top
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE CORRECT_COVER ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE correct_cover(cover_in,cover_new_f & 1,2
,cldtop_old,cldtop_new,i,j,nx,ny,nz &
,zs_1d,t_1d,tb8_k,t_gnd_k &
,istatus)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! Find a thinner value for cloud cover consistent with the new
! higher cloud top and the known brightness temperature.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Dan Birkenheuer?)
! 09/95.
!
! MODIFICATION HISTORY:
!
! 04/29/96 (J. Zhang)
! Modified for the ARPSDAS format.
! Added full documentation.
!
!-----------------------------------------------------------------------
!
! Variable Declaration
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
! INPUT:
INTEGER :: i,j ! grid point index
INTEGER :: nx,ny,nz ! grid size
REAL :: t_1d(nz) ! temp. analysis field
REAL :: zs_1d(nz) ! phycisal heights (m) for a column of scalar
! grid points
REAL :: tb8_k ! satellite band 8 brightness temp.
REAL :: t_gnd_k ! ground skin temp.
REAL :: cover_in ! cloud cover before correction
REAL :: cldtop_old ! cloud top height before correction
!
! OUTPUT:
INTEGER :: istatus
REAL :: cover_new_f ! cloud cover after correction
REAL :: cldtop_new ! cloud top height after correction
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
REAL :: z_temp,temp_old,temp_new,frac
REAL :: band8_cover ! a function
REAL :: cover_old,cover_new
INTEGER :: iz_temp
INTEGER :: iwrite
DATA iwrite /0/
SAVE iwrite
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!-----------------------------------------------------------------------
!
! Find Temperature of old cloud top
!
!-----------------------------------------------------------------------
!
CALL hgt_to_zk
(cldtop_old,z_temp,nz,zs_1d,istatus)
IF(istatus /= 1)THEN
PRINT*,' Old cldtop is out of domain range:', z_temp
PRINT*,' Old cldtop=',cldtop_old,' zs range from',zs_1d(1) &
,' to ',zs_1d(nz-1)
END IF
z_temp = MAX(1.,MIN(z_temp,FLOAT(nz-1)-.001))
iz_temp = INT(z_temp)
frac = z_temp - iz_temp
temp_old = t_1d(iz_temp) * (1. - frac) &
+ t_1d(iz_temp+1) * frac
!
!-----------------------------------------------------------------------
!
! Find Temperature of new cloud top
!
!-----------------------------------------------------------------------
!
CALL hgt_to_zk
(cldtop_new,z_temp,nz,zs_1d,istatus)
IF(istatus /= 1)THEN
PRINT*,' New cldtop is out of domain range:', z_temp
PRINT*,' New cldtop=',cldtop_new,' zs range from',zs_1d(1) &
,' to ',zs_1d(nz-1)
! return
END IF
z_temp = MAX(1.,MIN(z_temp,FLOAT(nz-1)-.001))
iz_temp = INT(z_temp)
frac = z_temp - iz_temp
temp_new = t_1d(iz_temp) * (1. - frac) &
+ t_1d(iz_temp+1) * frac
!
!-----------------------------------------------------------------------
!
! This one utilizes a linear approximation to
! the sigma T**4 relationship
!
!-----------------------------------------------------------------------
!
cover_old = MIN(cover_in,1.0)
cover_new = cover_old * (tb8_k-t_gnd_k)/(temp_new-t_gnd_k)
!
!-----------------------------------------------------------------------
!
! This one utilizes the sigma T**4 relationship
!
!-----------------------------------------------------------------------
!
cover_new_f = band8_cover(tb8_k,t_gnd_k,temp_new)
IF((j-1) == INT(j-1)/10*10) THEN
iwrite = iwrite + 1
IF(iwrite < 15) THEN
WRITE(6,601,ERR=2)
601 FORMAT(//1X,'**CORR_CVR** i j tg_k told tnew ' &
,' ctold ctnew cvnew cvrnewf')
WRITE(6,1,ERR=2) i,j,t_gnd_k,temp_old,temp_new,cldtop_old &
,cldtop_new,cover_new,cover_new_f
1 FORMAT(1X,12X,2I3,3F7.0,2F8.0,2F8.2)
2 END IF
END IF
istatus=1
RETURN
END SUBROUTINE correct_cover
!
!##################################################################
!##################################################################
!###### ######
!###### FUNCTION BAND8_COVER ######
!###### ######
!##################################################################
!##################################################################
!
FUNCTION band8_cover(tb8_k,t_gnd_k,t_cld)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! Convert the radiance to the brightness temperature
!
!-----------------------------------------------------------------------
!
! AUTHOR:
! 07/95
!
! MODIFICATION HISTORY:
! 05/01/96 (Jian Zhang)
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
! INPUT:
REAL :: tb8_k ! satellite band 8 brightness temp.
REAL :: t_gnd_k ! ground skin temp.
REAL :: t_cld ! estimated brightness temp. with SAO cld
!
! OUTPUT:
REAL :: band8_cover ! modified cld cover using sat. band 8 data
!
! LOCAL:
REAL :: r_sfc,r_sat,r_cld
REAL :: temp_to_rad ! a function
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
r_sfc = temp_to_rad(t_gnd_k)
r_sat = temp_to_rad(tb8_k)
r_cld = temp_to_rad(t_cld)
band8_cover = (r_sat-r_sfc) / (r_cld-r_sfc)
RETURN
END FUNCTION band8_cover
!
!##################################################################
!##################################################################
!###### ######
!###### FUNCTION TEMP_TO_RAD ######
!###### ######
!##################################################################
!##################################################################
!
FUNCTION temp_to_rad(temp),1
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! Convert the radiance to the brightness temperature
!
!-----------------------------------------------------------------------
!
! AUTHOR:
! 07/95
!
! MODIFICATION HISTORY:
! 05/01/96 (Jian Zhang)
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
! INPUT:
REAL :: temp
!
! OUTPUT:
REAL :: temp_to_rad
!
! LOCAL:
INTEGER :: init
DATA init /0/
SAVE init
INTEGER :: nsat
!
! FUNCTIONS: (in /vortex/lib/goeslib/invers.f)
REAL :: vplanc ! function that convert a brightness temperature
! to the radiance for a specific band
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
INCLUDE 'adas.inc'
IF(init == 0)THEN
init = 1
nsat = 3
PRINT*,' Calling PLNKIV. calibration file:',calib_fname
CALL plnkiv
(nsat,calib_fname)
PRINT*,' End calling PLNKIV'
END IF
temp_to_rad = temp
temp_to_rad = vplanc(temp,8)
RETURN
END FUNCTION temp_to_rad
!
!##################################################################
!##################################################################
!###### ######
!###### FUNCTION RAD_TO_TEMP ######
!###### ######
!##################################################################
!##################################################################
!
FUNCTION rad_to_temp(rad),1
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! Convert the radiance to the brightness temperature
!
!-----------------------------------------------------------------------
!
! AUTHOR:
! 07/95
!
! MODIFICATION HISTORY:
! 05/01/96 (Jian Zhang)
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
! INPUT:
REAL :: rad
!
! OUTPUT:
REAL :: rad_to_temp
!
! LOCAL:
INTEGER :: init
DATA init /0/
SAVE init
INTEGER :: nsat
!
! FUNCTIONS: (in /vortex/lib/goeslib/invers.f)
REAL :: vbrite ! function that convert a radiance to
! a brightness temp for a specific band
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
INCLUDE 'adas.inc'
IF(init == 0) THEN
init = 1
nsat = 3
CALL plnkiv
(nsat,calib_fname)
END IF
rad_to_temp = rad
rad_to_temp = vbrite(rad,8)
RETURN
END FUNCTION rad_to_temp
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE COMPARE_RAD ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE compare_rad (nx,ny,nz,clddiag,r_missing,zs,t_3d & 1,6
,cldcv,t_sfc_k,t_gnd_k,tb8_k &
,cvr_snow,nlyr)
!
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! This routine compares the analyzed clouds to the 11.2mm radiation
! and determines adjusted cloud fractions of the cloud layers to yield
! a better fit.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (?)
! 09/95.
!
! MODIFICATION HISTORY:
!
! 05/01/96 J. Zhang
! Modified for the ARPSDAS format.
! Added full documentation.
! 05/01/99 K. Brewster
! Added check for missing IR data.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! INPUT:
INTEGER :: nx,ny,nz ! grid size
!
! INPUT:
INTEGER :: clddiag ! print diagnostic fields?
REAL :: r_missing ! bad flag
REAL :: t_3d(nx,ny,nz) ! temp. analysis on the model grid
REAL :: zs(nx,ny,nz) ! physical heights (m) at model scalar pts.
REAL :: cvr_snow(nx,ny) ! sfc snow coverage fraction
REAL :: tb8_k(nx,ny) ! satellite band8 brightness temp.
REAL :: t_gnd_k(nx,ny) ! ground skin temp.
REAL :: t_sfc_k(nx,ny) ! surface air temperature
!
! OUTPUT:
REAL :: cldcv(nx,ny,nz) ! adjusted cloud cover analysis
!
! LOCAL:
REAL :: zs_1d(nz) ! phy. heights (m) in a column of grid
REAL :: t_1d(nz) ! temp in a column of grid
REAL :: cldcv_1d(nz) ! cloud cover in one culomn of grid.
REAL :: cldcv_1dref(nz) ! cloud cover in one culomn of grid.
REAL :: a(nz) ! max. cldcvr in each cloud layer
REAL :: f(nz)
REAL :: a_new(nz)
REAL :: f_new(nz)
INTEGER :: ilyr(nz) ! Dims needs to be changed to nz
INTEGER :: ilyr_new(nz) ! Dims needs to be changed to nz
INTEGER :: nlyr,nlyr_new
LOGICAL :: l_correct
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
REAL :: corr_thr,cover_step
REAL :: delta_cover,delta_cover_ref
INTEGER :: i_correct,iter,iter_max,n_iter
REAL :: t_effective,tdiff,tdiff_ref
INTEGER :: i,j,k,l,iwrite,imid,jmid,kmid,ibeg,iend
INTEGER :: n_clear,n_clear_ns,n_clear_sn,n_cloudy,n_total &
,n_correct
REAL :: tdiff_sumsq,tdiff_cld_sumsq,tdiff_corr_sumsq &
,tdiff_corr_sumsq2,tdiff_corr_sumsq3,tdiff_corr_cld_sumsq
REAL :: tb8_g_clr_sum,tb8_a_clr_sum,tb8_g_clr_sumsq &
,tb8_a_clr_sumsq,tb8_g_clr_ns_sum,tb8_a_clr_ns_sum &
,tb8_g_clr_ns_sumsq,tb8_a_clr_ns_sumsq,tb8_g_clr_sn_sum &
,tb8_a_clr_sn_sum,tb8_g_clr_sn_sumsq,tb8_a_clr_sn_sumsq
REAL :: frac,frac_clouds
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
imid=nx/2
jmid=ny/2
ibeg=MAX( 1,imid-5)
iend=MIN(nx,imid+5)
kmid=nz/2
IF(clddiag == 1) THEN
WRITE(6,'(a)')' Comparing radiation'
WRITE(6,611) nx,ny,nz
611 FORMAT(1X,' nx=',i3,' ny=',i3,' nz=',i3)
! 612 FORMAT(1X,10F7.0)
WRITE(6,'(a)')'grid point heights:'
WRITE(6,613) (zs(i,jmid,kmid),i=ibeg,iend)
613 FORMAT(10F8.0)
WRITE(6,'(a)')'grid point temp:'
WRITE(6,613) (t_3d(i,jmid,kmid),i=ibeg,iend)
WRITE(6,'(a)')
!
WRITE(6,'(a)') 'Surface temperatures: j=jmid, i=imid-5,+5'
WRITE(6,614) (t_sfc_k(i,jmid),i=ibeg,iend)
614 FORMAT(1X,10F7.0)
WRITE(6,'(a)') 'Ground skin temperatures: j=jmid, i=imid-5,+5'
WRITE(6,614) (t_gnd_k(i,jmid),i=ibeg,iend)
WRITE(6,'(a)') 'Band 8 temperatures: j=jmid, i=imid-5,+5'
WRITE(6,614) (tb8_k(i,jmid),i=ibeg,iend)
WRITE(6,'(a)')
END IF
corr_thr = 4. ! if diff of tb8-tb8e > 4K, correction
cover_step = 0.05 ! add/minus 0.05 cldcvr each correction
iter_max = 10 ! we'll do maximum of 10 iterns
iwrite = 0 ! output message flag
n_clear = 0 !
n_clear_ns = 0
n_clear_sn = 0
n_cloudy = 0
n_total = 0
n_correct = 0
n_iter = 0
tdiff_sumsq = 0. ! sum of sqr(tb8o-tb8e) for all pts
! before correction
tdiff_cld_sumsq = 0. ! sum of sqare(tb8o-tb8e) for cloudy pts
! before correction
tdiff_corr_sumsq3 = 0. ! sum of sqr(tb8o-tb8e) for cloudy pts
! to be corrected, before the correction
tdiff_corr_sumsq = 0. ! sum of sqr(tb8o-tb8e) for all pts
! after correction
tdiff_corr_cld_sumsq = 0. ! sum of sqr(tb8o-tb8e) for all cldy pts
! after correction
tdiff_corr_sumsq2 = 0. ! sum of sqr(tb8o-tb8e) for cloudy pts
! to be corrected, after the correction
tb8_g_clr_sum = 0. ! sum of tb8-tg for clear air pts
tb8_a_clr_sum = 0. ! sum of tb8-tsfc for clear air pts
tb8_g_clr_sumsq = 0. ! sum of sqare(tb8-tg) for clear air pts
tb8_a_clr_sumsq = 0. ! sum of sqare(tb8-tsfc) for clear air pts
tb8_g_clr_ns_sum = 0. ! for clear air with < 0.5 snow cover pts
tb8_a_clr_ns_sum = 0.
tb8_g_clr_ns_sumsq = 0.
tb8_a_clr_ns_sumsq = 0.
tb8_g_clr_sn_sum = 0. ! for clear air with > 0.5 snow cover pts
tb8_a_clr_sn_sum = 0.
tb8_g_clr_sn_sumsq = 0.
tb8_a_clr_sn_sumsq = 0.
!
!-----------------------------------------------------------------------
!
! Compare and correct (if necessary) the cloud cover analysis field
! for each grid point.
!
!-----------------------------------------------------------------------
!
DO j = 1,ny-1
DO i = 1,nx-1
IF(tb8_k(i,j) > 0.) THEN
!jz do k = 1,nz-1
DO k = 1,nz
zs_1d(k) = zs(i,j,k)
t_1d(k) = t_3d(i,j,k)
END DO
DO k = 1,nz
cldcv_1dref(k) = cldcv(i,j,k)
END DO
CALL cvr_to_tb8e
(nz,zs_1d,t_1d &
,cldcv_1dref,t_gnd_k(i,j) &
,a,f,ilyr,t_effective,nlyr)
!
tdiff = tb8_k(i,j)-t_effective ! Band 8 - calculated
frac_clouds = 1.-f(nlyr) ! column total cloud cover
IF(nlyr == 1) THEN
tb8_g_clr_sum = tb8_g_clr_sum + tdiff
tb8_g_clr_sumsq = tb8_g_clr_sumsq + tdiff**2
tb8_a_clr_sum = tb8_a_clr_sum + tb8_k(i,j)-t_sfc_k(i,j)
tb8_a_clr_sumsq=tb8_a_clr_sumsq+(tb8_k(i,j)-t_sfc_k(i,j))**2
n_clear = n_clear + 1
IF(cvr_snow(i,j) /= r_missing) THEN
IF(cvr_snow(i,j) < 0.5) THEN
tb8_g_clr_ns_sum = tb8_g_clr_ns_sum + tdiff
tb8_g_clr_ns_sumsq = tb8_g_clr_ns_sumsq + tdiff**2
tb8_a_clr_ns_sum = tb8_a_clr_ns_sum &
+ tb8_k(i,j)-t_sfc_k(i,j)
tb8_a_clr_ns_sumsq = tb8_a_clr_ns_sumsq &
+ (tb8_k(i,j) - t_sfc_k(i,j))**2
n_clear_ns = n_clear_ns + 1
ELSE
tb8_g_clr_sn_sum = tb8_g_clr_sn_sum + tdiff
tb8_g_clr_sn_sumsq = tb8_g_clr_sn_sumsq + tdiff**2
tb8_a_clr_sn_sum = tb8_a_clr_sn_sum &
+ tb8_k(i,j)-t_sfc_k(i,j)
tb8_a_clr_sn_sumsq = tb8_a_clr_sn_sumsq &
+(tb8_k(i,j)-t_sfc_k(i,j))**2
n_clear_sn = n_clear_sn + 1
END IF
END IF
ELSE
n_cloudy = n_cloudy + 1
tdiff_cld_sumsq = tdiff_cld_sumsq + tdiff**2
END IF
n_total = n_total + 1
tdiff_sumsq = tdiff_sumsq + tdiff**2
!
!-----------------------------------------------------------------------
!
! Apply corrections?
!
! Only when the following four conditions are satisfied:
! 1. at least one cloud layer
! 2. the difference between the observed and estimated tb8
! is larger than the threshold (4K)
! 3. tb8_obs - t_gnd < -8K
! 4. column total cloud cover is larger than 40%
!
!-----------------------------------------------------------------------
!
IF (nlyr >= 2 .AND. ABS(tdiff) > corr_thr &
.AND. t_gnd_k(i,j) - tb8_k(i,j) > 8. &
.AND. frac_clouds > 0.4 ) THEN
l_correct = .true.
n_correct = n_correct + 1
tdiff_corr_sumsq3 = tdiff_corr_sumsq3 + tdiff**2
ELSE
l_correct = .false.
END IF
!
!-----------------------------------------------------------------------
!
! This corrective section is now turned on
!
!-----------------------------------------------------------------------
!
iter = 0
delta_cover = 0.
905 IF (l_correct) THEN
iter = iter + 1
tdiff_ref = tdiff ! save initial difference
delta_cover_ref = delta_cover ! save initial correction
IF(tdiff < 0.) THEN
delta_cover = delta_cover + cover_step
ELSE
delta_cover = delta_cover - cover_step
END IF
CALL apply_correction
(cldcv_1dref,cldcv_1d &
,nz,ilyr,f,delta_cover)
CALL cvr_to_tb8e
(nz,zs_1d,t_1d &
,cldcv_1d,t_gnd_k(i,j) &
,a_new,f_new,ilyr_new,t_effective,nlyr_new)
!
tdiff = tb8_k(i,j)-t_effective
frac_clouds = 1.-f_new(nlyr_new)
!
!-----------------------------------------------------------------------
!
! Continue to apply corrections?
!
!-----------------------------------------------------------------------
!
IF(nlyr_new >= 2 .AND. frac_clouds > 0.4) THEN
i_correct = 1
ELSE
i_correct = 0
END IF
IF(MOD(iwrite,50) == 0) THEN
iwrite = iwrite + 1
WRITE(6,*) 'iter=',iter ,' tdiff_ref=',tdiff_ref &
,'tg=',t_gnd_k(i,j)
WRITE(6,*) (a(l),l=nlyr-1,1,-1)
WRITE(6,641)
641 FORMAT(1X,' i j ncn tb8o tb8e tdiff cldcvm i_c' &
,6(' cvrln'))
WRITE(6,642,ERR=912)i,j,nlyr_new-1,tb8_k(i,j),t_effective &
,tdiff,frac_clouds,i_correct &
,(a_new(l),l=nlyr_new-1,1,-1)
642 FORMAT(1X,2I3,i4,2F7.0,f7.1,f7.3,i2,2X,10F6.2)
912 END IF
IF(i_correct == 1 .AND. iter < iter_max &
.AND. ABS(tdiff) < ABS(tdiff_ref) &
.AND. tdiff * tdiff_ref > 0.) GO TO 905
! Loop back & increment cover
n_iter = n_iter + iter
!
!-----------------------------------------------------------------------
!
! Final iteration
!
!-----------------------------------------------------------------------
!
IF(.false. .OR. tdiff*tdiff_ref >= 0.) THEN
! Select best of last two increments
IF(ABS(tdiff) >= ABS(tdiff_ref)) THEN
delta_cover = delta_cover_ref
CALL apply_correction
(cldcv_1dref,cldcv_1d &
,nz,ilyr,f,delta_cover)
tdiff = tdiff_ref
END IF
ELSE ! Do one Newton iteration
frac = tdiff / (tdiff - tdiff_ref)
delta_cover=delta_cover+frac*(delta_cover_ref-delta_cover)
CALL apply_correction
(cldcv_1dref,cldcv_1d &
,nz,ilyr,f,delta_cover)
CALL cvr_to_tb8e
(nz,zs_1d,t_1d &
,cldcv_1d,t_gnd_k(i,j) &
,a_new,f_new,ilyr_new,t_effective,nlyr_new)
tdiff = tb8_k(i,j)-t_effective
n_iter = n_iter + 1
END IF
!
!-----------------------------------------------------------------------
!
! Put the corrected column cloud coverback to 3D cloud cover field
!
!-----------------------------------------------------------------------
!
DO k=1,nz
cldcv(i,j,k) = cldcv_1d(k)
END DO
END IF ! Corrections were made
tdiff_corr_sumsq = tdiff_corr_sumsq + tdiff**2
IF(nlyr > 1) & ! cloudy (at least before adjustment)
tdiff_corr_cld_sumsq = tdiff_corr_cld_sumsq + tdiff**2
IF(l_correct) THEN
tdiff_corr_sumsq2 = tdiff_corr_sumsq2 + tdiff**2
END IF
END IF
END DO ! I
END DO ! J
!
!-----------------------------------------------------------------------
!
! Write out statistics on consistency of Band 8 data and cloud cover
!
!-----------------------------------------------------------------------
!
IF(n_clear > 0) THEN
WRITE(6,951,ERR=960) n_clear, tb8_g_clr_sum/FLOAT(n_clear) &
,SQRT(tb8_g_clr_sumsq/FLOAT(n_clear))
951 FORMAT(/' Mean/RMS band 8/gnd temp residual in clear skies =' &
,i5,2F9.3)
960 WRITE(6,961,ERR=970) n_clear, tb8_a_clr_sum/FLOAT(n_clear) &
,SQRT(tb8_a_clr_sumsq/FLOAT(n_clear))
961 FORMAT(' Mean/RMS band 8/air temp residual in clear skies =' &
,i5,2F9.3)
970 END IF
IF(n_clear_ns > 0) THEN
WRITE(6,956,ERR=965) n_clear_ns &
,tb8_g_clr_ns_sum/FLOAT(n_clear_ns) &
,SQRT(tb8_g_clr_ns_sumsq/FLOAT(n_clear_ns))
956 FORMAT(/' Mean/RMS band 8/gnd temp resid in clear/nsnow skies =' &
,i5,2F9.3)
965 WRITE(6,966,ERR=975) n_clear_ns &
,tb8_a_clr_ns_sum/FLOAT(n_clear_ns) &
,SQRT(tb8_a_clr_ns_sumsq/FLOAT(n_clear_ns))
966 FORMAT(' Mean/RMS band 8/air temp resid in clear/nsnow skies =' &
,i5,2F9.3)
975 END IF
IF(n_clear_sn > 0) THEN
WRITE(6,976,ERR=985) n_clear_sn &
,tb8_g_clr_sn_sum/FLOAT(n_clear_sn) &
,SQRT(tb8_g_clr_sn_sumsq/FLOAT(n_clear_sn))
976 FORMAT(/' Mean/RMS band 8/gnd temp resid in clear/snow skies =' &
,i5,2F9.3)
985 WRITE(6,986,ERR=995) n_clear_sn &
,tb8_a_clr_sn_sum/FLOAT(n_clear_sn) &
,SQRT(tb8_a_clr_sn_sumsq/FLOAT(n_clear_sn))
986 FORMAT(' Mean/RMS band 8/air temp resid in clear/snow skies =' &
,i5,2F9.3)
995 END IF
IF(n_total > 0) THEN
WRITE(6,971,ERR=980)n_total,SQRT(tdiff_sumsq/FLOAT(n_total))
971 FORMAT(/' RMS band 8/teff residual (bfr corr) in all skies =' &
,i5, f9.3)
980 WRITE(6,981,ERR=990) n_total, &
SQRT(tdiff_corr_sumsq/FLOAT(n_total))
981 FORMAT(' RMS band 8/teff residual (aft corr) in all skies =' &
,i5, f9.3)
990 END IF
IF(n_cloudy > 0) THEN
WRITE(6,991,ERR=1000) n_cloudy, &
SQRT(tdiff_cld_sumsq/FLOAT(n_cloudy))
991 FORMAT(' RMS band 8/teff residual (bfr corr) in cldy skies =' &
,i5, f9.3)
1000 WRITE(6,1001,ERR=1010) n_cloudy, &
SQRT(tdiff_corr_cld_sumsq/FLOAT(n_cloudy))
1001 FORMAT(' RMS band 8/teff residual (aft corr) in cldy skies =' &
,i5, f9.3)
1010 END IF
IF(n_correct > 0) THEN
WRITE(6,1011,ERR=1020) &
n_correct,SQRT(tdiff_corr_sumsq3/FLOAT(n_correct))
1011 FORMAT(/' RMS band 8/teff resid (bfr corr - corrected pts) =' &
,i5, f9.3)
1020 WRITE(6,1021,ERR=1030) &
n_correct,SQRT(tdiff_corr_sumsq2/FLOAT(n_correct))
1021 FORMAT(' RMS band 8/teff resid (aft corr - corrected pts) =' &
,i5, f9.3)
WRITE(6,*)' Total/Average # of iterations = ',n_iter, &
FLOAT(n_iter)/FLOAT(n_correct)
WRITE(6,*)
1030 END IF
RETURN
END SUBROUTINE compare_rad
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE CVR_TO_TB8E ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE cvr_to_tb8e (nz,zs_1d,t_1d & 3
,cvr,t_gnd_k &
,a,f,ilyr,t_effective,nlyr)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! To calculate the estimated band8 brightness temperature using
! the cloud cover analysis.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 04/1996 Based on the LAPS cloud analysis code of 09/95
!
! MODIFICATION HISTORY:
!
! 04/26/96 J. Zhang
! Modified for the ARPSDAS format. Added full
! documentation.
! 07/27/96 J. Zhang
! Modified code so that the cloud layer with top at the
! upper boundary of the cloud grid is counted.
! 04/11/97 J. Zhang
! Include adascld24.inc for ncloud
! 08/06/97 J. Zhang
! Change adascld24.inc to adascld25.inc
! 09/11/97 J. Zhang
! Change adascld25.inc to adascld26.inc
! 04/20/98 J. Zhang
! Based on the arps4.3.3 version. Abandoned cloud grid,
! using the model grid.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! INPUT
INTEGER :: nz
!
! INPUT:
REAL :: cvr(nz) ! Cloud cover from analysis
REAL :: zs_1d(nz)
REAL :: t_1d(nz)
REAL :: t_gnd_k
!
! OUTPUT:
REAL :: t_effective ! effective brightness temp. estimated
! from cloud cover analysis
INTEGER :: nlyr
INTEGER :: ilyr(nz) ! Layer index for each cloud lvl (needs nz)
REAL :: a(nz) ! Cloud fractions of layers
REAL :: f(nz) ! Apparnt "x-sectn" of cldlyrs seen from above
!
! LOCAL:
INTEGER :: ik(nz) ! Height level representative of cloud layers
REAL :: temp_lyr(nz) ! temp. at "ik" lavels
!
! FUNCTIONS:
REAL :: temp_to_rad
REAL :: rad_to_temp
!
!-----------------------------------------------------------------------
!
! Misc local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: k,n
REAL :: rsum,sumf
REAL :: cvr_thresh
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.
!
!-----------------------------------------------------------------------
!
nlyr = 0
IF(cvr(nz) >= cvr_thresh) THEN ! cldtop at the upper boundary
nlyr = nlyr + 1
a(nlyr) = cvr(nz)
ik(nlyr) = nz
ilyr(nz) = nlyr
ELSE
ilyr(nz)=0
END IF
DO k = nz-1,1,-1
IF(cvr(k) >= cvr_thresh .AND. cvr(k+1) < cvr_thresh) THEN
nlyr = nlyr + 1
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
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
!
!-----------------------------------------------------------------------
!
! Get temperatures of the maximum cldcvr level in each cld deck.
!
!-----------------------------------------------------------------------
!
DO n = 1,nlyr
k = ik(n)
temp_lyr(n) = t_1d(k)
END DO ! n
!
!-----------------------------------------------------------------------
!
! Add a layer for the ground
!
!-----------------------------------------------------------------------
!
nlyr = nlyr + 1
a(nlyr) = 1.0
temp_lyr(nlyr) = t_gnd_k
!
!-----------------------------------------------------------------------
!
! Convert cloud layer fractions to "cross-section" seen from
! satellite. This solves for the "f" array given the "a" array
!
!-----------------------------------------------------------------------
!
a(1) = MIN( f(1) = a(1)
sumf = f(1)
IF(nlyr >= 2) THEN
DO n = 2,nlyr
a(n) = MIN( 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
END IF ! nlyr
!
!-----------------------------------------------------------------------
!
! Calculate total radiance from all cloud layers + ground
!
!-----------------------------------------------------------------------
!
rsum = 0
DO n = 1,nlyr
rsum = rsum + temp_to_rad(temp_lyr(n)) * f(n)
END DO ! n
!
!-----------------------------------------------------------------------
!
! Convert to effective temperature and compare to
! the observed brightness temp
!
!-----------------------------------------------------------------------
!
t_effective = rad_to_temp(rsum)
RETURN
END SUBROUTINE cvr_to_tb8e
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE APPLY_CORRECTION ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE apply_correction (cldcv_1dref,cldcv_1d & 3
,nz,ilyr,f,delcv)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
! To apply the correction to the cloud cover field.
! The amount for correction is an input parameter.
!
!-----------------------------------------------------------------------
!
! AUTHOR: (Jian Zhang)
! 05/02/96
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
!-----------------------------------------------------------------------
!
! INPUT:
INTEGER :: nz ! number of cloud analysis levels
REAL :: cldcv_1dref(nz) ! the column cldcvr to be corr.
INTEGER :: ilyr(nz) ! cld deck(layer) indices for ea.cldy level
REAL :: f(nz) ! fracn of rad. blocked by each cloud deck
REAL :: delcv ! the cld cvr increment added to the input
!
! OUTPUT:
REAL :: cldcv_1d(nz) ! corrected cloud cover
!
! LOCAL:
INTEGER :: k
!
!-----------------------------------------------------------------------
!
! Apply correction to 1D cloud cover field
!
!-----------------------------------------------------------------------
!
DO k = 1,nz
!jz if( ilyr(k).gt.0 .and. f(ilyr(k)).gt.0.0) then
IF(ilyr(k) > 0) THEN
IF( cldcv_1d(k) = MIN(cldcv_1dref(k)+delcv, 1.0)
cldcv_1d(k) = MAX(cldcv_1d(k), 0.0)
ELSE
cldcv_1d(k) = MAX(MIN(cldcv_1dref(k), 1.0), 0.0)
END IF
ELSE
cldcv_1d(k) = MAX(MIN(cldcv_1dref(k), 1.0), 0.0)
END IF
END DO
RETURN
END SUBROUTINE apply_correction