module clm_atmlnd !----------------------------------------------------------------------- !BOP ! ! !MODULE: clm_atmlnd ! ! !DESCRIPTION: ! Handle atm2lnd, lnd2atm mapping ! ! !USES: use clm_varpar , only : numrad, ndst, nlevgrnd !ndst = number of dust bins. use clm_varcon , only : rair, grav, cpair, hfus, tfrz use clm_varctl , only : iulog use decompMod , only : get_proc_bounds 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 shr_megan_mod, only : shr_megan_mechcomps_n ! ! !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_flood(:) ! rof flood (mm/s) 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 :: u_ref10m(:) !10m surface wind speed (m/sec) 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 + qflx_evap_can + 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 :: h2osoi_vol(:,:) !volumetric soil water (0~watsat, m3/m3, nlevgrnd) (for dust model) real(r8), pointer :: rofliq(:) ! rof liq forcing real(r8), pointer :: rofice(:) ! rof ice forcing 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 :: clm_a2l ! a2l fields on clm grid type(lnd2atm_type),public,target :: clm_l2a ! l2a fields on clm grid ! !PUBLIC MEMBER FUNCTIONS: public :: init_atm2lnd_type public :: init_lnd2atm_type public :: clm_map2gcell ! ! !REVISION HISTORY: ! Created by Mariana Vertenstein and Tony Craig, 2006-01-10 ! ! !PRIVATE MEMBER FUNCTIONS: !EOP !---------------------------------------------------- contains !------------------------------------------------------------------------ !BOP ! ! !IROUTINE: init_atm2lnd_type ! ! !INTERFACE: subroutine init_atm2lnd_type(beg, end, a2l) ! ! !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_flood(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_flood(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) ! ! !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%u_ref10m(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%h2osoi_vol(beg:end,1:nlevgrnd)) allocate(l2a%rofliq(beg:end)) allocate(l2a%rofice(beg:end)) allocate(l2a%flxdst(beg:end,1:ndst)) if (shr_megan_mechcomps_n>0) then allocate(l2a%flxvoc(beg:end,1:shr_megan_mechcomps_n)) endif 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%u_ref10m(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%h2osoi_vol(beg:end,1:nlevgrnd) = ival l2a%rofliq(beg:end) = ival l2a%rofice(beg:end) = ival l2a%flxdst(beg:end,1:ndst) = ival if (shr_megan_mechcomps_n>0) then l2a%flxvoc(beg:end,1:shr_megan_mechcomps_n) = ival endif 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_map2gcell ! ! !INTERFACE: subroutine clm_map2gcell(init) subroutine clm_map2gcell(init) ! ! !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 integer :: n ! Loop index over nmap 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 c2g(begc, endc, begl, endl, begg, endg, nlevgrnd, & cptr%cws%h2osoi_vol, clm_l2a%h2osoi_vol, & c2l_scale_type= 'urbanf', l2g_scale_type='unity') 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%pps%u10_clm, clm_l2a%u_ref10m, & 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) = gptr%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') #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 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') do g = begg,endg clm_l2a%rofliq(g) = gptr%gwf%qflx_runoffg(g) clm_l2a%rofice(g) = gptr%gwf%qflx_snwcp_iceg(g) end do 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') if (shr_megan_mechcomps_n>0) then call p2g(begp, endp, begc, endc, begl, endl, begg, endg, shr_megan_mechcomps_n, & pptr%pvf%vocflx, clm_l2a%flxvoc, & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') endif if ( n_drydep > 0 .and. drydep_method == DD_XLND ) then 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') endif ! 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 end if end subroutine clm_map2gcell !------------------------------------------------------------------------ !------------------------------------------------------------------------ end module clm_atmlnd