


MODULE module_diag_afwa

    USE diag_functions

CONTAINS

  SUBROUTINE afwa_diagnostics_driver (   grid , config_flags     &
                             , moist                             &
                             , scalar                            &
                             , chem                              &
                             , th_phy , pi_phy , p_phy           &
                             , u_phy , v_phy                     &
                             , dz8w , p8w , t8w , rho            &
                             , ids, ide, jds, jde, kds, kde      &
                             , ims, ime, jms, jme, kms, kme      &
                             , ips, ipe, jps, jpe, kps, kpe      &
                             , its, ite, jts, jte                &
                             , k_start, k_end               )

    USE module_domain, ONLY : domain , domain_clock_get
    USE module_configure, ONLY : grid_config_rec_type, model_config_rec
    USE module_state_description
    USE module_model_constants
    USE module_utility
    USE module_streams, ONLY: history_alarm, auxhist2_alarm
    USE module_dm, ONLY: wrf_dm_sum_real, wrf_dm_maxval

    IMPLICIT NONE

    TYPE ( domain ), INTENT(INOUT) :: grid
    TYPE ( grid_config_rec_type ), INTENT(IN) :: config_flags

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe
    INTEGER             :: k_start , k_end, its, ite, jts, jte

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme , num_moist),    &
         INTENT(IN   ) ::                                moist

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme , num_scalar),    &
         INTENT(IN   ) ::                                scalar

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme , num_chem),     &
         INTENT(IN   ) ::                                 chem

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                               th_phy  &
                                              ,         pi_phy  &
                                              ,          p_phy  &
                                              ,          u_phy  &
                                              ,          v_phy  &
                                              ,           dz8w  &
                                              ,            p8w  &
                                              ,            t8w  &
                                              ,            rho

    
    
    CHARACTER*512 :: message
    CHARACTER*256 :: timestr 
    INTEGER :: i,j,k,nz,ostat
    INTEGER :: icing_opt
    REAL :: bdump
    INTEGER :: i_start, i_end, j_start, j_end
    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) ::      qrain  &
                                              ,          qsnow  &
                                              ,          qgrpl  &
                                              ,          qvapr  &
                                              ,         qcloud  &
                                              ,           qice  &
                                              ,         ncloud  &
                                              ,         ngraup  &
                                              ,             rh  &
                                              ,         rh_cld  &
                                              ,           ptot  &
                                              ,            z_e  &
                                              ,           zagl

    REAL, DIMENSION( ims:ime, jms:jme, 5 ) ::            dustc
    REAL, DIMENSION( ims:ime, jms:jme ) ::                rh2m  &
                                              ,          rh20m  &
                                              ,           tv2m  &
                                              ,          tv20m  &
                                              ,        wind10m  &
                                              ,       wup_mask  &
                                              ,       wind125m  &
                                              ,           llws  &
                                              ,         pwater

    LOGICAL :: do_buoy_calc
    REAL :: zlfc_msl, dum1, dum2, dum3, wind_vel, wind_blend
    REAL :: prate_mm_per_hr, factor
    REAL :: u1km, v1km, ublend, vblend, u2000, v2000, us, vs
    LOGICAL :: is_target_level

    
    
    TYPE(WRFU_Time) :: hist_time, aux2_time, CurrTime, StartTime
    TYPE(WRFU_TimeInterval) :: dtint, histint, aux2int
    LOGICAL :: is_after_history_dump, is_output_timestep, is_first_timestep
    INTEGER , PARAMETER :: DEBUG_LEVEL = 1

    
    
    write ( message, * ) 'inside afwa_diagnostics_driver'
    CALL wrf_debug( 100 , message )

    
    
    
    
    
    CALL WRFU_ALARMGET( grid%alarms( HISTORY_ALARM ), prevringtime=hist_time, &
         ringinterval=histint)
    CALL WRFU_ALARMGET( grid%alarms( AUXHIST2_ALARM ), prevringtime=aux2_time, &
         ringinterval=aux2int)

    
    
    CALL domain_clock_get ( grid, current_time=CurrTime, &
         simulationStartTime=StartTime, &            
         current_timestr=timestr, time_step=dtint )

    
    
    
    is_after_history_dump = ( Currtime .lt. hist_time + dtint )

    
    
    is_output_timestep = (Currtime .ge. hist_time + histint - dtint .or. &
                         Currtime .ge. aux2_time + aux2int - dtint )
    write ( message, * ) 'is output timestep? ', is_output_timestep
    CALL wrf_debug( 100 , message )

    
    
    is_first_timestep = ( Currtime .eq. StartTime + dtint )
        
    
    
    
    
    
    IF ( config_flags%afwa_bad_data_check .GT. 0 ) THEN
      IF ( ( is_output_timestep ) .AND. ( .NOT. is_first_timestep ) ) THEN      
        DO i=its, MIN( ide-1, ite )
          DO k=k_start, k_end
            DO j=jts, MIN( jde-1, jte )
              IF ( ( u_phy(i,k,j)  .GT.  300.  ) .OR. &
                   ( u_phy(i,k,j)  .LT. -300.  ) .OR. &
                   ( v_phy(i,k,j)  .GT.  300.  ) .OR. &
                   ( v_phy(i,k,j)  .LT. -300.  ) .OR. &
                   ( th_phy(i,k,j) .GT.  9999. ) .OR. &
                   ( th_phy(i,k,j) .LT.  99.   ) ) THEN
                write ( message, * ) "AFWA Diagnostics: ERROR - Model winds and/or " // &
                "potential temperature appear to be bad. If you do not want this check, " // &
                "set afwa_bad_data_check=0. i=",i,", j=",j,", k=",k,", u_phy=",u_phy(i,k,j), &
                ", v_phy=", v_phy(i,k,j),", th_phy=",th_phy(i,k,j)
                CALL wrf_error_fatal3("<stdin>",164,&
message )
              ENDIF
            ENDDO
          ENDDO
        ENDDO
      ENDIF
    ENDIF

    
    

    IF ( F_QV ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qvapr(i,k,j) = moist(i,k,j,P_QV)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QR ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qrain(i,k,j) = moist(i,k,j,P_QR)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QS ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qsnow(i,k,j) = moist(i,k,j,P_QS)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QG ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qgrpl(i,k,j) = moist(i,k,j,P_QG)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QC ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qcloud(i,k,j) = moist(i,k,j,P_QC)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QI ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            qice(i,k,j) = moist(i,k,j,P_QI)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QNC ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            ncloud(i,k,j) = scalar(i,k,j,P_QNC)
          ENDDO
        ENDDO
      ENDDO
    END IF
    IF ( F_QNG ) THEN
      DO i=ims, ime
        DO k=kms, kme
          DO j=jms, jme
            ngraup(i,k,j) = scalar(i,k,j,P_QNG)
          ENDDO
        ENDDO
      ENDDO
    END IF
    
    
    
    DO i=ims, ime
      DO k=kms, kme
        DO j=jms, jme
          ptot(i,k,j)=grid%pb(i,k,j)+grid%p(i,k,j)
        ENDDO
      ENDDO
    ENDDO

    
    
    DO i=ims, ime
      DO k=kms, kme
        DO j=jms, jme
          zagl(i,k,j)=grid%z(i,k,j)-grid%ht(i,j)
        ENDDO
      ENDDO
    ENDDO

    
    
    IF ( F_QV ) THEN
      DO i=ims,ime
        DO k=kms,kme    
          DO j=jms,jme
            rh(i,k,j)=calc_rh(ptot(i,k,j),grid%t_phy(i,k,j), qvapr(i,k,j))
          ENDDO
        ENDDO
      ENDDO
    ELSE
      CALL wrf_debug ( DEBUG_LEVEL, 'Option rh requires: QV' )
    END IF
    IF ( F_QV .AND. F_QC .AND. F_QI ) THEN
      DO i=ims,ime
        DO k=kms,kme    
          DO j=jms,jme
            rh_cld(i,k,j)=calc_rh(ptot(i,k,j),grid%t_phy(i,k,j), qvapr(i,k,j)+qcloud(i,k,j)+qice(i,k,j))
          ENDDO
        ENDDO
      ENDDO
    ELSE
      CALL wrf_debug ( DEBUG_LEVEL, 'Option rh_cld requires: QV, QC, QI' )
    END IF

    
    
    DO i=ims,ime
      DO j=jms,jme
        grid % afwa_precip(i,j) = grid%raincv(i,j) + grid%rainncv(i,j)
        grid % afwa_totprecip(i,j) = grid%rainc(i,j) + grid%rainnc(i,j)
      ENDDO
    ENDDO

    
    
    IF ( F_QV .AND. F_QC ) THEN
      nz=kme-kms+1
      DO i=ims,ime
        DO j=jms,jme
          grid % afwa_pwat ( i, j ) = Pwat( nz,                  &
                                            qvapr(i,kms:kme,j),  &
                                            qcloud(i,kms:kme,j), &
                                            dz8w(i,kms:kme,j),   &
                                            rho(i,kms:kme,j) )
        ENDDO
      ENDDO
    ELSE
      CALL wrf_debug ( DEBUG_LEVEL, 'Option pwat requires: QV, QC' )
    END IF

    
    
    IF ( is_after_history_dump ) THEN
      IF ( config_flags % afwa_severe_opt == 1 ) THEN
        DO j = jms, jme
          DO i = ims, ime
            grid % wspd10max(i,j) = 0.
            grid % afwa_llws(i,j) = 0.
          ENDDO
        ENDDO
      ENDIF
    ENDIF 

    
    
    
    
    
    
    
    
    
    
    IF ( config_flags % afwa_severe_opt == 1 ) THEN
      DO j = jms, jme
        DO i = ims, ime
          wind_vel = uv_wind ( grid % u10(i,j) , grid % v10(i,j) )
          prate_mm_per_hr = ( grid % afwa_precip(i,j) / grid % dt ) * 3600.
  
          
          
          IF ( prate_mm_per_hr .GT. 50. ) THEN
            is_target_level=.false.
            DO k=kms,kme    
              IF ( ( zagl(i,k,j) >= 1000. ) .and. &
                   ( .NOT. is_target_level ) .and. &
                   ( k .ne. kms ) ) THEN
                is_target_level = .true.
                u1km = u_phy(i,k-1,j) + (1000. - (zagl(i,k-1,j))) &
                       * ((u_phy(i,k,j) - u_phy(i,k-1,j))/(zagl(i,k,j)))
                v1km = v_phy(i,k-1,j) + (1000. - (zagl(i,k-1,j))) &
                       * ((v_phy(i,k,j) - v_phy(i,k-1,j))/(zagl(i,k,j)))
                EXIT 
              ENDIF
            ENDDO
            
            
            
            factor = MAX ( ( ( 150. - prate_mm_per_hr ) / 100. ), 0. )
            ublend = grid % u10(i,j) * factor + u1km * (1. - factor)
            vblend = grid % v10(i,j) * factor + v1km * (1. - factor)
            wind_blend = uv_wind ( ublend, vblend )
  
            
            
            IF ( wind_blend .GT. wind_vel ) THEN
              wind_vel = wind_blend
            ENDIF
          ENDIF
  
          IF ( wind_vel .GT. grid % wspd10max(i,j) ) THEN
            grid % wspd10max(i,j) = wind_vel
          ENDIF
        ENDDO
      ENDDO
    ENDIF

    
    
    IF ( config_flags % afwa_severe_opt == 1 ) THEN
    DO j = jts, jte
      DO i = its, ite
        is_target_level=.false.
        DO k=kms,kme    
          IF ( ( zagl(i,k,j) >= 609.6 ) .and. &
               ( .NOT. is_target_level ) .and. &
               ( k .ne. kms ) ) THEN
            is_target_level = .true.
            u2000 = u_phy(i,k-1,j) + (609.6 - (zagl(i,k-1,j))) &
                    * ((u_phy(i,k,j) - u_phy(i,k-1,j))/(zagl(i,k,j)))
            v2000 = v_phy(i,k-1,j) + (609.6 - (zagl(i,k-1,j))) &
                    * ((v_phy(i,k,j) - v_phy(i,k-1,j))/(zagl(i,k,j)))
            us = u2000 - grid % u10(i,j) 
            vs = v2000 - grid % v10(i,j) 
            llws(i,j) = uv_wind ( us , vs )
            IF ( llws(i,j) .gt. grid % afwa_llws(i,j) ) THEN
              grid % afwa_llws(i,j) = llws(i,j)
            ENDIF
            EXIT 
          ENDIF
        ENDDO
      ENDDO
    ENDDO
    ENDIF

    dustc(ims:ime,jms:jme,:)=0.
   
    
    
    
    IF ( config_flags % afwa_severe_opt == 1 ) THEN

      
      
      
      
      
      IF ( is_after_history_dump ) THEN
        DO j = jms, jme
          DO i = ims, ime
            grid%w_up_max(i,j) = 0.
            grid%w_dn_max(i,j) = 0.
            grid%tcoli_max(i,j) = 0.
            grid%grpl_flx_max(i,j) = 0.
            grid%up_heli_max(i,j) = 0.
            grid%afwa_tornado(i,j) = 0.
            grid%midrh_min_old(i,j) = grid%midrh_min(i,j) 
            grid%midrh_min(i,j) = 999.
            grid%afwa_hail(i,j) = 0.
          ENDDO
        ENDDO
      ENDIF  

      IF ( ( is_first_timestep ) .OR. ( is_output_timestep ) ) THEN
        do_buoy_calc = .true.
      ELSE
        do_buoy_calc = .false.
      ENDIF

      IF ( F_QV .AND. F_QR .AND. F_QC .AND. F_QI .AND. F_QS .AND. F_QG .AND. F_QNG ) THEN
        
        

        
        
        i_start = its
        i_end   = ite
        j_start = jts
        j_end   = jte

        IF ( config_flags%open_xs .OR. config_flags%specified .OR. &
             config_flags%nested) i_start = MAX( ids+1, its )
        IF ( config_flags%open_xe .OR. config_flags%specified .OR. &
             config_flags%nested) i_end   = MIN( ide-1, ite )
        IF ( config_flags%open_ys .OR. config_flags%specified .OR. &
             config_flags%nested) j_start = MAX( jds+1, jts )
        IF ( config_flags%open_ye .OR. config_flags%specified .OR. &
             config_flags%nested) j_end   = MIN( jde-1, jte )
        IF ( config_flags%periodic_x ) i_start = its
        IF ( config_flags%periodic_x ) i_end = ite

        CALL severe_wx_diagnostics ( grid % wspd10max             &
                               , grid % w_up_max                  &
                               , grid % w_dn_max                  &
                               , grid % up_heli_max               &
                               , grid % tcoli_max                 &
                               , grid % midrh_min_old             &
                               , grid % midrh_min                 &
                               , grid % afwa_hail                 &
                               , grid % afwa_cape                 &
                               , grid % afwa_cin                  &
                               , grid % afwa_zlfc                 &
                               , grid % afwa_plfc                 &
                               , grid % afwa_lidx                 &
                               , llws                             &
                               , grid % afwa_tornado              &
                               , grid % grpl_flx_max              &
                               , grid % u10                       &
                               , grid % v10                       &
                               , grid % w_2                       &
                               , grid % uh                        &
                               , grid % t_phy                     &
                               , grid % t2                        &
                               , grid % z                         &
                               , grid % ht                        &
                               , grid % tornado_mask              &
                               , grid % tornado_dur               &
                               , grid % dt                        &
                               , grid % afwa_pwat                 &
                               , u_phy                            &
                               , v_phy                            &
                               , ptot                             &
                               , qice                             &
                               , qsnow                            &
                               , qgrpl                            &
                               , ngraup                           &
                               , qvapr, qrain, qcloud             &
                               , rho                              &
                               , dz8w                             &
                               , rh                               &
                               , do_buoy_calc                     &
                               , ims, ime, jms, jme, kms, kme     &
                               , its, ite, jts, jte               &
                               , k_start, k_end                   &
                               , j_start, j_end, i_start, i_end   )

      ELSE
        CALL wrf_debug ( DEBUG_LEVEL, 'Option severe_wx_diagnostics requires: QV, QR, QC, QI, QS, QG, QNG' )
      END IF
    ENDIF   

    
    
    IF ( config_flags % afwa_ptype_opt == 1 ) THEN
    
      
      
      IF ( grid % itimestep .eq. 1) THEN
        DO i=ims,ime
          DO j=jms,jme
            grid % afwa_rain(i,j)=0.
            grid % afwa_snow(i,j)=0.
            grid % afwa_ice(i,j)=0.
            grid % afwa_fzra(i,j)=0.
            grid % afwa_snowfall(i,j)=0.
          ENDDO
        ENDDO
      ENDIF
  
      
      
      CALL precip_type_diagnostics ( grid % t_phy               &
                             , grid % t2                        &
                             , rh                               &
                             , grid % z                         &
                             , dz8w                             &
                             , grid % ht                        &
                             , grid % afwa_precip               &
                             , grid % swdown                    &
                             , grid % afwa_rain                 &
                             , grid % afwa_snow                 &
                             , grid % afwa_ice                  &
                             , grid % afwa_fzra                 &
                             , grid % afwa_snowfall             &
                             , grid % afwa_ptype_ccn_tmp        &
                             , grid % afwa_ptype_tot_melt       &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )
    ENDIF  
  
    
    
    
    IF ( is_output_timestep ) THEN      

      
      
      DO j = jms, jme
        DO i = ims, ime
          grid % afwa_mslp  ( i, j ) =   MSLP ( grid % ht ( i, j )           & 
                                              , grid % psfc ( i, j )         &
                                              , grid % z ( i, kms, j )       & 
                                              , qvapr ( i, kms, j )          &  
                                              , grid % t_phy ( i, kms, j ) )
        ENDDO
      ENDDO

      
      
      DO i=ims,ime
        DO j=jms,jme
          wind10m(i,j)=uv_wind(grid%u10(i,j),grid%v10(i,j))
        ENDDO
      ENDDO

      
      
      DO i=ims,ime
        DO j=jms,jme
          rh2m(i,j)=calc_rh(grid%psfc(i,j), grid%t2(i,j), grid%q2(i,j))
          tv2m(i,j)=grid%t2(i,j) * (1 + 0.61 * grid%q2(i,j))
        ENDDO
      ENDDO
 
      
      
      IF ( config_flags % afwa_buoy_opt == 1 ) THEN
        nz = k_end - k_start + 1

        
        
        DO j = jts, jte
          DO i = its, ite
            ostat = Buoyancy (                                   nz &
                                     ,      grid%t_phy(i,kms:kme,j) &
                                     ,              rh(i,kms:kme,j) &
                                     ,            ptot(i,kms:kme,j) &
                                     ,        grid % z(i,kms:kme,j) &
                                     ,                            1 &
                                     ,        grid % afwa_cape(i,j) &
                                     ,         grid % afwa_cin(i,j) &
                                     ,                     zlfc_msl &
                                     ,        grid % afwa_plfc(i,j) &
                                     ,        grid % afwa_lidx(i,j) &
                                     ,                        3 ) 
        
            
            
            IF ( zlfc_msl .ge. grid % ht ( i, j ) ) THEN
              grid % afwa_zlfc ( i, j ) = zlfc_msl - grid % ht ( i, j )
            ELSE
              grid % afwa_zlfc( i, j ) = -1.
            ENDIF


            
            IF ( grid % afwa_lidx ( i, j ) .ne. 999. ) THEN
              grid % afwa_lidx ( i, j ) = grid % afwa_lidx ( i, j ) + 273.15
            ENDIF
 
            
            
            ostat = Buoyancy (                                   nz &
                                     ,      grid%t_phy(i,kms:kme,j) &
                                     ,              rh(i,kms:kme,j) &
                                     ,            ptot(i,kms:kme,j) &
                                     ,        grid % z(i,kms:kme,j) &
                                     ,                            1 &
                                     ,     grid % afwa_cape_mu(i,j) &
                                     ,      grid % afwa_cin_mu(i,j) &
                                     ,                         dum1 &
                                     ,                         dum2 &
                                     ,                         dum3 &
                                     ,                        1 ) 
        
          ENDDO
        ENDDO
      ENDIF  

      IF ( config_flags % afwa_therm_opt == 1 ) THEN
        write ( message, * ) 'Calculating thermal indices'
        CALL wrf_debug( 100 , message )
        CALL thermal_diagnostics ( grid % t2                        &
                                 , grid % psfc                      &
                                 , rh2m                             &
                                 , wind10m                          &
                                 , grid % afwa_heatidx              &
                                 , grid % afwa_wchill               &
                                 , grid % afwa_fits                 &
                                 , ids, ide, jds, jde, kds, kde     &
                                 , ims, ime, jms, jme, kms, kme     &
                                 , ips, ipe, jps, jpe, kps, kpe )
      ENDIF  

      IF ( config_flags % afwa_turb_opt == 1 ) THEN
        write ( message, * ) 'Calculating turbulence indices'

        
        
        grid % afwa_tlyrbot = (/ 1500., 3000., 4600., 6100., 7600., 9100.,   &
                                  10700. /)
        grid % afwa_tlyrtop = (/ 3000., 4600., 6100., 7600., 9100., 10700.,  &
                                  12700. /)
        call turbulence_diagnostics ( u_phy                     &
                             , v_phy                            &
                             , grid % t_phy                     &
                             , ptot                             &
                             , zagl                             &
                             , grid % defor11                   &
                             , grid % defor12                   &
                             , grid % defor22                   &
                             , grid % afwa_turb                 &
                             , grid % afwa_llturb               &
                             , grid % afwa_llturblgt            &
                             , grid % afwa_llturbmdt            &
                             , grid % afwa_llturbsvr            &
                             
                             , 7                                &
                             , grid % afwa_tlyrbot              &
                             , grid % afwa_tlyrtop              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )
      ENDIF  

      
      
      
      IF ( config_flags % afwa_radar_opt == 1 .or. &
         config_flags % afwa_vil_opt == 1 ) THEN
        write ( message, * ) 'Calculating Radar'
        CALL wrf_debug( 100 , message )
        CALL wrf_dbzcalc ( rho                                  &
                             , grid%t_phy                       &
                             , qrain                            &
                             , qsnow                            &
                             , qgrpl                            &
                             , z_e                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )
      ENDIF  

      
      
      
      
      
      
      
      IF ( config_flags % afwa_radar_opt == 1 ) THEN
        write ( message, * ) 'Calculating derived radar variables'
        CALL wrf_debug( 100 , message )
        CALL radar_diagnostics ( grid % refd                    &
                             , grid % refd_com                  &

                             , grid % echotop                   &
                             , grid % z                         &
                             , z_e                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )
      ENDIF  

      
      
      IF ( config_flags % afwa_vil_opt == 1 ) THEN
        write ( message, * ) 'Calculating VIL'
        CALL wrf_debug( 100 , message )
        CALL vert_int_liquid_diagnostics ( grid % vil           &
                             , grid % radarvil                  &
                             , grid % t_phy                     &
                             , qrain                            &
                             , qsnow                            &
                             , qgrpl                            &
                             , z_e                              &
                             , dz8w                             &
                             , rho                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )
      ENDIF  

      IF ( F_QR .AND. F_QC .AND. F_QNC ) THEN
        
        
        IF ( config_flags % afwa_icing_opt == 1 ) THEN
  
          
          
          
          IF ( config_flags % mp_physics == GSFCGCESCHEME ) THEN
            icing_opt=1
          ELSEIF ( config_flags % mp_physics == ETAMPNEW ) THEN
            icing_opt=2
          ELSEIF ( config_flags % mp_physics == THOMPSON ) THEN
            icing_opt=3
          ELSEIF ( config_flags % mp_physics == WSM5SCHEME .OR.   &
                   config_flags % mp_physics == WSM6SCHEME ) THEN
            icing_opt=4
          ELSEIF ( config_flags % mp_physics == MORR_TWO_MOMENT .OR. &
                   config_flags % mp_physics == MORR_TM_AERO ) THEN  
  
            
            
            IF (config_flags % progn > 0) THEN
               icing_opt=6
            ELSE
               icing_opt=5
            ENDIF
          ELSEIF ( config_flags % mp_physics == WDM6SCHEME ) THEN
            icing_opt=7
          ELSE
            icing_opt=0  
          ENDIF
   
          IF ( icing_opt .NE. 0 ) THEN
            write ( message, * ) 'Calculating Icing with icing opt ',icing_opt 
            CALL wrf_debug( 100 , message )
            CALL icing_diagnostics ( icing_opt                      &
                                 , grid % fzlev                     &
                                 , grid % icing_lg                  &
                                 , grid % icing_sm                  &
                                 , grid % qicing_lg_max             &
                                 , grid % qicing_sm_max             &
                                 , grid % qicing_lg                 &
                                 , grid % qicing_sm                 &
                                 , grid % icingtop                  &
                                 , grid % icingbot                  &
                                 , grid % t_phy                     &
                                 , grid % z                         &
                                 , dz8w                             &
                                 , rho                              &
                                 , qrain                            &
                                 , qcloud                           &
                                 , ncloud                           &
                                 , ids, ide, jds, jde, kds, kde     &
                                 , ims, ime, jms, jme, kms, kme     &
                                 , ips, ipe, jps, jpe, kps, kpe )
          ELSE
            CALL wrf_debug ( DEBUG_LEVEL, 'Icing diagnostics not processed due to unknown MP scheme' )
          END IF
        ENDIF  
      ELSE
        CALL wrf_debug ( DEBUG_LEVEL, 'Option icing_diagnostics requires: QC, QR, QNC' )
      END IF

      
      
      IF ( config_flags % afwa_vis_opt == 1 ) THEN
   
        
        
        DO i=ims,ime
          DO j=jms,jme
            tv20m(i,j) = -999.
            rh20m(i,j) = -999.
            DO k = kps, MIN(kpe,kde-1)
              IF (tv20m (i,j) .eq. -999. .AND. zagl (i,k,j) .ge. 20.) THEN

                
                
                IF (k .eq. kps) THEN
                  tv20m(i,j) = tv2m(i,j) + &
                               (20. - 2.) / &
                               (zagl(i,k,j) - 2.) * &
                               (grid%t_phy(i,k,j) * (1 + 0.61 * qvapr(i,k,j)) - tv2m(i,j))
                  rh20m(i,j) = rh2m(i,j) + &
                               (20. - 2.) / &
                               (zagl(i,k,j) - 2.) * &
                               (rh(i,k,j) - rh2m(i,j))
                ELSE
                  tv20m(i,j) = grid%t_phy(i,k-1,j) * (1 + 0.61 * qvapr(i,k-1,j)) + &
                               ((20. - zagl(i,k-1,j)) / &
                               (zagl(i,k,j) - zagl(i,k-1,j))) * &
                               (grid%t_phy(i,k,j) * (1 + 0.61 * qvapr(i,k,j)) - &
                               grid%t_phy(i,k-1,j) * (1 + 0.61 * qvapr(i,k-1,j)))
                  rh20m(i,j) = rh (i,k-1,j) + &
                               ((20. - zagl (i,k-1,j)) / &
                               (zagl (i,k,j) - zagl (i,k-1,j))) * &
                               (rh (i,k,j) - rh (i,k-1,j))
                ENDIF
              ENDIF
            ENDDO
          ENDDO
        ENDDO

        
        
        DO i=ims,ime
          DO j=jms,jme
            wind125m(i,j) = -999.
            DO k = kps, MIN(kpe,kde-1)
              IF (wind125m (i,j) .eq. -999. .AND. zagl (i,k,j) .ge. 125.) THEN

                
                
                IF (k .eq. kps) THEN
                  wind125m(i,j) = uv_wind(u_phy(i,k,j),v_phy(i,k,j))
                ELSE
                  wind125m(i,j) = uv_wind(u_phy(i,k-1,j),v_phy(i,k-1,j)) + &
                               ((125. - zagl(i,k-1,j)) / &
                               (zagl(i,k,j) - zagl(i,k-1,j))) * &
                               (uv_wind(u_phy(i,k,j),v_phy(i,k,j)) - &
                               uv_wind(u_phy(i,k-1,j),v_phy(i,k-1,j)))
                ENDIF
              ENDIF
            ENDDO
          ENDDO
        ENDDO

        IF ( F_QC .AND. F_QR .AND. F_QI .AND. F_QS .AND. F_QG ) THEN
          write ( message, * ) 'Calculating visibility'
          CALL wrf_debug( 100 , message )
          CALL vis_diagnostics ( qcloud(ims:ime,k_start,jms:jme)  &
                               , qrain(ims:ime,k_start,jms:jme)   &
                               , qice(ims:ime,k_start,jms:jme)    &
                               , qsnow(ims:ime,k_start,jms:jme)   &
                               , qgrpl(ims:ime,k_start,jms:jme)   &
                               , rho(ims:ime,k_start,jms:jme)     &
                               , wind10m                          &
                               , wind125m                         &
                               , grid % afwa_pwat                 &
                               , grid % q2                        &
                               , rh2m                             &
                               , rh20m                            &
                               , tv2m                             &
                               , tv20m                            &
                               , dustc                            &
                               , grid % afwa_vis                  &
                               , grid % afwa_vis_dust             &
                               , grid % afwa_vis_alpha            &
                               , ids, ide, jds, jde, kds, kde     &
                               , ims, ime, jms, jme, kms, kme     &
                               , ips, ipe, jps, jpe, kps, kpe ) 
        ELSE
          CALL wrf_debug ( DEBUG_LEVEL, 'Option vis_diagnostics requires: QC, QR, QI, QS, QG' )
        END IF
      ENDIF

      IF ( F_QC .AND. F_QI .AND. F_QS ) THEN
        
        
        IF ( config_flags % afwa_cloud_opt == 1 ) THEN
          write ( message, * ) 'Calculating cloud'
          CALL wrf_debug( 100 , message )
          CALL cloud_diagnostics (qcloud                          &
                               , qice                             &
                               , qsnow                            &
                               , rh_cld                           &
                               , dz8w                             &
                               , rho                              &
                               , grid % z                         &
                               , grid % ht                        &
                               , grid % afwa_cloud                &
                               , grid % afwa_cloud_ceil           &
                               , ids, ide, jds, jde, kds, kde     &
                               , ims, ime, jms, jme, kms, kme     &
                               , ips, ipe, jps, jpe, kps, kpe )
        ENDIF
      ELSE
        CALL wrf_debug ( DEBUG_LEVEL, 'Option cloud_diagnostics requires: QC, QI, QS' )
      END IF

    ENDIF  

  END SUBROUTINE afwa_diagnostics_driver



  SUBROUTINE severe_wx_diagnostics ( wspd10max                  &
                             , w_up_max                         &
                             , w_dn_max                         &
                             , up_heli_max                      &
                             , tcoli_max                        &
                             , midrh_min_old                    &
                             , midrh_min                        &
                             , afwa_hail                        &
                             , cape                             &
                             , cin                              &
                             , zlfc                             &
                             , plfc                             &
                             , lidx                             &
                             , llws                             &
                             , afwa_tornado                     &
                             , grpl_flx_max                     &
                             , u10                              &
                             , v10                              &
                             , w_2                              &
                             , uh                               &
                             , t_phy                            &
                             , t2                               &
                             , z                                &
                             , ht                               &
                             , tornado_mask                     &
                             , tornado_dur                      &
                             , dt                               &
                             , pwat                             &
                             , u_phy                            &
                             , v_phy                            &
                             , p                                &
                             , qi                               &
                             , qs                               &
                             , qg                               &
                             , ng                               &
                             , qv, qr, qc                       &
                             , rho                              &
                             , dz8w                             &
                             , rh                               &
                             , do_buoy_calc                     &
                             , ims, ime, jms, jme, kms, kme     &
                             , its, ite, jts, jte               &
                             , k_start, k_end                   &
                             , j_start, j_end, i_start, i_end   )


    INTEGER, INTENT(IN) :: its, ite, jts, jte, k_start, k_end   &
                         , ims, ime, jms, jme, kms, kme         &
                         , j_start, j_end, i_start, i_end


    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                                    p  &
                                              ,            w_2  &
                                              ,          t_phy  &
                                              ,          u_phy  &
                                              ,          v_phy  &
                                              ,             qi  &
                                              ,             qs  &
                                              ,             qg  &
                                              ,             ng  &
                                              ,     qv, qr, qc  &
                                              ,            rho  &
                                              ,              z  &
                                              ,           dz8w  &
                                              ,             rh


    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(IN   ) ::                                  u10  &
                                              ,            v10  &
                                              ,      wspd10max  &
                                              ,             uh  &
                                              ,             t2  &
                                              ,             ht  &
                                              ,  midrh_min_old  &
                                              ,    up_heli_max  &
                                              ,           llws  &
                                              ,           pwat


    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(INOUT) ::                             w_up_max  & 
                                              ,       w_dn_max  &
                                              ,      tcoli_max  &
                                              ,      midrh_min  &
                                              ,      afwa_hail  &
                                              ,   afwa_tornado  &
                                              ,   grpl_flx_max  &
                                              ,   tornado_mask  &
                                              ,    tornado_dur 


    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(INOUT) ::                                 cape  &
                                              ,            cin  &
                                              ,           zlfc  &
                                              ,           plfc  &
                                              ,           lidx

    REAL, INTENT(IN) ::                                     dt
    LOGICAL, INTENT(IN) ::                        do_buoy_calc

    
    
    INTEGER :: i,j,k
    INTEGER :: kts,kte
    REAL    :: zagl, zlfc_msl, melt_term, midrh_term, hail, midrh
    REAL    :: dum1, dum2, dum3
    REAL    :: tornado, lfc_term, shr_term, midrh2_term, uh_term
    REAL    :: wind_vel, p_tot, tcoli, grpl_flx, w_n15, qg_n15
    INTEGER :: nz, ostat
    REAL, DIMENSION( ims:ime, jms:jme ) ::                w_up  &
                                              ,           w_dn  &
                                           , tornado_mask_prev  &
                                           ,  tornado_dur_prev
    REAL :: time_factor, time_factor_prev
    LOGICAL :: is_target_level

    
    
    DO i=ims,ime
      DO j=jms,jme
        is_target_level=.false.
        DO k=kms,kme    
          zagl = z(i,k,j) - ht(i,j)
          IF ( ( zagl >= 3500. ) .and. &
               ( .NOT. is_target_level ) .and. &
               ( k .ne. kms ) ) THEN
            is_target_level = .true.
            midrh = rh(i,k-1,j) + (3500. - (z(i,k-1,j) - ht(i,j))) &
                    * ((rh(i,k,j) - rh(i,k-1,j))/(z(i,k,j) - z(i,k-1,j)))
            IF ( midrh .lt. midrh_min(i,j) ) THEN
              midrh_min(i,j) = midrh
            ENDIF
          ENDIF
        ENDDO
      ENDDO
    ENDDO

    
    
    
    
    
    
    
    
    
    
 
    
    
    w_up=0.
    w_dn=0.
    DO j = jts, jte
      DO k = k_start, k_end
        DO i = its, ite
          p_tot = p(i,k,j) / 100.
 
          
          IF ( p_tot .GT. 400. .AND. w_2(i,k,j) .GT. w_up(i,j) ) THEN
            w_up(i,j) = w_2(i,k,j)
            IF ( w_up(i,j) .GT. w_up_max(i,j) ) THEN
              w_up_max(i,j) = w_up(i,j)
            ENDIF
          ENDIF
          IF ( p_tot .GT. 400. .AND. w_2(i,k,j) .LT. w_dn(i,j) ) THEN
            w_dn(i,j) = w_2(i,k,j)
            IF ( w_dn(i,j) .LT. w_dn_max(i,j) ) THEN
              w_dn_max(i,j) = w_dn(i,j)
            ENDIF
          ENDIF
        ENDDO
      ENDDO
    ENDDO
   
    
    
    DO j = jts, jte
      DO i = its, ite
        melt_term=max(t2(i,j)-288.15,0.)
        midrh_term=max(2*(min(midrh_min(i,j),midrh_min_old(i,j))-70.),0.)
        
        
        hail=max((w_up(i,j)/1.4)**1.1-melt_term-midrh_term,0.)
        hail=hail*((uh(i,j)/100)+0.25)
        IF ( hail .gt. afwa_hail(i,j) ) THEN
          afwa_hail(i,j)=hail
        ENDIF
      ENDDO
    ENDDO

    
    
    
    DO j = jts, jte
      DO i = its, ite
        tcoli=0.
        DO k = k_start, k_end
          tcoli =  tcoli + &
          (qi (i,k,j) + &
           qs (i,k,j) + &
           qg (i,k,j))  &
           *dz8w (i,k,j) * rho(i,k,j)
        ENDDO
        IF ( tcoli .GT. tcoli_max(i,j) ) THEN
          tcoli_max(i,j) = tcoli
        ENDIF
      ENDDO
    ENDDO

    
    
    
    
    
    DO j = jts, jte
      DO i = its, ite
        grpl_flx=0
        w_n15=-999.
        DO k = k_start, k_end
          
          
          
          
          IF ( t_phy (i,k,j) .LE. 258.15 .AND. w_n15 .EQ. -999. .AND.   &
               k .GT. k_start .AND. qg (i,k,j) .GT. 1.E-20 ) THEN
            w_n15 = w_2 (i,k,j)
            qg_n15 = 1000. * qg (i,k,j) 
            grpl_flx =  qg_n15 * w_n15   
          ENDIF
        ENDDO
        IF ( grpl_flx .GT. grpl_flx_max(i,j) ) THEN
          grpl_flx_max(i,j) = grpl_flx
        ENDIF
      ENDDO
    ENDDO

    
    
    IF ( do_buoy_calc ) THEN
      nz = k_end - k_start + 1
      DO j = jts, jte
        DO i = its, ite
          ostat = Buoyancy (                                   nz &
                                       , t_phy(i,kms:kme      ,j) &
                                       ,    rh(i,kms:kme      ,j) &
                                       ,     p(i,kms:kme      ,j) &
                                       ,     z(i,kms:kme      ,j) &
                                       ,                        1 &
                                       ,                cape(i,j) &
                                       ,                 cin(i,j) &
                                       ,                 zlfc_msl &
                                       ,                plfc(i,j) &
                                       ,                lidx(i,j) &
                                       ,                        3 ) 


          
          IF ( lidx ( i, j ) .ne. 999. ) lidx ( i, j ) = lidx ( i, j ) + 273.15
  
          
          
          IF ( zlfc_msl .ge. 0. ) THEN
            zlfc ( i, j ) = zlfc_msl - ht ( i, j )
          ELSE
            zlfc( i, j ) = -1.
          ENDIF

        ENDDO
      ENDDO
    ENDIF

    
    
    
    tornado_dur_prev(:,:)=tornado_dur(:,:)
    tornado_mask_prev(:,:)=tornado_mask(:,:)

    
    
    tornado_mask(:,:)=0.
    tornado_dur(:,:)=0.

    DO j = j_start, j_end
      DO i = i_start, i_end
        tornado = 0.

        
        
        IF ( zlfc(i,j) .ge. 0. ) THEN
          uh_term = min(max((uh(i,j) - 25.) / 50., 0.), 1.)
          shr_term = min(max((llws(i,j) - 2.) / 10., 0.), 1.)
          lfc_term = min(max((3000. - zlfc(i,j)) / 1500., 0.), 1.)
          midrh2_term = min(max((90. - &
                        min(midrh_min(i,j),midrh_min_old(i,j))) / 30., 0.), 1.)
          tornado = 50. * uh_term * shr_term * lfc_term * midrh2_term
        ENDIF

        
        
        
        IF (tornado .GT. 0.) THEN
          tornado_mask(i,j) = 1.
        ENDIF
  
        
        
        
        IF ( ( tornado_mask(i,j) .GT. 0.5 )  .OR. &
           ( MAXVAL(tornado_mask_prev(i-1:i+1,j-1:j+1)) .GT. 0.5 ) ) THEN
          tornado_dur(i,j) = MAXVAL(tornado_dur_prev(i-1:i+1,j-1:j+1)) + dt
        ENDIF

        
        
        
        time_factor = MIN(tornado_dur(i,j)/900.,1.)
        tornado = tornado * time_factor

        
        
        
        
        
        
        
        
        
        

        
        
        
        IF ( tornado .GT. afwa_tornado(i,j) ) THEN
          afwa_tornado(i,j) = tornado
        ENDIF
      ENDDO
    ENDDO

  END SUBROUTINE severe_wx_diagnostics



  SUBROUTINE vert_int_liquid_diagnostics ( vil                  &
                             , radarvil                         &
                             , t_phy                            &
                             , qrain                            &
                             , qsnow                            &
                             , qgrpl                            &
                             , z_e                              &
                             , dz8w                             &
                             , rho                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN) ::                                     rho  &
                                              ,          qrain  &
                                              ,          qsnow  &
                                              ,          qgrpl  & 
                                              ,          t_phy  &
                                              ,            z_e  & 
                                              ,           dz8w

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(INOUT) ::                                  vil  &
                                              ,       radarvil

    
    
    INTEGER :: i,j,k,ktime

    
    
    
    DO i = ips, MIN(ipe,ide-1)
    DO j = jps, MIN(jpe,jde-1)
      vil (i,j) = 0.0
      DO k = kps, MIN(kpe,kde-1)
        vil (i,j) =  vil (i,j) + &
         (qrain (i,k,j) + &
          qsnow (i,k,j) + &
          qgrpl (i,k,j))  &
          *dz8w (i,k,j) * rho(i,k,j)
      ENDDO
    ENDDO
    ENDDO

    
    
    
    
    DO i = ips, MIN(ipe,ide-1)
    DO j = jps, MIN(jpe,jde-1)
      radarvil (i,j) = 0.0
      DO k = kps, MIN(kpe,kde-1)
        radarvil (i,j) = radarvil (i,j) + &
        0.00344 * z_e(i,k,j)**0.57143 &
        *dz8w (i,k,j)/1000.0
      END DO
    END DO
    END DO

  END SUBROUTINE vert_int_liquid_diagnostics



  SUBROUTINE icing_diagnostics ( icing_opt                      &
                             , fzlev                            &
                             , icing_lg                         &
                             , icing_sm                         & 
                             , qicing_lg_max                    &
                             , qicing_sm_max                    &
                             , qicing_lg                        &
                             , qicing_sm                        &
                             , icingtop                         &
                             , icingbot                         &
                             , t_phy                            &
                             , z                                &
                             , dz8w                             &
                             , rho                              &
                             , qrain                            &
                             , qcloud                           &
                             , ncloud                           &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    INTEGER, INTENT(IN) :: icing_opt

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN) ::                                       z  &
                                              ,          qrain  &
                                              ,         qcloud  &
                                              ,         ncloud  &
                                              ,            rho  &
                                              ,           dz8w  &
                                              ,          t_phy

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(  OUT) ::                                fzlev  &
                                              ,       icing_lg  &
                                              ,       icing_sm  &
                                              ,  qicing_lg_max  &
                                              ,  qicing_sm_max  &
                                              ,       icingtop  &
                                              ,       icingbot

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(  OUT) ::                            qicing_lg  &
                                              ,      qicing_sm
         

    
    
    INTEGER :: i,j,k,ktime,ktop,kbot
    REAL    :: qcfrac_lg, qcfrac_sm, qc, qr, small, all

    
    
    fzlev (ips:ipe,jps:jpe) = -999.        
    icingtop (ips:ipe,jps:jpe) = -999.     
    icingbot (ips:ipe,jps:jpe) = -999.     
    icing_lg (ips:ipe,jps:jpe) = 0.        
    icing_sm (ips:ipe,jps:jpe) = 0.
    qicing_lg_max (ips:ipe,jps:jpe) = 0. 
    qicing_sm_max (ips:ipe,jps:jpe) = 0. 
    qicing_sm(ips:ipe,kps:kpe,jps:jpe)=0.
    qicing_lg(ips:ipe,kps:kpe,jps:jpe)=0.   

    
    
    DO i = ips, MIN(ipe,ide-1)
    DO j = jps, MIN(jpe,jde-1)

      
      
      ktop=-1
      kbot=-1
      DO k = kps, MIN(kpe,kde-1)
        IF (t_phy(i,k,j) .lt. 273.15) THEN

          
          
          
          
          
          qc = qcloud (i,k,j)
          qr = qrain (i,k,j)
          nc = ncloud(i,k,j)
          den = rho(i,k,j)
          qcfrac_lg = 0.
          qcfrac_sm = 0.
          
          
          
          IF (icing_opt .eq. 2) THEN
            IF (qc .lt. 2.5E-4) THEN
              qcfrac_lg = 395000. * qc**2. + 102.9 * qc
            ELSEIF (qc .lt. 1.4E-3) THEN
              qcfrac_lg = 276.1 * qc - 0.01861
            ELSE
              qcfrac_lg = 0.3 * log(641.789 * qc) + 0.4
            ENDIF

          
          

          
          
          
          
          
          
          
          
          
          

          
          
          
          ELSEIF ((icing_opt .eq. 3) .OR. (icing_opt .eq. 4)) THEN
            IF (qc .lt. 5.E-4) THEN
              qcfrac_lg = 50420.0 * qc**2. + 29.39 * qc
            ELSEIF (qc .lt. 1.4E-3) THEN
              qcfrac_lg = 97.65 * qc - 0.02152
            ELSE
              qcfrac_lg = 0.2 * log(646.908 * qc) + 0.135
            ENDIF

          
          
          ELSEIF (icing_opt .eq. 5) THEN
            IF (qc .lt. 1.4E-3) THEN
              qcfrac_lg = 28000. * qc**2. + 0.1 * qc 
            ELSEIF (qc .lt. 2.6E-3) THEN
              qcfrac_lg = 112.351 * qc - 0.102272
            ELSE 
              qcfrac_lg = 0.3 * log(654.92 * qc) * 0.301607
            ENDIF

          
          
          ELSEIF ((icing_opt .eq. 6) .OR. (icing_opt .eq. 7)) THEN
            IF ((qc .gt. 1.0E-12) .and. (nc .gt. 1.0E-12)) THEN
               small = -nc * exp(-nc*3141.59265*(5.E-5)**3./(6000.*den*qc))+nc
               all = -nc * exp(-nc*3141.59265*(2.)**3./(6000.*den*qc))+nc
               qcfrac_lg = 1. - (small / all)
            ELSE
               qcfac_lg = 0.
            ENDIF
          ENDIF
          qcfrac_lg = max(qcfrac_lg, 0.)
          
          
          
          IF (icing_opt .ne. 0 ) THEN
            qcfrac_sm = 1 - qcfrac_lg
          ENDIF

          
          
          qicing_lg (i,k,j) = max(qr + qcfrac_lg * qc, 0.)
          qicing_sm (i,k,j) = max(qcfrac_sm * qc, 0.)        

          
          
          icing_lg (i,j) = icing_lg (i,j) + qicing_lg (i,k,j) &
                            * dz8w (i,k,j) * rho(i,k,j)
          icing_sm (i,j) = icing_sm (i,j) + qicing_sm (i,k,j) &
                            * dz8w (i,k,j) * rho(i,k,j)

          
          
          IF ( qicing_lg(i,k,j) .gt. qicing_lg_max(i,j) ) THEN
            qicing_lg_max (i,j) = qicing_lg(i,k,j)
          ENDIF
          IF ( qicing_sm(i,k,j) .gt. qicing_sm_max(i,j) ) THEN
            qicing_sm_max (i,j) = qicing_sm(i,k,j)
          ENDIF
           
          
          
          IF (fzlev (i,j) .eq. -999.) THEN  
            IF (k .ne. kps) THEN  
              fzlev (i,j) = z (i,k-1,j) + &
                             ((273.15 - t_phy (i,k-1,j)) &
                            /(t_phy (i,k,j) - t_phy (i,k-1,j))) &
                            *(z (i,k,j) - z (i,k-1,j))
            ELSE  
              fzlev(i,j) = z (i,k,j)
            ENDIF
          ENDIF

          
          
          
          
          IF ((qicing_lg (i,k,j) + qicing_sm (i,k,j)) .ge. 1.E-5) THEN
            IF (kbot .eq. -1) kbot = k  
            ktop=k
          ENDIF
        ENDIF
      END DO

      
      
      
      IF (kbot .ne. -1) THEN
        IF (kbot .ne. kps) THEN 
          icingbot (i,j) = z (i,kbot-1,j) + ((1.E-5 - &
                   (qicing_lg (i,kbot-1,j) + qicing_sm (i,kbot-1,j))) &
                  / ((qicing_lg (i,kbot,j) + qicing_sm (i,kbot,j)) &
                  - (qicing_lg (i,kbot-1,j) + qicing_sm (i,kbot-1,j)))) &
                  * (z (i,kbot,j) - z (i,kbot-1,j))
          icingbot (i,j) = MAX(icingbot (i,j), fzlev (i,j))
        ELSE  
          icingbot (i,j) = z(i,kbot,j)
        ENDIF
      ENDIF

      
      
      
      IF (ktop .ne. -1 .and. ktop .ne. kpe) THEN 
        icingtop (i,j) = z (i,ktop,j) + ((1.E-5 - &
                 (qicing_lg (i,ktop,j) + qicing_sm (i,ktop,j))) &
                 / ((qicing_lg (i,ktop+1,j) + qicing_sm (i,ktop+1,j)) &
                 - (qicing_lg (i,ktop,j) + qicing_sm (i,ktop,j)))) &
                 * (z (i,ktop+1,j) - z (i,ktop,j))
        icingtop (i,j) = MAX(icingtop (i,j), icingbot (i,j))
      ENDIF
    END DO
    END DO

  END SUBROUTINE icing_diagnostics



  SUBROUTINE radar_diagnostics ( refd                           &
                             , refd_com                         &

                             , echotop                          &
                             , z                                &
                             , z_e                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN) ::                                       z  &
                                              ,            z_e

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(INOUT) ::                                 refd  &
                                              ,       refd_com  &

                                              ,        echotop

    
    
    INTEGER :: i,j,k,ktime
    
    DO j = jps, MIN(jpe,jde-1)
    DO i = ips, MIN(ipe,ide-1)
      ktop = -1  
      echotop (i,j) = 0.
      refd_com (i,j) = 0.
      refd (i,j) = 0.
      DO k = kps, MIN(kpe,kde-1)
        IF (z_e(i,k,j) .gt. 1.e-20) THEN

          
          
          IF (k == kps) refd(i,j) = MAX(10.0 * log10(z_e(i,k,j)),0.)
   




          
          
          IF (10.0 * log10(z_e(i,k,j)) .gt. refd_com(i,j)) THEN
            refd_com(i,j) = 10.0 * log10(z_e(i,k,j))
          ENDIF
        ENDIF
        
        
        
        IF ( z_e(i,k,j) .gt. 63.0957) THEN
          ktop = k
        ENDIF
      END DO
      IF ( ktop .ne. -1 ) THEN  
        echotop (i,j) = z (i,ktop,j) + &
                          ((63.0957 - z_e (i,ktop,j)) &
                         /(z_e (i,ktop+1,j) - z_e (i,ktop,j))) &
                         *(z (i,ktop+1,j) - z (i,ktop,j))
      ENDIF
    END DO
    END DO

  END SUBROUTINE radar_diagnostics



  SUBROUTINE wrf_dbzcalc( rho                                   &
                             , t_phy                            &
                             , qr                               &
                             , qs                               &
                             , qg                               &
                             , z_e                              &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                                  rho  &
                                              ,          t_phy  &
                                              ,             qr  &
                                              ,             qs  &
                                              ,             qg

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(  OUT) ::                                  z_e

    REAL :: factor_r, factor_s, factor_g, factorb_s, factorb_g, ronv, sonv, gonv
    REAL :: temp_c, rhoair, qgr, qra, qsn
    INTEGER :: i, j, k

    INTEGER, PARAMETER :: iBrightBand = 1
    REAL, PARAMETER :: T_0 = 273.15
    REAL, PARAMETER :: PI = 3.1415926536
    REAL, PARAMETER :: rgas=287.04, gamma_seven = 720.0, alpha2 = 0.224

    
    
    REAL, PARAMETER :: rho_w = 1000.0, rho_r = 1000.0, rho_s = 100.0
    REAL, PARAMETER :: rho_g = 400.0, rho_i = 890.0
    REAL, PARAMETER :: ron=8.e6, son=2.e7, gon=5.e7, r1=1.e-15
    REAL, PARAMETER :: ron_min = 8.e6, ron2=1.e10
    REAL, PARAMETER :: ron_qr0 = 0.0001, ron_delqr0 = 0.25*ron_qr0
    REAL, PARAMETER :: ron_const1r = (ron2-ron_min)*0.5
    REAL, PARAMETER :: ron_const2r = (ron2+ron_min)*0.5

    
    
    ronv = 8.e6    
    sonv = 2.e7    
    gonv = 4.e6    

    factor_r = gamma_seven * 1.e18 * (1./(pi*rho_r))**1.75
    factor_s = gamma_seven * 1.e18 * (1./(pi*rho_s))**1.75  &
              * (rho_s/rho_w)**2 * alpha2
    factor_g = gamma_seven * 1.e18 * (1./(pi*rho_g))**1.75  &
              * (rho_g/rho_w)**2 * alpha2

    
    
    DO j = jps, jpe
    DO k = kps, kpe
    DO i = ips, ipe

      factorb_s = factor_s
      factorb_g = factor_g

      
      
      
      IF( iBrightBand == 1 ) THEN
        IF (t_phy(i,k,j) > T_0) THEN
          factorb_s = factor_s /alpha2
          factorb_g = factor_g /alpha2
        ENDIF
      ENDIF
 
      
      
      temp_c = amin1(-0.001, t_phy(i,k,j)- T_0)
      sonv = amin1(2.0e8, 2.0e6*exp(-0.12*temp_c))
      gonv = gon
      qgr = QG(i,k,j)
      qra = QR(i,k,j)
      qsn = QS(i,k,j)
      IF (qgr.gt.r1) THEN
        gonv = 2.38*(pi*rho_g/(rho(i,k,j)*qgr))**0.92
        gonv = max(1.e4, min(gonv,gon))
      ENDIF
      ronv = ron2
      IF (qra.gt. r1) THEN
        ronv = ron_const1r*tanh((ron_qr0-qra)/ron_delqr0) + ron_const2r
      ENDIF
 
      IF (qra < 0.0 ) qra = 0.0
      IF (qsn < 0.0 ) qsn = 0.0
      IF (qgr < 0.0 ) qgr = 0.0
      z_e(i,k,j) = factor_r * (rho(i,k,j) * qra)**1.75 / ronv**.75 + &
                     factorb_s * (rho(i,k,j) * qsn)**1.75 / sonv**.75 + &
                     factorb_g * (rho(i,k,j) * qgr)**1.75 / gonv**.75
 
      IF ( z_e(i,k,j) < 0.0 ) z_e(i,k,j) = 0.0
 
    END DO
    END DO
    END DO

  END SUBROUTINE wrf_dbzcalc



  SUBROUTINE precip_type_diagnostics ( t_phy                    &
                             , t2                               &
                             , rh                               &
                             , z                                &
                             , dz8w                             &
                             , ht                               &
                             , precip                           &
                             , swdown                           &
                             , rain                             &
                             , snow                             &
                             , ice                              &
                             , frz_rain                         &
                             , snowfall                         &
                             , ccn_tmp                          &
                             , total_melt                       &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                                t_phy  &
                                              ,             rh  &
                                              ,              z  &
                                              ,           dz8w
    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(IN   ) ::                                   t2  &
                                              ,             ht  &
                                              ,         precip  &
                                              ,         swdown
    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(INOUT) ::                             snowfall  &
                                              ,           rain  &
                                              ,       frz_rain  &
                                              ,           snow  &
                                              ,            ice
    REAL, INTENT(IN) :: ccn_tmp
    REAL, INTENT(IN) :: total_melt

    
    
    REAL, DIMENSION( ims:ime, jms:jme ) ::                      &
                                     melt                       &
                                   , mod_2m_tmp                 &
                                   , cloud_top_tmp              &
                                   , maxtmp

    INTEGER, DIMENSION( ims:ime, jms:jme ) ::                   &
                                     cloud_top_k_index          &
                                   , precip_type

    LOGICAL, DIMENSION (ims:ime, jms:jme ) ::                   &
                                     saturation 

    REAL, PARAMETER :: snow_ratio=5.0

    
    
    
    
    
    DO i=ips,ipe
    DO j=jps,jpe
  
      saturation(i,j)=.false.
      melt(i,j)=0.0 
      precip_type(i,j)=0
        
      
      
      
      mod_2m_tmp(i,j)=t2(i,j)+(swdown(i,j)/100.0)
      maxtmp(i,j)=mod_2m_tmp(i,j)
  
      
      
      IF (precip(i,j) .gt. 0.0) THEN
        
        IF (mod_2m_tmp(i,j) .gt. 275.15) THEN
          precip_type(i,j)=1  
        ELSE
  
          
          
          
          
          cloud_top_k_index(i,j)=kpe
          DO k=kpe,kps,-1
            IF ((z(i,k,j)-ht(i,j)) .gt. 0.0) THEN
              IF (t_phy(i,k,j) .gt. maxtmp(i,j)) THEN
                maxtmp(i,j)=t_phy(i,k,j)
              ENDIF
              IF (rh(i,k,j) .gt. 80 .and. saturation(i,j) .eqv. .false.) THEN
                cloud_top_tmp(i,j)=t_phy(i,k,j)
                cloud_top_k_index(i,j)=k
                saturation(i,j)=.true.
                precip_type(i,j)=2 
              ENDIF
              IF (rh(i,k,j) .le. 70 .and. saturation(i,j) .eqv. .true.) THEN
                saturation(i,j)=.false.
              ENDIF
            ENDIF
          ENDDO

          
          
          
          IF (cloud_top_tmp(i,j) .le. ccn_tmp .and. &
          maxtmp(i,j) .le. 273.15) THEN
            precip_type(i,j)=2  
          ENDIF

          
          
          
          DO k=cloud_top_k_index(i,j),kps,-1
            IF ((z(i,k,j)-ht(i,j)) .gt. 0.0) THEN
 
              
              
              
              IF (cloud_top_tmp(i,j) .eq. t_phy(i,k,j) .and. &
              cloud_top_tmp(i,j) .gt. ccn_tmp) THEN
                 precip_type(i,j)=1  
              ENDIF

              
              
              
              
              IF ((precip_type(i,j) .eq. 2 .or. precip_type(i,j) .eq. 3) .and. &
              t_phy(i,k,j) .gt. 273.15) THEN
                melt(i,j)=melt(i,j)+9.8*(((t_phy(i,k,j)-273.15)/273.15)* &
                          (dz8w(i,k,j)))
                IF (melt(i,j) .gt. total_melt) THEN
                  precip_type(i,j)=1  
                  melt(i,j)=0.0  
                ENDIF
              ENDIF

              
              
              
              
              IF (t_phy(i,k,j) .le. 273.15 .and. &
              melt(i,j) .gt. total_melt/4.0 .and. &
              (precip_type(i,j) .eq. 2 .or. precip_type(i,j) .eq. 3)) THEN
                precip_type(i,j)=3  
                melt(i,j)=0.0
              ENDIF
             
              
              
              
              IF (precip_type(i,j) .eq. 1) THEN
                IF (t_phy(i,k,j) .le. ccn_tmp) THEN
                  precip_type(i,j)=3  
                ENDIF
              ENDIF
            ENDIF  
          ENDDO  
        ENDIF  

        
        
        IF (precip_type(i,j) .eq. 3) THEN 
          ice(i,j)=ice(i,j)+precip(i,j)
        ENDIF
        IF (precip_type(i,j) .eq. 2) THEN
          snow(i,j)=snow(i,j)+precip(i,j)
          snowfall(i,j)=snowfall(i,j)+snow_ratio*precip(i,j) &
                        *(5.-mod_2m_tmp(i,j)+273.15)**0.4
        ENDIF
        IF (precip_type(i,j) .eq. 1) THEN
          IF (mod_2m_tmp(i,j) .gt. 273.15) THEN
            rain(i,j)=rain(i,j)+precip(i,j)
          ELSE
            frz_rain(i,j)=frz_rain(i,j)+precip(i,j)
          ENDIF
        ENDIF

      ENDIF  

    ENDDO  
    ENDDO  

  END SUBROUTINE precip_type_diagnostics



  SUBROUTINE vis_diagnostics ( qcloud                           &
                             , qrain                            &
                             , qice                             &
                             , qsnow                            &
                             , qgrpl                            &
                             , rho                              &
                             , wind10m                          &
                             , wind125m                         &
                             , pwater                           &
                             , q2m                              &
                             , rh2m                             &
                             , rh20m                            &
                             , tv2m                             &
                             , tv20m                            &
                             , dustc                            &
                             , vis                              &
                             , vis_dust                         &
                             , vis_alpha                        &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    INTEGER, PARAMETER :: ndust=5

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(IN   ) ::                               qcloud  &
                                              ,          qrain  &
                                              ,           qice  & 
                                              ,          qsnow  & 
                                              ,          qgrpl  & 
                                              ,            rho  & 
                                              ,        wind10m  & 
                                              ,       wind125m  & 
                                              ,         pwater  & 
                                              ,           rh2m  &
                                              ,            q2m  &
                                              ,          rh20m  &
                                              ,           tv2m  &
                                              ,          tv20m
    REAL, DIMENSION( ims:ime, jms:jme, ndust ),                 &
         INTENT(IN   ) ::                                dustc
    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(  OUT) ::                                  vis  &
                                              ,       vis_dust  &
                                              ,      vis_alpha

    
    
    INTEGER :: i,j,k,d
    REAL, PARAMETER :: visfactor=3.912
    REAL, DIMENSION (ndust) :: dustfact
    REAL :: bc, br, bi, bs, dust_extcoeff, hydro_extcoeff, extcoeff, vis_haze
    REAL :: tvd, rh, prob_ext_coeff_gt_p29, haze_ext_coeff
    REAL :: vis_hydlith, alpha_haze

    
    
    
    dustfact=(/1.470E-6,7.877E-7,4.623E-7,2.429E-7,1.387E-7/)

    DO i=ims,ime
      DO j=jms,jme

        
        
        
        

        
        
        
        
        
        
        
        
        
        
        
        br=1.1*(1000.*rho(i,j)*(qrain(i,j)+qgrpl(i,j)))**0.75
        bs=10.36*(1000.*rho(i,j)*qsnow(i,j))**0.78
        hydro_extcoeff=(br+bs)/1000.   

        
        
        dust_extcoeff=0.
        DO d=1,ndust
          dust_extcoeff=dust_extcoeff+dustfact(d)*dustc(i,j,d)
        ENDDO

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

        
        
        
        
        
        vis_haze=999999.
        IF (q2m(i,j) .gt. 0.) THEN
          
          vis_haze=1500.*(105.-rh2m(i,j))*(5./min(1000.*q2m(i,j),5.))
        ENDIF
 
        
        
        
        
        
        
        
        
        
        
        
        
        alpha_haze=3.6
        IF (q2m(i,j) .gt. 0.) THEN
          alpha_haze=0.1 + pwater(i,j)/25.     + wind125m(i,j)/3. + &
                          (100.-rh2m(i,j))/10. + 1./(1000.*q2m(i,j))
          alpha_haze=min(alpha_haze,3.6)
        ENDIF
        
        
        
        
        extcoeff=hydro_extcoeff+dust_extcoeff
        IF (extcoeff .gt. 0.) THEN
          vis_hydlith=min(visfactor/extcoeff, 999999.)
        ELSE
          vis_hydlith=999999.
        ENDIF

        
        
        
        
        
        IF (vis_hydlith < vis_haze) THEN
           vis(i,j)=vis_hydlith
           vis_alpha(i,j)=3.6
        ELSE
           vis(i,j)=vis_haze
           vis_alpha(i,j)=alpha_haze
        ENDIF

        
        
        
        IF (dust_extcoeff .gt. 0.) THEN
          vis_dust(i,j)=MIN(visfactor/dust_extcoeff,999999.)
        ELSE
          vis_dust(i,j)=999999.
        ENDIF
      ENDDO
    ENDDO

  END SUBROUTINE vis_diagnostics
  
  

  SUBROUTINE cloud_diagnostics (qcloud                          &
                             , qice                             &
                             , qsnow                            &
                             , rh                               &
                             , dz8w                             &
                             , rho                              &
                             , z                                &
                             , ht                               &
                             , cloud                            &
                             , cloud_ceil                       &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                               qcloud  &
                                              ,           qice  & 
                                              ,          qsnow  & 
                                              ,             rh  & 
                                              ,           dz8w  & 
                                              ,            rho  &
                                              ,              z

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(IN   ) ::                                   ht

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(  OUT) ::                                cloud  &
                                              ,     cloud_ceil

    
    
    INTEGER :: i, j, k
    REAL    :: tot_cld_cond, maxrh, cld_frm_cnd, cld_frm_rh, z_maxrh
    REAL    :: snow_extcoeff, vis_snow, cloud_lo, zagl_up, zagl_lo
    REAL, PARAMETER :: min_ceil = 125.    

    
    
    
    DO i=ims,ime
      DO j=jms,jme

        
        
        tot_cld_cond = 0.
        cloud(i,j) = 0.
        maxrh = -9999.
        cloud_ceil(i,j) = -9999.
        cloud_lo = 0.

        
        
        DO k=kms,kme

          

          
          
          
          IF ( z(i,k,j) - ht (i,j) .gt. min_ceil ) THEN

            
            
            IF (rh (i,k,j) .gt. maxrh) THEN
              maxrh = rh (i,k,j)
              z_maxrh = z(i,k,j)
            ENDIF










            
            
            
            
            
            
            
            
            
            
            cld_frm_rh = MAX(((rh (i,k,j) - 90.) / 10.),0.)
            cloud (i,j) = cloud (i,j) + ( cld_frm_rh * dz8w (i,k,j) ) / 250.

            
            
            
            
            
            
            
            
            
            IF ( cloud_ceil (i,j) .eq. -9999. .and. cloud (i,j) .gt. 0.8 ) THEN
              zagl_up = z (i,k,j) - ht (i,j)
              IF ( k .EQ. kps ) THEN
                cloud_ceil (i,j) = zagl_up
              ELSE
                zagl_lo = z (i,k-1,j) - ht (i,j)
                cloud_ceil (i,j) = zagl_lo + &
                             ((0.8 - cloud_lo) / &
                             (cloud (i,j) - cloud_lo)) * &
                             (zagl_up - zagl_lo)
                cloud_ceil (i,j) = MAX(cloud_ceil (i,j),ceil_min)
              ENDIF
            ENDIF
            
            
            
            cloud_lo=cloud(i,j)
          ENDIF
        ENDDO

        
        
        
        
        
        IF (cloud_ceil (i,j) .eq. -9999.) THEN
          cloud_ceil (i,j) = z_maxrh - ht (i,j)
        ENDIF

        
        
        
        IF (qsnow (i,1,j) .GT. 0. .AND. rho (i,1,j) .GT. 0.) THEN
          snow_extcoeff = 25. * (1000. * rho(i,1,j) * qsnow (i,1,j))**0.78
          snow_extcoeff = snow_extcoeff / 1000.
          vis_snow = 3.912 / snow_extcoeff
          IF (vis_snow .LT. cloud_ceil (i,j)) cloud_ceil (i,j) = vis_snow
        ENDIF

      ENDDO
    ENDDO

  END SUBROUTINE cloud_diagnostics



  SUBROUTINE thermal_diagnostics ( t2                           &
                             , psfc                             &
                             , rh2m                             &
                             , wind10m                          &
                             , heatidx                          &
                             , wchill                           &
                             , fits                             &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(IN   ) ::                                   t2  &
                                              ,           psfc  &
                                              ,           rh2m  & 
                                              ,        wind10m

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(  OUT) ::                              heatidx  &
                                              ,         wchill  & 
                                              ,           fits

    
    
    INTEGER :: i, j

    DO i=ims,ime
      DO j=jms,jme
       
        
        
        heatidx ( i, j ) = calc_hi   (   t2      ( i, j )    &
                                       , rh2m    ( i, j ) )

        
        
        wchill  ( i, j ) = calc_wc   (   t2      ( i, j )    &
                                       , wind10m ( i, j ) )

        
        
        fits    ( i, j ) = calc_fits (   psfc    ( i, j )    &
                                       , t2      ( i, j )    &
                                       , rh2m    ( i, j ) )

      ENDDO
    ENDDO

  END SUBROUTINE thermal_diagnostics



  SUBROUTINE turbulence_diagnostics ( u_phy                     &
                             , v_phy                            &
                             , t_phy                            &
                             , p                                &
                             , zagl                             &
                             , defor11                          &
                             , defor12                          &
                             , defor22                          &
                             , turb                             &
                             , llturb                           &
                             , llturblgt                        &
                             , llturbmdt                        &
                             , llturbsvr                        &
                             , nlyrs                            &
                             , lyrbot                           &
                             , lyrtop                           &
                             , ids, ide, jds, jde, kds, kde     &
                             , ims, ime, jms, jme, kms, kme     &
                             , ips, ipe, jps, jpe, kps, kpe )

    INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde,        &
                           ims, ime, jms, jme, kms, kme,        &
                           ips, ipe, jps, jpe, kps, kpe

    INTEGER, INTENT(IN) :: nlyrs

    REAL, DIMENSION( ims:ime, kms:kme, jms:jme ),               &
         INTENT(IN   ) ::                                u_phy  &
                                              ,          v_phy  &
                                              ,          t_phy  & 
                                              ,              p  & 
                                              ,           zagl  &
                                              ,        defor11  & 
                                              ,        defor12  & 
                                              ,        defor22

    REAL, DIMENSION( nlyrs ),                                   &
         INTENT(IN   ) ::                               lyrtop  &
                                              ,         lyrbot

    REAL, DIMENSION( ims:ime, nlyrs, jms:jme ),                 &
         INTENT(  OUT) ::                                 turb   

    REAL, DIMENSION( ims:ime, jms:jme ),                        &
         INTENT(  OUT) ::                               llturb  &
                                              ,      llturblgt  &
                                              ,      llturbmdt  & 
                                              ,      llturbsvr

    
    
    INTEGER :: i, j, k, n, bot, top, nlayer

    REAL ::                                            ugrdtop  &
                                              ,        ugrdbot  &
                                              ,        vgrdtop  &
                                              ,        vgrdbot  &
                                              ,     defor11top  &
                                              ,     defor11bot  &
                                              ,     defor12top  &
                                              ,     defor12bot  &
                                              ,     defor22top  &
                                              ,     defor22bot

    REAL, DIMENSION( kms:kme )            ::         this_zagl  &
                                              ,        this_tK  &
                                              ,         this_p  &
                                              ,         this_u  &
                                              ,         this_v

    REAL :: wind, therm, mtn_wave, tpd_wave

    
    
    turb = REAL ( 0 )
    llturb = REAL ( 0 )
    llturblgt = REAL ( 0 )
    llturbsvr = REAL ( 0 )

    
    
    DO i=ims,ime
      DO j=jms,jme
       
        
        
        DO n = 1, nlyrs

          
          
          ugrdtop    = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   ,   u_phy ( i, kms:kme-1, j )  &
                                   ,             lyrtop  ( n ) )
          ugrdbot    = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   ,   u_phy ( i, kms:kme-1, j )  &
                                   ,             lyrbot  ( n ) )
          vgrdtop    = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   ,   v_phy ( i, kms:kme-1, j )  &
                                   ,             lyrtop  ( n ) )
          vgrdbot    = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   ,   v_phy ( i, kms:kme-1, j )  &
                                   ,             lyrbot  ( n ) )
          defor11top = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor11 ( i, kms:kme-1, j )  &
                                   ,             lyrtop  ( n ) )
          defor11bot = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor11 ( i, kms:kme-1, j )  &
                                   ,             lyrbot  ( n ) )
          defor12top = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor12 ( i, kms:kme-1, j )  &
                                   ,             lyrtop  ( n ) )
          defor12bot = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor12 ( i, kms:kme-1, j )  &
                                   ,             lyrbot  ( n ) )
          defor22top = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor22 ( i, kms:kme-1, j )  &
                                   ,             lyrtop  ( n ) )
          defor22bot = lin_interp (     zagl ( i, kms:kme-1, j )  &
                                   , defor22 ( i, kms:kme-1, j )  &
                                   ,             lyrbot  ( n ) )

          
          
          turb ( i, n, j ) = CATTurbulence (                       ugrdbot  &
                                               ,                   ugrdtop  &
                                               ,                   vgrdbot  &
                                               ,                   vgrdtop  &
                                               ,                defor11bot  &
                                               ,                defor11top  &
                                               ,                defor12bot  &
                                               ,                defor12top  &
                                               ,                defor22bot  &
                                               ,                defor22top  &
                                               ,                lyrbot (n)  &
                                               ,                lyrtop (n) )

        ENDDO
 
        
        
        bot = kms
        top = kms
        DO k=kms+1,kme
          IF ( zagl ( i, k, j ) .gt. 1500. ) THEN
            top = k
            EXIT
          ENDIF
        ENDDO
        nlayer = top - bot + 1  

        
        
        this_zagl = zagl  ( i, kms:kme, j )
        this_tK   = t_phy ( i, kms:kme, j )
        this_p    = p     ( i, kms:kme, j )
        this_u    = u_phy ( i, kms:kme, j )
        this_v    = v_phy ( i, kms:kme, j )
                           

        
        
        this_zagl ( top ) = 1500.
        this_tK ( top )   = lin_interp (  zagl ( i, kms:kme-1, j )  &
                                     ,   t_phy ( i, kms:kme-1, j )  &
                                     ,           this_zagl (top) )
        this_p ( top )    = lin_interp (  zagl ( i, kms:kme-1, j )  &
                                     ,       p ( i, kms:kme-1, j )  &
                                     ,           this_zagl (top) )
        this_u ( top )    = lin_interp (  zagl ( i, kms:kme-1, j )  &
                                     ,   u_phy ( i, kms:kme-1, j )  &
                                     ,           this_zagl (top) )
        this_v ( top )    = lin_interp (  zagl ( i, kms:kme-1, j )  &
                                     ,   v_phy ( i, kms:kme-1, j )  &
                                     ,           this_zagl (top) )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        wind = LLT_WindSpeed ( nlayer, this_u (bot:top) &
                                , this_v (bot:top) )

        
        
        
        therm = LLT_Thermodynamic ( nlayer, this_tK(bot:top) &
                                , this_zagl(bot:top) )

        
        
        
        mtn_wave = LLT_MountainWave ( nlayer, terrain_dx, terrain_dy &
                                , this_u(bot:top), this_v(bot:top)   &
                                , this_tK(bot:top), this_zagl(bot:top) )

        
        
        
        tpd_wave = LLT_TrappedWave ( nlayer, this_u(bot:top) &
                                , this_v(bot:top), this_p(bot:top) )

        
        
        
        llturb ( i,j ) = 1.-((1.-wind)*(1.-therm)*(1.-mtn_wave)*(1.-tpd_wave))

        
        
        llturblgt ( i,j ) = (((((((llturb (i,j) * REAL (100))-REAL (30)) &
                                        *2.5)*.01)**2)*0.75)*REAL(100))
        IF ( llturb (i,j) < 0.3   ) llturblgt ( i,j ) = REAL ( 0 )
        IF ( llturblgt (i,j) > REAL (90) ) llturblgt ( i,j ) = REAL ( 90 )

        llturbmdt ( i,j ) = (((((((llturb (i,j) * REAL (100))-REAL (35)) &
                                     *2.22222)*.01)*0.75)**2)*88.88888)
        IF ( llturb (i,j) < 0.35  ) llturbmdt ( i,j ) = REAL ( 0 )
        IF ( llturbmdt (i,j) > REAL (70) ) llturbmdt ( i,j ) = REAL ( 70 )

        llturbsvr ( i,j ) = (((((((llturb (i,j) * REAL (100))-REAL (40)) &
                                     *REAL(2))*.01)*0.5)**2)*REAL(100))
        IF ( llturb (i,j) < 0.40  ) llturbsvr ( i,j ) = REAL ( 0 )
        IF ( llturbsvr (i,j) > REAL (35) ) llturbsvr ( i,j ) = REAL ( 35 )

      ENDDO
    ENDDO

  END SUBROUTINE turbulence_diagnostics

END MODULE module_diag_afwa

