#include <misc.h> #include <preproc.h> module SoilHydrologyMod 1 !----------------------------------------------------------------------- !BOP ! ! !MODULE: SoilHydrologyMod ! ! !DESCRIPTION: ! Calculate soil hydrology ! ! !PUBLIC TYPES: implicit none save ! ! !PUBLIC MEMBER FUNCTIONS: public :: SurfaceRunoff ! Calculate surface runoff public :: Infiltration ! Calculate infiltration into surface soil layer public :: SoilWater ! Calculate soil hydrology public :: Drainage ! Calculate subsurface drainage ! ! !REVISION HISTORY: ! Created by Mariana Vertenstein ! 04/25/07 Keith Oleson: CLM3.5 hydrology ! !EOP !----------------------------------------------------------------------- contains !----------------------------------------------------------------------- !BOP ! ! !IROUTINE: SurfaceRunoff ! ! !INTERFACE: subroutine SurfaceRunoff (lbc, ubc, lbp, ubp, num_hydrologyc, filter_hydrologyc, & 1,6 num_urbanc, filter_urbanc, vol_liq, icefrac) ! ! !DESCRIPTION: ! Calculate surface runoff ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use clmtype use clm_varcon , only : denice, denh2o, wimp, pondmx_urban, & icol_roof, icol_sunwall, icol_shadewall, & icol_road_imperv, icol_road_perv use clm_varpar , only : nlevsoi, maxpatch_pft use clm_time_manager, only : get_step_size ! ! !ARGUMENTS: implicit none integer , intent(in) :: lbc, ubc ! column bounds integer , intent(in) :: lbp, ubp ! pft bounds integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter integer , intent(in) :: filter_hydrologyc(ubc-lbc+1) ! column filter for soil points integer , intent(in) :: num_urbanc ! number of column urban points in column filter integer , intent(in) :: filter_urbanc(ubc-lbc+1) ! column filter for urban points real(r8), intent(out) :: vol_liq(lbc:ubc,1:nlevsoi) ! partial volume of liquid water in layer real(r8), intent(out) :: icefrac(lbc:ubc,1:nlevsoi) ! fraction of ice in layer (-) ! ! !CALLED FROM: ! subroutine Hydrology2 in module Hydrology2Mod ! ! !REVISION HISTORY: ! 15 September 1999: Yongjiu Dai; Initial code ! 12 November 1999: Z.-L. Yang and G.-Y. Niu ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision ! 2/26/02, Peter Thornton: Migrated to new data structures. ! 4/26/05, David Lawrence: Made surface runoff for dry soils a function ! of rooting fraction in top three soil layers. ! 04/25/07 Keith Oleson: Completely new routine for CLM3.5 hydrology ! ! !LOCAL VARIABLES: ! ! local pointers to original implicit in arguments ! integer , pointer :: cgridcell(:) ! gridcell index for each column integer , pointer :: ctype(:) ! column type index real(r8), pointer :: qflx_top_soil(:) !net water input into soil from top (mm/s) real(r8), pointer :: watsat(:,:) !volumetric soil water at saturation (porosity) real(r8), pointer :: hkdepth(:) !decay factor (m) real(r8), pointer :: zwt(:) !water table depth (m) real(r8), pointer :: fcov(:) !fractional impermeable area real(r8), pointer :: fsat(:) !fractional area with water table at surface real(r8), pointer :: dz(:,:) !layer depth (m) real(r8), pointer :: h2osoi_ice(:,:) !ice lens (kg/m2) real(r8), pointer :: h2osoi_liq(:,:) !liquid water (kg/m2) real(r8), pointer :: wtfact(:) !maximum saturated fraction for a gridcell real(r8), pointer :: hksat(:,:) ! hydraulic conductivity at saturation (mm H2O /s) real(r8), pointer :: bsw(:,:) ! Clapp and Hornberger "b" real(r8), pointer :: sucsat(:,:) ! minimum soil suction (mm) integer , pointer :: snl(:) ! minus number of snow layers real(r8), pointer :: qflx_evap_grnd(:) ! ground surface evaporation rate (mm H2O/s) [+] real(r8), pointer :: zi(:,:) ! interface level below a "z" level (m) ! ! local pointers to original implicit out arguments ! real(r8), pointer :: qflx_surf(:) ! surface runoff (mm H2O /s) real(r8), pointer :: eff_porosity(:,:) ! effective porosity = porosity - vol_ice real(r8), pointer :: fracice(:,:) !fractional impermeability (-) ! !EOP ! ! !OTHER LOCAL VARIABLES: ! integer :: c,j,fc,g !indices real(r8) :: dtime ! land model time step (sec) real(r8) :: xs(lbc:ubc) ! excess soil water above urban ponding limit real(r8) :: vol_ice(lbc:ubc,1:nlevsoi) !partial volume of ice lens in layer real(r8) :: fff(lbc:ubc) !decay factor (m-1) real(r8) :: s1 !variable to calculate qinmax real(r8) :: su !variable to calculate qinmax real(r8) :: v !variable to calculate qinmax real(r8) :: qinmax !maximum infiltration capacity (mm/s) !----------------------------------------------------------------------- ! Assign local pointers to derived subtype components (column-level) ctype => clm3%g%l%c%itype qflx_top_soil => clm3%g%l%c%cwf%qflx_top_soil qflx_surf => clm3%g%l%c%cwf%qflx_surf watsat => clm3%g%l%c%cps%watsat hkdepth => clm3%g%l%c%cps%hkdepth dz => clm3%g%l%c%cps%dz h2osoi_ice => clm3%g%l%c%cws%h2osoi_ice h2osoi_liq => clm3%g%l%c%cws%h2osoi_liq fcov => clm3%g%l%c%cws%fcov fsat => clm3%g%l%c%cws%fsat eff_porosity => clm3%g%l%c%cps%eff_porosity wtfact => clm3%g%l%c%cps%wtfact zwt => clm3%g%l%c%cws%zwt fracice => clm3%g%l%c%cps%fracice hksat => clm3%g%l%c%cps%hksat bsw => clm3%g%l%c%cps%bsw sucsat => clm3%g%l%c%cps%sucsat snl => clm3%g%l%c%cps%snl qflx_evap_grnd => clm3%g%l%c%cwf%pwf_a%qflx_evap_grnd zi => clm3%g%l%c%cps%zi ! Get time step dtime = get_step_size() do j = 1,nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! Porosity of soil, partial volume of ice and liquid, fraction of ice in each layer, ! fractional impermeability vol_ice(c,j) = min(watsat(c,j), h2osoi_ice(c,j)/(dz(c,j)*denice)) eff_porosity(c,j) = max(0.01_r8,watsat(c,j)-vol_ice(c,j)) vol_liq(c,j) = min(eff_porosity(c,j), h2osoi_liq(c,j)/(dz(c,j)*denh2o)) icefrac(c,j) = min(1._r8,h2osoi_ice(c,j)/(h2osoi_ice(c,j)+h2osoi_liq(c,j))) fracice(c,j) = max(0._r8,exp(-3._r8*(1._r8-icefrac(c,j)))- exp(-3._r8))/(1.0_r8-exp(-3._r8)) end do end do ! Saturated fraction !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) fff(c) = 0.5_r8 fsat(c) = wtfact(c) * exp(-0.5_r8*fff(c)*zwt(c)) fcov(c) = (1._r8 - fracice(c,1)) * fsat(c) + fracice(c,1) end do !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! Maximum infiltration capacity s1 = max(0.01_r8,vol_liq(c,1)/max(wimp,eff_porosity(c,1))) su = max(0._r8,(s1-fcov(c)) / (max(0.01_r8,1._r8-fcov(c)))) v = -bsw(c,1)*sucsat(c,1)/(0.5_r8*dz(c,1)*1000._r8) qinmax = (1._r8+v*(su-1._r8))*hksat(c,1) ! Surface runoff qflx_surf(c) = fcov(c) * qflx_top_soil(c) + & (1._r8-fcov(c)) * max(0._r8, qflx_top_soil(c)-qinmax) end do ! Determine water in excess of ponding limit for urban roof and impervious road. ! Excess goes to surface runoff. No surface runoff for sunwall and shadewall. !dir$ concurrent !cdir nodep do fc = 1, num_urbanc c = filter_urbanc(fc) if (ctype(c) == icol_roof .or. ctype(c) == icol_road_imperv) then ! If there are snow layers then all qflx_top_soil goes to surface runoff if (snl(c) < 0) then qflx_surf(c) = max(0._r8,qflx_top_soil(c)) else xs(c) = max(0._r8, & h2osoi_liq(c,1)/dtime + qflx_top_soil(c) - qflx_evap_grnd(c) - & pondmx_urban/dtime) if (xs(c) > 0.) then h2osoi_liq(c,1) = pondmx_urban else h2osoi_liq(c,1) = max(0._r8,h2osoi_liq(c,1)+ & (qflx_top_soil(c)-qflx_evap_grnd(c))*dtime) end if qflx_surf(c) = xs(c) end if else if (ctype(c) == icol_sunwall .or. ctype(c) == icol_shadewall) then qflx_surf(c) = 0._r8 end if end do end subroutine SurfaceRunoff !----------------------------------------------------------------------- !BOP ! ! !IROUTINE: Infiltration ! ! !INTERFACE: subroutine Infiltration(lbc, ubc, num_hydrologyc, filter_hydrologyc, & 1,3 num_urbanc, filter_urbanc) ! ! !DESCRIPTION: ! Calculate infiltration into surface soil layer (minus the evaporation) ! ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use clm_varcon , only : icol_roof, icol_road_imperv, icol_sunwall, icol_shadewall, & icol_road_perv use clmtype ! ! !ARGUMENTS: implicit none integer, intent(in) :: lbc, ubc ! column bounds integer, intent(in) :: num_hydrologyc ! number of column soil points in column filter integer, intent(in) :: filter_hydrologyc(ubc-lbc+1) ! column filter for soil points integer, intent(in) :: num_urbanc ! number of column urban points in column filter integer, intent(in) :: filter_urbanc(ubc-lbc+1) ! column filter for urban points ! ! !CALLED FROM: ! ! !REVISION HISTORY: ! 15 September 1999: Yongjiu Dai; Initial code ! 12 November 1999: Z.-L. Yang and G.-Y. Niu ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision ! 2/27/02, Peter Thornton: Migrated to new data structures. ! ! !LOCAL VARIABLES: ! ! local pointers to original implicit in arguments ! integer , pointer :: ctype(:) ! column type index integer , pointer :: snl(:) ! minus number of snow layers real(r8), pointer :: qflx_top_soil(:) ! net water input into soil from top (mm/s) real(r8), pointer :: qflx_surf(:) ! surface runoff (mm H2O /s) real(r8), pointer :: qflx_evap_grnd(:)! ground surface evaporation rate (mm H2O/s) [+] ! ! local pointers to original implicit out arguments ! real(r8), pointer :: qflx_infl(:) !infiltration (mm H2O /s) ! !EOP ! ! !OTHER LOCAL VARIABLES: ! integer :: c, fc !indices !----------------------------------------------------------------------- ! Assign local pointers to derived type members (column-level) ctype => clm3%g%l%c%itype snl => clm3%g%l%c%cps%snl qflx_top_soil => clm3%g%l%c%cwf%qflx_top_soil qflx_surf => clm3%g%l%c%cwf%qflx_surf qflx_infl => clm3%g%l%c%cwf%qflx_infl qflx_evap_grnd => clm3%g%l%c%cwf%pwf_a%qflx_evap_grnd ! Infiltration into surface soil layer (minus the evaporation) !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if (snl(c) >= 0) then qflx_infl(c) = qflx_top_soil(c) - qflx_surf(c) - qflx_evap_grnd(c) else qflx_infl(c) = qflx_top_soil(c) - qflx_surf(c) end if end do ! No infiltration for impervious urban surfaces !dir$ concurrent !cdir nodep do fc = 1, num_urbanc c = filter_urbanc(fc) if (ctype(c) /= icol_road_perv) then qflx_infl(c) = 0._r8 end if end do end subroutine Infiltration !----------------------------------------------------------------------- !BOP ! ! !IROUTINE: SoilWater ! ! !INTERFACE: subroutine SoilWater(lbc, ubc, num_hydrologyc, filter_hydrologyc, & 1,10 num_urbanc, filter_urbanc, & vol_liq, dwat, hk, dhkdw) ! ! !DESCRIPTION: ! Soil hydrology ! Soil moisture is predicted from a 10-layer model (as with soil ! temperature), in which the vertical soil moisture transport is governed ! by infiltration, runoff, gradient diffusion, gravity, and root ! extraction through canopy transpiration. The net water applied to the ! surface layer is the snowmelt plus precipitation plus the throughfall ! of canopy dew minus surface runoff and evaporation. ! CLM3.5 uses a zero-flow bottom boundary condition. ! ! The vertical water flow in an unsaturated porous media is described by ! Darcy's law, and the hydraulic conductivity and the soil negative ! potential vary with soil water content and soil texture based on the work ! of Clapp and Hornberger (1978) and Cosby et al. (1984). The equation is ! integrated over the layer thickness, in which the time rate of change in ! water mass must equal the net flow across the bounding interface, plus the ! rate of internal source or sink. The terms of water flow across the layer ! interfaces are linearly expanded by using first-order Taylor expansion. ! The equations result in a tridiagonal system equation. ! ! Note: length units here are all millimeter ! (in temperature subroutine uses same soil layer ! structure required but lengths are m) ! ! Richards equation: ! ! d wat d d wat d psi ! ----- = - -- [ k(----- ----- - 1) ] + S ! dt dz dz d wat ! ! where: wat = volume of water per volume of soil (mm**3/mm**3) ! psi = soil matrix potential (mm) ! dt = time step (s) ! z = depth (mm) ! dz = thickness (mm) ! qin = inflow at top (mm h2o /s) ! qout= outflow at bottom (mm h2o /s) ! s = source/sink flux (mm h2o /s) ! k = hydraulic conductivity (mm h2o /s) ! ! d qin d qin ! qin[n+1] = qin[n] + -------- d wat(j-1) + --------- d wat(j) ! d wat(j-1) d wat(j) ! ==================|================= ! < qin ! ! d wat(j)/dt * dz = qin[n+1] - qout[n+1] + S(j) ! ! > qout ! ==================|================= ! d qout d qout ! qout[n+1] = qout[n] + --------- d wat(j) + --------- d wat(j+1) ! d wat(j) d wat(j+1) ! ! ! Solution: linearize k and psi about d wat and use tridiagonal ! system of equations to solve for d wat, ! where for layer j ! ! ! r_j = a_j [d wat_j-1] + b_j [d wat_j] + c_j [d wat_j+1] ! ! !USES: use shr_kind_mod, only: r8 => shr_kind_r8 use clmtype use clm_varcon , only : wimp, icol_roof, icol_road_imperv use clm_varpar , only : nlevsoi, max_pft_per_col use clm_varctl , only : iulog use shr_const_mod , only : SHR_CONST_TKFRZ, SHR_CONST_LATICE, SHR_CONST_G use TridiagonalMod, only : Tridiagonal use clm_time_manager , only : get_step_size ! ! !ARGUMENTS: implicit none integer , intent(in) :: lbc, ubc ! column bounds integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter integer , intent(in) :: filter_hydrologyc(ubc-lbc+1) ! column filter for soil points integer , intent(in) :: num_urbanc ! number of column urban points in column filter integer , intent(in) :: filter_urbanc(ubc-lbc+1) ! column filter for urban points real(r8), intent(in) :: vol_liq(lbc:ubc,1:nlevsoi) ! soil water per unit volume [mm/mm] real(r8), intent(out) :: dwat(lbc:ubc,1:nlevsoi) ! change of soil water [m3/m3] real(r8), intent(out) :: hk(lbc:ubc,1:nlevsoi) ! hydraulic conductivity [mm h2o/s] real(r8), intent(out) :: dhkdw(lbc:ubc,1:nlevsoi) ! d(hk)/d(vol_liq) ! ! !CALLED FROM: ! subroutine Hydrology2 in module Hydrology2Mod ! ! !REVISION HISTORY: ! 15 September 1999: Yongjiu Dai; Initial code ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision ! 2/27/02, Peter Thornton: Migrated to new data structures. Includes ! treatment of multiple PFTs on a single soil column. ! 04/25/07 Keith Oleson: CLM3.5 hydrology ! ! !LOCAL VARIABLES: ! ! local pointers to original implicit in arguments ! integer , pointer :: ctype(:) ! column type index integer , pointer :: npfts(:) ! column's number of pfts - ADD real(r8), pointer :: pwtcol(:) ! weight relative to column for each pft real(r8), pointer :: pwtgcell(:) ! weight relative to gridcell for each pft real(r8), pointer :: z(:,:) ! layer depth (m) real(r8), pointer :: dz(:,:) ! layer thickness (m) real(r8), pointer :: smpmin(:) ! restriction for min of soil potential (mm) real(r8), pointer :: qflx_infl(:) ! infiltration (mm H2O /s) real(r8), pointer :: qflx_tran_veg_pft(:) ! vegetation transpiration (mm H2O/s) (+ = to atm) real(r8), pointer :: qflx_tran_veg_col(:) ! vegetation transpiration (mm H2O/s) (+ = to atm) real(r8), pointer :: eff_porosity(:,:) ! effective porosity = porosity - vol_ice real(r8), pointer :: watsat(:,:) ! volumetric soil water at saturation (porosity) real(r8), pointer :: hksat(:,:) ! hydraulic conductivity at saturation (mm H2O /s) real(r8), pointer :: bsw(:,:) ! Clapp and Hornberger "b" real(r8), pointer :: sucsat(:,:) ! minimum soil suction (mm) real(r8), pointer :: t_soisno(:,:) ! soil temperature (Kelvin) real(r8), pointer :: rootr_pft(:,:) ! effective fraction of roots in each soil layer integer , pointer :: pfti(:) ! beginning pft index for each column real(r8), pointer :: fracice(:,:) ! fractional impermeability (-) real(r8), pointer :: h2osoi_vol(:,:) ! volumetric soil water (0<=h2osoi_vol<=watsat) [m3/m3] real(r8), pointer :: qcharge(:) ! aquifer recharge rate (mm/s) real(r8), pointer :: hkdepth(:) ! decay factor (m) real(r8), pointer :: zwt(:) ! water table depth (m) real(r8), pointer :: zi(:,:) ! interface level below a "z" level (m) ! ! local pointers to original implicit inout arguments ! real(r8), pointer :: h2osoi_liq(:,:) ! liquid water (kg/m2) ! ! local pointer s to original implicit out arguments ! real(r8), pointer :: rootr_col(:,:) ! effective fraction of roots in each soil layer real(r8), pointer :: smp_l(:,:) ! soil matrix potential [mm] real(r8), pointer :: hk_l(:,:) ! hydraulic conductivity (mm/s) ! !EOP ! ! !OTHER LOCAL VARIABLES: ! integer :: p,c,fc,j ! do loop indices integer :: jtop(lbc:ubc) ! top level at each column real(r8) :: dtime ! land model time step (sec) real(r8) :: amx(lbc:ubc,1:nlevsoi+1) ! "a" left off diagonal of tridiagonal matrix real(r8) :: bmx(lbc:ubc,1:nlevsoi+1) ! "b" diagonal column for tridiagonal matrix real(r8) :: cmx(lbc:ubc,1:nlevsoi+1) ! "c" right off diagonal tridiagonal matrix real(r8) :: rmx(lbc:ubc,1:nlevsoi+1) ! "r" forcing term of tridiagonal matrix real(r8) :: zmm(lbc:ubc,1:nlevsoi+1) ! layer depth [mm] real(r8) :: dzmm(lbc:ubc,1:nlevsoi+1) ! layer thickness [mm] real(r8) :: den ! used in calculating qin, qout real(r8) :: dqidw0(lbc:ubc,1:nlevsoi+1) ! d(qin)/d(vol_liq(i-1)) real(r8) :: dqidw1(lbc:ubc,1:nlevsoi+1) ! d(qin)/d(vol_liq(i)) real(r8) :: dqodw1(lbc:ubc,1:nlevsoi+1) ! d(qout)/d(vol_liq(i)) real(r8) :: dqodw2(lbc:ubc,1:nlevsoi+1) ! d(qout)/d(vol_liq(i+1)) real(r8) :: dsmpdw(lbc:ubc,1:nlevsoi+1) ! d(smp)/d(vol_liq) real(r8) :: num ! used in calculating qin, qout real(r8) :: qin(lbc:ubc,1:nlevsoi+1) ! flux of water into soil layer [mm h2o/s] real(r8) :: qout(lbc:ubc,1:nlevsoi+1) ! flux of water out of soil layer [mm h2o/s] real(r8) :: s_node ! soil wetness real(r8) :: s1 ! "s" at interface of layer real(r8) :: s2 ! k*s**(2b+2) real(r8) :: smp(lbc:ubc,1:nlevsoi) ! soil matrix potential [mm] real(r8) :: sdamp ! extrapolates soiwat dependence of evaporation integer :: pi ! pft index real(r8) :: temp(lbc:ubc) ! accumulator for rootr weighting integer :: jwt(lbc:ubc) ! index of the soil layer right above the water table (-) real(r8) :: smp1,dsmpdw1,wh,wh_zwt,ka real(r8) :: dwat2(lbc:ubc,1:nlevsoi+1) real(r8) :: dzq ! used in calculating qin, qout (difference in equilbirium matric potential) real(r8) :: zimm(lbc:ubc,0:nlevsoi) ! layer interface depth [mm] real(r8) :: zq(lbc:ubc,1:nlevsoi+1) ! equilibrium matric potential for each layer [mm] real(r8) :: vol_eq(lbc:ubc,1:nlevsoi+1) ! equilibrium volumetric water content real(r8) :: tempi ! temp variable for calculating vol_eq real(r8) :: temp0 ! temp variable for calculating vol_eq real(r8) :: voleq1 ! temp variable for calculating vol_eq real(r8) :: zwtmm(lbc:ubc) ! water table depth [mm] !----------------------------------------------------------------------- ! Assign local pointers to derived type members (column-level) qcharge => clm3%g%l%c%cws%qcharge hkdepth => clm3%g%l%c%cps%hkdepth zi => clm3%g%l%c%cps%zi zwt => clm3%g%l%c%cws%zwt ctype => clm3%g%l%c%itype npfts => clm3%g%l%c%npfts z => clm3%g%l%c%cps%z dz => clm3%g%l%c%cps%dz smpmin => clm3%g%l%c%cps%smpmin watsat => clm3%g%l%c%cps%watsat hksat => clm3%g%l%c%cps%hksat bsw => clm3%g%l%c%cps%bsw sucsat => clm3%g%l%c%cps%sucsat eff_porosity => clm3%g%l%c%cps%eff_porosity rootr_col => clm3%g%l%c%cps%rootr_column t_soisno => clm3%g%l%c%ces%t_soisno h2osoi_liq => clm3%g%l%c%cws%h2osoi_liq h2osoi_vol => clm3%g%l%c%cws%h2osoi_vol qflx_infl => clm3%g%l%c%cwf%qflx_infl fracice => clm3%g%l%c%cps%fracice qflx_tran_veg_col => clm3%g%l%c%cwf%pwf_a%qflx_tran_veg pfti => clm3%g%l%c%pfti smp_l => clm3%g%l%c%cws%smp_l hk_l => clm3%g%l%c%cws%hk_l ! Assign local pointers to derived type members (pft-level) qflx_tran_veg_pft => clm3%g%l%c%p%pwf%qflx_tran_veg rootr_pft => clm3%g%l%c%p%pps%rootr pwtcol => clm3%g%l%c%p%wtcol pwtgcell => clm3%g%l%c%p%wtgcell ! Get time step dtime = get_step_size() ! Because the depths in this routine are in mm, use local ! variable arrays instead of pointers do j = 1, nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) zmm(c,j) = z(c,j)*1.e3_r8 dzmm(c,j) = dz(c,j)*1.e3_r8 zimm(c,j) = zi(c,j)*1.e3_r8 end do end do do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) zimm(c,0) = 0.0_r8 zwtmm(c) = zwt(c)*1.e3_r8 end do ! First step is to calculate the column-level effective rooting ! fraction in each soil layer. This is done outside the usual ! PFT-to-column averaging routines because it is not a simple ! weighted average of the PFT level rootr arrays. Instead, the ! weighting depends on both the per-unit-area transpiration ! of the PFT and the PFTs area relative to all PFTs. temp(:) = 0._r8 do j = 1, nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) rootr_col(c,j) = 0._r8 end do end do do pi = 1,max_pft_per_col do j = 1,nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if (pi <= npfts(c)) then p = pfti(c) + pi - 1 if (pwtgcell(p)>0._r8) then rootr_col(c,j) = rootr_col(c,j) + rootr_pft(p,j) * qflx_tran_veg_pft(p) * pwtcol(p) end if end if end do end do !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if (pi <= npfts(c)) then p = pfti(c) + pi - 1 if (pwtgcell(p)>0._r8) then temp(c) = temp(c) + qflx_tran_veg_pft(p) * pwtcol(p) end if end if end do end do do j = 1, nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if (temp(c) /= 0._r8) then rootr_col(c,j) = rootr_col(c,j)/temp(c) end if end do end do !compute jwt index ! The layer index of the first unsaturated layer, i.e., the layer right above ! the water table !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) jwt(c) = nlevsoi do j = 2,nlevsoi if(zwt(c) <= zi(c,j)) then jwt(c) = j-1 exit end if enddo end do ! calculate the equilibrium water content based on the water table depth do j=1,nlevsoi do fc=1, num_hydrologyc c = filter_hydrologyc(fc) if ((zwtmm(c) .lt. zimm(c,j-1))) then !fully saturated when wtd is less than the layer top vol_eq(c,j) = watsat(c,j) ! use the weighted average from the saturated part (depth > wtd) and the equilibrium solution for the ! rest of the layer else if ((zwtmm(c) .lt. zimm(c,j)) .and. (zwtmm(c) .gt. zimm(c,j-1))) then tempi = 1.0_r8 temp0 = (((sucsat(c,j)+zwtmm(c)-zimm(c,j-1))/sucsat(c,j)))**(1._r8-1._r8/bsw(c,j)) voleq1 = -sucsat(c,j)*watsat(c,j)/(1._r8-1._r8/bsw(c,j))/(zwtmm(c)-zimm(c,j-1))*(tempi-temp0) vol_eq(c,j) = (voleq1*(zwtmm(c)-zimm(c,j-1)) + watsat(c,j)*(zimm(c,j)-zwtmm(c)))/(zimm(c,j)-zimm(c,j-1)) vol_eq(c,j) = min(watsat(c,j),vol_eq(c,j)) vol_eq(c,j) = max(vol_eq(c,j),0.0_r8) else tempi = (((sucsat(c,j)+zwtmm(c)-zimm(c,j))/sucsat(c,j)))**(1._r8-1._r8/bsw(c,j)) temp0 = (((sucsat(c,j)+zwtmm(c)-zimm(c,j-1))/sucsat(c,j)))**(1._r8-1._r8/bsw(c,j)) vol_eq(c,j) = -sucsat(c,j)*watsat(c,j)/(1._r8-1._r8/bsw(c,j))/(zimm(c,j)-zimm(c,j-1))*(tempi-temp0) vol_eq(c,j) = max(vol_eq(c,j),0.0_r8) vol_eq(c,j) = min(watsat(c,j),vol_eq(c,j)) endif zq(c,j) = -sucsat(c,j)*(max(vol_eq(c,j)/watsat(c,j),0.01_r8))**(-bsw(c,j)) zq(c,j) = max(smpmin(c), zq(c,j)) end do end do ! If water table is below soil column calculate zq for the 11th layer j = nlevsoi do fc=1, num_hydrologyc c = filter_hydrologyc(fc) if(jwt(c) == nlevsoi) then tempi = 1._r8 temp0 = (((sucsat(c,j)+zwtmm(c)-zimm(c,j))/sucsat(c,j)))**(1._r8-1._r8/bsw(c,j)) vol_eq(c,j+1) = -sucsat(c,j)*watsat(c,j)/(1._r8-1._r8/bsw(c,j))/(zwtmm(c)-zimm(c,j))*(tempi-temp0) vol_eq(c,j+1) = max(vol_eq(c,j+1),0.0_r8) vol_eq(c,j+1) = min(watsat(c,j),vol_eq(c,j+1)) zq(c,j+1) = -sucsat(c,j)*(max(vol_eq(c,j+1)/watsat(c,j),0.01_r8))**(-bsw(c,j)) zq(c,j+1) = max(smpmin(c), zq(c,j+1)) end if end do ! Hydraulic conductivity and soil matric potential and their derivatives sdamp = 0._r8 do j = 1, nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) s1 = 0.5_r8*(h2osoi_vol(c,j) + h2osoi_vol(c,min(nlevsoi, j+1))) / & (0.5_r8*(watsat(c,j)+watsat(c,min(nlevsoi, j+1)))) s1 = min(1._r8, s1) s2 = hksat(c,j)*s1**(2._r8*bsw(c,j)+2._r8) hk(c,j) = (1._r8-0.5_r8*(fracice(c,j)+fracice(c,min(nlevsoi, j+1))))*s1*s2 dhkdw(c,j) = (1._r8-0.5_r8*(fracice(c,j)+fracice(c,min(nlevsoi, j+1))))* & (2._r8*bsw(c,j)+3._r8)*s2*0.5_r8/watsat(c,j) s_node = max(h2osoi_vol(c,j)/watsat(c,j), 0.01_r8) s_node = min(1.0_r8, s_node) smp(c,j) = -sucsat(c,j)*s_node**(-bsw(c,j)) smp(c,j) = max(smpmin(c), smp(c,j)) dsmpdw(c,j) = -bsw(c,j)*smp(c,j)/(s_node*watsat(c,j)) smp_l(c,j) = smp(c,j) hk_l(c,j) = hk(c,j) end do end do ! aquifer (11th) layer !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) zmm(c,nlevsoi+1) = 0.5*(1.e3_r8*zwt(c) + zmm(c,nlevsoi)) if(jwt(c) < nlevsoi) then dzmm(c,nlevsoi+1) = dzmm(c,nlevsoi) else dzmm(c,nlevsoi+1) = (1.e3_r8*zwt(c) - zmm(c,nlevsoi)) end if end do ! Set up r, a, b, and c vectors for tridiagonal solution ! Node j=1 (top) j = 1 !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) qin(c,j) = qflx_infl(c) den = (zmm(c,j+1)-zmm(c,j)) dzq = (zq(c,j+1)-zq(c,j)) num = (smp(c,j+1)-smp(c,j)) - dzq qout(c,j) = -hk(c,j)*num/den dqodw1(c,j) = -(-hk(c,j)*dsmpdw(c,j) + num*dhkdw(c,j))/den dqodw2(c,j) = -( hk(c,j)*dsmpdw(c,j+1) + num*dhkdw(c,j))/den rmx(c,j) = qin(c,j) - qout(c,j) - qflx_tran_veg_col(c) * rootr_col(c,j) amx(c,j) = 0._r8 bmx(c,j) = dzmm(c,j)*(sdamp+1._r8/dtime) + dqodw1(c,j) cmx(c,j) = dqodw2(c,j) end do ! Nodes j=2 to j=nlevsoi-1 do j = 2, nlevsoi - 1 !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) den = (zmm(c,j) - zmm(c,j-1)) dzq = (zq(c,j)-zq(c,j-1)) num = (smp(c,j)-smp(c,j-1)) - dzq qin(c,j) = -hk(c,j-1)*num/den dqidw0(c,j) = -(-hk(c,j-1)*dsmpdw(c,j-1) + num*dhkdw(c,j-1))/den dqidw1(c,j) = -( hk(c,j-1)*dsmpdw(c,j) + num*dhkdw(c,j-1))/den den = (zmm(c,j+1)-zmm(c,j)) dzq = (zq(c,j+1)-zq(c,j)) num = (smp(c,j+1)-smp(c,j)) - dzq qout(c,j) = -hk(c,j)*num/den dqodw1(c,j) = -(-hk(c,j)*dsmpdw(c,j) + num*dhkdw(c,j))/den dqodw2(c,j) = -( hk(c,j)*dsmpdw(c,j+1) + num*dhkdw(c,j))/den rmx(c,j) = qin(c,j) - qout(c,j) - qflx_tran_veg_col(c)*rootr_col(c,j) amx(c,j) = -dqidw0(c,j) bmx(c,j) = dzmm(c,j)/dtime - dqidw1(c,j) + dqodw1(c,j) cmx(c,j) = dqodw2(c,j) end do end do ! Node j=nlevsoi (bottom) j = nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if(j > jwt(c)) then !water table is in soil column den = (zmm(c,j) - zmm(c,j-1)) dzq = (zq(c,j)-zq(c,j-1)) num = (smp(c,j)-smp(c,j-1)) - dzq qin(c,j) = -hk(c,j-1)*num/den dqidw0(c,j) = -(-hk(c,j-1)*dsmpdw(c,j-1) + num*dhkdw(c,j-1))/den dqidw1(c,j) = -( hk(c,j-1)*dsmpdw(c,j) + num*dhkdw(c,j-1))/den qout(c,j) = 0._r8 dqodw1(c,j) = 0._r8 rmx(c,j) = qin(c,j) - qout(c,j) - qflx_tran_veg_col(c)*rootr_col(c,j) amx(c,j) = -dqidw0(c,j) bmx(c,j) = dzmm(c,j)/dtime - dqidw1(c,j) + dqodw1(c,j) cmx(c,j) = 0._r8 !scs: next set up aquifer layer; hydrologically inactive rmx(c,j+1) = 0._r8 amx(c,j+1) = 0._r8 bmx(c,j+1) = dzmm(c,j+1)/dtime cmx(c,j+1) = 0._r8 else ! water table is below soil column !scs: compute aquifer soil moisture as average of layer 10 and saturation s_node = max(0.5*(1.0_r8+h2osoi_vol(c,j)/watsat(c,j)), 0.01_r8) s_node = min(1.0_r8, s_node) !scs: compute smp for aquifer layer smp1 = -sucsat(c,j)*s_node**(-bsw(c,j)) smp1 = max(smpmin(c), smp1) !scs: compute dsmpdw for aquifer layer dsmpdw1 = -bsw(c,j)*smp1/(s_node*watsat(c,j)) !scs: first set up bottom layer of soil column den = (zmm(c,j) - zmm(c,j-1)) dzq = (zq(c,j)-zq(c,j-1)) num = (smp(c,j)-smp(c,j-1)) - dzq qin(c,j) = -hk(c,j-1)*num/den dqidw0(c,j) = -(-hk(c,j-1)*dsmpdw(c,j-1) + num*dhkdw(c,j-1))/den dqidw1(c,j) = -( hk(c,j-1)*dsmpdw(c,j) + num*dhkdw(c,j-1))/den den = (zmm(c,j+1)-zmm(c,j)) dzq = (zq(c,j+1)-zq(c,j)) num = (smp1-smp(c,j)) - dzq qout(c,j) = -hk(c,j)*num/den dqodw1(c,j) = -(-hk(c,j)*dsmpdw(c,j) + num*dhkdw(c,j))/den dqodw2(c,j) = -( hk(c,j)*dsmpdw1 + num*dhkdw(c,j))/den rmx(c,j) = qin(c,j) - qout(c,j) - qflx_tran_veg_col(c)*rootr_col(c,j) amx(c,j) = -dqidw0(c,j) bmx(c,j) = dzmm(c,j)/dtime - dqidw1(c,j) + dqodw1(c,j) cmx(c,j) = dqodw2(c,j) !scs: next set up aquifer layer; den/num unchanged, qin=qout qin(c,j+1) = qout(c,j) dqidw0(c,j+1) = -(-hk(c,j)*dsmpdw(c,j) + num*dhkdw(c,j))/den dqidw1(c,j+1) = -( hk(c,j)*dsmpdw1 + num*dhkdw(c,j))/den qout(c,j+1) = 0._r8 ! zero-flow bottom boundary condition dqodw1(c,j+1) = 0._r8 ! zero-flow bottom boundary condition rmx(c,j+1) = qin(c,j+1) - qout(c,j+1) amx(c,j+1) = -dqidw0(c,j+1) bmx(c,j+1) = dzmm(c,j+1)/dtime - dqidw1(c,j+1) + dqodw1(c,j+1) cmx(c,j+1) = 0._r8 endif end do ! Solve for dwat jtop(:) = 1 call Tridiagonal(lbc, ubc, 1, nlevsoi+1, jtop, num_hydrologyc, filter_hydrologyc, & amx, bmx, cmx, rmx, dwat2 ) !scs: set dwat do fc = 1,num_hydrologyc c = filter_hydrologyc(fc) do j = 1, nlevsoi dwat(c,j)=dwat2(c,j) end do end do ! Renew the mass of liquid water !scs: also compute qcharge from dwat in aquifer layer !scs: update in drainage for case jwt < nlevsoi !dir$ concurrent !cdir nodep do fc = 1,num_hydrologyc c = filter_hydrologyc(fc) do j = 1, nlevsoi h2osoi_liq(c,j) = h2osoi_liq(c,j) + dwat2(c,j)*dzmm(c,j) end do !scs: calculate qcharge for case jwt < nlevsoi if(jwt(c) < nlevsoi) then wh_zwt = 0._r8 !since wh_zwt = -sucsat - zq_zwt, where zq_zwt = -sucsat s_node = max(h2osoi_vol(c,jwt(c))/watsat(c,jwt(c)), 0.01_r8) s_node = min(1.0_r8, s_node) !scs: use average moisture between water table and layer jwt s1 = 0.5_r8*(1.0+s_node) s1 = min(1._r8, s1) !scs: this is the expression for unsaturated hk ka = hksat(c,jwt(c))*s1**(2._r8*bsw(c,jwt(c))+3._r8) ! Recharge rate qcharge to groundwater (positive to aquifer) smp1 = -sucsat(c,jwt(c))*s_node**(-bsw(c,jwt(c))) smp1 = max(smpmin(c), smp(c,jwt(c))) wh = smp1 - zq(c,jwt(c)) qcharge(c) = -ka * (wh_zwt-wh) /((zwt(c)-z(c,jwt(c)))*1000._r8) ! To limit qcharge (for the first several timesteps) qcharge(c) = max(-10.0_r8/dtime,qcharge(c)) qcharge(c) = min( 10.0_r8/dtime,qcharge(c)) else !scs: if water table is below soil column, compute qcharge from dwat2(11) qcharge(c) = dwat2(c,nlevsoi+1)*dzmm(c,nlevsoi+1)/dtime endif end do end subroutine SoilWater !----------------------------------------------------------------------- !BOP ! ! !IROUTINE: Drainage ! ! !INTERFACE: subroutine Drainage(lbc, ubc, num_hydrologyc, filter_hydrologyc, & 1,6 num_urbanc, filter_urbanc, vol_liq, hk, & icefrac) ! ! !DESCRIPTION: ! Calculate subsurface drainage ! ! !USES: use shr_kind_mod, only : r8 => shr_kind_r8 use clmtype use clm_time_manager, only : get_step_size use clm_varcon , only : pondmx, tfrz, icol_roof, icol_road_imperv, icol_road_perv, watmin use clm_varpar , only : nlevsoi ! ! !ARGUMENTS: implicit none integer , intent(in) :: lbc, ubc ! column bounds integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter integer , intent(in) :: num_urbanc ! number of column urban points in column filter integer , intent(in) :: filter_urbanc(ubc-lbc+1) ! column filter for urban points integer , intent(in) :: filter_hydrologyc(ubc-lbc+1) ! column filter for soil points real(r8), intent(in) :: vol_liq(lbc:ubc,1:nlevsoi) ! partial volume of liquid water in layer real(r8), intent(in) :: hk(lbc:ubc,1:nlevsoi) ! hydraulic conductivity (mm h2o/s) real(r8), intent(in) :: icefrac(lbc:ubc,1:nlevsoi) ! fraction of ice in layer ! ! !CALLED FROM: ! ! !REVISION HISTORY: ! 15 September 1999: Yongjiu Dai; Initial code ! 12 November 1999: Z.-L. Yang and G.-Y. Niu ! 15 December 1999: Paul Houser and Jon Radakovich; F90 Revision ! 4/26/05, Peter Thornton and David Lawrence: Turned off drainage from ! middle soil layers for both wet and dry fractions. ! 04/25/07 Keith Oleson: Completely new routine for CLM3.5 hydrology ! 27 February 2008: Keith Oleson; Saturation excess modification ! ! !LOCAL VARIABLES: ! ! local pointers to original implicit in arguments ! integer , pointer :: ctype(:) !column type index integer , pointer :: snl(:) !number of snow layers real(r8), pointer :: qflx_snwcp_liq(:) !excess rainfall due to snow capping (mm H2O /s) [+] real(r8), pointer :: qflx_dew_grnd(:) !ground surface dew formation (mm H2O /s) [+] real(r8), pointer :: qflx_dew_snow(:) !surface dew added to snow pack (mm H2O /s) [+] real(r8), pointer :: qflx_sub_snow(:) !sublimation rate from snow pack (mm H2O /s) [+] real(r8), pointer :: dz(:,:) !layer depth (m) real(r8), pointer :: bsw(:,:) !Clapp and Hornberger "b" real(r8), pointer :: eff_porosity(:,:) !effective porosity = porosity - vol_ice real(r8), pointer :: t_soisno(:,:) !soil temperature (Kelvin) real(r8), pointer :: hksat(:,:) !hydraulic conductivity at saturation (mm H2O /s) real(r8), pointer :: sucsat(:,:) !minimum soil suction (mm) real(r8), pointer :: z(:,:) !layer depth (m) real(r8), pointer :: zi(:,:) !interface level below a "z" level (m) real(r8), pointer :: watsat(:,:) !volumetric soil water at saturation (porosity) real(r8), pointer :: hkdepth(:) !decay factor (m) real(r8), pointer :: zwt(:) !water table depth (m) real(r8), pointer :: wa(:) !water in the unconfined aquifer (mm) real(r8), pointer :: wt(:) !total water storage (unsaturated soil water + groundwater) (mm) real(r8), pointer :: qcharge(:) !aquifer recharge rate (mm/s) ! ! local pointers to original implicit inout arguments ! real(r8), pointer :: h2osoi_ice(:,:) !ice lens (kg/m2) real(r8), pointer :: h2osoi_liq(:,:) !liquid water (kg/m2) ! ! local pointers to original implicit out arguments ! real(r8), pointer :: qflx_drain(:) !sub-surface runoff (mm H2O /s) real(r8), pointer :: qflx_qrgwl(:) !qflx_surf at glaciers, wetlands, lakes (mm H2O /s) real(r8), pointer :: eflx_impsoil(:) !implicit evaporation for soil temperature equation real(r8), pointer :: qflx_rsub_sat(:) !soil saturation excess [mm h2o/s] ! !EOP ! ! !OTHER LOCAL VARIABLES: ! !KO integer :: c,j,fc !indices !KO integer :: c,j,fc,i !indices !KO real(r8) :: dtime !land model time step (sec) real(r8) :: xs(lbc:ubc) !water needed to bring soil moisture to watmin (mm) real(r8) :: dzmm(lbc:ubc,1:nlevsoi) !layer thickness (mm) integer :: jwt(lbc:ubc) !index of the soil layer right above the water table (-) real(r8) :: rsub_bot(lbc:ubc) !subsurface runoff - bottom drainage (mm/s) real(r8) :: rsub_top(lbc:ubc) !subsurface runoff - topographic control (mm/s) real(r8) :: fff(lbc:ubc) !decay factor (m-1) real(r8) :: xsi(lbc:ubc) !excess soil water above saturation at layer i (mm) real(r8) :: xsia(lbc:ubc) !available pore space at layer i (mm) real(r8) :: xs1(lbc:ubc) !excess soil water above saturation at layer 1 (mm) real(r8) :: smpfz(1:nlevsoi) !matric potential of layer right above water table (mm) real(r8) :: wtsub !summation of hk*dzmm for layers below water table (mm**2/s) real(r8) :: rous !aquifer yield (-) real(r8) :: wh !smpfz(jwt)-z(jwt) (mm) real(r8) :: wh_zwt !water head at the water table depth (mm) real(r8) :: ws !summation of pore space of layers below water table (mm) real(r8) :: s_node !soil wetness (-) real(r8) :: dzsum !summation of dzmm of layers below water table (mm) real(r8) :: icefracsum !summation of icefrac*dzmm of layers below water table (-) real(r8) :: fracice_rsub(lbc:ubc) !fractional impermeability of soil layers (-) real(r8) :: ka !hydraulic conductivity of the aquifer (mm/s) real(r8) :: dza !fff*(zwt-z(jwt)) (-) !KO real(r8) :: available_h2osoi_liq !available soil liquid water in a layer !KO !----------------------------------------------------------------------- ! Assign local pointers to derived subtypes components (column-level) ctype => clm3%g%l%c%itype ! cgridcell => clm3%g%l%c%gridcell snl => clm3%g%l%c%cps%snl dz => clm3%g%l%c%cps%dz bsw => clm3%g%l%c%cps%bsw t_soisno => clm3%g%l%c%ces%t_soisno hksat => clm3%g%l%c%cps%hksat sucsat => clm3%g%l%c%cps%sucsat z => clm3%g%l%c%cps%z zi => clm3%g%l%c%cps%zi watsat => clm3%g%l%c%cps%watsat hkdepth => clm3%g%l%c%cps%hkdepth zwt => clm3%g%l%c%cws%zwt wa => clm3%g%l%c%cws%wa wt => clm3%g%l%c%cws%wt qcharge => clm3%g%l%c%cws%qcharge eff_porosity => clm3%g%l%c%cps%eff_porosity qflx_snwcp_liq => clm3%g%l%c%cwf%pwf_a%qflx_snwcp_liq qflx_dew_grnd => clm3%g%l%c%cwf%pwf_a%qflx_dew_grnd qflx_dew_snow => clm3%g%l%c%cwf%pwf_a%qflx_dew_snow qflx_sub_snow => clm3%g%l%c%cwf%pwf_a%qflx_sub_snow qflx_drain => clm3%g%l%c%cwf%qflx_drain qflx_qrgwl => clm3%g%l%c%cwf%qflx_qrgwl qflx_rsub_sat => clm3%g%l%c%cwf%qflx_rsub_sat eflx_impsoil => clm3%g%l%c%cef%eflx_impsoil h2osoi_liq => clm3%g%l%c%cws%h2osoi_liq h2osoi_ice => clm3%g%l%c%cws%h2osoi_ice ! Get time step dtime = get_step_size() ! Convert layer thicknesses from m to mm do j = 1,nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) dzmm(c,j) = dz(c,j)*1.e3_r8 end do end do ! Initial set !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) qflx_drain(c) = 0._r8 rsub_bot(c) = 0._r8 qflx_rsub_sat(c) = 0._r8 rsub_top(c) = 0._r8 fracice_rsub(c) = 0._r8 end do ! The layer index of the first unsaturated layer, i.e., the layer right above ! the water table !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) jwt(c) = nlevsoi do j = 2,nlevsoi if(zwt(c) <= zi(c,j)) then jwt(c) = j-1 exit end if enddo end do ! Topographic runoff !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) fff(c) = 1._r8/ hkdepth(c) dzsum = 0._r8 icefracsum = 0._r8 do j = jwt(c), nlevsoi dzsum = dzsum + dzmm(c,j) icefracsum = icefracsum + icefrac(c,j) * dzmm(c,j) end do fracice_rsub(c) = max(0._r8,exp(-3._r8*(1._r8-(icefracsum/dzsum)))- exp(-3._r8))/(1.0_r8-exp(-3._r8)) rsub_top(c) = (1._r8 - fracice_rsub(c)) * 5.5e-3_r8 * exp(-fff(c)*zwt(c)) end do rous = 0.2_r8 ! Water table calculation !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! Water storage in aquifer + soil wt(c) = wt(c) + (qcharge(c) - rsub_top(c)) * dtime if(jwt(c) == nlevsoi) then ! water table is below the soil column wa(c) = wa(c) + (qcharge(c) -rsub_top(c)) * dtime wt(c) = wa(c) zwt(c) = (zi(c,nlevsoi) + 25._r8) - wa(c)/1000._r8/rous h2osoi_liq(c,nlevsoi) = h2osoi_liq(c,nlevsoi) + max(0._r8,(wa(c)-5000._r8)) wa(c) = min(wa(c), 5000._r8) else ! water table within soil layers if (jwt(c) == nlevsoi-1) then ! water table within bottom soil layer zwt(c) = zi(c,nlevsoi)- (wt(c)-rous*1000._r8*25._r8) /eff_porosity(c,nlevsoi)/1000._r8 else ! water table within soil layers 1-9 ws = 0._r8 ! water used to fill soil air pores regardless of water content do j = jwt(c)+2,nlevsoi ws = ws + eff_porosity(c,j) * 1000._r8 * dz(c,j) enddo zwt(c) = zi(c,jwt(c)+1)-(wt(c)-rous*1000_r8*25._r8-ws) /eff_porosity(c,jwt(c)+1)/1000._r8 endif wtsub = 0._r8 do j = jwt(c)+1, nlevsoi wtsub = wtsub + hk(c,j)*dzmm(c,j) end do ! Remove subsurface runoff do j = jwt(c)+1, nlevsoi h2osoi_liq(c,j) = h2osoi_liq(c,j) - rsub_top(c)*dtime*hk(c,j)*dzmm(c,j)/wtsub end do end if zwt(c) = max(0.05_r8,zwt(c)) zwt(c) = min(80._r8,zwt(c)) end do ! excessive water above saturation added to the above unsaturated layer like a bucket ! if column fully saturated, excess water goes to runoff do j = nlevsoi,2,-1 !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) xsi(c) = max(h2osoi_liq(c,j)-eff_porosity(c,j)*dzmm(c,j),0._r8) h2osoi_liq(c,j) = min(eff_porosity(c,j)*dzmm(c,j), h2osoi_liq(c,j)) h2osoi_liq(c,j-1) = h2osoi_liq(c,j-1) + xsi(c) end do end do !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) xs1(c) = max(max(h2osoi_liq(c,1),0._r8)-max(0._r8,(pondmx+watsat(c,1)*dzmm(c,1)-h2osoi_ice(c,1))),0._r8) h2osoi_liq(c,1) = min(max(0._r8,pondmx+watsat(c,1)*dzmm(c,1)-h2osoi_ice(c,1)), h2osoi_liq(c,1)) qflx_rsub_sat(c) = xs1(c) / dtime end do ! Limit h2osoi_liq to be greater than or equal to watmin. ! Get water needed to bring h2osoi_liq equal watmin from lower layer. ! If insufficient water in soil layers, get from aquifer water do j = 1, nlevsoi-1 !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) !KO if (h2osoi_liq(c,j) < 0._r8) then !KO if (h2osoi_liq(c,j) < watmin) then !KO xs(c) = watmin - h2osoi_liq(c,j) else xs(c) = 0._r8 end if h2osoi_liq(c,j ) = h2osoi_liq(c,j ) + xs(c) h2osoi_liq(c,j+1) = h2osoi_liq(c,j+1) - xs(c) end do end do !KO j = nlevsoi !KO!dir$ concurrent !KO!cdir nodep !KO do fc = 1, num_hydrologyc !KO c = filter_hydrologyc(fc) !KO if (h2osoi_liq(c,j) < watmin) then !KO xs(c) = watmin-h2osoi_liq(c,j) !KO else !KO xs(c) = 0._r8 !KO end if !KO h2osoi_liq(c,j) = h2osoi_liq(c,j) + xs(c) !KO wa(c) = wa(c) - xs(c) !KO wt(c) = wt(c) - xs(c) !KO end do !KO ! Get water for bottom layer from layers above if possible j = nlevsoi !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) if (h2osoi_liq(c,j) < watmin) then xs(c) = watmin-h2osoi_liq(c,j) searchforwater: do i = nlevsoi-1, 1, -1 available_h2osoi_liq = max(h2osoi_liq(c,i)-watmin-xs(c),0._r8) if (available_h2osoi_liq .ge. xs(c)) then h2osoi_liq(c,j) = h2osoi_liq(c,j) + xs(c) h2osoi_liq(c,i) = h2osoi_liq(c,i) - xs(c) xs(c) = 0._r8 exit searchforwater else h2osoi_liq(c,j) = h2osoi_liq(c,j) + available_h2osoi_liq h2osoi_liq(c,i) = h2osoi_liq(c,i) - available_h2osoi_liq xs(c) = xs(c) - available_h2osoi_liq end if end do searchforwater else xs(c) = 0._r8 end if ! Needed in case there is no water to be found h2osoi_liq(c,j) = h2osoi_liq(c,j) + xs(c) wt(c) = wt(c) - xs(c) ! Instead of removing water from aquifer where it eventually ! shows up as excess drainage to the ocean, take it back out of ! drainage rsub_top(c) = rsub_top(c) - xs(c)/dtime end do !KO !dir$ concurrent !cdir nodep do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! Sub-surface runoff and drainage qflx_drain(c) = qflx_rsub_sat(c) + rsub_top(c) ! Set imbalance for snow capping qflx_qrgwl(c) = qflx_snwcp_liq(c) ! Implicit evaporation term is now zero eflx_impsoil(c) = 0._r8 ! Renew the ice and liquid mass due to condensation if (snl(c)+1 >= 1) then h2osoi_liq(c,1) = h2osoi_liq(c,1) + qflx_dew_grnd(c) * dtime h2osoi_ice(c,1) = h2osoi_ice(c,1) + (qflx_dew_snow(c) * dtime) if (qflx_sub_snow(c)*dtime > h2osoi_ice(c,1)) then qflx_sub_snow(c) = h2osoi_ice(c,1)/dtime h2osoi_ice(c,1) = 0._r8 else h2osoi_ice(c,1) = h2osoi_ice(c,1) - (qflx_sub_snow(c) * dtime) end if end if end do ! No drainage for urban columns (except for pervious road as computed above) !dir$ concurrent !cdir nodep do fc = 1, num_urbanc c = filter_urbanc(fc) if (ctype(c) /= icol_road_perv) then qflx_drain(c) = 0._r8 ! This must be done for roofs and impervious road (walls will be zero) qflx_qrgwl(c) = qflx_snwcp_liq(c) eflx_impsoil(c) = 0._r8 end if ! Renew the ice and liquid mass due to condensation for urban roof and impervious road if (ctype(c) == icol_roof .or. ctype(c) == icol_road_imperv) then if (snl(c)+1 >= 1) then h2osoi_liq(c,1) = h2osoi_liq(c,1) + qflx_dew_grnd(c) * dtime h2osoi_ice(c,1) = h2osoi_ice(c,1) + (qflx_dew_snow(c) * dtime) if (qflx_sub_snow(c)*dtime > h2osoi_ice(c,1)) then qflx_sub_snow(c) = h2osoi_ice(c,1)/dtime h2osoi_ice(c,1) = 0._r8 else h2osoi_ice(c,1) = h2osoi_ice(c,1) - (qflx_sub_snow(c) * dtime) end if end if end if end do end subroutine Drainage end module SoilHydrologyMod