module polar_avg 4,8
!-----------------------------------------------------------------------
!
! Purpose:
! These routines are used by the fv dycore to set the collocated
! pole points at the limits of the latitude dimension to the same
! value.
!
! Methods:
! The repro_sum reproducible distributed sum is used for these
! calculations.
!
! Author: A. Mirin
!
!-----------------------------------------------------------------------
!-----------------------------------------------------------------------
!- use statements ------------------------------------------------------
!-----------------------------------------------------------------------
use shr_kind_mod
, only: r8 => shr_kind_r8
use dycore
, only: dycore_is
use dyn_grid
, only: get_dyn_grid_parm
use phys_grid
, only: get_ncols_p, get_lat_all_p
use ppgrid
, only: begchunk, endchunk, pcols
use repro_sum_mod
, only: repro_sum
!-----------------------------------------------------------------------
!- module boilerplate --------------------------------------------------
!-----------------------------------------------------------------------
implicit none
private
save
!-----------------------------------------------------------------------
! Public interfaces ----------------------------------------------------
!-----------------------------------------------------------------------
public :: &
polar_average ! support for LR dycore polar averaging
interface polar_average 5
module procedure polar_average2d
, polar_average3d
end interface
CONTAINS
!
!========================================================================
!
subroutine polar_average2d(field) 1,9
!-----------------------------------------------------------------------
! Purpose: Set the collocated pole points at the limits of the latitude
! dimension to the same value.
! Author: J. Edwards
!-----------------------------------------------------------------------
!
! Arguments
!
real(r8), intent(inout) :: field(pcols,begchunk:endchunk)
!
! Local workspace
!
integer :: i, c, ln, ls, ncols
integer :: plat, plon
integer, allocatable :: lats(:)
real(r8) :: sum(2)
real(r8), allocatable :: n_pole(:), s_pole(:)
!
!-----------------------------------------------------------------------
!
if(.not. dycore_is
('LR')) return
plon = get_dyn_grid_parm
('plon')
plat = get_dyn_grid_parm
('plat')
allocate(lats(pcols), n_pole(plon), s_pole(plon))
ln=0
ls=0
do c=begchunk,endchunk
call get_lat_all_p
(c,pcols,lats)
ncols = get_ncols_p
(c)
do i=1,ncols
if(lats(i).eq.1) then
ln=ln+1
n_pole(ln) = field(i,c)
else if(lats(i).eq.plat) then
ls=ls+1
s_pole(ls) = field(i,c)
end if
enddo
end do
call repro_sum
(n_pole, sum(1:1), ln, plon, 1, gbl_count=plon)
call repro_sum
(s_pole, sum(2:2), ls, plon, 1, gbl_count=plon)
ln=0
ls=0
do c=begchunk,endchunk
call get_lat_all_p
(c,pcols,lats)
ncols = get_ncols_p
(c)
do i=1,ncols
if(lats(i).eq.1) then
ln=ln+1
field(i,c) = sum(1)/plon
else if(lats(i).eq.plat) then
ls=ls+1
field(i,c) = sum(2)/plon
end if
enddo
end do
deallocate(lats, n_pole, s_pole)
end subroutine polar_average2d
!
!========================================================================
!
subroutine polar_average3d(nlev, field) 1,9
!-----------------------------------------------------------------------
! Purpose: Set the collocated pole points at the limits of the latitude
! dimension to the same value.
! Author: J. Edwards
!-----------------------------------------------------------------------
!
! Arguments
!
integer, intent(in) :: nlev
real(r8), intent(inout) :: field(pcols,nlev,begchunk:endchunk)
!
! Local workspace
!
integer :: i, c, ln, ls, ncols, k
integer :: plat, plon
integer, allocatable :: lats(:)
real(r8) :: sum(nlev,2)
real(r8), allocatable :: n_pole(:,:), s_pole(:,:)
!
!-----------------------------------------------------------------------
!
if(.not. dycore_is
('LR')) return
plon = get_dyn_grid_parm
('plon')
plat = get_dyn_grid_parm
('plat')
allocate(lats(pcols), n_pole(plon,nlev), s_pole(plon,nlev))
ln=0
ls=0
do c=begchunk,endchunk
call get_lat_all_p
(c,pcols,lats)
ncols = get_ncols_p
(c)
do i=1,ncols
if(lats(i).eq.1) then
ln=ln+1
do k=1,nlev
n_pole(ln,k) = field(i,k,c)
end do
else if(lats(i).eq.plat) then
ls=ls+1
do k=1,nlev
s_pole(ls,k) = field(i,k,c)
end do
end if
enddo
end do
call repro_sum
(n_pole, sum(:,1), ln, plon, nlev, gbl_count=plon)
call repro_sum
(s_pole, sum(:,2), ls, plon, nlev, gbl_count=plon)
ln=0
ls=0
do c=begchunk,endchunk
call get_lat_all_p
(c,pcols,lats)
ncols = get_ncols_p
(c)
do i=1,ncols
if(lats(i).eq.1) then
ln=ln+1
do k=1,nlev
field(i,k,c) = sum(k,1)/plon
end do
else if(lats(i).eq.plat) then
ls=ls+1
do k=1,nlev
field(i,k,c) = sum(k,2)/plon
end do
end if
enddo
end do
deallocate(lats, n_pole, s_pole)
end subroutine polar_average3d
end module polar_avg