#include <misc.h>
#include <preproc.h>
module decompMod 87,5
!------------------------------------------------------------------------------
!BOP
!
! !MODULE: decompMod
!
! !USES:
use shr_kind_mod
, only : r8 => shr_kind_r8
use spmdMod
, only : masterproc, iam, npes, mpicom, comp_id
use clm_varctl
, only : iulog
use clm_mct_mod
use abortutils
, only : endrun
!
! !PUBLIC TYPES:
implicit none
integer, public :: clump_pproc ! number of clumps per MPI process
!
! !PUBLIC MEMBER FUNCTIONS:
public get_clump_bounds ! beg and end gridcell, landunit, column,
! pft indices for clump
public get_proc_clumps ! number of clumps for this processor
public get_proc_bounds_atm ! beg and end gridcell for atm
public get_proc_bounds ! beg and end gridcell, landunit, column,
! pft indices for this processor
public get_proc_total ! total number of gridcells, landunits,
! columns and pfts for any processor
public get_proc_global ! total gridcells, landunits, columns, pfts
! across all processors
public get_proc_global_atm ! total atm cells on all pes
public get_clmlevel_gsize ! get global size associated with clmlevel
public get_clmlevel_dsize ! get global size associated with clmlevel
public get_clmlevel_gsmap ! get gsmap associated with clmlevel
!
! !DESCRIPTION:
! Module provides a descomposition into a clumped data structure which can
! be mapped back to atmosphere physics chunks.
!
! !REVISION HISTORY:
! 2002.09.11 Forrest Hoffman Creation.
! 2005.11.01 T Craig Rewrite
! 2006.06.06 T Craig Reduce memory, cleanup
!
!
! !PRIVATE TYPES:
private ! (now mostly public for decompinitmod)
integer,public :: nclumps ! total number of clumps across all processors
integer,public :: numg ! total number of gridcells on all procs
integer,public :: numl ! total number of landunits on all procs
integer,public :: numc ! total number of columns on all procs
integer,public :: nump ! total number of pfts on all procs
integer,public :: numa ! total number of atm gridcells on all procs
!---global information on each pe
type processor_type
integer :: nclumps ! number of clumps for processor_type iam
integer,pointer :: cid(:) ! clump indices
integer :: ncells ! number of gridcells in proc
integer :: nlunits ! number of landunits in proc
integer :: ncols ! number of columns in proc
integer :: npfts ! number of pfts in proc
integer :: begg, endg ! beginning and ending gridcell index
integer :: begl, endl ! beginning and ending landunit index
integer :: begc, endc ! beginning and ending column index
integer :: begp, endp ! beginning and ending pft index
integer :: abegg,aendg ! beginning and ending atm gridcell index
end type processor_type
public processor_type
type(processor_type),public :: procinfo
!---global information on each pe
type clump_type
integer :: owner ! process id owning clump
integer :: ncells ! number of gridcells in clump
integer :: nlunits ! number of landunits in clump
integer :: ncols ! number of columns in clump
integer :: npfts ! number of pfts in clump
integer :: begg, endg ! beginning and ending gridcell index
integer :: begl, endl ! beginning and ending landunit index
integer :: begc, endc ! beginning and ending column index
integer :: begp, endp ! beginning and ending pft index
end type clump_type
public clump_type
type(clump_type),public, allocatable :: clumps(:)
!---global information on each pe
!--- i,j = 2d global
!--- glo = 1d global sn ordered
!--- gsn = 1d global sn ordered compressed
!--- gdc = 1d global dc ordered compressed
type decomp_type
integer,pointer :: glo2gdc(:) ! 1d glo to 1d gdc
integer,pointer :: gdc2glo(:) ! 1d gdc to 1d glo
end type decomp_type
public decomp_type
type(decomp_type),public,target :: ldecomp
type(decomp_type),public,target :: adecomp
type(mct_gsMap) ,public,target :: gsMap_atm_gdc2glo
type(mct_gsMap) ,public,target :: gsMap_lnd_gdc2glo
type(mct_gsMap) ,public,target :: gsMap_gce_gdc2glo
type(mct_gsMap) ,public,target :: gsMap_lun_gdc2glo
type(mct_gsMap) ,public,target :: gsMap_col_gdc2glo
type(mct_gsMap) ,public,target :: gsMap_pft_gdc2glo
!EOP
!------------------------------------------------------------------------------
!
!
!------------------------------------------------------------------------------
contains
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_clump_bounds
!
! !INTERFACE:
subroutine get_clump_bounds (n, begg, endg, begl, endl, begc, endc, & 8,1
begp, endp)
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: n ! proc clump index
integer, intent(out) :: begp, endp ! clump beginning and ending
! pft indices
integer, intent(out) :: begc, endc ! clump beginning and ending
! column indices
integer, intent(out) :: begl, endl ! clump beginning and ending
! landunit indices
integer, intent(out) :: begg, endg ! clump beginning and ending
! gridcell indices
!
! !DESCRIPTION:
! Determine clump beginning and ending pft, column, landunit and
! gridcell indices.
!
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
!
! !LOCAL VARIABLES:
!EOP
character(len=32), parameter :: subname = 'get_clump_bounds' ! Subroutine name
integer :: cid ! clump id
#ifdef _OPENMP
integer, external :: OMP_GET_MAX_THREADS
integer, external :: OMP_GET_NUM_THREADS
#endif
!------------------------------------------------------------------------------
!
! Make sure this IS being called from a threaded region
!
#ifdef _OPENMP
if ( OMP_GET_NUM_THREADS() == 1 .and. OMP_GET_MAX_THREADS() > 1 )then
call endrun
( trim(subname)//' ERROR: Calling from inside a non-threaded region -- this results in bad performance' )
end if
#endif
cid = procinfo%cid(n)
begp = clumps(cid)%begp
endp = clumps(cid)%endp
begc = clumps(cid)%begc
endc = clumps(cid)%endc
begl = clumps(cid)%begl
endl = clumps(cid)%endl
begg = clumps(cid)%begg
endg = clumps(cid)%endg
end subroutine get_clump_bounds
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_bounds
!
! !INTERFACE:
subroutine get_proc_bounds (begg, endg, begl, endl, begc, endc, & 80,1
begp, endp)
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, optional, intent(out) :: begp, endp ! proc beginning and ending
! pft indices
integer, optional, intent(out) :: begc, endc ! proc beginning and ending
! column indices
integer, optional, intent(out) :: begl, endl ! proc beginning and ending
! landunit indices
integer, optional, intent(out) :: begg, endg ! proc beginning and ending
! gridcell indices
! !DESCRIPTION:
! Retrieve gridcell, landunit, column, and pft bounds for process.
!
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
! !LOCAL VARIABLES:
!EOP
character(len=32), parameter :: subname = 'get_proc_bounds' ! Subroutine name
#ifdef _OPENMP
integer, external :: OMP_GET_NUM_THREADS
#endif
!------------------------------------------------------------------------------
!
! Make sure this is NOT being called from a threaded region
!
#ifdef _OPENMP
if ( OMP_GET_NUM_THREADS() > 1 )then
call endrun
( trim(subname)//' ERROR: Calling from inside a threaded region -- this is illegal' )
end if
#endif
if (present(begp)) then
begp = procinfo%begp
endif
if (present(endp)) then
endp = procinfo%endp
endif
if (present(begc)) then
begc = procinfo%begc
endif
if (present(endc)) then
endc = procinfo%endc
endif
if (present(begl)) then
begl = procinfo%begl
endif
if (present(endl)) then
endl = procinfo%endl
endif
if (present(begg)) then
begg = procinfo%begg
endif
if (present(endg)) then
endg = procinfo%endg
endif
end subroutine get_proc_bounds
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_bounds_atm
!
! !INTERFACE:
subroutine get_proc_bounds_atm (begg, endg) 18,1
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, intent(out) :: begg, endg ! proc beginning and ending
! gridcell indices for atm grid
! !DESCRIPTION:
! Retrieve gridcell begg, endg for atm decomp
!
! !REVISION HISTORY:
! 2005.12.15 T Craig Added
!
!------------------------------------------------------------------------------
! !LOCAL VARIABLES:
!EOP
character(len=32), parameter :: subname = 'get_proc_bounds_atm' ! Subroutine name
#ifdef _OPENMP
integer, external :: OMP_GET_NUM_THREADS
#endif
!------------------------------------------------------------------------------
!
! Make sure this is NOT being called from a threaded region
!
#ifdef _OPENMP
if ( OMP_GET_NUM_THREADS() > 1 )then
call endrun
( trim(subname)//' ERROR: Calling from inside a threaded region -- this is illegal' )
end if
#endif
begg = procinfo%abegg
endg = procinfo%aendg
end subroutine get_proc_bounds_atm
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_total
!
! !INTERFACE:
subroutine get_proc_total(pid, ncells, nlunits, ncols, npfts)
!
! !DESCRIPTION:
! Count up gridcells, landunits, columns, and pfts on process.
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: pid ! proc id
integer, intent(out) :: ncells ! total number of gridcells
! on the processor
integer, intent(out) :: nlunits ! total number of landunits
! on the processor
integer, intent(out) :: ncols ! total number of columns
! on the processor
integer, intent(out) :: npfts ! total number of pfts
! on the processor
!
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
!
! !LOCAL VARIABLES:
!EOP
integer :: cid ! clump index
!------------------------------------------------------------------------------
npfts = 0
nlunits = 0
ncols = 0
ncells = 0
do cid = 1,nclumps
if (clumps(cid)%owner == pid) then
ncells = ncells + clumps(cid)%ncells
nlunits = nlunits + clumps(cid)%nlunits
ncols = ncols + clumps(cid)%ncols
npfts = npfts + clumps(cid)%npfts
end if
end do
end subroutine get_proc_total
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_global
!
! !INTERFACE:
subroutine get_proc_global(ng, nl, nc, np) 17
!
! !DESCRIPTION:
! Return number of gridcells, landunits, columns, and pfts across all
! processes.
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, intent(out) :: ng ! total number of gridcells
! across all processors
integer, intent(out) :: nl ! total number of landunits
! across all processors
integer, intent(out) :: nc ! total number of columns
! across all processors
integer, intent(out) :: np ! total number of pfts
! across all processors
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
!EOP
!------------------------------------------------------------------------------
np = nump
nc = numc
nl = numl
ng = numg
end subroutine get_proc_global
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_global_atm
!
! !INTERFACE:
subroutine get_proc_global_atm(na) 3
!
! !DESCRIPTION:
! Return number of gridcells, landunits, columns, and pfts across all
! processes.
!
! !USES:
!
! !ARGUMENTS:
implicit none
integer, intent(out) :: na ! total number of atm gridcells
! across all processors
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
!EOP
!------------------------------------------------------------------------------
na = numa
end subroutine get_proc_global_atm
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_proc_clumps
!
! !INTERFACE:
integer function get_proc_clumps() 6
!
! !DESCRIPTION:
! Return the number of clumps.
!
! !USES:
!
! !ARGUMENTS:
implicit none
!
! !RETURN VALUE:
! integer :: get_proc_clumps
!
! !REVISION HISTORY:
! 2003.09.12 Mariana Vertenstein Creation.
!
!EOP
!------------------------------------------------------------------------------
get_proc_clumps = procinfo%nclumps
end function get_proc_clumps
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_clmlevel_gsize
!
! !INTERFACE:
integer function get_clmlevel_gsize (clmlevel) 11,4
!
! !DESCRIPTION:
! Determine 1d size from clmlevel
!
! !USES:
use clmtype
, only : gratm, grlnd, nameg, namel, namec, namep, allrof
use domainMod
, only : adomain,ldomain
#ifdef RTM
use clm_varpar
,only : rtmlon,rtmlat
#endif
!
! !ARGUMENTS:
implicit none
character(len=*), intent(in) :: clmlevel !type of clm 1d array
!
! !REVISION HISTORY:
!
!
! !LOCAL VARIABLES:
!EOP
!-----------------------------------------------------------------------
! Determine necessary indices
select case (clmlevel)
case(gratm)
get_clmlevel_gsize = adomain%ns
case(grlnd)
get_clmlevel_gsize = ldomain%ns
case(nameg)
get_clmlevel_gsize = numg
case(namel)
get_clmlevel_gsize = numl
case(namec)
get_clmlevel_gsize = numc
case(namep)
get_clmlevel_gsize = nump
#ifdef RTM
case(allrof)
get_clmlevel_gsize = rtmlon*rtmlat
#endif
case default
write(iulog,*) 'get_clmlevel_gsize does not match clmlevel type: ', trim(clmlevel)
call endrun
()
end select
end function get_clmlevel_gsize
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_clmlevel_dsize
!
! !INTERFACE:
subroutine get_clmlevel_dsize (clmlevel,dims,s1,s2,s3,s4) 4,4
!
! !DESCRIPTION:
! Determine number of dims and size of dims from clmlevel
!
! !USES:
use clmtype
, only : gratm, grlnd, nameg, namel, namec, namep, allrof
use domainMod
, only : adomain,ldomain
#ifdef RTM
use clm_varpar
,only : rtmlon,rtmlat
#endif
!
! !ARGUMENTS:
implicit none
character(len=*), intent(in ) :: clmlevel !type of clm 1d array
integer, intent(out) :: dims ! number of dimensions
integer,optional, intent(out) :: s1 ! size of dim1
integer,optional, intent(out) :: s2 ! size of dim2
integer,optional, intent(out) :: s3 ! size of dim3
integer,optional, intent(out) :: s4 ! size of dim4
!
! !REVISION HISTORY:
!
!
! !LOCAL VARIABLES:
!EOP
integer :: ls(4)
!-----------------------------------------------------------------------
! Determine necessary indices
dims = 1
ls = 1
select case (clmlevel)
case(gratm)
dims = 2
ls(1) = adomain%ni
ls(2) = adomain%nj
case(grlnd)
dims = 2
ls(1) = ldomain%ni
ls(2) = ldomain%nj
case(nameg)
ls(1) = numg
case(namel)
ls(1) = numl
case(namec)
ls(1) = numc
case(namep)
ls(1) = nump
#ifdef RTM
case(allrof)
dims = 2
ls(1) = rtmlon
ls(2) = rtmlat
#endif
case default
write(iulog,*) 'get_clmlevel_dsize does not match clmlevel type: ', trim(clmlevel)
call endrun
()
end select
if (present(s1)) then
s1 = ls(1)
endif
if (present(s2)) then
s2 = ls(2)
endif
if (present(s3)) then
s3 = ls(3)
endif
if (present(s4)) then
s4 = ls(4)
endif
end subroutine get_clmlevel_dsize
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: get_clmlevel_gsmap
!
! !INTERFACE:
subroutine get_clmlevel_gsmap (clmlevel, gsmap) 9,3
!
! !DESCRIPTION:
! Compute arguments for gatherv, scatterv for vectors
!
! !USES:
use clmtype
, only : gratm, grlnd, nameg, namel, namec, namep, allrof
#if (defined RTM)
use RunoffMod
, only : gsMap_rtm_gdc2glo
#endif
!
! !ARGUMENTS:
implicit none
character(len=*), intent(in) :: clmlevel ! type of input data
type(mct_gsmap), pointer :: gsmap
! !REVISION HISTORY:
! Author: Mariana Vertenstein
!
!
! !LOCAL VARIABLES:
!EOP
!----------------------------------------------------------------------
select case (clmlevel)
case(gratm)
gsmap => gsmap_atm_gdc2glo
case(grlnd)
gsmap => gsmap_lnd_gdc2glo
case(nameg)
gsmap => gsmap_gce_gdc2glo
case(namel)
gsmap => gsmap_lun_gdc2glo
case(namec)
gsmap => gsmap_col_gdc2glo
case(namep)
gsmap => gsmap_pft_gdc2glo
#if (defined RTM)
case(allrof)
gsmap => gsmap_rtm_gdc2glo
#endif
case default
write(iulog,*) 'get_clmlevel_gsmap: Invalid expansion character: ',trim(clmlevel)
call endrun
end select
end subroutine get_clmlevel_gsmap
!------------------------------------------------------------------------------
end module decompMod