Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Radar-derived microphysics temperature tendencies similar to operational HRRR #823

Merged
76 changes: 66 additions & 10 deletions physics/GFS_MP_generic.F90
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ end subroutine GFS_MP_generic_pre_init
!! \htmlinclude GFS_MP_generic_pre_run.html
!!
subroutine GFS_MP_generic_pre_run(im, levs, ldiag3d, qdiag3d, do_aw, ntcw, nncl, &
ntrac, gt0, gq0, save_t, save_q, errmsg, errflg)
ntrac, gt0, gq0, save_t, save_q, num_dfi_radar, errmsg, errflg)
!
use machine, only: kind_phys

implicit none
integer, intent(in) :: im, levs, ntcw, nncl, ntrac
integer, intent(in) :: im, levs, ntcw, nncl, ntrac, num_dfi_radar
logical, intent(in) :: ldiag3d, qdiag3d, do_aw
real(kind=kind_phys), dimension(:,:), intent(in) :: gt0
real(kind=kind_phys), dimension(:,:,:), intent(in) :: gq0
Expand All @@ -35,12 +35,14 @@ subroutine GFS_MP_generic_pre_run(im, levs, ldiag3d, qdiag3d, do_aw, ntcw, nncl,
errmsg = ''
errflg = 0

if (ldiag3d .or. do_aw) then
if (ldiag3d .or. do_aw .or. num_dfi_radar>0) then
do k=1,levs
do i=1,im
save_t(i,k) = gt0(i,k)
enddo
enddo
endif
if (ldiag3d .or. do_aw) then
if(qdiag3d) then
do n=1,ntrac
do k=1,levs
Expand Down Expand Up @@ -91,28 +93,36 @@ subroutine GFS_MP_generic_post_run(
graupel0, del, rain, domr_diag, domzr_diag, domip_diag, doms_diag, tprcp, srflag, sr, cnvprcp, totprcp, totice, &
totsnw, totgrp, cnvprcpb, totprcpb, toticeb, totsnwb, totgrpb, rain_cpl, rainc_cpl, snow_cpl, pwat, &
drain_cpl, dsnow_cpl, lsm, lsm_ruc, lsm_noahmp, raincprv, rainncprv, iceprv, snowprv, &
graupelprv, draincprv, drainncprv, diceprv, dsnowprv, dgraupelprv, dtp, &
dtend, dtidx, index_of_temperature, index_of_process_mp,ldiag3d, qdiag3d, lssav, &
errmsg, errflg)
graupelprv, draincprv, drainncprv, diceprv, dsnowprv, dgraupelprv, dtp, dfi_radar_max_intervals, &
dtend, dtidx, index_of_temperature, index_of_process_mp,ldiag3d, qdiag3d, lssav, num_dfi_radar, fh_dfi_radar, &
index_of_process_dfi_radar, ix_dfi_radar, dfi_radar_tten, radar_tten_limits, fhour, errmsg, errflg)
!
use machine, only: kind_phys

implicit none

integer, intent(in) :: im, levs, kdt, nrcm, nncl, ntcw, ntrac
integer, intent(in) :: im, levs, kdt, nrcm, nncl, ntcw, ntrac, num_dfi_radar, index_of_process_dfi_radar
integer, intent(in) :: imp_physics, imp_physics_gfdl, imp_physics_thompson, imp_physics_mg, imp_physics_fer_hires
logical, intent(in) :: cal_pre, lssav, ldiag3d, qdiag3d, cplflx, cplchm
integer, intent(in) :: index_of_temperature,index_of_process_mp

integer :: dfi_radar_max_intervals
real(kind=kind_phys), intent(in) :: fh_dfi_radar(:), fhour
real(kind=kind_phys), intent(in) :: radar_tten_limits(:)
integer :: ix_dfi_radar(:)
real(kind=kind_phys), dimension(:,:), intent(inout) :: gt0

real(kind=kind_phys), intent(in) :: dtf, frain, con_g, rainmin
real(kind=kind_phys), dimension(:), intent(in) :: rain1, xlat, xlon, tsfc
real(kind=kind_phys), dimension(:), intent(inout) :: ice, snow, graupel, rainc
real(kind=kind_phys), dimension(:), intent(in) :: rain0, ice0, snow0, graupel0
real(kind=kind_phys), dimension(:,:), intent(in) :: rann
real(kind=kind_phys), dimension(:,:), intent(in) :: gt0, prsl, save_t, del
real(kind=kind_phys), dimension(:,:), intent(in) :: prsl, save_t, del
real(kind=kind_phys), dimension(:,:), intent(in) :: prsi, phii
real(kind=kind_phys), dimension(:,:,:), intent(in) :: gq0, save_q

