!-----------------------------------------------------------------------
!BOP
! !ROUTINE: uv3s_update -- update u3s, v3s (XY decomposition)
!
! !INTERFACE:
subroutine uv3s_update(grid, dua, u3s, dva, v3s, dt5) 1,15
! !USES:
use shr_kind_mod
, only: r8 => shr_kind_r8
#if defined( SPMD )
use parutilitiesmodule
, only : pargatherreal
use mod_comm
, only : mp_send3d, mp_recv3d
#endif
use cam_history
, only: outfld
use dynamics_vars
, only: T_FVDYCORE_GRID
implicit none
! !INPUT PARAMETERS:
type (T_FVDYCORE_GRID), intent(in) :: grid
! dudt on A-grid
real(r8),intent(in) :: dua(grid%ifirstxy:grid%ilastxy,grid%km,grid%jfirstxy:grid%jlastxy)
! dvdt on A-grid
real(r8),intent(in) :: dva(grid%ifirstxy:grid%ilastxy,grid%km,grid%jfirstxy:grid%jlastxy)
real(r8),intent(in) :: dt5 ! weighting factor
! !INPUT/OUTPUT PARAMETERS:
real(r8), intent(inout) :: u3s(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy, &
grid%km) ! U-Wind on D Grid
real(r8), intent(inout) :: v3s(grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy, &
grid%km) ! V-Wind on D Grid
! !DESCRIPTION:
!
! This routine performs the update for the N-S staggered u-wind
! and the E-W staggered v-wind
!
! !REVISION HISTORY:
! WS 00.12.22 : Creation from d2a3d
! SJL 01.01.20 : modifications
! AAM 01.06.08 : Name change; folding in of v3s update and outfld calls
! WS 02.04.25 : New mod_comm interfaces
! WS 02.07.04 : Fixed 2D decomposition bug dest/src for mp_send3d
! WS 03.07.22 : Removed strip3zatyt4 from use list (no longer used)
! WS 05.07.14 : Simplified interface with grid argument
! WS 05.09.23 : Modified for XY decomposition
!
!EOP
!-----------------------------------------------------------------------
!BOC
integer :: i, j, k
integer :: im, jm, km, ifirstxy, ilastxy, jfirstxy, jlastxy, idim
#if defined( SPMD )
real(r8) :: duasouth(grid%ifirstxy:grid%ilastxy,grid%km)
real(r8) :: dvawest(grid%km,grid%jfirstxy:grid%jlastxy)
integer :: dest, src
integer :: iam, nprxy_x, myidxy_y
#endif
real(r8) :: tmp
real(r8) :: u3s_tmp (grid%ifirstxy:grid%ilastxy,grid%km)
real(r8) :: v3s_tmp (grid%ifirstxy:grid%ilastxy,grid%km)
real(r8) :: fu3s (grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km)
real(r8) :: fv3s (grid%ifirstxy:grid%ilastxy,grid%jfirstxy:grid%jlastxy,grid%km)
real(r8) :: fu3s_tmp(grid%ifirstxy:grid%ilastxy,grid%km)
real(r8) :: fv3s_tmp(grid%ifirstxy:grid%ilastxy,grid%km)
fu3s(:,:,:) = 0._r8
fv3s(:,:,:) = 0._r8
im = grid%im
jm = grid%jm
km = grid%km
ifirstxy = grid%ifirstxy
ilastxy = grid%ilastxy
jfirstxy = grid%jfirstxy
jlastxy = grid%jlastxy
#if ( ! defined OFFLINE_DYN ) || ( defined WACCM_GHG ) || ( defined WACCM_MOZART )
#if defined( SPMD )
iam = grid%iam
nprxy_x = grid%nprxy_x
myidxy_y = grid%myidxy_y
!
! Transfer dua(:,jlast) to the node directly to the north; dva(ifirst, to east)
!
call mp_send3d
( grid%commxy, iam+nprxy_x, iam-nprxy_x, im, km, jm, &
ifirstxy, ilastxy, 1, km, jfirstxy, jlastxy, &
ifirstxy, ilastxy, 1, km, jlastxy, jlastxy, dua )
call mp_recv3d
( grid%commxy, iam-nprxy_x, im, km, jm, &
ifirstxy, ilastxy, 1, km, jfirstxy-1, jfirstxy-1, &
ifirstxy, ilastxy, 1, km, jfirstxy-1, jfirstxy-1, duasouth )
dest = myidxy_y*nprxy_x + MOD(iam+1,nprxy_x)
src = myidxy_y*nprxy_x + MOD(iam+nprxy_x-1,nprxy_x)
call mp_send3d
( grid%commxy, dest, src, im, km, jm, &
ifirstxy, ilastxy, 1, km, jfirstxy, jlastxy, &
ilastxy, ilastxy, 1, km, jfirstxy, jlastxy, dva )
call mp_recv3d
( grid%commxy, src, im, km, jm, &
ifirstxy-1, ifirstxy-1, 1, km, jfirstxy, jlastxy, &
ifirstxy-1, ifirstxy-1, 1, km, jfirstxy, jlastxy, dvawest )
#endif
!$omp parallel do private (i, j, k)
do k = 1, km
!
! Adjust D-grid winds by interpolating A-grid tendencies.
!
do j = jfirstxy+1, jlastxy
do i = ifirstxy, ilastxy
tmp = u3s(i,j,k)
u3s (i,j,k) = u3s(i,j,k) + dt5*(dua(i,k,j)+dua(i,k,j-1))
fu3s(i,j,k) = (u3s(i,j,k) - tmp)/(2._r8*dt5)
enddo
enddo
do j = max(jfirstxy,2), min(jlastxy,jm-1)
do i=ifirstxy+1,ilastxy
tmp = v3s(i,j,k)
v3s (i,j,k) = v3s(i,j,k) + dt5*(dva(i,k,j)+dva(i-1,k,j))
fv3s(i,j,k) = (v3s(i,j,k) - tmp)/(2._r8*dt5)
enddo
enddo
#if defined( SPMD )
if ( jfirstxy .gt. 1 ) then
do i = ifirstxy, ilastxy
tmp = u3s(i,jfirstxy,k)
u3s (i,jfirstxy,k) = u3s(i,jfirstxy,k) + &
dt5*( dua(i,k,jfirstxy) + duasouth(i,k) )
fu3s(i,jfirstxy,k) = (u3s(i,jfirstxy,k) - tmp)/(2._r8*dt5)
enddo
endif
do j = max(jfirstxy,2), min(jlastxy,jm-1)
tmp = v3s(ifirstxy,j,k)
v3s (ifirstxy,j,k) = v3s(ifirstxy,j,k) + dt5*(dva(ifirstxy,k,j)+dvawest(k,j))
fv3s(ifirstxy,j,k) = (v3s(ifirstxy,j,k) - tmp)/(2._r8*dt5)
enddo
#else
do j = max(jfirstxy,2), min(jlastxy,jm-1)
tmp = v3s(1,j,k)
v3s (1,j,k) = v3s(1,j,k) + dt5*(dva(1,k,j)+dva(im,k,j))
fv3s(1,j,k) = (v3s(1,j,k) - tmp)/(2._r8*dt5)
enddo
#endif
enddo
#endif
idim = ilastxy - ifirstxy + 1
!$omp parallel do private (i, j, k, u3s_tmp, v3s_tmp, fu3s_tmp, fv3s_tmp)
do j = jfirstxy, jlastxy
do k = 1, km
do i = ifirstxy, ilastxy
u3s_tmp (i,k) = u3s (i,j,k)
v3s_tmp (i,k) = v3s (i,j,k)
fu3s_tmp(i,k) = fu3s(i,j,k)
fv3s_tmp(i,k) = fv3s(i,j,k)
enddo
enddo
call outfld
('FU ', dua(:,:,j), idim, j )
call outfld
('FV ', dva(:,:,j), idim, j )
call outfld
('US ', u3s_tmp , idim, j )
call outfld
('VS ', v3s_tmp , idim, j )
call outfld
('FU_S ', fu3s_tmp , idim, j )
call outfld
('FV_S ', fv3s_tmp , idim, j )
enddo
return
!EOC
end subroutine uv3s_update
!-----------------------------------------------------------------------