#include <misc.h>
module dyn_grid 5,3
!-----------------------------------------------------------------------
!
! Purpose: Definition of dynamics computational grid.
!
! Method: Variables are private; interface routines used to extract
! information for use in user code.
!
! Entry points:
!
! get_block_bounds_d get first and last indices in global
! block ordering
! get_block_owner_d get process "owning" given block
! get_block_col_cnt_d get number of columns in given block
! get_block_lvl_cnt_d get number of vertical levels in column
! get_block_levels_d get vertical levels in column
!
! get_block_coord_cnt_d get number of blocks containing
! data from a given vertical column
! get_block_coord_d get global block indices and local columns
! index for given coordinates
!
! get_xxx_d get global indices or coordinates for a single
! column
! where xxx is
! lat for global latitude index
! lon for global longitude index
!
! Author: John Drake and Patrick Worley
!
!-----------------------------------------------------------------------
use shr_kind_mod
, only: r8 => shr_kind_r8
use pmgrid
, only: plev
use abortutils
, only: endrun
contains
!========================================================================
!
Subroutine get_block_bounds_d(block_first,block_last) 2,1
!-----------------------------------------------------------------------
!
!
! Purpose: Return first and last indices used in global block ordering
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use pmgrid
, only: plat, spmd_on, nprxy_x, nprxy_y
implicit none
!------------------------------Arguments--------------------------------
integer, intent(out) :: block_first ! first (global) index used for blocks
integer, intent(out) :: block_last ! last (global) index used for blocks
!-----------------------------------------------------------------------
! latitude slice block
block_first = 1
if (spmd_on .eq. 1) then
! Assume 1 block per subdomain
block_last = nprxy_x*nprxy_y
else
block_last = plat
endif
return
end subroutine get_block_bounds_d
!
!========================================================================
!
integer function get_block_coord_cnt_d(glon,glat) 7
!-----------------------------------------------------------------------
!
!
! Purpose: Return number of blocks that contain data for the vertical
! column at location (glon,glat)
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: glon ! global longitude index
integer, intent(in) :: glat ! global latitude index
!-----------------------------------------------------------------------
! latitude slice block
get_block_coord_cnt_d = 1
return
end function get_block_coord_cnt_d
!
!========================================================================
!
subroutine get_block_coord_d(glon,glat,cnt,blockid,bcid) 9,4
!-----------------------------------------------------------------------
!
!
! Purpose: Return global block index and local column index
! for column at location (glon,glat)
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use pmgrid
, only: spmd_on, nprxy_x, nprxy_y
#if ( defined SPMD )
use spmd_dyn
, only: lonrangexy, latrangexy
#endif
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: glon ! global longitude index
integer, intent(in) :: glat ! global latitude index
integer, intent(in) :: cnt ! size of blockid and bcid arrays
integer, intent(out) :: blockid(cnt) ! block index
integer, intent(out) :: bcid(cnt) ! column index within block
!---------------------------Local workspace-----------------------------
!
integer i,j,ii,jj ! loop indices
integer ddlon ! number of longitudes in block
!-----------------------------------------------------------------------
! lon/lat block
if (cnt < 1) then
write(6,*)'GET_BLOCK_COORD_D: arrays not large enough (', cnt,' < ',1,' ) '
call endrun
else
if (spmd_on .eq. 1) then
! Determine block coordinates (ii,jj), where ii ranges from 1 to
! nprxy_x and jj ranges from 1 to nprxy_y.
#if ( defined SPMD )
ii=0
do i=1,nprxy_x
if (lonrangexy(1,i) .le. glon .and. glon .le. lonrangexy(2,i)) ii=i
enddo
jj=0
do j=1,nprxy_y
if (latrangexy(1,j) .le. glat .and. glat .le. latrangexy(2,j)) jj=j
enddo
if (ii .eq. 0 .or. jj .eq. 0) then
write(6,*)'GET_BLOCK_COORD_D: could not find block indices for (', &
glon,',',glat,' ) '
call endrun
endif
! Global block index
blockid(1) = (jj-1)*nprxy_x+ii
! Local coordinates in block
j = glat-latrangexy(1,jj)+1
i = glon-lonrangexy(1,ii)+1
ddlon = lonrangexy(2,ii)-lonrangexy(1,ii)+1
! Local column index in block
bcid(1) = (j-1)*ddlon+i
!
#endif
else
blockid(1) = glat
bcid(1) = glon
endif
!
do j=2,cnt
blockid(j) = -1
bcid(j) = -1
enddo
!
endif
!
return
end subroutine get_block_coord_d
!
!========================================================================
!
integer function get_block_lvl_cnt_d(blockid,bcid) 2
!-----------------------------------------------------------------------
!
!
! Purpose: Return number of levels in indicated column. If column
! includes surface fields, then it is defined to also
! include level 0.
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
integer, intent(in) :: bcid ! column index within block
!-----------------------------------------------------------------------
! latitude slice block
get_block_lvl_cnt_d = plev + 1
return
end function get_block_lvl_cnt_d
!
!========================================================================
!
integer function get_block_col_cnt_d(blockid) 4,4
!-----------------------------------------------------------------------
!
!
! Purpose: Return number of lon/lat coordinates in indicated block
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use shr_kind_mod
, only: r8 => shr_kind_r8
use rgrid
, only: nlon
use pmgrid
, only: spmd_on, nprxy_x
#if ( defined SPMD )
use spmd_dyn
, only: lonrangexy, latrangexy
#endif
implicit none
!
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
!---------------------------Local workspace-----------------------------
integer i, j
!-----------------------------------------------------------------------
if (spmd_on .eq. 1) then
j = (blockid-1) / nprxy_x + 1
i = blockid - (j-1) * nprxy_x
#if ( defined SPMD )
get_block_col_cnt_d = (lonrangexy(2,i)-lonrangexy(1,i)+1) * &
(latrangexy(2,j)-latrangexy(1,j)+1)
#endif
else
get_block_col_cnt_d = nlon(blockid)
endif
return
end function get_block_col_cnt_d
!
!========================================================================
!
subroutine get_block_levels_d(blockid, bcid, lvlsiz, levels) 1,1
!-----------------------------------------------------------------------
!
!
! Purpose: Return level indices in indicated column. If column
! includes surface fields, then it is defined to also
! include level 0.
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
integer, intent(in) :: bcid ! column index within block
integer, intent(in) :: lvlsiz ! dimension of levels array
integer, intent(out) :: levels(lvlsiz) ! levels indices for block
!---------------------------Local workspace-----------------------------
!
integer k ! loop index
!-----------------------------------------------------------------------
! latitude slice block
if (lvlsiz < plev + 1) then
write(6,*)'GET_BLOCK_LEVELS_D: levels array not large enough (', &
lvlsiz,' < ',plev + 1,' ) '
call endrun
else
do k=0,plev
levels(k+1) = k
enddo
do k=plev+2,lvlsiz
levels(k) = -1
enddo
endif
return
end subroutine get_block_levels_d
!
!========================================================================
!
integer function get_lon_d(blockid,bcid) 2,2
!-----------------------------------------------------------------------
!
!
! Purpose: Return global longitude index for the column at location bcid
! in block blockid.
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use pmgrid
, only: spmd_on, nprxy_x
#if ( defined SPMD )
use spmd_dyn
, only: lonrangexy, latrangexy
#endif
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
integer, intent(in) :: bcid ! block column index
!-----------------------------------------------------------------------
integer i, j, ddlon, ddlat, ii, jj
! latitude slice block
if (spmd_on .eq. 1) then
j = (blockid-1) / nprxy_x + 1
i = blockid - (j-1) * nprxy_x
#if ( defined SPMD )
ddlon = lonrangexy(2,i)-lonrangexy(1,i)+1
ddlat = latrangexy(2,j)-latrangexy(1,j)+1
jj = (bcid-1) / ddlon + 1
ii = bcid - (jj-1) * ddlon
get_lon_d = lonrangexy(1,i) - 1 + ii
#endif
else
get_lon_d = bcid
endif
return
end function get_lon_d
!
!========================================================================
!
integer function get_lat_d(blockid,bcid) 2,2
!-----------------------------------------------------------------------
!
!
! Purpose: Return global latitude index for the column at location bcid
! in block blockid.
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use pmgrid
, only: spmd_on, nprxy_x
#if ( defined SPMD )
use spmd_dyn
, only: lonrangexy, latrangexy
#endif
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
integer, intent(in) :: bcid ! block column index
!-----------------------------------------------------------------------
integer i, j, ddlon, ddlat, ii, jj
! latitude slice block
if (spmd_on .eq. 1) then
j = (blockid-1) / nprxy_x + 1
i = blockid - (j-1) * nprxy_x
#if ( defined SPMD )
ddlon = lonrangexy(2,i)-lonrangexy(1,i)+1
ddlat = latrangexy(2,j)-latrangexy(1,j)+1
jj = (bcid-1) / ddlon + 1
ii = bcid - (jj-1) * ddlon
get_lat_d = latrangexy(1,j) - 1 + jj
#endif
else
get_lat_d = blockid
endif
return
end function get_lat_d
!
!========================================================================
!
integer function get_block_owner_d(blockid) 10,2
!-----------------------------------------------------------------------
!
!
! Purpose: Return id of processor that "owns" the indicated block
!
! Method:
!
! Author: Patrick Worley
!
!-----------------------------------------------------------------------
use pmgrid
, only: spmd_on
#if ( defined SPMD )
use spmd_dyn
, only: proc
#endif
implicit none
!------------------------------Arguments--------------------------------
integer, intent(in) :: blockid ! global block id
!-----------------------------------------------------------------------
! latitude slice block
#if (defined SPMD)
if (spmd_on .eq. 1) then
get_block_owner_d = blockid - 1
else
get_block_owner_d = proc(blockid)
endif
#else
get_block_owner_d = 0
#endif
return
end function get_block_owner_d
!#######################################################################
end module dyn_grid