module clm_glclnd 6,6 !----------------------------------------------------------------------- !BOP ! ! !MODULE: clm_glclnd ! ! !DESCRIPTION: ! Handle arrays used for exchanging data between glc and land model. ! Based on clm_atmlnd (but without mapping routines because glc data ! is send and received on the lnd decomposition, at least for now). ! ! The fields sent from the lnd component to the glc component via ! the coupler are labeled 's2x', or sno to coupler. ! The fields received by the lnd component from the glc component ! via the coupler are labeled 'x2s', or coupler to sno. ! 'Sno' is a misnomer in that the exchanged data are related to ! the ice beneath the snow, not the snow itself. But by CCSM convention, ! 'ice' refers to sea ice, not land ice. ! ! !USES: 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 clm_varctl , only : iulog use clm_varctl , only : glc_nec ! ! !REVISION HISTORY: ! Created by William Lipscomb, Dec. 2007, based on clm_atmlnd.F90. ! ! !PUBLIC TYPES: implicit none !---------------------------------------------------- ! glc -> land variables structure !---------------------------------------------------- type glc2lnd_type real(r8), pointer :: frac(:,:) real(r8), pointer :: topo(:,:) real(r8), pointer :: rofi(:,:) real(r8), pointer :: rofl(:,:) real(r8), pointer :: hflx(:,:) end type glc2lnd_type !---------------------------------------------------- ! land -> glc variables structure !---------------------------------------------------- type lnd2glc_type real(r8), pointer :: tsrf(:,:) real(r8), pointer :: topo(:,:) real(r8), pointer :: qice(:,:) end type lnd2glc_type type (lnd2glc_type), public, target :: clm_s2x ! s2x fields on clm grid type (glc2lnd_type), public, target :: clm_x2s ! x2s fields on clm grid type (lnd2glc_type), public, target :: atm_s2x ! s2x fields on atm grid type (glc2lnd_type), public, target :: atm_x2s ! x2s fields on atm grid ! !PUBLIC MEMBER FUNCTIONS: public :: init_glc2lnd_type public :: init_lnd2glc_type public :: clm_maps2x public :: clm_mapx2s ! ! !PRIVATE MEMBER FUNCTIONS: !EOP !---------------------------------------------------- contains !------------------------------------------------------------------------ !BOP ! ! !IROUTINE: init_glc2lnd_type ! ! !INTERFACE: subroutine init_glc2lnd_type(beg, end, x2s) 2 ! ! !DESCRIPTION: ! Initialize glc variables required by the land ! ! !ARGUMENTS: implicit none integer, intent(in) :: beg, end type (glc2lnd_type), intent(inout):: x2s ! ! !REVISION HISTORY: ! Created by William Lipscomb, based on init_atm2lnd_type !EOP ! ! !LOCAL VARIABLES: real(r8) :: ival ! initial value !------------------------------------------------------------------------ allocate(x2s%frac(beg:end,glc_nec)) allocate(x2s%topo(beg:end,glc_nec)) allocate(x2s%rofi(beg:end,glc_nec)) allocate(x2s%rofl(beg:end,glc_nec)) allocate(x2s%hflx(beg:end,glc_nec)) ! ival = nan ! causes core dump in map_maparray, tcx fix ival = 0.0_r8 x2s%frac(beg:end,:) = ival x2s%topo(beg:end,:) = ival x2s%rofi(beg:end,:) = ival x2s%rofl(beg:end,:) = ival x2s%hflx(beg:end,:) = ival end subroutine init_glc2lnd_type !------------------------------------------------------------------------ !BOP ! ! !IROUTINE: init_lnd2glc_type ! ! !INTERFACE: subroutine init_lnd2glc_type(beg, end, s2x) 2 ! ! !DESCRIPTION: ! Initialize land variables required by glc ! ! !ARGUMENTS: implicit none integer, intent(in) :: beg, end type (lnd2glc_type), intent(inout):: s2x ! ! !REVISION HISTORY: ! Created by William Lipscomb, based on init_lnd2atm_type ! !EOP ! ! !LOCAL VARIABLES: real(r8) :: ival ! initial value !------------------------------------------------------------------------ allocate(s2x%tsrf(beg:end,glc_nec)) allocate(s2x%topo(beg:end,glc_nec)) allocate(s2x%qice(beg:end,glc_nec)) ! ival = nan ! causes core dump in map_maparray, tcx fix ival = 0.0_r8 s2x%tsrf(beg:end,:) = ival s2x%topo(beg:end,:) = ival s2x%qice(beg:end,:) = ival end subroutine init_lnd2glc_type !------------------------------------------------------------------------------ !BOP ! ! !IROUTINE: clm_maps2x ! ! !INTERFACE: subroutine clm_maps2x(s2x_src, s2x_dst) 2,4 ! ! !DESCRIPTION: ! Maps lnd2glc fields from clm grid to external grid ! ! !USES: use areaMod , only : map_maparrayl, map1dl_l2a ! ! !ARGUMENTS: implicit none type(lnd2glc_type), intent(in) :: s2x_src type(lnd2glc_type), intent(out) :: s2x_dst ! ! !REVISION HISTORY: ! Created by William Lipscomb based on clm_mapl2a ! !EOP ! ! !LOCAL VARIABLES: integer :: n ! loop counter integer :: ix ! field index integer :: nflds ! number of fields to be mapped integer :: begg_s,endg_s ! beg,end of input grid integer :: begg_d,endg_d ! beg,end of output grid real(r8),pointer :: asrc(:,:) ! temporary source data real(r8),pointer :: adst(:,:) ! temporary dest data !------------------------------------------------------------------------------ !--- allocate temporaries call get_proc_bounds (begg_s, endg_s) call get_proc_bounds_atm(begg_d, endg_d) nflds = 3 allocate(asrc(begg_s:endg_s,nflds)) allocate(adst(begg_d:endg_d,nflds)) do n = 1, glc_nec ix = 0 ix=ix+1; asrc(:,ix) = s2x_src%tsrf(:,n) ix=ix+1; asrc(:,ix) = s2x_src%topo(:,n) ix=ix+1; asrc(:,ix) = s2x_src%qice(:,n) call map_maparrayl(begg_s, endg_s, begg_d, endg_d, nflds, asrc, adst, map1dl_l2a) ix = 0 ix=ix+1; s2x_dst%tsrf(:,n) = adst(:,ix) ix=ix+1; s2x_dst%topo(:,n) = adst(:,ix) ix=ix+1; s2x_dst%qice(:,n) = adst(:,ix) enddo ! loop over elevation classes deallocate(asrc) deallocate(adst) end subroutine clm_maps2x !------------------------------------------------------------------------------ !BOP ! ! !IROUTINE: clm_mapx2s ! ! !INTERFACE: subroutine clm_mapx2s(x2s_src, x2s_dst) 1,6 ! ! !DESCRIPTION: ! Maps glc2lnd fields from external grid to clm grid ! ! !USES: use areaMod , only : map_maparrayl, map1dl_a2l, map1dl_l2a, map_setptrs use decompMod, only : ldecomp,adecomp use domainMod, only : ldomain,adomain ! ! !ARGUMENTS: implicit none type(glc2lnd_type), intent(in) :: x2s_src type(glc2lnd_type), intent(out) :: x2s_dst ! ! !REVISION HISTORY: ! Created by William Lipscomb based on clm_mapa2l ! !EOP ! ! !LOCAL VARIABLES: integer :: n ! loop counter integer :: ix ! field index integer :: nflds ! number of fields to be mapped integer :: begg_s,endg_s ! beg,end of input grid integer :: begg_d,endg_d ! beg,end of output grid real(r8),pointer :: asrc(:,:) ! temporary source data real(r8),pointer :: adst(:,:) ! temporary dest data logical :: first_call = .true. !------------------------------------------------------------------------------ if (first_call .and. masterproc) then write(iulog,*) 'clm_mapx2s subroutine' endif !--- allocate temporaries call get_proc_bounds_atm(begg_s, endg_s) call get_proc_bounds (begg_d, endg_d) nflds = 5 allocate(asrc(begg_s:endg_s,nflds)) allocate(adst(begg_d:endg_d,nflds)) do n = 1, glc_nec ix = 0 ix=ix+1; asrc(:,ix) = x2s_src%frac(:,n) ix=ix+1; asrc(:,ix) = x2s_src%topo(:,n) ix=ix+1; asrc(:,ix) = x2s_src%rofi(:,n) ix=ix+1; asrc(:,ix) = x2s_src%rofl(:,n) ix=ix+1; asrc(:,ix) = x2s_src%hflx(:,n) call map_maparrayl(begg_s, endg_s, begg_d, endg_d, nflds, asrc, adst, map1dl_a2l) ix = 0 ix=ix+1; x2s_dst%frac(:,n) = adst(:,ix) ix=ix+1; x2s_dst%topo(:,n) = adst(:,ix) ix=ix+1; x2s_dst%rofi(:,n) = adst(:,ix) ix=ix+1; x2s_dst%rofl(:,n) = adst(:,ix) ix=ix+1; x2s_dst%hflx(:,n) = adst(:,ix) enddo deallocate(asrc) deallocate(adst) if (first_call.and.masterproc) then write(iulog,*) 'clm_mapx2s mapping complete' endif first_call = .false. end subroutine clm_mapx2s !------------------------------------------------------------------------------ !BOP ! ! !IROUTINE: create_clm_s2x ! ! !INTERFACE: subroutine create_clm_s2x(clm_s2x) 2,7 ! ! !DESCRIPTION: ! Assign values to clm_s2x based on the appropriate derived types ! ! !USES: use clm_varctl, only : glc_smb !! use clm_varctl , only : csm_doflxave_lg use clmtype , only : clm3 !! use clm_varpar , only : nlevsoi use domainMod , only : ldomain use clm_varcon , only : istice_mec use clm_atmlnd , only : clm_l2a, clm_a2l use clm_varcon , only : spval ! ! !ARGUMENTS: implicit none type(lnd2glc_type), intent(out) :: clm_s2x ! ! !REVISION HISTORY: ! Written by William Lipscomb, Feb. 2009 ! integer :: begg, endg ! per-proc beginning and ending gridcell indices integer :: begc, endc ! per-proc beginning and ending column indices integer :: c, l, g, n ! indices integer , pointer :: ityplun(:) ! landunit type integer , pointer :: clandunit(:) ! column's landunit index integer , pointer :: cgridcell(:) ! column's gridcell index ! Assign local pointers to derived type members clandunit => clm3%g%l%c%landunit cgridcell => clm3%g%l%c%gridcell ityplun => clm3%g%l%itype ! Get processor bounds call get_proc_bounds(begg, endg, begc=begc, endc=endc) ! initialize to be safe clm_s2x%tsrf(:,:) = 0._r8 clm_s2x%topo(:,:) = 0._r8 clm_s2x%qice(:,:) = 0._r8 ! fill the clm_s2x vector on the clm grid if (glc_smb) then ! send surface mass balance info do c = begc, endc l = clandunit(c) g = cgridcell(c) if (ityplun(l) == istice_mec) then n = c - clm3%g%l%coli(l) + 1 ! elevation class index ! (assumes all elevation classes are populated) clm_s2x%tsrf(g,n) = clm3%g%l%c%ces%t_soisno(c,1) clm_s2x%qice(g,n) = clm3%g%l%c%cwf%qflx_glcice(c) clm_s2x%topo(g,n) = clm3%g%l%c%cps%glc_topo(c) ! Check for bad values of qice if ( abs(clm_s2x%qice(g,n)) > 1.0_r8 .and. clm_s2x%qice(g,n) /= spval) then write(iulog,*) 'WARNING: qice out of bounds: g, n, qice =', g, n, clm_s2x%qice(g,n) endif endif ! istice_mec enddo ! c else ! Pass PDD info (same info in each elevation class) ! It might make sense to require glc_nec = 1 for this case do n = 1, glc_nec do g = begg, endg clm_s2x%tsrf(g,n) = clm_l2a%t_ref2m(g) clm_s2x%qice(g,n) = clm_a2l%forc_snow(g) ! Assume rain runs off clm_s2x%topo(g,n) = ldomain%topo(g) ! Check for bad values of qice if (clm_s2x%qice(g,n) > -1.0_r8 .and. clm_s2x%qice(g,n) < 1.0_r8) then continue else write(iulog,*) 'WARNING: qice out of bounds: g, n, qice =', g, n, clm_s2x%qice(g,n) write(iulog,*) 'forc_rain =', clm_a2l%forc_rain(g) write(iulog,*) 'forc_snow =', clm_a2l%forc_snow(g) endif enddo enddo endif ! glc_smb end subroutine create_clm_s2x !------------------------------------------------------------------------------ !BOP ! ! !IROUTINE: unpack_clm_x2s ! ! !INTERFACE: subroutine unpack_clm_x2s(clm_x2s) 1,2 ! ! !DESCRIPTION: ! Unpack clm_x2s and update the appropriate derived types ! ! !USES: use clm_varcon , only : istice_mec use clmtype , only : clm3 ! ! !ARGUMENTS: implicit none type(glc2lnd_type), intent(in) :: clm_x2s ! ! !REVISION HISTORY: ! Written by William Lipscomb, Feb. 2009 ! integer :: begc, endc ! per-proc beginning and ending column indices integer :: c, l, g, n ! indices integer , pointer :: ityplun(:) ! landunit type integer , pointer :: clandunit(:) ! column's landunit index integer , pointer :: cgridcell(:) ! column's gridcell index logical :: update_glc2sno_fields ! if true, update glacier_mec fields ! Assign local pointers to derived type members clandunit => clm3%g%l%c%landunit cgridcell => clm3%g%l%c%gridcell ityplun => clm3%g%l%itype update_glc2sno_fields = .false. if (update_glc2sno_fields) then do c = begc, endc l = clandunit(c) g = cgridcell(c) if (ityplun(l) == istice_mec) then n = c - clm3%g%l%coli(l) + 1 ! elevation class index clm3%g%l%c%cps%glc_frac(c) = clm_x2s%frac(g,n) clm3%g%l%c%cps%glc_topo(c) = clm_x2s%topo(g,n) clm3%g%l%c%cwf%glc_rofi(c) = clm_x2s%rofi(g,n) clm3%g%l%c%cwf%glc_rofl(c) = clm_x2s%rofl(g,n) clm3%g%l%c%cef%eflx_bot(c) = clm_x2s%hflx(g,n) endif enddo endif ! update fields end subroutine unpack_clm_x2s !------------------------------------------------------------------------ end module clm_glclnd