subroutine latlon_zmean ( q,qz,undef,grid,rc)
real, intent(inout) :: q(:,:)
real, intent(inout) :: qz(:)
real, intent(in) :: undef
type(ESMF_Grid), intent(inout) :: grid
integer, optional, intent(out) :: rc
integer :: im,jm,im_global,jm_global,local_dims(3),global_dims(3),status,nx,ny
real, allocatable :: qg(:,:)
real, allocatable :: buf(:,:)
real :: qsum
integer :: mpistatus(mpi_status_size)
integer, allocatable :: ims(:),jms(:)
integer j,n,peid,peid0,i1,j1,in,jn,mypet,i_start,i_end,isum
type(ESMF_VM) :: vm
call ESMF_VMGetCurrent(vm,_RC)
call ESMF_VMGet(vm,localPet=mypet,_RC)
call MAPL_GridGet(grid,localCellCountPerDim=local_dims,globalCellCountPerDim=global_dims,_RC)
im = local_dims(1)
jm = local_dims(2)
im_global = global_dims(1)
jm_global = global_dims(2)
call get_esmf_grid_layout(grid,nx,ny,ims,jms,_RC)
call mapl_grid_interior(grid,i1,in,j1,jn)
qz = 0.0
allocate( qg(im_global,jm) )
peid0 = (mypet/nx)*ny
if (i1==1) then
i_start = 1
i_end = ims(1)
qg(i_start:i_end,:)=q
do n=1,nx-1
allocate(buf(ims(n+1),jm))
peid = mypet + n
call mpi_recv(buf,ims(n+1)*jm,MPI_FLOAT,peid,peid,MPI_COMM_WORLD,mpistatus,status)
_VERIFY(status)
i_start=i_end+1
i_end = i_start+ims(n)-1
qg(i_start:i_end,:)=buf
deallocate(buf)
enddo
else
call mpi_send(q,im*jm,MPI_FLOAT,peid0,mypet,MPI_COMM_WORLD,status)
_VERIFY(status)
end if
! compute zonal mean
if (i1 == 1) then
do j=1,jm
isum = count(qg(:,j) /= undef)
qsum = sum(qg(:,j),mask=qg(:,j)/=undef)
if (isum == 0) then
qz(j)=undef
else
qz(j)=qsum/real(isum)
end if
enddo
! send mean back to other ranks
do n=1,nx-1
peid = peid0+n
call mpi_send(qz,jm,MPI_FLOAT,peid,peid0,MPI_COMM_WORLD,status)
_VERIFY(status)
enddo
else
call mpi_recv(qz,jm,MPI_FLOAT,peid0,peid0,MPI_COMM_WORLD,mpistatus,status)
_VERIFY(status)
end if
if (present(rc)) then
rc=_SUCCESS
endif
end subroutine latlon_zmean