module flux_avg 3,6
!---------------------------------------------------------------------------------
! Purpose: Contains code to smooth the surface fluxes to reduce
! instabilities in the surface layer.
!---------------------------------------------------------------------------------
use shr_kind_mod
, only: r8=>shr_kind_r8
use ppgrid
, only: begchunk, endchunk, pcols
use phys_buffer
, only: pbuf_add, pbuf_size_max, pbuf_fld
use physics_types
, only: physics_state
use camsrfexch_types
, only: srfflx_state
use phys_grid
, only: get_ncols_p
implicit none
private
save
! Public interfaces
public :: flux_avg_register
public :: flux_avg_init
public :: flux_avg_run
! Private module data
integer :: lhflx_idx ! lhflx index in physics buffer
integer :: shflx_idx ! shflx index in physics buffer
integer :: qflx_idx ! qflx index in physics buffer
integer :: taux_idx ! taux index in physics buffer
integer :: tauy_idx ! tauy index in physics buffer
integer :: lhflx_res_idx ! lhflx_res index in physics buffer
integer :: shflx_res_idx ! shflx_res index in physics buffer
integer :: qflx_res_idx ! qflx_res index in physics buffer
integer :: taux_res_idx ! taux_res index in physics buffer
integer :: tauy_res_idx ! tauy_res index in physics buffer
!===============================================================================
contains
!===============================================================================
subroutine flux_avg_register() 1,10
!----------------------------------------------------------------------
!
! Register the fluxes in the physics buffer.
!
!-----------------------------------------------------------------------
! Request physics buffer space for fields that persist across timesteps.
call pbuf_add
('LHFLX', 'global', 1, 1, 1, lhflx_idx)
call pbuf_add
('SHFLX', 'global', 1, 1, 1, shflx_idx)
call pbuf_add
('TAUX', 'global', 1, 1, 1, taux_idx)
call pbuf_add
('TAUY', 'global', 1, 1, 1, tauy_idx)
call pbuf_add
('QFLX', 'global', 1, 1, 1, qflx_idx)
call pbuf_add
('LHFLX_RES', 'global', 1, 1, 1, lhflx_res_idx)
call pbuf_add
('SHFLX_RES', 'global', 1, 1, 1, shflx_res_idx)
call pbuf_add
('TAUX_RES', 'global', 1, 1, 1, taux_res_idx)
call pbuf_add
('TAUY_RES', 'global', 1, 1, 1, tauy_res_idx)
call pbuf_add
('QFLX_RES', 'global', 1, 1, 1, qflx_res_idx)
end subroutine flux_avg_register
!===============================================================================
subroutine flux_avg_init(cam_in, pbuf) 1,1
! Initialize the surface fluxes in the physics buffer using the cam import state
type(srfflx_state), intent(in) :: cam_in(begchunk:endchunk)
type(pbuf_fld), intent(inout) :: pbuf(:)
integer :: lchnk
integer :: ncol
!-----------------------------------------------------------------------
do lchnk = begchunk, endchunk
ncol = get_ncols_p
(lchnk)
pbuf(lhflx_idx)%fld_ptr(1,:ncol,1,lchnk,1) = cam_in(lchnk)%lhf(:ncol)
pbuf(shflx_idx)%fld_ptr(1,:ncol,1,lchnk,1) = cam_in(lchnk)%shf(:ncol)
pbuf(qflx_idx)%fld_ptr(1,:ncol,1,lchnk,1) = cam_in(lchnk)%cflx(:ncol,1)
pbuf(taux_idx)%fld_ptr(1,:ncol,1,lchnk,1) = cam_in(lchnk)%wsx(:ncol)
pbuf(tauy_idx)%fld_ptr(1,:ncol,1,lchnk,1) = cam_in(lchnk)%wsy(:ncol)
pbuf(lhflx_res_idx)%fld_ptr(1,:ncol,1,lchnk,1) = 0.0_r8
pbuf(shflx_res_idx)%fld_ptr(1,:ncol,1,lchnk,1) = 0.0_r8
pbuf(qflx_res_idx)%fld_ptr(1,:ncol,1,lchnk,1) = 0.0_r8
pbuf(taux_res_idx)%fld_ptr(1,:ncol,1,lchnk,1) = 0.0_r8
pbuf(tauy_res_idx)%fld_ptr(1,:ncol,1,lchnk,1) = 0.0_r8
end do
end subroutine flux_avg_init
!===============================================================================
subroutine flux_avg_run(state, cam_in, pbuf, nstep, deltat) 1,8
!-----------------------------------------------------------------------
!
! Purpose:
!
!-----------------------------------------------------------------------
!++ debug code to be removed after PBL code validated
use phys_debug
, only: phys_debug_flux1, phys_debug_flux2
!-- debug code to be removed after PBL code validated
! Input arguments
type(physics_state), intent(in) :: state
type(srfflx_state), intent(inout) :: cam_in
type(pbuf_fld), intent(inout) :: pbuf(pbuf_size_max)
integer, intent(in) :: nstep
real(r8), intent(in) :: deltat
! Local variables
integer :: lchnk ! chunk identifier
integer :: ncol ! number of atmospheric columns
! physics buffer fields
integer :: i, itim
real(r8), pointer, dimension(:) :: lhflx ! latent heat flux
real(r8), pointer, dimension(:) :: shflx ! sensible heat flux
real(r8), pointer, dimension(:) :: qflx ! water vapor heat flux
real(r8), pointer, dimension(:) :: taux ! x momentum flux
real(r8), pointer, dimension(:) :: tauy ! y momentum flux
real(r8), pointer, dimension(:) :: lhflx_res ! latent heat flux
real(r8), pointer, dimension(:) :: shflx_res ! sensible heat flux
real(r8), pointer, dimension(:) :: qflx_res ! water vapor heat flux
real(r8), pointer, dimension(:) :: taux_res ! x momentum flux
real(r8), pointer, dimension(:) :: tauy_res ! y momentum flux
!-----------------------------------------------------------------------
lchnk = state%lchnk
ncol = state%ncol
! Associate pointers with physics buffer fields
lhflx => pbuf(lhflx_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
shflx => pbuf(shflx_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
qflx => pbuf(qflx_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
taux => pbuf(taux_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
tauy => pbuf(tauy_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
lhflx_res => pbuf(lhflx_res_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
shflx_res => pbuf(shflx_res_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
qflx_res => pbuf(qflx_res_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
taux_res => pbuf(taux_res_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
tauy_res => pbuf(tauy_res_idx)%fld_ptr(1,1:pcols,1,lchnk,1)
!++ debug code to be removed after PBL code validated
call phys_debug_flux1
(lchnk, cam_in, lhflx, shflx, taux, tauy, qflx, &
lhflx_res, shflx_res, taux_res, tauy_res, qflx_res)
!-- debug code to be removed after PBL code validated
call smooth
(cam_in%lhf, lhflx, lhflx_res, nstep, deltat, ncol)
call smooth
(cam_in%shf, shflx, shflx_res, nstep, deltat, ncol)
call smooth
(cam_in%wsx, taux, taux_res, nstep, deltat, ncol)
call smooth
(cam_in%wsy, tauy, tauy_res, nstep, deltat, ncol)
call smooth
(cam_in%cflx(:pcols,1), qflx, qflx_res, nstep, deltat, ncol)
!++ debug code to be removed after PBL code validated
call phys_debug_flux2
(lchnk, cam_in, lhflx, &
lhflx_res, shflx_res, taux_res, tauy_res, qflx_res)
!-- debug code to be removed after PBL code validated
end subroutine flux_avg_run
!===============================================================================
subroutine smooth(new, old, res, nstep, deltat, ncol) 5
real(r8), intent(inout) :: new(pcols)
real(r8), intent(inout) :: old(pcols)
real(r8), intent(inout) :: res(pcols)
real(r8), intent(in) :: deltat
integer, intent(in) :: nstep
integer, intent(in) :: ncol
real(r8) :: temp(pcols)
integer i
temp(1:ncol) = new(1:ncol)
if (nstep > 0) then
new(1:ncol) = 0.5*(new(1:ncol)+old(1:ncol))
else
old(1:ncol) = new(1:ncol)
res(1:ncol) = 0.
endif
! storing the old value for smoothing on the next step
! doesnt seem to be stable
! old(1:ncol) = temp(1:ncol)
! storing the smoothed value for the next step
! first add the flux that the surface model wanted to provide less
! the flux the atmosphere will actually see to the residual
res(1:ncol) = res(1:ncol) + temp(1:ncol)-new(1:ncol)
! now calculate the amount that we might increment the new flux
! to include some of the residual
! If the residual is small we will just add it all,
! but if it is large we will add it at the rate required to put
! the residual back into the flux over a 2 hour period
do i = 1,ncol
if (abs(res(i)).lt.max(abs(new(i)),abs(old(i)))*0.05) then
temp(i) = res(i)
res(i) = 0.
else
temp(i) = res(i)*deltat/7200.
! temp(i) = res(i)*deltat*0.5/7200.
res(i) = res(i)-temp(i)
endif
end do
! dont do conservative smoothing for first 12 hours
if (nstep*deltat/86400. < 0.5) then
! use this line if your dont want to use the residual
!if (.true.) then
temp = 0.
res = 0.
endif
! make the new flux the average of the sfc model and last timestep
! plus some of the residual
new(1:ncol) = new(1:ncol) + temp(1:ncol)
old(1:ncol) = new(1:ncol)
end subroutine smooth
!===============================================================================
end module flux_avg