!######################################################################## !######################################################################## !######### ######### !######### SUBROUTINE adjust_refl ######### !######### ######### !######### Developed by ######### !######### Center for Analysis and Prediction of Storms ######### !######### University of Oklahoma ######### !######### ######### !######################################################################## !######################################################################## SUBROUTINE adjust_refl(nx,ny,nz,refl,zs,et_nids,vil_nids) 1,2 !------------------------------------------------------------------------ ! ! PURPOSE: ! ! Adjusts the remapped 3D reflectivity field using NIDS echo top and VIL ! data. A linear function R = A*H + B is used as a first guess between ! the NIDS echo top product level and the top of the original remapped ! reflectivity field (R being reflectivity, A being a slope, H is height, ! and B is the intercept). However, a quadratic function R = (A*H*H) + ! (B*H) + C is used if "too much" reflectivity is inserted by the linear ! function. ! !------------------------------------------------------------------------ ! ! AUTHOR: ! ! Eric Kemp, 6 September 2001. Developed for WDT. ! !------------------------------------------------------------------------ ! ! Force explicit declarations. ! !------------------------------------------------------------------------ IMPLICIT NONE !------------------------------------------------------------------------ ! ! Declare arguments ! !------------------------------------------------------------------------ INTEGER, INTENT(IN) :: nx,ny,nz ! Dimensions of grid REAL, INTENT(INOUT) :: refl(nx,ny,nz) ! 3D reflectivity (dBZ) REAL, INTENT(IN) :: zs(nx,ny,nz) ! Height of scalar points (m MSL) REAL, INTENT(IN) :: et_nids(nx,ny) ! NIDS Echo top (m MSL) REAL, INTENT(IN) :: vil_nids(nx,ny) ! NIDS VIL (kg m**-2) !------------------------------------------------------------------------ ! ! Functions ! !------------------------------------------------------------------------ REAL, EXTERNAL :: vil_88d !------------------------------------------------------------------------ ! ! Internal parameters ! !------------------------------------------------------------------------ REAL, PARAMETER :: K_const = 3.44E-6 REAL, PARAMETER :: foursevenths = 4./7. REAL, PARAMETER :: sevenfourths = 7./4. INTEGER, PARAMETER :: iterationmax = 40 !------------------------------------------------------------------------ ! ! Internal variables ! !------------------------------------------------------------------------ REAL :: refl_adj(nx,ny,nz) REAL :: et_refl(nx,ny) INTEGER :: k_et_refl(nx,ny) INTEGER :: k_et_nids(nx,ny) REAL :: vil_refl(nx,ny) REAL :: vil_residual(nx,ny) REAL :: reflthresh REAL :: Z, r REAL :: slope, intercept REAL :: Mtop, Mr, M REAL :: reflthreshexp REAL :: maxresidual,minresidual INTEGER :: i,j,k INTEGER :: iteration REAL :: A, B, C REAL :: N, N1, N2, N3, N4 REAL :: D, D1, D2, D3, D4 !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !------------------------------------------------------------------------ ! ! Calculate the echo top from the 3D reflectivity field. Also, ! determine k-levels of NIDS echo tops. ! !------------------------------------------------------------------------ reflthresh = 18.5 CALL calc_et_refl(nx,ny,nz,refl,reflthresh,zs,et_refl,k_et_refl) CALL calc_k_et(nx,ny,nz,zs,et_nids,k_et_nids) refl_adj(:,:,:) = refl(:,:,:) DO j = 1,ny-1 DO i = 1,nx-1 IF (et_nids(i,j) == 0.) THEN ! WRITE(6,*)'WARNING: No NIDS echo top.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (vil_nids(i,j) == 0.) THEN ! WRITE(6,*)'WARNING: No NIDS VIL.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (et_nids(i,j) == -9999. .OR. k_et_nids(i,j) == -9999) THEN ! WRITE(6,*)'WARNING: NIDS echo top value missing.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (vil_nids(i,j) == -9999.) THEN ! WRITE(6,*)'WARNING: NIDS VIL value missing.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (et_refl(i,j) == -9999. .OR. k_et_refl(i,j) == -9999) THEN ! WRITE(6,*)'WARNING: Estimated echo top value missing.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (vil_refl(i,j) == -9999.) THEN ! WRITE(6,*)'WARNING: Estimated VIL value missing.' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (k_et_nids(i,j) == k_et_refl(i,j)) THEN ! WRITE(6,*)'NOTE: Echo top k levels are equal. Skipping...' ! WRITE(6,*)'i: ',i,' j: ',j CYCLE ! Skip to next column ELSE IF (k_et_nids(i,j) < k_et_refl(i,j)) THEN ! WRITE(6,*)'WARNING: NIDS echo top below estimated value.' ! WRITE(6,*)'i: ',i,' j: ',j ! WRITE(6,*)'et_nids: ',et_nids(i,j),' et_refl: ',et_refl(i,j) CYCLE ! Skip to next column END IF reflthresh = 18.5 DO iteration = 1,iterationmax vil_refl(i,j) = vil_88d(nz,refl_adj(i,j,:),zs(i,j,:)) IF ( (vil_refl(i,j) < (vil_nids(i,j) - 5.) ) .OR. & (iteration == 1) ) THEN !------------------------------------------------------------------------ ! ! To use the linear function, we must first calculate the slope ! and intercept values. With some algebra and calculus, it can ! be shown that: ! ! slope = (Mtop - Mr)/(et_nids - et_refl), and ! ! intercept = Mr - (slope*et_refl) ! ! where Mtop is M at et_nids and Mr is M at et_refl. So, we need ! to calculate Mtop and Mr, and then slope and intercept. ! !------------------------------------------------------------------------ Z = 10.**(refl(i,j,k_et_refl(i,j))*0.1) Mr = K_const*(Z**foursevenths) reflthreshexp = reflthresh*0.1 Z = 10.**(reflthreshexp) Mtop = K_const*(Z**foursevenths) slope = (Mtop - Mr)/(et_nids(i,j) - et_refl(i,j)) intercept = Mr - (slope*et_refl(i,j)) !------------------------------------------------------------------------ ! ! Now apply the linear function to the refl_adj field between ! k_et_refl and k_ef_nids. ! !------------------------------------------------------------------------ DO k = k_et_refl(i,j),k_et_nids(i,j) M = (slope*zs(i,j,k)) + intercept Z = (M/K_const)**sevenfourths refl_adj(i,j,k) = 10.*ALOG10(Z) END DO ! k loop vil_refl(i,j) = vil_88d(nz,refl_adj(i,j,:),zs(i,j,:)) reflthresh = reflthresh + 1.5 IF (reflthresh > 55.) EXIT ELSE IF (vil_refl(i,j) > (vil_nids(i,j) + 5.) ) THEN reflthresh = 18.5 !------------------------------------------------------------------------ ! ! To use the quadratic function, we must first calculate the A, ! B, and C coefficients. By performing much algebra and ! calculus, it can be shown that: ! ! A = N/D ! ! N = N1 + N2 + N3 + N4 ! ! N1 = 6.*r*(et_nids - et_refl) ! ! N2 = -3.*(Mtop - Mr)*(et_nids*et_nids - et_refl*et_refl) ! ! N3 = 6.*et_refl*(Mtop - Mr)*(et_nids - et_refl) ! ! N4 = -6.*Mr*(et_nids - et_refl)**3. ! ! D = D1 + D2 + D3 + D4 ! ! D1 = 2.*(et_nids**3 - et_refl**3.)*(et_nids-et_refl) ! ! D2 = -6.*(et_refl*et_refl)*(et_nids - et_refl)**2. ! ! D3 = -3.*(et_nids**2. - et_refl**2.) ! ! D4 = 6.*et_refl*(et_nids**2. - et_refl**2.)* ! (et_nids - et_refl) ! ! B = (Mtop - Mr - A*(et_nids**2. - et_refl**2.))/(et_nids-et_refl) ! ! C = Mr - (A*et_refl*et_refl) - (B*et_refl) ! ! where Mtop is M at et_nids, Mr is M at et_refl, and r is the ! residual VIL (NIDS VIL - reflectivity field VIL). So, we need ! to calculate Mtop, Mr, and r, and then A, B, and C ! !------------------------------------------------------------------------ IF (iteration > 2) THEN refl_adj(i,j,k_et_refl(i,j)) = & refl_adj(i,j,k_et_refl(i,j)) - 1.5 END IF Z = 10.**(refl_adj(i,j,k_et_refl(i,j))*0.1) Mr = K_const*(Z**foursevenths) reflthreshexp = reflthresh*0.1 Z = 10.**(reflthreshexp) Mtop = K_const*(Z**foursevenths) r = vil_nids(i,j) - vil_refl(i,j) N1 = 6.*r*(et_nids(i,j) - et_refl(i,j)) N2 = -3.*(Mtop - Mr)*(et_nids(i,j)*et_nids(i,j) - & et_refl(i,j)*et_refl(i,j)) N3 = 6.*et_refl(i,j)*(Mtop - Mr)*(et_nids(i,j) - et_refl(i,j)) N4 = -6.*Mr*(et_nids(i,j) - et_refl(i,j))**3. N = N1 + N2 + N3 + N4 D1 = 2.*(et_nids(i,j)**3. - & et_refl(i,j)**3.)*(et_nids(i,j)-et_refl(i,j)) D2 = -6.*(et_refl(i,j)*et_refl(i,j))* & (et_nids(i,j)-et_refl(i,j))**2. D3 = -3.*(et_nids(i,j)*et_nids(i,j) - & et_refl(i,j)*et_refl(i,j)) D4 = 6.*et_refl(i,j)*(et_nids(i,j)*et_nids(i,j) - & et_refl(i,j)*et_refl(i,j))*(et_nids(i,j) - et_refl(i,j)) D = D1 + D2 + D3 + D4 A = N/D B = (Mtop - Mr - A*(et_nids(i,j)*et_nids(i,j) - & et_refl(i,j)*et_refl(i,j)))/(et_nids(i,j) - et_refl(i,j)) C = Mr - (A*et_refl(i,j)*et_refl(i,j)) - (B*et_refl(i,j)) !------------------------------------------------------------------------ ! ! Now apply the quadratic function to the refl_adj field between ! k_et_refl and k_ef_nids. ! !------------------------------------------------------------------------ DO k = k_et_refl(i,j),k_et_nids(i,j) M = (A*zs(i,j,k)*zs(i,j,k)) + (B*zs(i,j,k)) + C Z = (M/K_const)**sevenfourths refl_adj(i,j,k) = 10.*ALOG10(Z) END DO ! k loop END IF ! linear or quadratic vil_refl(i,j) = vil_88d(nz,refl_adj(i,j,:),zs(i,j,:)) END DO ! iteration loop !------------------------------------------------------------------------ ! ! Move on to next column. ! !------------------------------------------------------------------------ END DO ! i loop END DO ! j loop !------------------------------------------------------------------------ ! ! Calculate new VIL and residual VIL from adjusted reflectivity field. ! !------------------------------------------------------------------------ vil_residual(:,:) = -9999. maxresidual = 0. minresidual = 0. DO j = 1,ny-1 DO i = 1,nx-1 IF (vil_nids(i,j) /= -9999. .AND. et_nids(i,j) /= -9999. .AND. & vil_refl(i,j) /= -9999. .AND. et_refl(i,j) /= -9999. .AND. & k_et_nids(i,j) /= -9999 .AND. k_et_refl(i,j) /= -9999 .AND. & k_et_nids(i,j) > k_et_refl(i,j)) THEN vil_residual(i,j) = vil_nids(i,j) - vil_refl(i,j) IF (vil_residual(i,j) < minresidual) THEN minresidual = vil_residual(i,j) END IF IF (vil_residual(i,j) > maxresidual) THEN maxresidual = vil_residual(i,j) END IF END IF END DO END DO WRITE(6,*)'Max Residual VIL: ',maxresidual WRITE(6,*)'Min Residual VIL: ',minresidual !------------------------------------------------------------------------ ! ! Overwrite original reflectivity and exit. ! !------------------------------------------------------------------------ refl(:,:,:) = refl_adj(:,:,:) RETURN END SUBROUTINE adjust_refl !######################################################################## !######################################################################## !######### ######### !######### SUBROUTINE calc_et_refl ######### !######### ######### !######### Developed by ######### !######### Center for Analysis and Prediction of Storms ######### !######### University of Oklahoma ######### !######### ######### !######################################################################## !######################################################################## SUBROUTINE calc_et_refl(nx,ny,nz,refl,reflthresh,zs,et,k_et) 1 !------------------------------------------------------------------------ ! ! PURPOSE: ! ! Determines echo tops for 3D reflectivity field using a dBZe threshold ! specified as an argument. Also returns the k-levels. ! !------------------------------------------------------------------------ ! ! AUTHOR: ! ! Eric Kemp, 31 August 2001. Developed for WDT. ! !------------------------------------------------------------------------ ! ! Force explicit declarations. ! !------------------------------------------------------------------------ IMPLICIT NONE !------------------------------------------------------------------------ ! ! Declare arguments. ! !------------------------------------------------------------------------ INTEGER, INTENT(IN) :: nx,ny,nz ! Dimensions of grid REAL, INTENT(IN) :: refl(nx,ny,nz) ! 3D reflectivity (dBZ) REAL, INTENT(IN) :: reflthresh ! Reflectivity threshold for ! echo top (dBZ) REAL, INTENT(IN) :: zs(nx,ny,nz) ! Scalar heights (m MSL) REAL, INTENT(INOUT) :: et(nx,ny) ! Echo top heights (m MSL) INTEGER, INTENT(INOUT) :: k_et(nx,ny) ! k-level of echo top height. !------------------------------------------------------------------------ ! ! Declare internal variables ! !------------------------------------------------------------------------ INTEGER :: i,j,k !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ et(:,:) = -9999. k_et(:,:) = -9999 DO j = 1,ny-1 DO i = 1,nx-1 DO k = nz-1,2,-1 IF (refl(i,j,k) > reflthresh) THEN et(i,j) = zs(i,j,k) k_et(i,j) = k EXIT ! Get out of k loop END IF END DO ! k loop END DO ! i loop END DO ! j loop RETURN END SUBROUTINE calc_et_refl !######################################################################## !######################################################################## !######### ######### !######### SUBROUTINE calc_k_et ######### !######### ######### !######### Developed by ######### !######### Center for Analysis and Prediction of Storms ######### !######### University of Oklahoma ######### !######### ######### !######################################################################## !######################################################################## SUBROUTINE calc_k_et(nx,ny,nz,zs,et,k_et) 1 !------------------------------------------------------------------------ ! ! PURPOSE: ! ! Determines the k-level of the (NIDS) echo tops. Developed for WDT. ! !------------------------------------------------------------------------ ! ! AUTHOR: ! ! Eric Kemp, 31 August 2001 ! !------------------------------------------------------------------------ ! ! Force explicit declarations. ! !------------------------------------------------------------------------ IMPLICIT NONE !------------------------------------------------------------------------ ! ! Declare arguments. ! !------------------------------------------------------------------------ INTEGER, INTENT(IN) :: nx,ny,nz ! Dimensions of grid REAL, INTENT(IN) :: zs(nx,ny,nz) ! Scalar heights (m MSL) REAL, INTENT(IN) :: et(nx,ny) ! Echo top heights (m MSL) INTEGER, INTENT(INOUT) :: k_et(nx,ny) ! k-level of echo tops !------------------------------------------------------------------------ ! ! Declare internal variables ! !------------------------------------------------------------------------ INTEGER :: i,j,k !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ k_et(:,:) = -9999 DO j = 1,ny-1 DO i = 1,nx-1 DO k = nz-1,2,-1 IF (et(i,j) > zs(i,j,k)) THEN k_et(i,j) = k EXIT ! Get out of k loop END IF END DO ! k loop END DO ! i loop END DO ! j loop RETURN END SUBROUTINE calc_k_et !######################################################################## !######################################################################## !######### ######### !######### FUNCTION vil_88d ######### !######### ######### !######### Developed by ######### !######### Center for Analysis and Prediction of Storms ######### !######### University of Oklahoma ######### !######### ######### !######################################################################## !######################################################################## REAL FUNCTION vil_88d(nz,refl,zs) !------------------------------------------------------------------------ ! ! PURPOSE: ! ! Calculates vertically integrated liquid from 3D reflectivity data ! following the WSR-88D algorithm. ! !------------------------------------------------------------------------ ! ! REFERENCES: ! ! Edwards, R., and R. L. Thompson, 1998: Nationwide comparisons of hail ! size with WSR-88D vertically integrated liquid water and derived ! thermodynamic sounding data. _Wea. Forecasting_, 12, 277-285. ! Greene, D. R., and R. A. Clark, 1972: Vertically integrated liquid ! water -- A new analysis tool. _Mon. Wea. Rev._, 100, 548-552. ! OSF, Undated Document: Vertically-integrated liquid water algorithm ! description. NX-DR-03-006/25, 7pp. Available on the Internet at ! http://120.125.144.136/~swimm/wsr88d/algorithms.htm ! Witt, A., and Coauthors, 1998: An enhanced hail detection algorithm ! for the WSR-88D. _Wea. Forecasting_, 13, 286-303. ! !------------------------------------------------------------------------ ! ! AUTHOR: ! ! Eric Kemp, 7 September 2001. Developed for WDT. ! !------------------------------------------------------------------------ ! ! Force explicit declarations ! !------------------------------------------------------------------------ IMPLICIT NONE !------------------------------------------------------------------------ ! ! Declare arguments. ! !------------------------------------------------------------------------ INTEGER, INTENT(IN) :: nz ! Dimension of column REAL, INTENT(IN) :: refl(nz) ! Reflectivity in column (dBZ) REAL, INTENT(IN) :: zs(nz) ! Scalar heights (m MSL) !------------------------------------------------------------------------ ! ! Declare internal parameters. ! !------------------------------------------------------------------------ REAL, PARAMETER :: minrefl = 18.5 ! Minimum point reflectivity used ! in VIL algorithm. REAL, PARAMETER :: maxrefl = 55. ! Maximum point reflectivity used ! in VIL algorithm. REAL, PARAMETER :: maxreflexp = 55.*0.1 ! Exponent used for cases ! with reflectivity > maxrefl REAL, PARAMETER :: K_const = 3.44E-6 ! Conversion factor for Z to M. REAL, PARAMETER :: maxvil = 80. ! Maximum VIL permitted (kg m**-2) REAL, PARAMETER :: foursevenths = 4./7. !------------------------------------------------------------------------ ! ! Declare internal variables. ! !------------------------------------------------------------------------ REAL :: Z, M, dh, VIL INTEGER :: k !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ VIL = 0. DO k = 2,nz-1 !------------------------------------------------------------------------ ! ! Calculate reflectivity factor Z in mm**6 m**-3. Logarithmic ! reflectivities less than 18.5 dBZ are set to zero, while ! those values above 55 dBZ are truncated. ! !------------------------------------------------------------------------ IF (refl(k) < minrefl) THEN Z = 0. ELSE IF (refl(k) > maxrefl) THEN Z = 10.**(maxreflexp) ELSE Z = 10.**(refl(k)*0.1) END IF !------------------------------------------------------------------------ ! ! Now calculate liquid water content (M) in kg m**-3. ! !------------------------------------------------------------------------ M = K_const*(Z**foursevenths) !------------------------------------------------------------------------ ! ! Calculate local dh. ! !------------------------------------------------------------------------ dh = zs(k+1) - zs(k) !------------------------------------------------------------------------ ! ! Add to VIL. ! !------------------------------------------------------------------------ VIL = VIL + (M*dh) END DO !------------------------------------------------------------------------ ! ! Return value and exit. ! !------------------------------------------------------------------------ vil_88d = MIN(VIL,maxvil) RETURN END FUNCTION vil_88d