real(kind=kind_phys), dimension(:,:,:), intent(in) :: dfi_radar_tten

real(kind=kind_phys), dimension(:), intent(in ) :: sr
real(kind=kind_phys), dimension(:), intent(inout) :: rain, domr_diag, domzr_diag, domip_diag, doms_diag, tprcp, &
srflag, cnvprcp, totprcp, totice, totsnw, totgrp, cnvprcpb, &
Expand Down Expand Up @@ -150,10 +160,10 @@ subroutine GFS_MP_generic_post_run(
real(kind=kind_phys), parameter :: p850 = 85000.0_kind_phys
! *DH

integer :: i, k, ic, itrac, idtend
integer :: i, k, ic, itrac, idtend, itime, idtend_radar, idtend_mp

real(kind=kind_phys), parameter :: zero = 0.0_kind_phys, one = 1.0_kind_phys
real(kind=kind_phys) :: crain, csnow, onebg, tem, total_precip, tem1, tem2
real(kind=kind_phys) :: crain, csnow, onebg, tem, total_precip, tem1, tem2, ttend
real(kind=kind_phys), dimension(im) :: domr, domzr, domip, doms, t850, work1

! Initialize CCPP error handling variables
Expand Down Expand Up @@ -244,6 +254,52 @@ subroutine GFS_MP_generic_post_run(

endif

do itime=1,num_dfi_radar
if(ix_dfi_radar(itime)<1) cycle
if(fhour<fh_dfi_radar(itime)) cycle
if(fhour>=fh_dfi_radar(itime+1)) cycle
exit
enddo
if_radar: if(itime<=num_dfi_radar) then
radar_k: do k=3,levs-2 ! Avoid model top and bottom in case DA forgets to
radar_i: do i=1,im
ttend = dfi_radar_tten(i,k,itime)
if_active: if (ttend>-19) then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the hard-coded test for >-19. What if a user specifies radar_tten_limits(1) < -19?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a large value would be meaningless. The fill value in the data assimilation code is -20, and that is what the "if" block tests for.

ttend = max(ttend,radar_tten_limits(1))
ttend = min(ttend,radar_tten_limits(2))

! add radar temp tendency
! there is radar coverage
gt0(i,k) = save_t(i,k) + ttend*dtp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reservations about this functionality being added to this interstitial scheme. Other than one interstitial scheme that updates the state variables after the process-split section of physics is completed, I don't think that any others update the state. In general, they are supposed to have "glue code", not necessarily algorithms that actually affect the state variables. Why could this functionality not be added to a new scheme, especially if it is supposed to be used with HRRR-based suites at this point?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, this is sorta a physics parameterization itself, "helping out" microphysics. Why should it not exist as its own scheme?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't because the calcpreciptype has to use the actual microphysics temperature tendencies, or it'll get meaningless values. Somehow it has to go after that calculation, but before the later code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I see what you mean. It's a bit messy and goes against precedent, but given how the code is organized now, I don't see an alternative if the constraint you mentioned is legit.

end if if_active
end do radar_i
end do radar_k
if(ldiag3d) then
idtend_radar = dtidx(index_of_temperature,index_of_process_dfi_radar)
idtend_mp = dtidx(index_of_temperature,index_of_process_mp)
if(idtend_radar>0 .or. idtend_mp>0) then
if(idtend_mp>0) then
dtend(:,1:2,idtend_mp) = dtend(:,1:2,idtend_mp) + (gt0(:,1:2)-save_t(:,1:2))*frain
endif
do k=3,levs-2 ! Avoid model top and bottom in case DA forgets to
do i=1,im
ttend = dfi_radar_tten(i,k,itime)
if (ttend>-19) then
if(idtend_radar>0) then
dtend(i,k,idtend_radar) = dtend(i,k,idtend_radar) + (gt0(i,k)-save_t(i,k)) * frain
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't you saving microphysics tendency + radar tendency in the radar tendency slice here? Won't it be possible for both microphysics and radar tendencies to be nonzero simultaneously?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The radar tendencies override the microphysics tendency; that is the purpose of this PR. In each gridpoint, you can have one, or the other, not both.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the point where this interstitial scheme is called, microphysics tendencies have already been applied since they are being used as time-split in every CCPP suite that I'm aware of. Unless I'm mistaken, this is only replacing the microphysics tendency diagnostic, not the one that actually gets applied to the state. Wouldn't one need to insert code in every microphysics scheme to bypass it when you wanted to apply the radar tendencies?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. In the RAP and HRRR suites, only the thompson scheme is run between GFS_MP_generic_pre and _post.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so the Thompson scheme is called and updates gt0. Then, this is called and replaces the previously calculated gt0 if a radar tendency is present.

endif
else if(idtend_mp>0) then
dtend(i,k,idtend_mp) = dtend(i,k,idtend_mp) + (gt0(i,k)-save_t(i,k)) * frain
endif
enddo
enddo
if(idtend_mp>0) then
dtend(:,levs-1:levs,idtend_mp) = dtend(:,levs-1:levs,idtend_mp) + (gt0(:,levs-1:levs)-save_t(:,levs-1:levs))*frain
endif
endif
endif
endif if_radar

t850(1:im) = gt0(1:im,1)

do k = 1, levs-1
Expand Down
67 changes: 67 additions & 0 deletions physics/GFS_MP_generic.meta
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@
type = real
kind = kind_phys
intent = inout
[num_dfi_radar]
standard_name = number_of_radar_derived_temperature_or_convection_suppression_intervals
long_name = number of time ranges with radar-derived microphysics temperature tendencies or radar-derived convection suppression
units = count
dimensions = ()
type = integer
intent = in
[errmsg]
standard_name = ccpp_error_message
long_name = error message for error handling in CCPP
Expand Down Expand Up @@ -727,6 +734,66 @@
type = real
kind = kind_phys
intent = in
[dfi_radar_max_intervals]
standard_name = maximum_number_of_radar_derived_temperature_or_convection_suppression_intervals
long_name = maximum allowed number of time ranges with radar-derived microphysics temperature tendencies or radar-derived convection suppression
units = count
dimensions = ()
type = integer
intent = in
[num_dfi_radar]
standard_name = number_of_radar_derived_temperature_or_convection_suppression_intervals
long_name = number of time ranges with radar-derived microphysics temperature tendencies or radar-derived convection suppression
units = count
dimensions = ()
type = integer
intent = in
[fh_dfi_radar]
standard_name = forecast_lead_times_bounding_radar_derived_temperature_or_convection_suppression_intervals
long_name = forecast lead times bounding radar derived temperature or convection suppression intervals
units = h
dimensions = (maximum_number_of_radar_derived_temperature_or_convection_suppression_intervals_plus_one)
type = real
kind = kind_phys
intent = in
[ix_dfi_radar]
standard_name = indices_with_radar_derived_temperature_or_convection_suppression_data
long_name = indices with radar derived temperature or convection suppression data
units = index
dimensions = (maximum_number_of_radar_derived_temperature_or_convection_suppression_intervals)
type = integer
intent = in
[dfi_radar_tten]
standard_name = radar_derived_microphysics_temperature_tendency
long_name = radar-derived microphysics temperature tendency
units = K s-1
dimensions = (horizontal_loop_extent,vertical_layer_dimension,number_of_radar_derived_temperature_or_convection_suppression_intervals)
type = real
kind = kind_phys
intent = in
[fhour]
standard_name = forecast_time
long_name = current forecast time
units = h
dimensions = ()
type = real
kind = kind_phys
intent = in
[radar_tten_limits]
standard_name = allowed_bounds_of_radar_prescribed_tendencies
long_name = allowed bounds of prescribed microphysics temperature tendencies
units = K s-1
dimensions = (2)
type = real
kind = kind_phys
intent = in
[index_of_process_dfi_radar]
standard_name = index_of_radar_derived_microphysics_temperature_forcing_in_cumulative_change_index
long_name = index of radar-derived microphysics temperature forcing in second dimension of array cumulative change index
units = index
dimensions = ()
type = integer
intent = in
[dtend]
standard_name = cumulative_change_of_state_variables
long_name = diagnostic tendencies for state variables
Expand Down
24 changes: 12 additions & 12 deletions physics/cu_gf_deep.F90
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ subroutine cu_gf_deep_run( &
!! more is possible, talk to developer or
!! implement yourself. pattern is expected to be
!! betwee -1 and +1
#if ( wrf_dfi_radar == 1 )
,do_capsuppress,cap_suppress_j & !
#endif
,k22 & !
,jmin,tropics) !

Expand All @@ -129,16 +127,8 @@ subroutine cu_gf_deep_run( &
real(kind=kind_phys), dimension (its:ite) &
,intent (in ) :: rand_mom,rand_vmas

#if ( wrf_dfi_radar == 1 )
!
! option of cap suppress:
! do_capsuppress = 1 do
! do_capsuppress = other don't
!
!
integer, intent(in ) ,optional :: do_capsuppress
real(kind=kind_phys), dimension( its:ite ) :: cap_suppress_j
#endif
integer, intent(in) :: do_capsuppress
real(kind=kind_phys), intent(in), optional, dimension(:) :: cap_suppress_j
!
!
!
Expand Down Expand Up @@ -458,6 +448,16 @@ subroutine cu_gf_deep_run( &
ztexec(:)=0
zqexec(:)=0
endif
if(do_capsuppress == 1) then
do i=its,itf
cap_max(i)=cap_maxs
if (abs(cap_suppress_j(i) - 1.0 ) < 0.1 ) then
cap_max(i)=cap_maxs+75.
elseif (abs(cap_suppress_j(i) - 0.0 ) < 0.1 ) then
cap_max(i)=10.0
endif
enddo
endif
!
!--- initial entrainment rate (these may be changed later on in the
!--- program
Expand Down
37 changes: 30 additions & 7 deletions physics/cu_gf_driver.F90
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
flag_for_scnv_generic_tend,flag_for_dcnv_generic_tend, &
dtend,dtidx,ntqv,ntiw,ntcw,index_of_temperature,index_of_x_wind, &
index_of_y_wind,index_of_process_scnv,index_of_process_dcnv, &
ldiag3d,qci_conv,errmsg,errflg)
fhour,fh_dfi_radar,ix_dfi_radar,num_dfi_radar,cap_suppress, &
dfi_radar_max_intervals,ldiag3d,qci_conv,do_cap_suppress, &
errmsg,errflg)
!-------------------------------------------------------------
implicit none
integer, parameter :: maxiens=1
Expand All @@ -98,6 +100,7 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
integer, parameter :: ichoicem=13 ! 0 2 5 13
integer, parameter :: ichoice_s=3 ! 0 1 2 3

logical, intent(in) :: do_cap_suppress
real(kind=kind_phys), parameter :: aodc0=0.14
real(kind=kind_phys), parameter :: aodreturn=30.
real(kind=kind_phys) :: dts,fpi,fp
Expand Down Expand Up @@ -125,6 +128,11 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&

real(kind=kind_phys), allocatable :: clcw_save(:,:), cliw_save(:,:)

integer, intent(in) :: dfi_radar_max_intervals
real(kind=kind_phys), intent(in) :: fhour, fh_dfi_radar(:)
integer, intent(in) :: num_dfi_radar, ix_dfi_radar(:)
real(kind=kind_phys), intent(in) :: cap_suppress(:,:)

integer, dimension (:), intent(out) :: hbot,htop,kcnv
integer, dimension (:), intent(in) :: xland
real(kind=kind_phys), dimension (:), intent(in) :: pbl
Expand Down Expand Up @@ -213,6 +221,9 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
real(kind=kind_phys) :: cliw_deep,clcw_deep,tem_deep, clcw_both
integer :: cliw_deep_idx, clcw_deep_idx, cliw_shal_idx, clcw_shal_idx

real(kind=kind_phys) :: cap_suppress_j(im)
integer :: itime, do_cap_suppress_here

!parameter (tf=243.16, tcr=270.16, tcrf=1.0/(tcr-tf)) ! FV3 original
!parameter (tf=263.16, tcr=273.16, tcrf=1.0/(tcr-tf))
!parameter (tf=233.16, tcr=263.16, tcrf=1.0/(tcr-tf))
Expand All @@ -221,6 +232,22 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
errmsg = ''
errflg = 0

if(do_cap_suppress) then
do itime=1,num_dfi_radar
if(ix_dfi_radar(itime)<1) cycle
if(fhour<fh_dfi_radar(itime)) cycle
if(fhour>=fh_dfi_radar(itime+1)) cycle
exit
enddo
endif
if(do_cap_suppress .and. itime<=num_dfi_radar) then
do_cap_suppress_here = 1
cap_suppress_j = cap_suppress(:,itime)
else
do_cap_suppress_here = 0
cap_suppress_j = 0
endif

if(ldiag3d) then
if(flag_for_dcnv_generic_tend) then
cliw_deep_idx=0
Expand Down Expand Up @@ -643,9 +670,7 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
! more is possible, talk to developer or
! implement yourself. pattern is expected to be
! betwee -1 and +1
#if ( wrf_dfi_radar == 1 )
,do_capsuppress,cap_suppress_j &
#endif
,do_cap_suppress_here,cap_suppress_j &
,k22m &
,jminm,tropics)

Expand Down Expand Up @@ -726,9 +751,7 @@ subroutine cu_gf_driver_run(ntracer,garea,im,km,dt,flag_init,flag_restart,&
! more is possible, talk to developer or
! implement yourself. pattern is expected to be
! betwee -1 and +1
#if ( wrf_dfi_radar == 1 )
,do_capsuppress,cap_suppress_j &
#endif
,do_cap_suppress_here,cap_suppress_j &
,k22 &
,jmin,tropics)
jpr=0
Expand Down
Loading