module clm_atmlnd 44,10
!-----------------------------------------------------------------------
!BOP
!
! !MODULE: clm_atmlnd
!
! !DESCRIPTION:
! Handle atm2lnd, lnd2atm mapping/downscaling/upscaling/data
!
! !USES:
use clm_varpar
, only : numrad, ndst !ndst = number of dust bins.
!only used # ifdef DUST
use clm_varcon
, only : rair, grav, cpair, hfus, tfrz
use clm_varctl
, only : iulog
use decompMod
, only : get_proc_bounds, get_proc_bounds_atm
use shr_kind_mod
, only : r8 => shr_kind_r8
use nanMod
, only : nan
use spmdMod
, only : masterproc
use abortutils
, only : endrun
use seq_drydep_mod
, only : n_drydep, drydep_method, DD_XLND
use clm_varpar
, only : nvoc
!
! !PUBLIC TYPES:
implicit none
!----------------------------------------------------
! atmosphere -> land variables structure
!----------------------------------------------------
type atm2lnd_type
real(r8), pointer :: forc_t(:) !atmospheric temperature (Kelvin)
real(r8), pointer :: forc_u(:) !atm wind speed, east direction (m/s)
real(r8), pointer :: forc_v(:) !atm wind speed, north direction (m/s)
real(r8), pointer :: forc_wind(:) !atmospheric wind speed
real(r8), pointer :: forc_q(:) !atmospheric specific humidity (kg/kg)
real(r8), pointer :: forc_hgt(:) !atmospheric reference height (m)
real(r8), pointer :: forc_hgt_u(:) !obs height of wind [m] (new)
real(r8), pointer :: forc_hgt_t(:) !obs height of temperature [m] (new)
real(r8), pointer :: forc_hgt_q(:) !obs height of humidity [m] (new)
real(r8), pointer :: forc_pbot(:) !atmospheric pressure (Pa)
real(r8), pointer :: forc_th(:) !atm potential temperature (Kelvin)
real(r8), pointer :: forc_vp(:) !atmospheric vapor pressure (Pa)
real(r8), pointer :: forc_rho(:) !density (kg/m**3)
real(r8), pointer :: forc_rh(:) !atmospheric relative humidity (%)
real(r8), pointer :: forc_psrf(:) !surface pressure (Pa)
real(r8), pointer :: forc_pco2(:) !CO2 partial pressure (Pa)
real(r8), pointer :: forc_lwrad(:) !downwrd IR longwave radiation (W/m**2)
real(r8), pointer :: forc_solad(:,:) !direct beam radiation (numrad) (vis=forc_sols , nir=forc_soll )
real(r8), pointer :: forc_solai(:,:) !diffuse radiation (numrad) (vis=forc_solsd, nir=forc_solld)
real(r8), pointer :: forc_solar(:) !incident solar radiation
real(r8), pointer :: forc_rain(:) !rain rate [mm/s]
real(r8), pointer :: forc_snow(:) !snow rate [mm/s]
real(r8), pointer :: forc_ndep(:) !nitrogen deposition rate (gN/m2/s)
real(r8), pointer :: rainf(:) !ALMA rain+snow [mm/s]
#ifdef C13
real(r8), pointer :: forc_pc13o2(:) !C13O2 partial pressure (Pa)
#endif
real(r8), pointer :: forc_po2(:) !O2 partial pressure (Pa)
real(r8), pointer :: forc_aer(:,:) ! aerosol deposition array
end type atm2lnd_type
!----------------------------------------------------
! land -> atmosphere variables structure
!----------------------------------------------------
type lnd2atm_type
real(r8), pointer :: t_rad(:) !radiative temperature (Kelvin)
real(r8), pointer :: t_ref2m(:) !2m surface air temperature (Kelvin)
real(r8), pointer :: q_ref2m(:) !2m surface specific humidity (kg/kg)
real(r8), pointer :: h2osno(:) !snow water (mm H2O)
real(r8), pointer :: albd(:,:) !(numrad) surface albedo (direct)
real(r8), pointer :: albi(:,:) !(numrad) surface albedo (diffuse)
real(r8), pointer :: taux(:) !wind stress: e-w (kg/m/s**2)
real(r8), pointer :: tauy(:) !wind stress: n-s (kg/m/s**2)
real(r8), pointer :: eflx_lh_tot(:) !total latent HF (W/m**2) [+ to atm]
real(r8), pointer :: eflx_sh_tot(:) !total sensible HF (W/m**2) [+ to atm]
real(r8), pointer :: eflx_lwrad_out(:) !IR (longwave) radiation (W/m**2)
real(r8), pointer :: qflx_evap_tot(:)!qflx_evap(_soi + _veg) + qflx_tran_veg
real(r8), pointer :: fsa(:) !solar rad absorbed (total) (W/m**2)
real(r8), pointer :: nee(:) !net CO2 flux (kg CO2/m**2/s) [+ to atm]
real(r8), pointer :: ram1(:) !aerodynamical resistance (s/m)
real(r8), pointer :: fv(:) !friction velocity (m/s) (for dust model)
real(r8), pointer :: flxdst(:,:) !dust flux (size bins)
real(r8), pointer :: ddvel(:,:) !dry deposition velocities
real(r8), pointer :: flxvoc(:,:) ! VOC flux (size bins)
end type lnd2atm_type
type(atm2lnd_type),public,target :: atm_a2l ! a2l fields on atm grid
type(lnd2atm_type),public,target :: atm_l2a ! l2a fields on atm grid
type(atm2lnd_type),public,target :: clm_a2l ! a2l fields on clm grid
type(lnd2atm_type),public,target :: clm_l2a ! l2a fields on clm grid
real(r8), pointer, public :: adiag_arain(:)
real(r8), pointer, public :: adiag_asnow(:)
real(r8), pointer, public :: adiag_aflux(:)
real(r8), pointer, public :: adiag_lflux(:)
! !PUBLIC MEMBER FUNCTIONS:
public :: init_adiag_type
public :: init_atm2lnd_type
public :: init_lnd2atm_type
public :: clm_mapa2l
public :: clm_map2gcell
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein and Tony Craig, 2006-01-10
!
! !PRIVATE MEMBER FUNCTIONS:
!EOP
!----------------------------------------------------
contains
!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: init_adiag_type
!
! !INTERFACE:
subroutine init_adiag_type 1,2
!
! !DESCRIPTION:
! Initialize downscaling diagnostics
!
! !ARGUMENTS:
implicit none
!
! !REVISION HISTORY:
! Created by T Craig for downscaling diagnostics, 4/2007
!
!
! !LOCAL VARIABLES:
!EOP
!
integer :: beg,end
!------------------------------------------------------------------------
call get_proc_bounds
(beg, end)
allocate(adiag_lflux(beg:end))
adiag_lflux = 0.0_r8
call get_proc_bounds_atm
(beg, end)
allocate(adiag_arain(beg:end))
allocate(adiag_asnow(beg:end))
allocate(adiag_aflux(beg:end))
adiag_arain = 0.0_r8
adiag_asnow = 0.0_r8
adiag_aflux = 0.0_r8
end subroutine init_adiag_type
!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: init_atm2lnd_type
!
! !INTERFACE:
subroutine init_atm2lnd_type(beg, end, a2l) 2
!
! !DESCRIPTION:
! Initialize atmospheric variables required by the land
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: beg, end
type (atm2lnd_type), intent(inout):: a2l
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
! Modified by T Craig, 11/01/05 for finemesh project
!
!
! !LOCAL VARIABLES:
!EOP
real(r8) :: ival ! initial value
!------------------------------------------------------------------------
allocate(a2l%forc_t(beg:end))
allocate(a2l%forc_u(beg:end))
allocate(a2l%forc_v(beg:end))
allocate(a2l%forc_wind(beg:end))
allocate(a2l%forc_q(beg:end))
allocate(a2l%forc_rh(beg:end))
allocate(a2l%forc_hgt(beg:end))
allocate(a2l%forc_hgt_u(beg:end))
allocate(a2l%forc_hgt_t(beg:end))
allocate(a2l%forc_hgt_q(beg:end))
allocate(a2l%forc_pbot(beg:end))
allocate(a2l%forc_th(beg:end))
allocate(a2l%forc_vp(beg:end))
allocate(a2l%forc_rho(beg:end))
allocate(a2l%forc_psrf(beg:end))
allocate(a2l%forc_pco2(beg:end))
allocate(a2l%forc_lwrad(beg:end))
allocate(a2l%forc_solad(beg:end,numrad))
allocate(a2l%forc_solai(beg:end,numrad))
allocate(a2l%forc_solar(beg:end))
allocate(a2l%forc_rain(beg:end))
allocate(a2l%forc_snow(beg:end))
allocate(a2l%forc_ndep(beg:end))
allocate(a2l%rainf(beg:end))
#if (defined C13)
allocate(a2l%forc_pc13o2(beg:end))
#endif
allocate(a2l%forc_po2(beg:end))
allocate(a2l%forc_aer(beg:end,14))
! ival = nan ! causes core dump in map_maparray, tcx fix
ival = 0.0_r8
a2l%forc_t(beg:end) = ival
a2l%forc_u(beg:end) = ival
a2l%forc_v(beg:end) = ival
a2l%forc_wind(beg:end) = ival
a2l%forc_q(beg:end) = ival
a2l%forc_rh(beg:end) = ival
a2l%forc_hgt(beg:end) = ival
a2l%forc_hgt_u(beg:end) = ival
a2l%forc_hgt_t(beg:end) = ival
a2l%forc_hgt_q(beg:end) = ival
a2l%forc_pbot(beg:end) = ival
a2l%forc_th(beg:end) = ival
a2l%forc_vp(beg:end) = ival
a2l%forc_rho(beg:end) = ival
a2l%forc_psrf(beg:end) = ival
a2l%forc_pco2(beg:end) = ival
a2l%forc_lwrad(beg:end) = ival
a2l%forc_solad(beg:end,1:numrad) = ival
a2l%forc_solai(beg:end,1:numrad) = ival
a2l%forc_solar(beg:end) = ival
a2l%forc_rain(beg:end) = ival
a2l%forc_snow(beg:end) = ival
a2l%forc_ndep(beg:end) = ival
a2l%rainf(beg:end) = nan
#ifdef C13
a2l%forc_pc13o2(beg:end) = ival
#endif
a2l%forc_po2(beg:end) = ival
a2l%forc_aer(beg:end,:) = ival
end subroutine init_atm2lnd_type
!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: init_lnd2atm_type
!
! !INTERFACE:
subroutine init_lnd2atm_type(beg, end, l2a) 2
!
! !DESCRIPTION:
! Initialize land variables required by the atmosphere
!
! !ARGUMENTS:
implicit none
integer, intent(in) :: beg, end
type (lnd2atm_type), intent(inout):: l2a
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
! Modified by T Craig, 11/01/05 for finemesh project
!
!
! !LOCAL VARIABLES:
!EOP
real(r8) :: ival ! initial value
!------------------------------------------------------------------------
allocate(l2a%t_rad(beg:end))
allocate(l2a%t_ref2m(beg:end))
allocate(l2a%q_ref2m(beg:end))
allocate(l2a%h2osno(beg:end))
allocate(l2a%albd(beg:end,1:numrad))
allocate(l2a%albi(beg:end,1:numrad))
allocate(l2a%taux(beg:end))
allocate(l2a%tauy(beg:end))
allocate(l2a%eflx_lwrad_out(beg:end))
allocate(l2a%eflx_sh_tot(beg:end))
allocate(l2a%eflx_lh_tot(beg:end))
allocate(l2a%qflx_evap_tot(beg:end))
allocate(l2a%fsa(beg:end))
allocate(l2a%nee(beg:end))
allocate(l2a%ram1(beg:end))
allocate(l2a%fv(beg:end))
allocate(l2a%flxdst(beg:end,1:ndst))
allocate(l2a%flxvoc(beg:end,1:nvoc))
if ( n_drydep > 0 .and. drydep_method == DD_XLND )then
allocate(l2a%ddvel(beg:end,1:n_drydep))
end if
! ival = nan ! causes core dump in map_maparray, tcx fix
ival = 0.0_r8
l2a%t_rad(beg:end) = ival
l2a%t_ref2m(beg:end) = ival
l2a%q_ref2m(beg:end) = ival
l2a%h2osno(beg:end) = ival
l2a%albd(beg:end,1:numrad) = ival
l2a%albi(beg:end,1:numrad) = ival
l2a%taux(beg:end) = ival
l2a%tauy(beg:end) = ival
l2a%eflx_lwrad_out(beg:end) = ival
l2a%eflx_sh_tot(beg:end) = ival
l2a%eflx_lh_tot(beg:end) = ival
l2a%qflx_evap_tot(beg:end) = ival
l2a%fsa(beg:end) = ival
l2a%nee(beg:end) = ival
l2a%ram1(beg:end) = ival
l2a%fv(beg:end) = ival
l2a%flxdst(beg:end,1:ndst) = ival
l2a%flxvoc(beg:end,1:nvoc) = ival
if ( n_drydep > 0 .and. drydep_method == DD_XLND )then
l2a%ddvel(beg:end, : ) = ival
end if
end subroutine init_lnd2atm_type
!------------------------------------------------------------------------------
!BOP
!
! !IROUTINE: clm_mapa2l
!
! !INTERFACE:
subroutine clm_mapa2l(a2l_src, a2l_dst) 1,19
!
! !DESCRIPTION:
! Maps atm2lnd fields from external grid to clm grid
!
! !USES:
use areaMod
, only : map1dl_a2l, map1dl_l2a, map_setptrs
use decompMod
, only : ldecomp,adecomp
use domainMod
, only : ldomain,adomain
use QSatMod
, only : QSat
use clm_varctl
,only : set_caerdep_from_file, set_dustdep_from_file
!
! !ARGUMENTS:
implicit none
type(atm2lnd_type), intent(in) :: a2l_src
type(atm2lnd_type), intent(out) :: a2l_dst
!
! !REVISION HISTORY:
! 2005.11.15 T Craig Creation.
! 2006.3.30 P Worley Restructuring for improved vector performance
!
!
! !LOCAL VARIABLES:
!EOP
integer :: n ! loop counter
integer :: ix ! field index
integer :: nflds ! number of fields to be mapped
integer :: nradflds ! size of 2nd dim in arrays
integer :: begg_s,endg_s ! beg,end of input grid
integer :: begg_d,endg_d ! beg,end of output grid
integer :: nmap ! size of map
integer :: mo ! size of map
integer, pointer :: src(:) ! map src index
integer, pointer :: dst(:) ! map dst index
real(r8),pointer :: wts(:) ! map wts values
integer :: ns !source (atm) indexes
integer :: nd !destination (lnd) indexes
! temporaries for topo downscaling:
real(r8) :: hsurf_a,hsurf_l,Hbot,Hsrf,lapse
real(r8) :: zbot_a, tbot_a, pbot_a, thbot_a, qbot_a, qs_a, es_a
real(r8) :: zbot_l, tbot_l, pbot_l, thbot_l, qbot_l, qs_l, es_l
real(r8) :: tsrf_l, psrf_l, egcm_l, rhos_l
real(r8) :: dum1,dum2,sum1,sum2,sum3,sum4,sum5,sum6,sum7,sum8
real(r8) :: mu
real(r8) :: precip_max
real(r8) :: rand_num(6) ! random number
real(r8),allocatable :: rain_l(:),snow_l(:)
real(r8),allocatable :: pnorm(:)
real(r8),allocatable :: pchance(:),pamount(:)
integer ,allocatable :: pchance_min(:)
real(r8),allocatable :: qsum(:)
integer :: ier
logical :: first_call = .true.
!------------------------------------------------------------------------------
if (first_call .and. masterproc) then
write(iulog,*) 'clm_mapa2l subroutine'
endif
nradflds = size(a2l_src%forc_solad,dim=2)
if (nradflds /= numrad) then
write(iulog,*) 'clm_mapa2l ERROR: nradflds ne numrad ',nradflds,numrad
call endrun
()
endif
call get_proc_bounds_atm
(begg_s, endg_s)
call get_proc_bounds
(begg_d, endg_d)
!-topographic downscaling
!-only call this if there is more than 1 land cell / atm cell somewhere
call map_setptrs
(map1dl_l2a, dstmo=mo)
if (mo > 1) then
if (first_call.and.masterproc) then
write(iulog,*) 'clm_mapa2l downscaling ON'
endif
call map_setptrs
(map1dl_a2l,nwts=nmap,src=src,dst=dst,dstmo=mo)
if (mo /= 1) then
write(iulog,*)' clm_mapa2l ERROR: map1dl_a2l mo not 1 ',mo
call endrun
()
endif
lapse = 0.0065_r8 ! hardwired in multiple places in cam
mu = 0.20 ! chance of precip coverage [0.,1.]
precip_max = 10.0_r8 ! mm/hr
allocate(pchance(begg_d:endg_d),pamount(begg_d:endg_d))
do n = 1,nmap
ns = src(n)
nd = dst(n)
hsurf_a = adomain%topo(ns) ! atm elevation
hsurf_l = ldomain%ntop(nd) ! lnd elevation
!tcx DOWNSCALING turns off topo downscaling
! hsurf_l = hsurf_a
if (abs(hsurf_a - hsurf_l) .gt. 0.1_r8) then
!tcx DOWNSCALING if atm lapse rate is available
! lapse = a2l_src%lapse(ns) ! atm lapse rate
tbot_a = a2l_src%forc_t(ns) ! atm temp at bot
thbot_a= a2l_src%forc_th(ns) ! atm pot temp at bot
pbot_a = a2l_src%forc_pbot(ns) ! atm press at bot
qbot_a = a2l_src%forc_q(ns) ! atm sp humidity at bot
zbot_a = a2l_src%forc_hgt(ns) ! atm ref height
zbot_l = zbot_a
tbot_l = tbot_a-lapse*(hsurf_l-hsurf_a) ! lnd temp for topo
Hbot = rair*0.5_r8*(tbot_a+tbot_l)/grav ! scale ht at avg temp
pbot_l = pbot_a*exp(-(hsurf_l-hsurf_a)/Hbot) ! lnd press for topo
thbot_l= tbot_l*exp((zbot_l/Hbot)*(rair/cpair)) ! pot temp calc
tsrf_l = tbot_l-lapse*(-zbot_l) ! lnd temp at surface
Hsrf = rair*0.5_r8*(tbot_l+tsrf_l)/grav ! scale ht at avg temp
psrf_l = pbot_l*exp(-(zbot_l)/Hsrf) ! lnd press for topo
call Qsat
(tbot_a,pbot_a,es_a,dum1,qs_a,dum2)
call Qsat
(tbot_l,pbot_l,es_l,dum1,qs_l,dum2)
qbot_l = qbot_a*(qs_l/qs_a)
a2l_dst%forc_hgt(nd) = zbot_l
a2l_dst%forc_t(nd) = tbot_l
a2l_dst%forc_pbot(nd) = pbot_l
a2l_dst%forc_th(nd) = thbot_l
a2l_dst%forc_q(nd) = qbot_l
a2l_dst%forc_vp(nd) = es_l
a2l_dst%forc_psrf(nd) = psrf_l
endif
! DOWNSCALING set random numbers (must be "reproducible") for downscaling
rand_num(1) = mod(abs(a2l_dst%forc_t(nd)) *1.0e3_r8,1.0_r8)
rand_num(2) = 0.5_r8
rand_num(3) = mod(abs(sin(ldecomp%gdc2glo(nd)*1._r8))*1.0e3_r8,1.0_r8)
rand_num(4) = mod(abs(a2l_dst%forc_psrf(nd)) *1.0e1_r8,1.0_r8)
rand_num(5) = 0.5_r8
rand_num(6) = mod(abs(cos(ldecomp%gdc2glo(nd)*1._r8))*1.0e3_r8,1.0_r8)
pchance(nd) = mod(rand_num(1)+rand_num(2)+rand_num(3),1.0_r8)
pamount(nd) = -log(max(1.0_r8-(mod(rand_num(4)+rand_num(5)+rand_num(6),1.0_r8)),1.0e-20_r8))
!tcx DOWNSCALING this will remove random aspects, turn on either or both
! pchance(nd) = 0._r8 ! sets all fine gridcells to precip true
! pamount(nd) = 1._r8 ! sets all precip gridcells to equal amount
enddo
!tcx diagnostics
! write(iulog,*) 'tcx mm1 ',minval(a2l_dst%forc_t),maxval(a2l_dst%forc_t)
! write(iulog,*) 'tcx mm2 ',minval(a2l_dst%forc_psrf),maxval(a2l_dst%forc_psrf)
! write(iulog,*) 'tcx mm3 ',minval(a2l_dst%forc_q),maxval(a2l_dst%forc_q)
! write(iulog,*) 'tcx mm4 ',minval(a2l_dst%forc_th),maxval(a2l_dst%forc_th)
! write(iulog,*) 'tcx mm5 ',minval(pchance),maxval(pchance)
! write(iulog,*) 'tcx mm6 ',minval(pamount),maxval(pamount)
call map_setptrs
(map1dl_l2a,nwts=nmap,src=src,dst=dst,wts=wts)
! compute precipitation disaggregation
!--- find min pchance in finemesh cells of coarse mesh, set that cell's
!--- pchance to 0. to force it to be below mu and take precip
allocate(pchance_min(begg_s:endg_s))
pchance_min = -999
do n = 1,nmap
ns = dst(n)
nd = src(n)
if (pchance_min(ns) < 1) pchance_min(ns) = nd
if (pchance(nd) < pchance(pchance_min(ns))) pchance_min(ns) = nd
enddo
do n = begg_s,endg_s
if (pchance_min(n) > 0) pchance(pchance_min(n)) = 0._r8
enddo
deallocate(pchance_min)
!--- set rain/snow amounts and compute sums for normalization
allocate(rain_l(begg_s:endg_s),snow_l(begg_s:endg_s))
rain_l = 0.0_r8
snow_l = 0.0_r8
do n = 1,nmap
ns = dst(n)
nd = src(n)
!tcx DOWNSCALING turn off precip disaggr completely
#if (1 == 1)
if (pchance(nd) < mu) then
!--- rain/snow refractionation
!--- set to 100% snow < -5C and 100% rain > 0C
dum2 = (a2l_dst%forc_t(nd)-tfrz + 5.0_r8)/(5.0_r8)
dum2 = max(dum2,0.0_r8)
dum2 = min(dum2,1.0_r8)
!tcx DOWNSCALING turn on refractionation and spatial variability
a2l_dst%forc_rain(nd) = ( dum2) * pamount(nd)
a2l_dst%forc_snow(nd) = (1.0_r8 - dum2) * pamount(nd)
!tcx DOWNSCALING turn on just spatial variability but not refractionation
! comment out lines above and comment in the two lines below
! a2l_dst%forc_rain(nd) = a2l_dst%forc_rain(nd)* pamount(nd)
! a2l_dst%forc_snow(nd) = a2l_dst%forc_snow(nd)* pamount(nd)
!
else
a2l_dst%forc_rain(nd) = 0._r8
a2l_dst%forc_snow(nd) = 0._r8
endif
#endif
rain_l(ns) = rain_l(ns) + a2l_dst%forc_rain(nd) * wts(n)
snow_l(ns) = snow_l(ns) + a2l_dst%forc_snow(nd) * wts(n)
enddo
deallocate(pchance,pamount)
!--- compute normalization of disaggregation amounts
allocate(pnorm(begg_s:endg_s))
pnorm = 0.0_r8
do ns = begg_s, endg_s
if (rain_l(ns) + snow_l(ns) == 0._r8) then
if (a2l_src%forc_rain(ns) + a2l_src%forc_snow(ns) /= 0._r8) then
write(iulog,*)' clm_mapa2l ERROR: rain/snow normalization',rain_l(ns),snow_l(ns), &
a2l_src%forc_rain(ns),a2l_src%forc_snow(ns)
call endrun
()
endif
else
pnorm(ns) = (a2l_src%forc_rain(ns) + a2l_src%forc_snow(ns)) / (rain_l(ns)+snow_l(ns))
endif
!--- set pnorm=1 if close, for bfb consitency when coarse=finemesh cases
if (abs(pnorm(ns) - 1.0_r8) < 1.0e-12) pnorm(ns) = 1.0_r8
enddo
deallocate(rain_l,snow_l)
!--- apply normalization
do n = 1,nmap
ns = dst(n)
nd = src(n)
a2l_dst%forc_rain(nd) = a2l_dst%forc_rain(nd) * pnorm(ns)
a2l_dst%forc_snow(nd) = a2l_dst%forc_snow(nd) * pnorm(ns)
enddo
deallocate(pnorm)
!--- compute q normalization amounts
call map_setptrs
(map1dl_l2a,nwts=nmap,src=src,dst=dst,wts=wts)
allocate(qsum(begg_s:endg_s))
qsum = 0.0_r8
do n = 1,nmap
ns = dst(n)
nd = src(n)
qsum(ns) = qsum(ns) + wts(n)* a2l_dst%forc_q(nd)
enddo
call map_setptrs
(map1dl_a2l,nwts=nmap,src=src,dst=dst)
do n = 1,nmap
ns = src(n)
nd = dst(n)
qbot_a = a2l_src%forc_q(ns) ! atm specific humidity
qbot_l = a2l_dst%forc_q(nd) ! lnd specific humidity
pbot_l = a2l_dst%forc_pbot(nd)
tbot_l = a2l_dst%forc_t(nd)
qbot_l = qbot_l - (qsum(ns) - qbot_a) ! normalize
egcm_l = qbot_l*pbot_l/(0.622+0.378*qbot_l)
rhos_l = (pbot_l-0.378*egcm_l) / (rair*tbot_l)
a2l_dst%forc_q(nd) = qbot_l
a2l_dst%forc_rho(nd) = rhos_l
enddo
deallocate(qsum)
! --- check ---
call map_setptrs
(map1dl_l2a,nwts=nmap,src=src,dst=dst,wts=wts)
adiag_arain = 0.0_r8
adiag_asnow = 0.0_r8
adiag_aflux = 0.0_r8
adiag_lflux = 0.0_r8
do ns = begg_s,endg_s
sum1 = 0.0_r8
sum2 = 0.0_r8
sum3 = 0.0_r8
sum4 = 0.0_r8
sum5 = 0.0_r8
sum6 = 0.0_r8
sum7 = 0.0_r8
sum8 = 0.0_r8
do n = 1,nmap
if (dst(n) == ns) then
nd = src(n)
sum1 = sum1 + ldomain%ntop(nd) * wts(n)
sum2 = sum2 + a2l_dst%forc_t(nd) * wts(n)
sum3 = sum3 + a2l_dst%forc_q(nd) * wts(n)
sum4 = sum4 + a2l_dst%forc_hgt(nd) * wts(n)
sum5 = sum5 + a2l_dst%forc_pbot(nd) * wts(n)
sum6 = sum6 + a2l_dst%forc_th(nd) * wts(n)
sum7 = sum7 + a2l_dst%forc_rain(nd) * wts(n)
sum8 = sum8 + a2l_dst%forc_snow(nd) * wts(n)
adiag_lflux(nd) = (a2l_dst%forc_snow(nd) - a2l_src%forc_snow(ns))*wts(n)*hfus
endif
enddo
adiag_arain(ns) = sum7
adiag_asnow(ns) = sum8
adiag_aflux(ns) = (sum8 - a2l_src%forc_snow(ns))*hfus
!--- add up rain and snow, compute relative diff vs source
dum1 = (sum7 + sum8 - a2l_src%forc_rain(ns) - a2l_src%forc_snow(ns))
if ((sum7+sum8) == 0.0_r8 .and. &
(a2l_src%forc_rain(ns)+a2l_src%forc_snow(ns)) == 0.0_r8) then
dum1 = 0.0_r8
else
dum1 = dum1 / (max(sum7+sum8,a2l_src%forc_rain(ns)+a2l_src%forc_snow(ns)))
endif
if ((abs(sum1 - adomain%topo(ns)) > 1.0e-8) &
.or.(abs(sum2 - a2l_src%forc_t(ns)) > 1.0e-3) &
.or.(abs(sum3 - a2l_src%forc_q(ns)) > 1.0e-8) &
.or.(abs(sum4 - a2l_src%forc_hgt(ns)) > 1.0e-6) &
! .or.(abs(sum5 - a2l_src%forc_pbot(ns)) > 1.0e-6) &
! .or.(abs(sum6 - a2l_src%forc_th(ns)) > 1.0e-6) &
.or.(abs(dum1) > 1.0e-8) &
) then
write(iulog,*) 'clm_map2l check ERROR topo ',ns,sum1,adomain%topo(ns)
write(iulog,*) 'clm_map2l check ERROR t ',ns,sum2,a2l_src%forc_t(ns)
write(iulog,*) 'clm_map2l check ERROR q ',ns,sum3,a2l_src%forc_q(ns)
write(iulog,*) 'clm_map2l check ERROR hgt ',ns,sum4,a2l_src%forc_hgt(ns)
write(iulog,*) 'clm_map2l check ERROR pbot ',ns,sum5,a2l_src%forc_pbot(ns)
write(iulog,*) 'clm_map2l check ERROR th ',ns,sum6,a2l_src%forc_th(ns)
write(iulog,*) 'clm_map2l check ERROR rain ',ns,sum7,a2l_src%forc_rain(ns)
write(iulog,*) 'clm_map2l check ERROR snow ',ns,sum8,a2l_src%forc_snow(ns)
write(iulog,*) 'clm_map2l check ERROR adiag',ns,adiag_arain(ns),adiag_asnow(ns)
call endrun
()
endif
enddo
else ! mx_ovr > 1
! adomain and ldomain same, copy asca from adomain
ldomain%asca = adomain%asca
endif ! mx_ovr > 1
first_call = .false.
end subroutine clm_mapa2l
!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: clm_map2gcell
!
! !INTERFACE: subroutine clm_map2gcell(init)
subroutine clm_map2gcell(init) 2,29
!
! !DESCRIPTION:
! Compute l2a component of gridcell derived type
!
! !USES:
use shr_kind_mod
, only : r8 => shr_kind_r8
use clmtype
use subgridAveMod
use clm_varcon
, only : sb
use clm_varpar
, only : numrad
!
! !ARGUMENTS:
implicit none
save
logical, optional, intent(in) :: init ! if true=>only set a subset of arguments
!
! !REVISION HISTORY:
! Mariana Vertenstein: created 03/10-25
!
!
! !LOCAL VARIABLES:
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
!
! !USES:
!
! !REVISION HISTORY:
! 03-04-27 : Created by Mariana Vertenstein
! 03-08-25 : Updated to vector data structure (Mariana Vertenstein)
!
!
! !LOCAL VARIABLES:
!EOP
integer :: g ! indices
type(gridcell_type), pointer :: gptr ! pointer to gridcell derived subtype
type(landunit_type), pointer :: lptr ! pointer to landunit derived subtype
type(column_type) , pointer :: cptr ! pointer to column derived subtype
type(pft_type) , pointer :: pptr ! pointer to pft derived subtype
#if (defined DUST)
type(pft_dflux_type),pointer :: pdf ! local pointer to derived subtype
integer n
#endif
real(r8), parameter :: amC = 12.0_r8 ! Atomic mass number for Carbon
real(r8), parameter :: amO = 16.0_r8 ! Atomic mass number for Oxygen
real(r8), parameter :: amCO2 = amC + 2.0_r8*amO ! Atomic mass number for CO2
! The following converts g of C to kg of CO2
real(r8), parameter :: convertgC2kgCO2 = 1.0e-3_r8 * (amCO2/amC)
!------------------------------------------------------------------------
! Set pointers into derived type
gptr => clm3%g
lptr => clm3%g%l
cptr => clm3%g%l%c
pptr => clm3%g%l%c%p
! Determine processor bounds
call get_proc_bounds
(begg, endg, begl, endl, begc, endc, begp, endp)
! Compute gridcell averages.
if (present(init)) then
call c2g
(begc, endc, begl, endl, begg, endg, &
cptr%cws%h2osno, clm_l2a%h2osno, &
c2l_scale_type= 'urbanf', l2g_scale_type='unity')
do g = begg,endg
clm_l2a%h2osno(g) = clm_l2a%h2osno(g)/1000._r8
end do
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, numrad, &
pptr%pps%albd, clm_l2a%albd,&
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, numrad, &
pptr%pps%albi, clm_l2a%albi,&
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pef%eflx_lwrad_out, clm_l2a%eflx_lwrad_out,&
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
do g = begg,endg
clm_l2a%t_rad(g) = sqrt(sqrt(clm_l2a%eflx_lwrad_out(g)/sb))
end do
else
call c2g
(begc, endc, begl, endl, begg, endg, cptr%cws%h2osno, clm_l2a%h2osno,&
c2l_scale_type= 'urbanf', l2g_scale_type='unity')
do g = begg,endg
clm_l2a%h2osno(g) = clm_l2a%h2osno(g)/1000._r8
end do
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, numrad, &
pptr%pps%albd, clm_l2a%albd, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, numrad, &
pptr%pps%albi, clm_l2a%albi, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pes%t_ref2m, clm_l2a%t_ref2m, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pes%q_ref2m, clm_l2a%q_ref2m, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pmf%taux, clm_l2a%taux, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pmf%tauy, clm_l2a%tauy, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pef%eflx_lh_tot, clm_l2a%eflx_lh_tot, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
!DML note: use new array: clm3%g%gef%eflx_sh_totg
! call p2g(begp, endp, begc, endc, begl, endl, begg, endg, &
! pptr%pef%eflx_sh_tot, clm_l2a%eflx_sh_tot, &
! p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
do g = begg,endg
clm_l2a%eflx_sh_tot(g) = clm3%g%gef%eflx_sh_totg(g)
end do
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pwf%qflx_evap_tot, clm_l2a%qflx_evap_tot, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pef%fsa, clm_l2a%fsa, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pef%eflx_lwrad_out, clm_l2a%eflx_lwrad_out, &
p2c_scale_type='unity', c2l_scale_type= 'urbanf', l2g_scale_type='unity')
#if (defined CN)
call c2g
(begc, endc, begl, endl, begg, endg, &
cptr%ccf%nee, clm_l2a%nee, &
c2l_scale_type= 'unity', l2g_scale_type='unity')
#elif (defined CASA)
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pps%co2flux, clm_l2a%nee, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
#else
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pcf%fco2, clm_l2a%nee, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
! Note that fco2 in is umolC/m2/sec so units need to be changed to gC/m2/sec
do g = begg,endg
clm_l2a%nee(g) = clm_l2a%nee(g)*12.011e-6_r8
end do
#endif
#if (defined DUST || defined PROGSSLT )
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pps%fv, clm_l2a%fv, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, &
pptr%pps%ram1, clm_l2a%ram1, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
#endif
#if (defined DUST )
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, ndst, &
pptr%pdf%flx_mss_vrt_dst, clm_l2a%flxdst, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
#endif
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, nvoc, &
pptr%pvf%vocflx, clm_l2a%flxvoc, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
if ( n_drydep > 0 .and. drydep_method == DD_XLND ) &
call p2g
(begp, endp, begc, endc, begl, endl, begg, endg, n_drydep, &
pptr%pdd%drydepvel, clm_l2a%ddvel, &
p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity')
! Convert from gC/m2/s to kgCO2/m2/s
do g = begg,endg
clm_l2a%nee(g) = clm_l2a%nee(g)*convertgC2kgCO2
end do
do g = begg,endg
clm_l2a%t_rad(g) = sqrt(sqrt(clm_l2a%eflx_lwrad_out(g)/sb))
end do
! DOWNSCALING add rain snow conversion heat flux to latent heat flux
do g = begg,endg
clm_l2a%eflx_lh_tot(g) = clm_l2a%eflx_lh_tot(g) + adiag_lflux(g)
end do
end if
end subroutine clm_map2gcell
!------------------------------------------------------------------------
!------------------------------------------------------------------------
end module clm_atmlnd