#include <misc.h>
#include <preproc.h>
#define L2R_Decomp
#undef L2R_Decomp
module RtmMod 4,12
#if (defined RTM)
!-----------------------------------------------------------------------
!BOP
!
! !MODULE: RtmMod
!
! !DESCRIPTION:
! River Routing Model (U. of Texas River Transport
! Model)~\cite{Branstetter:2001}
!
! !USES:
use shr_kind_mod
, only : r8 => shr_kind_r8
use spmdMod
, only : masterproc,npes,iam,mpicom,comp_id,MPI_REAL8,MPI_INTEGER
use spmdMod
, only : MPI_MAX,MPI_SUM
use clm_varpar
, only : lsmlon, lsmlat, rtmlon, rtmlat
use clm_varcon
, only : re, spval
use clm_varctl
, only : iulog
use shr_sys_mod
, only : shr_sys_flush
use domainMod
, only : latlon_type, latlon_init, latlon_clean
use abortutils
, only : endrun
use RunoffMod
, only : runoff, nt_rtm, rtm_tracers
use RunoffMod
, only : gsMap_rtm_gdc2glo,sMatP_l2r
use clm_mct_mod
use perf_mod
!
! !PUBLIC TYPES:
implicit none
private
!
! !PUBLIC MEMBER FUNCTIONS:
public Rtmini ! Initialize RTM grid and land mask
public Rtmriverflux ! Interface with RTM river routing model
public RtmRest ! Read/write RTM restart data (netcdf)
!
! !REVISION HISTORY:
! Author: Sam Levis
!
!
! !PRIVATE MEMBER FUNCTIONS:
!
private RtmUpdateInput ! Update rtm inputs
private Rtm ! River routing model (based on U. Texas code)
! !PRIVATE TYPES:
! RTM tracers
character(len=256) :: rtm_trstr ! tracer string
! RTM input
real(r8), pointer :: rtmin_acc(:,:) ! RTM averaging buffer for runoff
real(r8), pointer :: rtmin_avg(:,:) ! RTM global input
integer :: ncount_rtm ! RTM time averaging = number of time samples to average over
real(r8) :: delt_rtm ! RTM time step
real(r8) :: delt_rtm_max ! RTM max timestep
real(r8) :: cfl_scale = 0.1_r8 ! cfl scale factor, must be <= 1.0
real(r8), parameter :: effvel(nt_rtm) = 0.35_r8 ! downstream velocity (m/s)
!glo
integer , pointer :: dwnstrm_index(:)! downstream index
!gdc
real(r8), pointer :: ddist(:) ! downstream dist (m)
real(r8), pointer :: evel(:,:) ! effective tracer velocity (m/s)
real(r8), pointer :: sfluxin(:,:) ! cell tracer influx (m3/s)
real(r8), pointer :: fluxout(:,:) ! cell tracer outlflux (m3/s)
real(r8), pointer :: totrunin(:,:) ! cell tracer lnd forcing on rtm grid (mm/s)
!map
type(mct_sMat) :: sMat0_l2r
type(mct_sMat) :: sMat0_l2r_d
!EOP
!-----------------------------------------------------------------------
contains
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: Rtmini
!
! !INTERFACE:
subroutine Rtmini 1,50
!
! !DESCRIPTION:
! Initialize RTM grid, mask, decomp
!
! !USES:
use shr_const_mod
, only : SHR_CONST_PI
use domainMod
, only : llatlon,ldomain,domain_check
use areaMod
, only : celledge, cellarea, map_setmapsAR
use clm_varctl
, only : frivinp_rtm
use clm_varctl
, only : rtm_nsteps
use decompMod
, only : get_proc_bounds, get_proc_global, ldecomp
use decompMod
, only : gsMap_lnd_gdc2glo
use clm_time_manager
, only : get_curr_date
use clm_time_manager
, only : get_step_size
use clmtype
, only : grlnd
use spmdGathScatMod
!
! !ARGUMENTS:
implicit none
!
! !CALLED FROM:
! subroutine initialize in module initializeMod
!
! !REVISION HISTORY:
! Author: Sam Levis
! Update: T Craig, Dec 2006
!
!
! !LOCAL VARIABLES:
!EOP
real(r8), dimension(4) :: rtmedge = (/ 90._r8, 180._r8, -90._r8, -180._r8 /) !N,E,S,W edges of rtm grid
integer :: ioff(0:8) = (/0,0,1,1,1,0,-1,-1,-1/) !rdirc input to i
integer :: joff(0:8) = (/0,1,1,0,-1,-1,-1,0,1/) !rdirc input to j
integer :: i,j,k,n,g,n2,nt ! loop indices
integer :: im1,ip1,jm1,jp1,ir,jr,nr ! neighbor indices
integer :: i2,j2 ! downstream i and j
real(r8) :: deg2rad ! pi/180
real(r8) :: dx,dx1,dx2,dx3 ! lon dist. betn grid cells (m)
real(r8) :: dy ! lat dist. betn grid cells (m)
real(r8),allocatable :: tempg(:) ! temporary buffer
integer ,allocatable :: rdirc(:) ! temporary buffer
integer ,allocatable :: iocn(:) ! downstream ocean cell
integer ,allocatable :: nocn(:) ! number of rtm cells in basin
integer ,allocatable :: pocn(:) ! pe number assigned to basin
integer ,allocatable :: nop(:) ! number of rtm cells on a pe
integer ,allocatable :: nba(:) ! number of basins on each pe
integer ,allocatable :: nrs(:) ! begr on each pe
integer ,allocatable :: baslc(:) ! basin overlap land cell
integer ,allocatable :: basnp(:) ! basin pe number
integer ,allocatable :: basin(:) ! basin to rtm mapping
integer :: nbas ! number of basins
integer :: nrtm ! num of rtm points
integer :: baspe ! pe with min number of rtm cells
integer :: maxrtm ! max num of rtms per pe for decomp
integer :: minbas,maxbas ! used for decomp search
integer :: nl,nloops ! used for decomp search
integer :: ier ! error code
integer :: mon ! month (1, ..., 12)
integer :: day ! day of month (1, ..., 31)
integer :: ncsec ! seconds of current date
integer :: begg,endg ! local start/end gridcell indices
integer :: numg ! tot num of gridcells on all pes
integer :: numl ! tot num of landunits on all pes
integer :: numc ! tot num of columns on all pes
integer :: nump ! tot num of pfts on all pes
integer :: begr,endr,numr ! tot num of roff pts on all pes
real(r8) :: dtover,dtovermax ! ts calc temporaries
character(len=16), dimension(50) :: river_name
character(len=30), dimension(50) :: rivstat_name
real(r8) , dimension(50) :: rivstat_lon
real(r8) , dimension(50) :: rivstat_lat
integer :: nroflnd
integer :: nrofocn
integer :: pid,np,npmin,npmax,npint ! log loop control
integer,parameter :: dbug = 1 ! 0 = none, 1=normal, 2=much, 3=max
integer lsize,gsize ! sizes to initialize GsMap
integer :: na,nb,ns ! mct sizes
integer :: igrow,igcol,iwgt ! mct field indices
integer :: ii,ji,ni,no,gi,go ! tmps
real(r8) :: wt ! mct wt
integer ,pointer :: rgdc2glo(:) ! temporary for initialization
integer ,pointer :: rglo2gdc(:) ! temporary for initialization
real(r8),pointer :: lfield(:) ! tmp lnd field
real(r8),pointer :: rfield(:) ! tmp rtm field
real(r8),pointer :: glatc(:),glonc(:) ! global lat/lon
real(r8),pointer :: gfrac(:) ! global frac
real(r8),pointer :: lfrac(:) ! global land frac
integer ,pointer :: gmask(:) ! global mask
type(latlon_type):: rlatlon ! rtm grid
!-----------------------------------------------------------------------
call t_startf('rtmi_grid')
!--- Initialize rtm_trstr
rtm_trstr = trim(rtm_tracers(1))
do n = 2,nt_rtm
rtm_trstr = trim(rtm_trstr)//':'//trim(rtm_tracers(n))
enddo
if (masterproc) then
write(iulog,*)'rtm tracers = ',nt_rtm,trim(rtm_trstr)
end if
!--- Allocate rtm grid variables
call latlon_init
(rlatlon,rtmlon,rtmlat)
!--- Allocate inputs and outputs to rtm at 1/2 degree resolution
allocate (glatc(rtmlon*rtmlat), glonc(rtmlon*rtmlat), &
stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'glatc,glonc'
call endrun
end if
allocate (runoff%rlat(rtmlat), runoff%rlon(rtmlon), &
stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'rlat,rlon'
call endrun
end if
!--- Allocate temporaries
allocate(rdirc(rtmlon*rtmlat),tempg(rtmlon*rtmlat),stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'rdirc'
call endrun
end if
!--- Useful constants and initial values
deg2rad = SHR_CONST_PI / 180._r8
! Open and read input data (river direction file)
! rtm operates from south to north and from the dateline
! River station data is currently not used by the model -
! it is only used by the diagnostic package
! If the river direction file is modified - the river station
! part must also be modified
rlatlon%edges(1:4) = rtmedge(1:4)
if (masterproc) then
open (1,file=frivinp_rtm)
do n = 1,rtmlon*rtmlat
read(1,*) glatc(n),glonc(n),tempg(n)
rdirc(n) = nint(tempg(n))
enddo
do n = 1,50
read(1,10,iostat=ier) river_name(n), rivstat_lon(n), rivstat_lat(n), &
rivstat_name(n)
if (ier /= 0) exit
10 format(1x,a16,f7.2,1x,f7.2,a30)
end do
close(1)
endif
deallocate(tempg)
call mpi_bcast(glatc,size(glatc),MPI_REAL8,0,mpicom,ier)
call mpi_bcast(glonc,size(glonc),MPI_REAL8,0,mpicom,ier)
call mpi_bcast(rdirc,size(rdirc),MPI_INTEGER,0,mpicom,ier)
if (masterproc) then
write(iulog,*)'Columns in RTM = ',rtmlon
write(iulog,*)'Rows in RTM = ',rtmlat
write(iulog,*)'read river direction data'
end if
!--- set 1d lat/lon values
do j=1,rtmlat
n = (j-1)*rtmlon + 1
runoff%rlat(j) = glatc(n)
rlatlon%latc(j) = glatc(n)
enddo
do i=1,rtmlon
n = i
runoff%rlon(i) = glonc(n)
rlatlon%lonc(i) = glonc(n)
enddo
deallocate(glatc,glonc)
allocate (dwnstrm_index(rtmlon*rtmlat), &
gfrac(rtmlon*rtmlat), lfrac(lsmlon*lsmlat), &
gmask(rtmlon*rtmlat), &
stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'dwnstrm_index,gfrac'
call endrun
end if
!--- Set dwnstrm_index from rdirc values
!--- The following assumes that there is no runoff
!--- south of j=1 or north of j=rtmlat
!--- This is true for rdirc.05
!--- Determine dwnstrmm_index from rtm river flow direction (0-8)
dwnstrm_index = 0
do j=1,rtmlat
do i=1,rtmlon
n = (j-1)*rtmlon + i
if (rdirc(n) /= 0) then
ir = i + ioff(abs(rdirc(n)))
jr = j + joff(abs(rdirc(n)))
if (ir < 1 ) ir = ir + rtmlon
if (ir > rtmlon) ir = ir - rtmlon
!--- check cross pole flow, etc
if (jr < 1 .or. jr > rtmlat .or. ir < 1 .or. ir > rtmlon) then
write(iulog,*) 'Rtmini ERROR ir jr bounds ',i,j,rdirc(n),ir,jr
call endrun
()
endif
nr = (jr-1)*rtmlon + ir
if (n == nr) then
write(iulog,*) 'Rtmini ERROR dwnstrm_index ',i,j,n,rdirc(n),ir,jr,nr
call endrun
()
endif
dwnstrm_index(n) = nr
endif
enddo
enddo
!--- Determine RTM celledges and areas
call celledge
(rlatlon, &
rlatlon%edges(1), rlatlon%edges(2), &
rlatlon%edges(3), rlatlon%edges(4))
call t_stopf('rtmi_grid')
!--- Set sMat0_l2r, full mapping weights for l2r, just on root pe
!--- for now use lfield to "ignore" non-active land cells in sMat0_l2r
!--- Later these will be "reduced" to just the useful weights
!--- Compute gfrac on root pe and bcast
!--- Change 9/2007, compute on all pes for decomp based on overlap
call t_startf('rtmi_setl2r')
call get_proc_bounds
(begg, endg)
call gather_data_to_master
(ldomain%frac,lfrac,grlnd)
call mpi_bcast(lfrac,size(lfrac),MPI_REAL8,0,mpicom,ier)
allocate(lfield(lsmlon*lsmlat),rfield(rtmlon*rtmlat))
lfield = 0._r8
do n = 1,lsmlon*lsmlat
if (ldecomp%glo2gdc(n) > 0) lfield(n) = 1._r8
enddo
rfield = 1._r8
call map_setmapsAR
(llatlon,rlatlon,sMat0_l2r, &
fracin=lfield, fracout=rfield)
igrow = mct_sMat_indexIA(sMat0_l2r,'grow')
igcol = mct_sMat_indexIA(sMat0_l2r,'gcol')
iwgt = mct_sMat_indexRA(sMat0_l2r,'weight')
gfrac = 0._r8
do n = 1,mct_sMat_lsize(sMat0_l2r)
nr = sMat0_l2r%data%iAttr(igrow,n)
ns = sMat0_l2r%data%iAttr(igcol,n)
wt = sMat0_l2r%data%rAttr(iwgt ,n)
gfrac(nr) = gfrac(nr) + lfrac(ns)
enddo
deallocate(lfield,rfield)
call t_stopf('rtmi_setl2r')
!--- Determine rtm ocn/land mask, 0=none, 1=land, 2=ocean outflow, -1=reroute over ocean to ocean outflow points
call t_startf('rtmi_decomp')
gmask = 0 ! assume neither land nor ocn
do n=1,rtmlon*rtmlat ! set downstream value first
nr = dwnstrm_index(n)
if (nr /= 0) then ! assume downstream cell is ocn
gmask(nr) = 2
end if
enddo
do n=1,rtmlon*rtmlat ! override downstream setting from local info
nr = dwnstrm_index(n)
if (nr /= 0) then ! n is always land if dwnstrm_index exists
if (rdirc(n) > 0) then
gmask(n) = 1
else if (rdirc(n) < 0) then
gmask(n) = -1
end if
else ! n is ocn if no dwnstrm_index and some frac
if (gfrac(n)>0._r8) gmask(n) = 2
end if
enddo
deallocate(rdirc)
deallocate(gfrac,lfrac)
!--- Compute river basins, actually compute ocean outlet gridcell
!--- iocn = final downstream cell, index is global 1d ocean gridcell
!--- nocn = number of source gridcells for ocean gridcell
allocate(iocn(rtmlon*rtmlat),nocn(rtmlon*rtmlat),stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'iocn,nocn'
call endrun
end if
call t_startf('rtmi_dec_basins')
iocn = 0
nocn = 0
do nr=1,rtmlon*rtmlat
n = nr
if (abs(gmask(n)) == 1) then ! land
g = 0
do while (abs(gmask(n)) == 1 .and. g < rtmlon*rtmlat) ! follow downstream
n = dwnstrm_index(n)
g = g + 1
end do
if (gmask(n) == 2) then ! found ocean outlet
iocn(nr) = n ! set ocean outlet or nr to n
nocn(n) = nocn(n) + 1 ! one more land cell for n
elseif (abs(gmask(n)) == 1) then ! no ocean outlet, warn user, ignore cell
write(iulog,*) 'rtmini WARNING no downstream ocean cell - IGNORED', &
g,nr,gmask(nr),dwnstrm_index(nr), &
n,gmask(n),dwnstrm_index(n)
else
write(iulog,*) 'rtmini ERROR downstream cell is non-ocean,non-land', &
g,nr,gmask(nr),dwnstrm_index(nr), &
n,gmask(n),dwnstrm_index(n)
call endrun
()
endif
elseif (gmask(n) == 2) then ! ocean, give to self
iocn(nr) = n
nocn(n) = nocn(n) + 1
endif
enddo
call t_stopf('rtmi_dec_basins')
!--- Now allocate those basins to pes
!--- pocn is the pe that gets the basin associated with ocean outlet nr
!--- nop is a running count of the number of rtm cells/pe
call t_startf('rtmi_dec_distr')
nbas = 0
nrtm = 0
do nr=1,rtmlon*rtmlat
if (nocn(nr) > 0) then
nbas = nbas + 1
nrtm = nrtm + nocn(nr)
endif
enddo
allocate(pocn(rtmlon*rtmlat), &
nop(0:npes-1),nba(0:npes-1),nrs(0:npes-1), &
rglo2gdc(rtmlon*rtmlat),runoff%num_rtm(0:npes-1))
!------- compute l2r based decomp, comment out to turn off
#if (defined L2R_Decomp)
allocate(basin(rtmlon*rtmlat),basnp(nbas),baslc(nbas))
! use pocn as temporary storage
pocn = -99
basnp = -99
igrow = mct_sMat_indexIA(sMat0_l2r,'grow')
igcol = mct_sMat_indexIA(sMat0_l2r,'gcol')
iwgt = mct_sMat_indexRA(sMat0_l2r,'weight')
do n = 1,mct_sMat_lsize(sMat0_l2r)
nr = sMat0_l2r%data%iAttr(igrow,n)
ns = sMat0_l2r%data%iAttr(igcol,n)
! wt = sMat0_l2r%data%rAttr(iwgt ,n)
if (ldecomp%glo2gdc(ns) > 0) then
pocn(nr) = ns ! set ocean overlap to one of the lnd cells
endif
enddo
n = 0
do nr = 1,rtmlon*rtmlat
if (nocn(nr) > 0) then
n = n + 1
if (n > nbas) then
write(iulog,*) ' ERROR: basin decomp out of bounds ',n,nbas
call endrun
()
endif
basin(nr) = n
baslc(n) = pocn(nr) ! set basin land cell to the oceancell overlap
endif
enddo
if (n /= nbas) then
write(iulog,*) ' ERROR: basin decomp sum incorrect ',n,nbas
call endrun
()
endif
call mct_gsmap_pelocs(gsmap_lnd_gdc2glo,nbas,baslc,basnp)
deallocate(baslc)
#endif
nop = 0
nba = 0
nrs = 0
pocn = -99
rglo2gdc = 0
baspe = 0
maxrtm = int(float(nrtm)/float(npes)*0.445) + 1
call shr_sys_flush
(iulog)
nloops = 3
minbas = nrtm
do nl=1,nloops
maxbas = minbas - 1
minbas = maxval(nocn)/(2**nl)
if (nl == nloops) minbas = min(minbas,1)
do nr=1,rtmlon*rtmlat
! if (nocn(nr) /= 0) then
if (nocn(nr) > 0 .and. nocn(nr) >= minbas .and. nocn(nr) <= maxbas) then
! Decomp options
! find min pe (implemented but scales poorly)
! use increasing thresholds (implemented, ok load balance for l2r or calc)
! distribute basins using above methods but work from max to min basin size
! distribute basins to minimize l2r time, basins put on pes associated
! with lnd forcing, need to know l2r map and lnd decomp
!
#if (defined L2R_Decomp)
!--------------
! put it on a pe that is associated with the land decomp if valid
if (basnp(basin(nr)) >= 0 .and. basnp(basin(nr)) <= npes-1) then
baspe = basnp(basin(nr))
else
#endif
!--------------
! find min pe
! baspe = 0
! do n = 1,npes-1
! if (nop(n) < nop(baspe)) baspe = n
! enddo
!--------------
! find next pe below maxrtm threshhold and increment
do while (nop(baspe) > maxrtm)
baspe = baspe + 1
if (baspe > npes-1) then
baspe = 0
maxrtm = max(maxrtm*1.5, maxrtm+1.0) ! 3 loop, .445 and 1.5 chosen carefully
endif
enddo
#if (defined L2R_Decomp)
endif
#endif
!--------------
if (baspe > npes-1 .or. baspe < 0) then
write(iulog,*) 'error in decomp for rtm ',nr,npes,baspe
call endrun
()
endif
nop(baspe) = nop(baspe) + nocn(nr)
nba(baspe) = nba(baspe) + 1
pocn(nr) = baspe
endif
enddo ! nr
enddo ! nl
#if (defined L2R_Decomp)
deallocate(basin,basnp)
#endif
! set pocn for land cells, was set for ocean above
do nr=1,rtmlon*rtmlat
if (iocn(nr) > 0) then
pocn(nr) = pocn(iocn(nr))
if (pocn(nr) < 0 .or. pocn(nr) > npes-1) then
write(iulog,*) 'Rtmini ERROR pocn lnd setting ',nr,iocn(nr),iocn(iocn(nr)),pocn(iocn(nr)),pocn(nr),npes
call endrun
()
endif
endif
enddo
if (masterproc) write(iulog,*) 'rtm cells and basins total = ',nrtm,nbas
if (masterproc) write(iulog,*) 'rtm cells per basin avg/max = ',nrtm/nbas,maxval(nocn)
if (masterproc) write(iulog,*) 'rtm cells per pe min/max = ',minval(nop),maxval(nop)
if (masterproc) write(iulog,*) 'basins per pe min/max = ',minval(nba),maxval(nba)
!--- Count and distribute cells to rglo2gdc
runoff%numr = 0
runoff%numro = 0
runoff%numrl = 0
runoff%lnumr = 0
runoff%lnumro = 0
runoff%lnumrl = 0
runoff%num_rtm = 0
do n = 0,npes-1
if (iam == n) then
runoff%begr = runoff%numr + 1
runoff%begrl = runoff%numrl + 1
runoff%begro = runoff%numro + 1
endif
runoff%num_rtm(n) = runoff%num_rtm(n) + nop(n)
runoff%numr = runoff%numr + nop(n)
runoff%numro = runoff%numro + nba(n)
runoff%numrl = runoff%numrl + nop(n) - nba(n)
if (iam == n) then
runoff%lnumr = runoff%lnumr + nop(n)
runoff%lnumro = runoff%lnumro + nba(n)
runoff%lnumrl = runoff%lnumrl + nop(n) - nba(n)
runoff%endr = runoff%begr + runoff%lnumr - 1
runoff%endro = runoff%begro + runoff%lnumro - 1
runoff%endrl = runoff%begrl + runoff%lnumrl - 1
endif
enddo
! nrs is begr on each pe
nrs(0) = 1
do n = 1,npes-1
nrs(n) = nrs(n-1) + nop(n-1)
enddo
! reuse nba for nop-like counter here
! pocn -99 is unused cell
nba = 0
do nr = 1,rtmlon*rtmlat
if (pocn(nr) >= 0) then
rglo2gdc(nr) = nrs(pocn(nr)) + nba(pocn(nr))
nba(pocn(nr)) = nba(pocn(nr)) + 1
endif
enddo
do n = 0,npes-1
if (nba(n) /= nop(n)) then
write(iulog,*) 'Rtmini ERROR rtm cell count ',n,nba(n),nop(n)
call endrun
()
endif
enddo
#if (1 == 0)
do n = 0,npes-1
if (iam == n) then
runoff%begr = runoff%numr + 1
runoff%begrl = runoff%numrl + 1
runoff%begro = runoff%numro + 1
endif
do nr=1,rtmlon*rtmlat
if (pocn(nr) == n .and. nocn(nr) /= 0) then
runoff%num_rtm(n) = runoff%num_rtm(n) + nocn(nr)
runoff%numr = runoff%numr + nocn(nr)
runoff%numro = runoff%numro + 1
runoff%numrl = runoff%numrl + nocn(nr) - 1
k = g
if (nocn(nr) == 1) then ! avoid the double rtm nested loop
n2 = nr
g = g + 1
rglo2gdc(n2) = g
else
do n2 = 1,rtmlon*rtmlat
if (iocn(n2) == nr) then
g = g + 1
rglo2gdc(n2) = g
endif
enddo
endif
if ((g-k) /= nocn(nr)) then
write(iulog,*) 'Rtmini ERROR rtm cell count ',n,nr,k,g,g-k,nocn(nr)
call endrun
()
endif
if (iam == n) then
runoff%lnumr = runoff%lnumr + nocn(nr)
runoff%lnumro = runoff%lnumro + 1
runoff%lnumrl = runoff%lnumrl + nocn(nr) - 1
endif
endif
enddo
if (iam == n) then
runoff%endr = runoff%numr
runoff%endro = runoff%begro + runoff%lnumro - 1
runoff%endrl = runoff%begrl + runoff%lnumrl - 1
endif
enddo
#endif
deallocate(nop,nba,nrs)
deallocate(iocn,nocn)
deallocate(pocn)
call t_stopf('rtmi_dec_distr')
!--- set some local values
nroflnd = runoff%numrl
nrofocn = runoff%numro
numr = nroflnd + nrofocn
begr = runoff%begr
endr = runoff%endr
call t_stopf('rtmi_decomp')
!--- Write per-processor runoff bounds depending on dbug level
call t_startf('rtmi_print')
#ifndef UNICOSMP
call shr_sys_flush
(iulog)
#endif
if (masterproc) then
write(iulog,*) 'total runoff cells numr = ',runoff%numr, &
'numrl = ',runoff%numrl,'numro = ',runoff%numro
endif
#ifndef UNICOSMP
call shr_sys_flush
(iulog)
#endif
call mpi_barrier(mpicom,ier)
npmin = 0
npmax = npes-1
npint = 1
if (dbug == 0) then
npmax = 0
elseif (dbug == 1) then
npmax = min(npes-1,4)
elseif (dbug == 2) then
npint = npes/8
endif
do np = npmin,npmax,npint
pid = np
if (dbug == 1) then
if (np == 2) pid=npes/2-1
if (np == 3) pid=npes-2
if (np == 4) pid=npes-1
endif
pid = max(pid,0)
pid = min(pid,npes-1)
if (iam == pid) then
write(iulog,*) 'rtm decomp info',' proc = ',iam, &
' begr = ',runoff%begr,' endr = ',runoff%endr, &
' numr = ',runoff%lnumr
write(iulog,*) ' ',' proc = ',iam, &
' begrl= ',runoff%begrl,' endrl= ',runoff%endrl, &
' numrl= ',runoff%lnumrl
write(iulog,*) ' ',' proc = ',iam, &
' begro= ',runoff%begro,' endro= ',runoff%endro, &
' numro= ',runoff%lnumro
endif
#ifndef UNICOSMP
call shr_sys_flush
(iulog)
#endif
call mpi_barrier(mpicom,ier)
enddo
call t_stopf('rtmi_print')
!--- allocate runoff variables
call t_startf('rtmi_vars')
allocate(runoff%runoff(begr:endr,nt_rtm),runoff%dvolrdt(begr:endr,nt_rtm), &
runoff%runofflnd(begr:endr,nt_rtm),runoff%dvolrdtlnd(begr:endr,nt_rtm), &
runoff%runoffocn(begr:endr,nt_rtm),runoff%dvolrdtocn(begr:endr,nt_rtm), &
runoff%area(begr:endr), &
runoff%volr(begr:endr,nt_rtm), runoff%volrlnd(begr:endr,nt_rtm), &
runoff%lonc(begr:endr), runoff%latc(begr:endr), &
runoff%dsi(begr:endr), stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmini ERROR allocation of runoff%runoff'
call endrun
end if
allocate(runoff%runofflnd_nt1(begr:endr),runoff%runofflnd_nt2(begr:endr), &
runoff%runoffocn_nt1(begr:endr),runoff%runoffocn_nt2(begr:endr), &
runoff%volr_nt1(begr:endr), runoff%volr_nt2(begr:endr), &
runoff%dvolrdtlnd_nt1(begr:endr),runoff%dvolrdtlnd_nt2(begr:endr), &
runoff%dvolrdtocn_nt1(begr:endr),runoff%dvolrdtocn_nt2(begr:endr), &
stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmini ERROR allocation of runoff%runoff_nt'
call endrun
end if
allocate(rgdc2glo(numr), runoff%mask(numr), stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmini ERROR allocation of runoff%gcd2glo'
call endrun
end if
!--- Allocate rtm flux variables
allocate (fluxout (begr:endr,nt_rtm), &
ddist (begr:endr), &
totrunin(begr:endr,nt_rtm), &
evel (begr:endr,nt_rtm), &
sfluxin (begr:endr,nt_rtm), stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmgridini: Allocation error for ',&
'volr, fluxout, ddist'
call endrun
end if
fluxout = 0._r8
ddist = 0._r8
sfluxin = 0._r8
do nt = 1,nt_rtm
do nr = begr,endr
evel(nr,nt) = effvel(nt)
enddo
enddo
!--- Initialize runoff data
numr = 0
do j = 1,rtmlat
do i = 1,rtmlon
n = (j-1)*rtmlon + i
nr = rglo2gdc(n)
if (nr /= 0) then
numr = numr + 1
rgdc2glo(nr) = n
runoff%mask(nr) = gmask(n) ! global for hist file
endif
enddo
enddo
if (numr /= runoff%numr) then
write(iulog,*) 'Rtmini ERROR numr numr ',numr,runoff%numr
call endrun
()
endif
runoff%runoff = 0._r8
runoff%runofflnd = spval
runoff%runoffocn = spval
runoff%dvolrdt = 0._r8
runoff%dvolrdtlnd = spval
runoff%dvolrdtocn = spval
runoff%volr = 0._r8
runoff%volrlnd = spval
do nr = begr,endr
n = rgdc2glo(nr)
i = mod(n-1,rtmlon) + 1
j = (n-1)/rtmlon + 1
if (n <= 0 .or. n > rtmlon*rtmlat) then
write(iulog,*) 'Rtmini ERROR gdc2glo ',nr,rgdc2glo(nr)
call endrun
()
endif
runoff%lonc(nr) = runoff%rlon(i)
runoff%latc(nr) = runoff%rlat(j)
if (runoff%mask(nr) == 1) then
do nt = 1,nt_rtm
runoff%runofflnd(nr,nt) = runoff%runoff(nr,nt)
runoff%dvolrdtlnd(nr,nt)= runoff%dvolrdt(nr,nt)
runoff%volrlnd(nr,nt)= runoff%volr(nr,nt)
enddo
elseif (runoff%mask(nr) == 2) then
do nt = 1,nt_rtm
runoff%runoffocn(nr,nt) = runoff%runoff(nr,nt)
runoff%dvolrdtocn(nr,nt)= runoff%dvolrdt(nr,nt)
enddo
endif
!tcx testing
dx = (rlatlon%lone(i) - rlatlon%lonw(i)) * deg2rad
dy = sin(rlatlon%latn(j)*deg2rad) - sin(rlatlon%lats(j)*deg2rad)
runoff%area(nr) = 1.e6_r8 * dx*dy*re*re
! runoff%area(nr) = cellarea(rlatlon,i,j) * 1.e6_r8 ! m2 cellarea is km2
if (dwnstrm_index(n) == 0) then
runoff%dsi(nr) = 0
else
if (rglo2gdc(dwnstrm_index(n)) == 0) then
write(iulog,*) 'Rtmini ERROR glo2gdc dwnstrm ',nr,n,dwnstrm_index(n),rglo2gdc(dwnstrm_index(n))
call endrun
()
endif
runoff%dsi(nr) = rglo2gdc(dwnstrm_index(n))
endif
enddo
!--- Determine downstream distance - instead of reading a distance file
!--- calculate the downstream distance
do nr=begr,endr
g = runoff%dsi(nr)
if (g == 0) then
ddist(nr) = 0._r8
elseif (g < begr .or. g > endr) then
write(iulog,*) 'Rtmini: error in ddist calc ',nr,g,begr,endr
call endrun
else
dy = deg2rad * abs(runoff%latc(nr)-runoff%latc(g)) * re*1000._r8
dx = runoff%lonc(nr)-runoff%lonc(g)
dx1 = abs(dx)
dx2 = abs(dx+360._r8)
dx3 = abs(dx-360._r8)
dx = min(dx1,dx2,dx3)
dx = deg2rad * dx * re*1000._r8 * &
0.5_r8*(cos(runoff%latc(nr)*deg2rad)+ &
cos(runoff%latc(g)*deg2rad))
ddist(nr) = sqrt(dx*dx + dy*dy)
endif
enddo
!--- Compute timestep and subcycling number
if (rtm_nsteps < 1) then
write(iulog,*) 'rtm ERROR in rtm_nsteps',rtm_nsteps
call endrun
()
endif
delt_rtm = rtm_nsteps*get_step_size
()
dtover = 0._r8
dtovermax = 0._r8
do nt=1,nt_rtm
do nr=begr,endr
if (ddist(nr) /= 0._r8) then
dtover = evel(nr,nt)/ddist(nr)
else
dtover = 0._r8
endif
dtovermax = max(dtovermax,dtover)
enddo
enddo
dtover = dtovermax
call mpi_allreduce(dtover,dtovermax,1,MPI_REAL8,MPI_MAX,mpicom,ier)
if (dtovermax > 0._r8) then
delt_rtm_max = (1.0_r8/dtovermax)*cfl_scale
else
write(iulog,*) 'rtmini error in delt_rtm_max ',delt_rtm_max,dtover
call endrun
endif
if (masterproc) write(iulog,*) 'rtm max timestep = ',delt_rtm_max,' (sec) for cfl_scale = ',cfl_scale
if (masterproc) write(iulog,*) 'rtm act timestep ~ ',delt_rtm
!--- Allocate and initialize rtm input fields on clm decomp
call get_proc_global
(numg, numl, numc, nump)
call get_proc_bounds
(begg, endg)
allocate (rtmin_avg(begg:endg,nt_rtm), rtmin_acc(begg:endg,nt_rtm), stat=ier)
if (ier /= 0) then
write(iulog,*)'Rtmlandini: Allocation error for rtmin, rtmin_avg, rtmin_acc'
call endrun
end if
rtmin_avg = 0._r8
rtmin_acc = 0._r8
!--- clean up temporaries
deallocate(dwnstrm_index,gmask)
call t_stopf('rtmi_vars')
!--- initialization rtm gsmap
call t_startf('rtmi_mctdata')
allocate(runoff%gindex(begr:endr))
do n = begr,endr
runoff%gindex(n) = rgdc2glo(n)
enddo
lsize = endr-begr+1
gsize = rtmlon * rtmlat
call mct_gsMap_init( gsMap_rtm_gdc2glo, runoff%gindex, mpicom, comp_id, lsize, gsize )
!--- initialize sMat0_l2r_d, from sMat0_l2r - remove unused weights
!--- root pe only
if (masterproc) then
na = llatlon%ni * llatlon%nj
nb = rtmlon * rtmlat
igrow = mct_sMat_indexIA(sMat0_l2r,'grow')
igcol = mct_sMat_indexIA(sMat0_l2r,'gcol')
iwgt = mct_sMat_indexRA(sMat0_l2r,'weight')
ns = 0
do n = 1,mct_sMat_lsize(sMat0_l2r)
ni = sMat0_l2r%data%iAttr(igcol,n)
no = sMat0_l2r%data%iAttr(igrow,n)
if (ldecomp%glo2gdc(ni) > 0 .and. rglo2gdc(no) > 0) then
ns = ns + 1
endif
enddo
call mct_sMat_init(sMat0_l2r_d, nb, na, ns)
ns = 0
do n = 1,mct_sMat_lsize(sMat0_l2r)
ni = sMat0_l2r%data%iAttr(igcol,n)
no = sMat0_l2r%data%iAttr(igrow,n)
if (ldecomp%glo2gdc(ni) > 0 .and. rglo2gdc(no) > 0) then
ns = ns + 1
sMat0_l2r_d%data%iAttr(igcol,ns) = sMat0_l2r%data%iAttr(igcol,n)
sMat0_l2r_d%data%iAttr(igrow,ns) = sMat0_l2r%data%iAttr(igrow,n)
sMat0_l2r_d%data%rAttr(iwgt ,ns) = sMat0_l2r%data%rAttr(iwgt ,n)
endif
enddo
endif ! masterproc
!--- initialize sMatP_l2r, scatter sMat0_l2r_d based on gsmaps
call mct_sMatP_init(sMatP_l2r, sMat0_l2r_d, &
gsmap_lnd_gdc2glo, gsMap_rtm_gdc2glo, &
'Xonly',0,mpicom,comp_id)
#ifdef CPP_VECTOR
!--- initialize the vector parts of the sMat
call mct_sMatP_Vecinit(sMatP_l2r)
#endif
deallocate(rgdc2glo,rglo2gdc)
call latlon_clean
(rlatlon)
!--- clean up the root sMat0 datatypes
call mct_sMat_clean(sMat0_l2r)
if (masterproc) then
call mct_sMat_clean(sMat0_l2r_d)
write(iulog,*) 'Rtmini complete'
endif
!--- update rtm history fields
call rtm_sethist
()
call t_stopf('rtmi_mctdata')
end subroutine Rtmini
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: Rtmriverflux
!
! !INTERFACE:
subroutine Rtmriverflux() 1,6
!
! !DESCRIPTION:
! Interface with RTM river routing model.
!
! !USES:
use decompMod
, only : get_proc_bounds, get_proc_global
use decompMod
, only : gsMap_lnd_gdc2glo
use domainMod
, only : ldomain
!
! !ARGUMENTS:
implicit none
!
! !CALLED FROM:
! subroutine clm_driver2
!
! !REVISION HISTORY:
! Author: Sam Levis
!
!EOP
!
integer :: i,j,n,n2,nr,ns,nt ! indices
logical :: do_rtm ! true => perform rtm calculation
integer :: begg,endg
logical :: usevector = .false.
real(r8) :: suml(nt_rtm),sumr(nt_rtm),sumlt(nt_rtm),sumrt(nt_rtm) ! water diagnostics
integer :: ier
integer,parameter :: dbug = 1
type(mct_aVect) :: aV_lndr,aV_rtmr
!-----------------------------------------------------------------------
! Determine RTM inputs on land model grid
call RtmUpdateInput
(do_rtm)
if (do_rtm) then
call t_startf('clmrtm_l2r')
! Map RTM inputs from land model grid to RTM grid (1/2 degree resolution)
ns = mct_gsMap_lsize(gsmap_lnd_gdc2glo, mpicom)
call mct_aVect_init(aV_lndr,rlist=trim(rtm_trstr),lsize=ns)
ns = mct_gsMap_lsize(gsMap_rtm_gdc2glo, mpicom)
call mct_aVect_init(aV_rtmr,rlist=trim(rtm_trstr),lsize=ns)
suml = 0._r8
sumr = 0._r8
call get_proc_bounds
(begg, endg)
do n = begg,endg
do nt = 1,nt_rtm
n2 = n-begg+1
av_lndr%rAttr(nt,n2) = rtmin_avg(n,nt)*ldomain%frac(n)
suml(nt) = suml(nt) + av_lndr%rAttr(nt,n2)*ldomain%area(n)
enddo
enddo
call mct_Smat_AvMult (av_lndr,sMatP_l2r,av_rtmr,vector=usevector)
do n = runoff%begr,runoff%endr
do nt = 1,nt_rtm
n2 = n-runoff%begr+1
totrunin(n,nt) = av_rtmr%rAttr(nt,n2)
sumr(nt) = sumr(nt) + totrunin(n,nt)*runoff%area(n)*1.0e-6_r8 ! area m2 to km2
enddo
enddo
if (dbug > 1) then
call mpi_reduce(suml, sumlt, nt_rtm, MPI_REAL8, MPI_SUM, 0, mpicom, ier)
call mpi_reduce(sumr, sumrt, nt_rtm, MPI_REAL8, MPI_SUM, 0, mpicom, ier)
if (masterproc) then
do nt = 1,nt_rtm
if (abs(sumlt(nt)+sumrt(nt)) > 0.0_r8) then
if (abs(sumlt(nt) - sumrt(nt))/(sumlt(nt)+sumrt(nt)) > 1.0e-6) then
write(iulog,*) 'WARNING: l2r water not conserved ',nt,sumlt(nt),sumrt(nt)
endif
endif
enddo
endif
endif
call mct_aVect_clean(aV_lndr)
call mct_aVect_clean(aV_rtmr)
call t_stopf('clmrtm_l2r')
! Determine RTM runoff fluxes
call t_startf('clmrtm_calc')
call Rtm
()
call t_stopf('clmrtm_calc')
else
! for clean timing log output
call t_startf('clmrtm_l2r')
call t_stopf('clmrtm_l2r')
call t_startf('clmrtm_calc')
call t_stopf('clmrtm_calc')
end if
end subroutine Rtmriverflux
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: RtmUpdateInput
!
! !INTERFACE:
subroutine RtmUpdateInput(do_rtm) 1,12
!
! !DESCRIPTION:
! Update RTM inputs.
!
! !USES:
use clmtype
, only : clm3,nameg
use domainMod
, only : ldomain
use decompMod
, only : get_proc_bounds, get_proc_global
use clm_varctl
, only : rtm_nsteps
use clm_time_manager
, only : get_step_size, get_nstep
!
! !ARGUMENTS:
implicit none
logical , intent(out) :: do_rtm
!
! !CALLED FROM:
! subroutine rtmriverflux
!
! !REVISION HISTORY:
! Author: Sam Levis
!
! !LOCAL VARIABLES:
!
! local pointers to implicit in arguments
!
integer , pointer :: cgridcell(:) ! corresponding gridcell index for each column
real(r8), pointer :: wtgcell(:) ! weight (relative to gridcell) for each column (0-1)
real(r8), pointer :: qflx_runoffg(:) ! total runoff (mm H2O /s)
real(r8), pointer :: qflx_snwcp_iceg(:) ! excess snowfall due to snow capping (mm H2O /s)
!
!
! !OTHER LOCAL VARIABLES:
!EOP
!
integer :: i,j,k,n,g,l,c,p,nt ! indices
integer :: io,jo,ir,jr,is,js ! mapping indices
integer :: begp, endp ! per-proc beginning and ending pft indices
integer :: begc, endc ! per-proc beginning and ending column indices
integer :: begl, endl ! per-proc beginning and ending landunit indices
integer :: begg, endg ! per-proc gridcell ending gridcell indices
integer :: numg ! total number of gridcells across all processors
integer :: numl ! total number of landunits across all processors
integer :: numc ! total number of columns across all processors
integer :: nump ! total number of pfts across all processors
integer :: ier ! error status
integer :: nliq,nfrz ! field indices
integer :: nstep ! time step index
!-----------------------------------------------------------------------
call t_barrierf('sync_clmrtm', mpicom)
! Assign local pointers to derived type members
cgridcell => clm3%g%l%c%gridcell
wtgcell => clm3%g%l%c%wtgcell
qflx_runoffg => clm3%g%gwf%qflx_runoffg
qflx_snwcp_iceg => clm3%g%gwf%qflx_snwcp_iceg
! Determine subgrid bounds for this processor
call get_proc_bounds
(begg, endg, begl, endl, begc, endc, begp, endp)
call get_proc_global
(numg, numl, numc, nump)
! Make gridded representation of runoff from clm for tracers
nliq = 0
nfrz = 0
do nt = 1,nt_rtm
if (trim(rtm_tracers(nt)) == 'LIQ') then
nliq = nt
endif
if (trim(rtm_tracers(nt)) == 'ICE') then
nfrz = nt
endif
enddo
if (nliq == 0 .or. nfrz == 0) then
write(iulog,*)'RtmUpdateInput: ERROR in rtm_tracers LIQ ICE ',nliq,nfrz,nt_rtm,rtm_tracers
call endrun
()
endif
do g = begg, endg
rtmin_acc(g,nliq) = rtmin_acc(g,nliq)+qflx_runoffg(g)
rtmin_acc(g,nfrz) = rtmin_acc(g,nfrz)+qflx_snwcp_iceg(g)
enddo
ncount_rtm = ncount_rtm + 1
nstep = get_nstep
()
if (mod(nstep,rtm_nsteps)==0 .and. nstep>1) then
if (ncount_rtm*get_step_size
() /= delt_rtm) then
if (masterproc) write(iulog,*) 'RtmUpdateInput timestep out of sync ',delt_rtm,ncount_rtm*get_step_size
()
delt_rtm = ncount_rtm*get_step_size
()
endif
do nt = 1,nt_rtm
do g = begg,endg
rtmin_avg(g,nt) = rtmin_acc(g,nt)*ldomain%asca(g)/(ncount_rtm*1.0_r8)
rtmin_acc(g,nt) = 0._r8
end do
end do
ncount_rtm = 0 !reset counter to 0
do_rtm = .true.
else
do_rtm = .false.
endif
end subroutine RtmUpdateInput
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: Rtm
!
! !INTERFACE:
subroutine Rtm 1,2
!
! !DESCRIPTION:
! River routing model (based on U. Texas code).
! Input is rtmin\_avg.
! Input/output is fluxout, volr.
! Outputs are dvolrdt\_r, dvolrdt\_lnd\_r, dvolrdt\_ocn\_r, flxocn\_r, flxlnd\_r.
!
! !USES:
!
! !ARGUMENTS:
implicit none
!
! !CALLED FROM:
! subroutine Rtmriverflux in this module
!
! !REVISION HISTORY:
! Author: Sam Levis
!
!
! !LOCAL VARIABLES:
!EOP
integer :: i, j, n, ns, nt !loop indices
integer :: ir,jr,nr !neighbor indices
real(r8) :: dvolrdt !change in storage (m3/s)
real(r8) :: sumfin(nt_rtm),sumfex(nt_rtm)
real(r8) :: sumrin(nt_rtm),sumdvt(nt_rtm)
real(r8) :: sum1,sum2
integer :: nsub !subcyling for cfl
integer, save :: nsub_save !previous nsub
real(r8) :: delt !delt associated with subcycling
real(r8), save :: delt_save !previous delt
integer,parameter :: dbug = 1 !local debug flag
!-----------------------------------------------------------------------
nsub = int(delt_rtm/delt_rtm_max) + 1
delt = delt_rtm/float(nsub)
if (delt /= delt_save) then
if (masterproc) write(iulog,*) 'rtm delt update from/to',delt_save,delt,nsub_save,nsub
endif
nsub_save = nsub
delt_save = delt
sumfin = 0._r8
sumfex = 0._r8
sumrin = 0._r8
sumdvt = 0._r8
runoff%runoff = 0._r8
runoff%runofflnd = spval
runoff%runoffocn = spval
runoff%dvolrdt = 0._r8
runoff%dvolrdtlnd = spval
runoff%dvolrdtocn = spval
!--- subcycling ---
do ns = 1,nsub
sfluxin = 0._r8
do n = runoff%begr,runoff%endr
nr = runoff%dsi(n)
if (abs(runoff%mask(n)) == 1) then
if (nr < runoff%begr .or. nr > runoff%endr) then
write(iulog,*) 'Rtm ERROR: non-local communication ',n,nr
call endrun
()
endif
do nt = 1,nt_rtm
sfluxin(nr,nt) = sfluxin(nr,nt) + fluxout(n,nt)
enddo
endif
enddo
if (dbug > 1) then
do nt = 1,nt_rtm
sum1 = 0._r8
sum2 = 0._r8
do n = runoff%begr,runoff%endr
sum1 = sum1 + sfluxin(n,nt)
sum2 = sum2 + fluxout(n,nt)
enddo
if (abs(sum1+sum2) > 0.0_r8) then
if (abs(sum1-sum2)/(sum1+sum2) > 1.0e-12) then
write(iulog,*) 'RTM Warning: fluxin = ',sum1,&
' not equal to fluxout = ',sum2,' for tracer ',nt
endif
endif
enddo
endif
do nt = 1,nt_rtm
do n = runoff%begr,runoff%endr
dvolrdt = sfluxin(n,nt) + 0.001_r8*totrunin(n,nt)*runoff%area(n) - fluxout(n,nt)
if (dbug > 1) then
sumfin(nt) = sumfin(nt) + sfluxin(n,nt)
sumfex(nt) = sumfex(nt) + fluxout(n,nt)
sumrin(nt) = sumrin(nt) + 0.001_r8*totrunin(n,nt)*runoff%area(n)
sumdvt(nt) = sumdvt(nt) + dvolrdt
endif
if (abs(runoff%mask(n)) == 1) then ! land points
runoff%volr(n,nt) = runoff%volr(n,nt) + dvolrdt*delt
fluxout(n,nt) = runoff%volr(n,nt) * evel(n,nt)/ddist(n)
! --- old cfl constraint. now use subcycling. for reference only
! fluxout(n) = min(fluxout(n), volr(n)/delt)
! --- this would stop upstream flow if volr/fluxout < 0
! --- negative flow largely a function of negative forcing
! --- can still have negative runoff where there is negative
! forcing over a mask=2 (ocn) point since forcing is put onto
! the ocean instantly at these points
! --- also, want to allow negative flow so it doesn't build up
! fluxout(n) = max(fluxout(n),0._r8)
else
runoff%volr(n,nt) = 0._r8
fluxout(n,nt) = 0._r8
endif
if (abs(runoff%mask(n)) == 1) then
runoff%runoff(n,nt) = runoff%runoff(n,nt) + fluxout(n,nt)
elseif (runoff%mask(n) == 2) then
runoff%runoff(n,nt) = runoff%runoff(n,nt) + dvolrdt
endif
runoff%dvolrdt(n,nt) = runoff%dvolrdt(n,nt) + 1000._r8*dvolrdt/runoff%area(n)
enddo
enddo
enddo
! average fluxes over subcycling
runoff%runoff = runoff%runoff / float(nsub)
runoff%dvolrdt = runoff%dvolrdt / float(nsub)
do n = runoff%begr,runoff%endr
if (runoff%mask(n) == 1) then
do nt = 1,nt_rtm
runoff%volrlnd(n,nt)= runoff%volr(n,nt)
runoff%runofflnd(n,nt) = runoff%runoff(n,nt)
runoff%dvolrdtlnd(n,nt)= runoff%dvolrdt(n,nt)
enddo
elseif (runoff%mask(n) == 2) then
do nt = 1,nt_rtm
runoff%runoffocn(n,nt) = runoff%runoff(n,nt)
runoff%dvolrdtocn(n,nt)= runoff%dvolrdt(n,nt)
enddo
endif
enddo
call rtm_sethist
()
! Global water balance calculation and error check
if (dbug > 1) then
do nt = 1,nt_rtm
if (abs(sumdvt(nt)+sumrin(nt)) > 0.0_r8) then
if (abs((sumdvt(nt)-sumrin(nt))/(sumdvt(nt)+sumrin(nt))) > 1.0e-6) then
write(iulog,*) 'RTM Warning: water balance nt,dvt,rin,fin,fex = ', &
nt,sumdvt(nt),sumrin(nt),sumfin(nt),sumfex(nt)
! call endrun
endif
endif
enddo
endif
end subroutine Rtm
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: RtmRest
!
! !INTERFACE:
subroutine RtmRest(ncid, flag) 3,14
!
! !DESCRIPTION:
! Read/write RTM restart data.
!
! !USES:
use ncdio
use decompMod
, only : get_proc_bounds
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: ncid ! netcdf id
character(len=*), intent(in) :: flag ! 'read' or 'write'
!
! !CALLED FROM:
! subroutine restart in module restFileMod
!
! !REVISION HISTORY:
! Author: Mariana Vertenstein
!
!
! !OTHER LOCAL VARIABLES:
!EOP
logical :: readvar ! determine if variable is on initial file
integer :: nt,nv,n ! indices
integer :: begg,endg ! start end indices
integer :: ier ! error flag
real(r8),pointer :: dfld(:) ! temporary array
character(len=32) :: vname,uname
character(len=128) :: lname
!-----------------------------------------------------------------------
do nv = 1,4
do nt = 1,nt_rtm
if (nv == 1) then
vname = 'RTM_VOLR_'//trim(rtm_tracers(nt))
lname = 'water volume in cell (volr)'
uname = 'm3'
dfld => runoff%volr(:,nt)
elseif (nv == 2) then
vname = 'RTM_FLUXOUT_'//trim(rtm_tracers(nt))
lname = 'water fluxout in cell (fluxout)'
uname = 'm3/s'
dfld => fluxout(:,nt)
elseif (nv == 3) then
vname = 'RTM_RUNOFF_'//trim(rtm_tracers(nt))
lname = 'runoff (runoff)'
uname = 'm3/s'
dfld => runoff%runoff(:,nt)
elseif (nv == 4) then
vname = 'RTM_DVOLRDT_'//trim(rtm_tracers(nt))
lname = 'water volume change in cell (dvolrdt)'
uname = 'mm/s'
dfld => runoff%dvolrdt(:,nt)
else
write(iulog,*) 'Rtm ERROR: illegal nv value a ',nv
call endrun
()
endif
if (flag == 'define') then
call ncd_defvar
(ncid=ncid, varname=trim(vname), &
xtype=nf_double, dim1name='rtmlon', dim2name='rtmlat', &
long_name=trim(lname), units=trim(uname))
else if (flag == 'read' .or. flag == 'write') then
call ncd_iolocal
(varname=trim(vname), data=dfld, dim1name='allrof', &
ncid=ncid, flag=flag, nlonxy=rtmlon,nlatxy=rtmlat,readvar=readvar)
if (flag=='read' .and. .not. readvar) then
if (is_restart
()) then
!tcx this is for backward compatability, will not be bfb, endrun should be used
write(iulog,*) 'Rtm ERROR: data not found on restart, set to zero ',trim(vname)
dfld = 0._r8
! call endrun()
else
dfld = 0._r8
end if
end if
end if
enddo
enddo
do nt = 1,nt_rtm
vname = 'RTM_INPUT_'//trim(rtm_tracers(nt))
lname = 'average input on clm grid (rtmin_acc)'
uname = 'mm/s'
dfld => rtmin_acc(:,nt)
if (flag == 'define') then
call ncd_defvar
(ncid=ncid, varname=trim(vname), &
xtype=nf_double, dim1name='gridcell', &
long_name=trim(lname), units=trim(uname))
else if (flag == 'read' .or. flag == 'write') then
call ncd_iolocal
(varname=trim(vname), data=dfld, dim1name='gridcell', &
ncid=ncid, flag=flag, readvar=readvar)
if (flag=='read' .and. .not. readvar) then
if (is_restart
()) then
!tcx this is for backward compatability, will not be bfb, endrun should be used
write(iulog,*) 'Rtm ERROR: data not found on restart, set to zero ',trim(vname)
dfld = 0._r8
! call endrun()
else
dfld = 0._r8
end if
end if
end if
enddo
! counter for rtm averaged input (on clm grid)
vname = 'RTM_NCOUNT'
if (flag == 'define') then
call ncd_defvar
(ncid=ncid, varname=trim(vname), xtype=nf_int, &
long_name='counter for RTM averaged input on CLM grid', units='')
else if (flag == 'read' .or. flag == 'write') then
call ncd_ioglobal
(varname=trim(vname), data=ncount_rtm, &
ncid=ncid, flag=flag, readvar=readvar, bcast=.true.)
if (flag=='read' .and. .not. readvar) then
if (is_restart
()) then
write(iulog,*) 'Rtm ERROR: data not found on restart RTM_NCOUNT'
call endrun
()
else
ncount_rtm = 0
end if
end if
end if
if (flag == 'read') then
do n = runoff%begr,runoff%endr
if (runoff%mask(n) == 1) then
do nt = 1,nt_rtm
runoff%runofflnd(n,nt) = runoff%runoff(n,nt)
runoff%dvolrdtlnd(n,nt)= runoff%dvolrdt(n,nt)
runoff%volrlnd(n,nt)= runoff%volr(n,nt)
enddo
elseif (runoff%mask(n) == 2) then
do nt = 1,nt_rtm
runoff%runoffocn(n,nt) = runoff%runoff(n,nt)
runoff%dvolrdtocn(n,nt)= runoff%dvolrdt(n,nt)
enddo
endif
enddo
call rtm_sethist
()
endif
end subroutine RtmRest
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: rtm_sethist
!
! !INTERFACE:
subroutine rtm_sethist() 3
!
! !DESCRIPTION:
! set rtm history fields
!
! !USES:
!
! !ARGUMENTS:
implicit none
!
! !REVISION HISTORY:
! Author: T Craig
!
!
! !OTHER LOCAL VARIABLES:
!EOP
runoff%runofflnd_nt1(:) = runoff%runofflnd(:,1)
runoff%runofflnd_nt2(:) = runoff%runofflnd(:,2)
runoff%runoffocn_nt1(:) = runoff%runoffocn(:,1)
runoff%runoffocn_nt2(:) = runoff%runoffocn(:,2)
runoff%dvolrdtlnd_nt1(:) = runoff%dvolrdtlnd(:,1)
runoff%dvolrdtlnd_nt2(:) = runoff%dvolrdtlnd(:,2)
runoff%dvolrdtocn_nt1(:) = runoff%dvolrdtocn(:,1)
runoff%dvolrdtocn_nt2(:) = runoff%dvolrdtocn(:,2)
runoff%volr_nt1(:) = runoff%volrlnd(:,1)
runoff%volr_nt2(:) = runoff%volrlnd(:,2)
end subroutine rtm_sethist
!-----------------------------------------------------------------------
!BOP
!
! !IROUTINE: is_restart
!
! !INTERFACE:
logical function is_restart( ) 307,6
!
! !DESCRIPTION:
! Determine if restart run
!
! !USES:
use clm_varctl
, only : nsrest
!
! !ARGUMENTS:
implicit none
!
! !CALLED FROM:
! subroutine initialize in this module
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
!
!EOP
!-----------------------------------------------------------------------
if (nsrest == 1) then
is_restart = .true.
else
is_restart = .false.
end if
end function is_restart
#endif
end module RtmMod