! SUMMA - Structure for Unifying Multiple Modeling Alternatives ! Copyright (C) 2014-2020 NCAR/RAL; University of Saskatchewan; University of Washington ! ! This file is part of SUMMA ! ! For more information see: http://www.ral.ucar.edu/projects/summa ! ! This program is free software: you can redistribute it and/or modify ! it under the terms of the GNU General Public License as published by ! the Free Software Foundation, either version 3 of the License, or ! (at your option) any later version. ! ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! GNU General Public License for more details. ! ! You should have received a copy of the GNU General Public License ! along with this program. If not, see <http://www.gnu.org/licenses/>. module groundwatr_module ! data types USE nrtype ! model constants USE multiconst,only:iden_water ! density of water (kg m-3) ! derived types to define the data structures USE data_types,only:& var_d, & ! data vector (dp) var_dlength ! data vector with variable length dimension (dp) ! named variables defining elements in the data structures USE var_lookup,only:iLookATTR ! named variables for structure elements USE var_lookup,only:iLookPROG ! named variables for structure elements USE var_lookup,only:iLookDIAG ! named variables for structure elements USE var_lookup,only:iLookFLUX ! named variables for structure elements USE var_lookup,only:iLookPARAM ! named variables for structure elements ! look-up values for the choice of groundwater parameterization USE mDecisions_module,only: & qbaseTopmodel, & ! TOPMODEL-ish baseflow parameterization bigBucket, & ! a big bucket (lumped aquifer model) noExplicit ! no explicit groundwater parameterization ! privacy implicit none ! constant parameters real(dp),parameter :: valueMissing=-9999._dp ! missing value parameter real(dp),parameter :: verySmall=epsilon(1.0_dp) ! a very small number (used to avoid divide by zero) real(dp),parameter :: dx=1.e-8_dp ! finite difference increment private public::groundwatr contains ! ************************************************************************************************ ! public subroutine groundwatr: compute the groundwater sink term in Richards' equation ! ************************************************************************************************ ! ! Method ! ------ ! ! Here we assume that water avaialble for shallow groundwater flow includes is all water above ! "field capacity" below the depth zCrit, where zCrit is defined as the lowest point in the soil ! profile where the volumetric liquid water content is less than field capacity. ! ! We further assume that transmssivity (m2 s-1) for each layer is defined asuming that the water ! available for saturated flow is located at the bottom of the soil profile. Specifically: ! trTotal(iLayer) = tran0*(zActive(iLayer)/soilDepth)**zScale_TOPMODEL ! trSoil(iLayer) = trTotal(iLayer) - trTotal(iLayer+1) ! where zActive(iLayer) is the effective water table thickness for all layers up to and including ! the current layer (working from the bottom to the top). ! ! The outflow from each layer is then (m3 s-1) ! mLayerOutflow(iLayer) = trSoil(iLayer)*tan_slope*contourLength ! where contourLength is the width of a hillslope (m) parallel to a stream ! ! ************************************************************************************************ subroutine groundwatr(& ! input: model control nSnow, & ! intent(in): number of snow layers nSoil, & ! intent(in): number of soil layers nLayers, & ! intent(in): total number of layers getSatDepth, & ! intent(in): logical flag to compute index of the lowest saturated layer ! input: state and diagnostic variables mLayerdTheta_dPsi, & ! intent(in): derivative in the soil water characteristic w.r.t. matric head in each layer (m-1) mLayerMatricHeadLiq, & ! intent(in): liquid water matric potential (m) mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water (-) mLayerVolFracIce, & ! intent(in): volumetric fraction of ice (-) ! input/output: data structures attr_data, & ! intent(in): spatial attributes mpar_data, & ! intent(in): model parameters prog_data, & ! intent(in): model prognostic variables for a local HRU diag_data, & ! intent(in): model diagnostic variables for a local HRU flux_data, & ! intent(inout): model fluxes for a local HRU ! output: baseflow ixSaturation, & ! intent(inout) index of lowest saturated layer (NOTE: only computed on the first iteration) mLayerBaseflow, & ! intent(out): baseflow from each soil layer (m s-1) dBaseflow_dMatric, & ! intent(out): derivative in baseflow w.r.t. matric head (s-1) ! output: error control err,message) ! intent(out): error control ! --------------------------------------------------------------------------------------- ! utility modules USE soil_utils_module,only:volFracLiq ! compute volumetric fraction of liquid water as a function of matric head USE soil_utils_module,only:hydCond_psi ! compute hydraulic conductivity as a function of matric head implicit none ! --------------------------------------------------------------------------------------- ! * dummy variables ! --------------------------------------------------------------------------------------- ! input: model control integer(i4b),intent(in) :: nSnow ! number of snow layers integer(i4b),intent(in) :: nSoil ! number of soil layers integer(i4b),intent(in) :: nLayers ! total number of layers logical(lgt),intent(in) :: getSatDepth ! logical flag to compute index of the lowest saturated layer ! input: state and diagnostic variables real(dp),intent(in) :: mLayerdTheta_dPsi(:) ! derivative in the soil water characteristic w.r.t. matric head in each layer (m-1) real(dp),intent(in) :: mLayerMatricHeadLiq(:) ! matric head in each layer at the current iteration (m) real(dp),intent(in) :: mLayerVolFracLiq(:) ! volumetric fraction of liquid water (-) real(dp),intent(in) :: mLayerVolFracIce(:) ! volumetric fraction of ice (-) ! input/output: data structures type(var_d),intent(in) :: attr_data ! spatial attributes type(var_dlength),intent(in) :: mpar_data ! model parameters type(var_dlength),intent(in) :: prog_data ! prognostic variables for a local HRU type(var_dlength),intent(in) :: diag_data ! diagnostic variables for a local HRU type(var_dlength),intent(inout) :: flux_data ! model fluxes for a local HRU ! output: baseflow integer(i4b),intent(inout) :: ixSaturation ! index of lowest saturated layer (NOTE: only computed on the first iteration) real(dp),intent(out) :: mLayerBaseflow(:) ! baseflow from each soil layer (m s-1) real(dp),intent(out) :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1) ! output: error control integer(i4b),intent(out) :: err ! error code character(*),intent(out) :: message ! error message ! --------------------------------------------------------------------------------------- ! * local variables ! --------------------------------------------------------------------------------------- ! general local variables integer(i4b) :: iLayer ! index of soil layer real(dp),dimension(nSoil,nSoil) :: dBaseflow_dVolLiq ! derivative in the baseflow flux w.r.t. volumetric liquid water content (m s-1) ! local variables to compute the numerical Jacobian logical(lgt),parameter :: doNumericalJacobian=.false. ! flag to compute the numerical Jacobian real(dp),dimension(nSoil) :: mLayerMatricHeadPerturbed ! perturbed matric head (m) real(dp),dimension(nSoil) :: mLayerVolFracLiqPerturbed ! perturbed volumetric fraction of liquid water (-) real(dp),dimension(nSoil) :: mLayerBaseflowPerturbed ! perturbed baseflow (m s-1) real(dp),dimension(nSoil,nSoil) :: nJac ! numerical Jacobian (s-1) ! *************************************************************************************** ! *************************************************************************************** ! initialize error control err=0; message='groundwatr/' ! --------------------------------------------------------------------------------------- ! --------------------------------------------------------------------------------------- ! associate variables in data structures associate(& ! input: baseflow parameters fieldCapacity => mpar_data%var(iLookPARAM%fieldCapacity)%dat(1), & ! intent(in): [dp] field capacity (-) theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat, & ! intent(in): [dp] soil porosity (-) theta_res => mpar_data%var(iLookPARAM%theta_res)%dat, & ! intent(in): [dp] residual volumetric water content (-) ! input: van Genuchten soil parametrers vGn_alpha => mpar_data%var(iLookPARAM%vGn_alpha)%dat, & ! intent(in): [dp] van Genutchen "alpha" parameter (m-1) vGn_n => mpar_data%var(iLookPARAM%vGn_n)%dat, & ! intent(in): [dp] van Genutchen "n" parameter (-) vGn_m => diag_data%var(iLookDIAG%scalarVGn_m)%dat, & ! intent(in): [dp] van Genutchen "m" parameter (-) ! output: diagnostic variables scalarExfiltration => flux_data%var(iLookFLUX%scalarExfiltration)%dat(1), & ! intent(out):[dp] exfiltration from the soil profile (m s-1) mLayerColumnOutflow => flux_data%var(iLookFLUX%mLayerColumnOutflow)%dat & ! intent(out):[dp(:)] column outflow from each soil layer (m3 s-1) ) ! end association to variables in data structures ! ************************************************************************************************ ! (1) compute the "active" portion of the soil profile ! ************************************************************************************************ ! get index of the lowest saturated layer if(getSatDepth)then ! NOTE: only compute for the first flux call ixSaturation = nSoil+1 ! unsaturated profile when ixSaturation>nSoil do iLayer=nSoil,1,-1 ! start at the lowest soil layer and work upwards to the top layer if(mLayerVolFracLiq(iLayer) > fieldCapacity)then; ixSaturation = iLayer ! index of saturated layer -- keeps getting over-written as move upwards else; exit; end if ! (only consider saturated layer at the bottom of the soil profile) end do ! (looping through soil layers) end if ! check for an early return (no layers are "active") if(ixSaturation > nSoil)then scalarExfiltration = 0._dp ! exfiltration from the soil profile (m s-1) mLayerColumnOutflow(:) = 0._dp ! column outflow from each soil layer (m3 s-1) mLayerBaseflow(:) = 0._dp ! baseflow from each soil layer (m s-1) dBaseflow_dMatric(:,:) = 0._dp ! derivative in baseflow w.r.t. matric head (s-1) return end if ! if some layers are saturated ! ************************************************************************************************ ! (2) compute the baseflow flux and its derivative w.r.t volumetric liquid water content ! ************************************************************************************************ ! use private subroutine to compute baseflow (for multiple calls for numerical Jacobian) call computeBaseflow(& ! input: control and state variables nSnow, & ! intent(in): number of snow layers nSoil, & ! intent(in): number of soil layers nLayers, & ! intent(in): total number of layers .true., & ! intent(in): .true. if analytical derivatives are desired ixSaturation, & ! intent(in): index of upper-most "saturated" layer mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water in each soil layer (-) mLayerVolFracIce, & ! intent(in): volumetric fraction of ice in each soil layer (-) ! input/output: data structures attr_data, & ! intent(in): spatial attributes mpar_data, & ! intent(in): model parameters prog_data, & ! intent(in): model prognostic variables for a local HRU flux_data, & ! intent(inout): model fluxes for a local HRU ! output: fluxes and derivatives mLayerBaseflow, & ! intent(out): baseflow flux in each soil layer (m s-1) dBaseflow_dVolLiq) ! intent(out): derivative in baseflow w.r.t. volumetric liquid water content (s-1) ! use the chain rule to compute the baseflow derivative w.r.t. matric head (s-1) do iLayer=1,nSoil dBaseflow_dMatric(1:iLayer,iLayer) = dBaseflow_dVolLiq(1:iLayer,iLayer)*mLayerdTheta_dPsi(iLayer) if(iLayer<nSoil) dBaseflow_dMatric(iLayer+1:nSoil,iLayer) = 0._dp end do ! ************************************************************************************************ ! (4) compute the numerical Jacobian ! ************************************************************************************************ if(doNumericalJacobian)then ! first, print the analytical Jacobian print*, '** analytical Jacobian:' write(*,'(a4,1x,100(i12,1x))') 'xCol', (iLayer, iLayer=1,nSoil) do iLayer=1,nSoil; write(*,'(i4,1x,100(e12.5,1x))') iLayer, dBaseflow_dMatric(1:nSoil,iLayer); end do ! get a copy of the state vector to perturb mLayerMatricHeadPerturbed(:) = mLayerMatricHeadLiq(:) mLayerVolFracLiqPerturbed(:) = mLayerVolFracLiq(:) ! loop through the state variables do iLayer=1,nSoil ! perturb state vector mLayerMatricHeadPerturbed(iLayer) = mLayerMatricHeadPerturbed(iLayer) + dx ! compute the columetruc liquid water content mLayerVolFracLiqPerturbed(iLayer) = volFracLiq(mLayerMatricHeadPerturbed(iLayer),vGn_alpha(iLayer),theta_res(iLayer),theta_sat(iLayer),vGn_n(iLayer),vGn_m(iLayer)) ! compute baseflow flux ! NOTE: This is an optional second call to computeBaseflow that is invoked when computing numerical derivatives. ! Since the purpose here is to compute the numerical derivatives, we do not need to compute analytical derivatives also. ! Hence, analytical derivatives are not desired call computeBaseflow(& ! input: control and state variables nSnow, & ! intent(in): number of snow layers nSoil, & ! intent(in): number of soil layers nLayers, & ! intent(in): total number of layers .false., & ! intent(in): .true. if analytical derivatives are desired ixSaturation, & ! intent(in): index of upper-most "saturated" layer mLayerVolFracLiqPerturbed, & ! intent(in): volumetric fraction of liquid water in each soil layer (-) mLayerVolFracIce, & ! intent(in): volumetric fraction of ice in each soil layer (-) ! input/output: data structures attr_data, & ! intent(in): spatial attributes mpar_data, & ! intent(in): model parameters prog_data, & ! intent(in): model prognostic variables for a local HRU flux_data, & ! intent(inout): model fluxes for a local HRU ! output: fluxes and derivatives mLayerBaseflowPerturbed, & ! intent(out): baseflow flux in each soil layer (m s-1) dBaseflow_dVolLiq) ! intent(out): ** NOT USED ** derivative in baseflow w.r.t. volumetric liquid water content (s-1) ! compute the numerical Jacobian nJac(:,iLayer) = (mLayerBaseflowPerturbed(:) - mLayerBaseflow(:))/dx ! compute the Jacobian ! set the state back to the input value mLayerMatricHeadPerturbed(iLayer) = mLayerMatricHeadLiq(iLayer) mLayerVolFracLiqPerturbed(iLayer) = mLayerVolFracLiq(iLayer) end do ! looping through state variables ! print the numerical Jacobian print*, '** numerical Jacobian:' write(*,'(a4,1x,100(i12,1x))') 'xCol', (iLayer, iLayer=1,nSoil) do iLayer=1,nSoil; write(*,'(i4,1x,100(e12.5,1x))') iLayer, nJac(1:nSoil,iLayer); end do !pause 'testing Jacobian' end if ! if desire to compute the Jacobian ! end association to variables in data structures end associate end subroutine groundwatr ! *********************************************************************************************************************** ! * private subroutine computeBaseflow: private subroutine so can be used to test the numerical jacobian ! *********************************************************************************************************************** subroutine computeBaseflow(& ! input: control and state variables nSnow, & ! intent(in): number of snow layers nSoil, & ! intent(in): number of soil layers nLayers, & ! intent(in): total number of layers derivDesired, & ! intent(in): .true. if derivatives are desired ixSaturation, & ! intent(in): index of upper-most "saturated" layer mLayerVolFracLiq, & ! intent(in): volumetric fraction of liquid water in each soil layer (-) mLayerVolFracIce, & ! intent(in): volumetric fraction of ice in each soil layer (-) ! input/output: data structures attr_data, & ! intent(in): spatial attributes mpar_data, & ! intent(in): model parameters prog_data, & ! intent(in): model prognostic variables for a local HRU flux_data, & ! intent(inout): model fluxes for a local HRU ! output: fluxes and derivatives mLayerBaseflow, & ! intent(out): baseflow flux in each soil layer (m s-1) dBaseflow_dVolLiq) ! intent(out): derivative in baseflow w.r.t. volumetric liquid water content (s-1) implicit none ! --------------------------------------------------------------------------------------- ! * dummy variables ! --------------------------------------------------------------------------------------- ! input: control and state variables integer(i4b),intent(in) :: nSnow ! number of snow layers integer(i4b),intent(in) :: nSoil ! number of soil layers integer(i4b),intent(in) :: nLayers ! total number of layers logical(lgt),intent(in) :: derivDesired ! .true. if derivatives are desired integer(i4b),intent(in) :: ixSaturation ! index of upper-most "saturated" layer real(dp),intent(in) :: mLayerVolFracLiq(:) ! volumetric fraction of liquid water (-) real(dp),intent(in) :: mLayerVolFracIce(:) ! volumetric fraction of ice (-) ! input/output: data structures type(var_d),intent(in) :: attr_data ! spatial attributes type(var_dlength),intent(in) :: mpar_data ! model parameters type(var_dlength),intent(in) :: prog_data ! prognostic variables for a local HRU type(var_dlength),intent(inout) :: flux_data ! model fluxes for a local HRU ! output: baseflow real(dp),intent(out) :: mLayerBaseflow(:) ! baseflow from each soil layer (m s-1) real(dp),intent(out) :: dBaseflow_dVolLiq(:,:) ! derivative in baseflow w.r.t. matric head (s-1) ! --------------------------------------------------------------------------------------- ! * local variables ! --------------------------------------------------------------------------------------- ! general local variables integer(i4b) :: iLayer,jLayer ! index of model layer ! local variables for the exfiltration real(dp) :: totalColumnInflow ! total column inflow (m s-1) real(dp) :: totalColumnOutflow ! total column outflow (m s-1) real(dp) :: availStorage ! available storage (m) real(dp),parameter :: xMinEval=0.002_dp ! minimum value to evaluate the exfiltration function (m) real(dp),parameter :: xCenter=0.001_dp ! center of the exfiltration function (m) real(dp),parameter :: xWidth=0.0001_dp ! width of the exfiltration function (m) real(dp) :: expF,logF ! logistic smoothing function (-) ! local variables for the lateral flux among soil columns real(dp) :: activePorosity ! "active" porosity associated with storage above a threshold (-) real(dp) :: drainableWater ! drainable water in eaxch layer (m) real(dp) :: tran0 ! maximum transmissivity (m2 s-1) real(dp),dimension(nSoil) :: zActive ! water table thickness associated with storage below and including the given layer (m) real(dp),dimension(nSoil) :: trTotal ! total transmissivity associated with total water table depth zActive (m2 s-1) real(dp),dimension(nSoil) :: trSoil ! transmissivity of water in a given layer (m2 s-1) ! local variables for the derivatives real(dp) :: qbTotal ! total baseflow (m s-1) real(dp) :: length2area ! ratio of hillslope width to hillslope area (m m-2) real(dp),dimension(nSoil) :: depth2capacity ! ratio of layer depth to total subsurface storage capacity (-) real(dp),dimension(nSoil) :: dXdS ! change in dimensionless flux w.r.t. change in dimensionless storage (-) real(dp),dimension(nSoil) :: dLogFunc_dLiq ! derivative in the logistic function w.r.t. volumetric liquid water content (-) real(dp),dimension(nSoil) :: dExfiltrate_dVolLiq ! derivative in exfiltration w.r.t. volumetric liquid water content (-) ! local variables for testing (debugging) logical(lgt),parameter :: printFlag=.false. ! flag for printing (debugging) real(dp) :: xDepth,xTran,xFlow ! temporary variables (depth, transmissivity, flow) ! --------------------------------------------------------------------------------------- ! * association to data in structures ! --------------------------------------------------------------------------------------- associate(& ! input: coordinate variables soilDepth => prog_data%var(iLookPROG%iLayerHeight)%dat(nLayers), & ! intent(in): [dp] total soil depth (m) mLayerDepth => prog_data%var(iLookPROG%mLayerDepth)%dat(nSnow+1:nLayers),& ! intent(in): [dp(:)] depth of each soil layer (m) ! input: diagnostic variables surfaceHydCond => flux_data%var(iLookFLUX%mLayerSatHydCondMP)%dat(1), & ! intent(in): [dp] saturated hydraulic conductivity at the surface (m s-1) mLayerColumnInflow => flux_data%var(iLookFLUX%mLayerColumnInflow)%dat, & ! intent(in): [dp(:)] inflow into each soil layer (m3/s) ! input: local attributes HRUarea => attr_data%var(iLookATTR%HRUarea), & ! intent(in): [dp] HRU area (m2) tan_slope => attr_data%var(iLookATTR%tan_slope), & ! intent(in): [dp] tan water table slope, taken as tan local ground surface slope (-) contourLength => attr_data%var(iLookATTR%contourLength), & ! intent(in): [dp] length of contour at downslope edge of HRU (m) ! input: baseflow parameters zScale_TOPMODEL => mpar_data%var(iLookPARAM%zScale_TOPMODEL)%dat(1), & ! intent(in): [dp] TOPMODEL exponent (-) kAnisotropic => mpar_data%var(iLookPARAM%kAnisotropic)%dat(1), & ! intent(in): [dp] anisotropy factor for lateral hydraulic conductivity (- fieldCapacity => mpar_data%var(iLookPARAM%fieldCapacity)%dat(1), & ! intent(in): [dp] field capacity (-) theta_sat => mpar_data%var(iLookPARAM%theta_sat)%dat, & ! intent(in): [dp(:)] soil porosity (-) ! output: diagnostic variables scalarExfiltration => flux_data%var(iLookFLUX%scalarExfiltration)%dat(1), & ! intent(out):[dp] exfiltration from the soil profile (m s-1) mLayerColumnOutflow => flux_data%var(iLookFLUX%mLayerColumnOutflow)%dat & ! intent(out):[dp(:)] column outflow from each soil layer (m3 s-1) ) ! end association to variables in data structures ! *********************************************************************************************************************** ! *********************************************************************************************************************** ! start routine here ! *********************************************************************************************************************** ! (1) compute the baseflow flux in each soil layer ! *********************************************************************************************************************** ! compute the maximum transmissivity ! NOTE: this can be done as a pre-processing step tran0 = kAnisotropic*surfaceHydCond*soilDepth/zScale_TOPMODEL ! maximum transmissivity (m2 s-1) ! compute the water table thickness (m) and transmissivity in each layer (m2 s-1) do iLayer=nSoil,ixSaturation,-1 ! loop through "active" soil layers, from lowest to highest ! define drainable water in each layer (m) activePorosity = theta_sat(iLayer) - fieldCapacity ! "active" porosity (-) drainableWater = mLayerDepth(iLayer)*(max(0._dp,mLayerVolFracLiq(iLayer) - fieldCapacity))/activePorosity ! compute layer transmissivity if(iLayer==nSoil)then zActive(iLayer) = drainableWater ! water table thickness associated with storage in a given layer (m) trTotal(iLayer) = tran0*(zActive(iLayer)/soilDepth)**zScale_TOPMODEL ! total transmissivity for total depth zActive (m2 s-1) trSoil(iLayer) = trTotal(iLayer) ! transmissivity of water in a given layer (m2 s-1) else zActive(iLayer) = zActive(iLayer+1) + drainableWater trTotal(iLayer) = tran0*(zActive(iLayer)/soilDepth)**zScale_TOPMODEL trSoil(iLayer) = trTotal(iLayer) - trTotal(iLayer+1) end if !write(*,'(a,1x,i4,1x,10(f20.15,1x))') 'iLayer, mLayerMatricHeadLiq(iLayer), mLayerVolFracLiq(iLayer), zActive(iLayer), trTotal(iLayer), trSoil(iLayer) = ', & ! iLayer, mLayerMatricHeadLiq(iLayer), mLayerVolFracLiq(iLayer), zActive(iLayer), trTotal(iLayer), trSoil(iLayer) end do ! looping through soil layers ! set un-used portions of the vectors to zero if(ixSaturation>1)then zActive(1:ixSaturation-1) = 0._dp trTotal(1:ixSaturation-1) = 0._dp trSoil(1:ixSaturation-1) = 0._dp end if ! compute the outflow from each layer (m3 s-1) mLayerColumnOutflow(1:nSoil) = trSoil(1:nSoil)*tan_slope*contourLength ! compute total column inflow and total column outflow (m s-1) totalColumnInflow = sum(mLayerColumnInflow(1:nSoil))/HRUarea totalColumnOutflow = sum(mLayerColumnOutflow(1:nSoil))/HRUarea ! compute the available storage (m) availStorage = sum(mLayerDepth(1:nSoil)*(theta_sat - (mLayerVolFracLiq(1:nSoil)+mLayerVolFracIce(1:nSoil))) ) ! compute the smoothing function (-) if(availStorage < xMinEval)then ! (compute the logistic function) expF = exp((availStorage - xCenter)/xWidth) logF = 1._dp / (1._dp + expF) ! (compute the derivative in the logistic function w.r.t. volumetric liquid water content in each soil layer) dLogFunc_dLiq(1:nSoil) = mLayerDepth(1:nSoil)*(expF/xWidth)/(1._dp + expF)**2._dp else logF = 0._dp dLogFunc_dLiq(:) = 0._dp end if ! compute the exfiltartion (m s-1) if(totalColumnInflow > totalColumnOutflow .and. logF > tiny(1._dp))then scalarExfiltration = logF*(totalColumnInflow - totalColumnOutflow) ! m s-1 !write(*,'(a,1x,10(f30.20,1x))') 'scalarExfiltration = ', scalarExfiltration else scalarExfiltration = 0._dp end if ! check !write(*,'(a,1x,10(f30.20,1x))') 'zActive(1), soilDepth, availStorage, logF, scalarExfiltration = ', & ! zActive(1), soilDepth, availStorage, logF, scalarExfiltration !if(scalarExfiltration > tiny(1.0_dp)) pause 'exfiltrating' ! compute the baseflow in each layer (m s-1) mLayerBaseflow(1:nSoil) = (mLayerColumnOutflow(1:nSoil) - mLayerColumnInflow(1:nSoil))/HRUarea ! compute the total baseflow qbTotal = sum(mLayerBaseflow) ! add exfiltration to the baseflow flux at the top layer mLayerBaseflow(1) = mLayerBaseflow(1) + scalarExfiltration mLayerColumnOutflow(1) = mLayerColumnOutflow(1) + scalarExfiltration*HRUarea ! test if(printFlag)then xDepth = sum(mLayerDepth(ixSaturation:nSoil)*(mLayerVolFracLiq(ixSaturation:nSoil) - fieldCapacity))/sum(theta_sat(ixSaturation:nSoil) - fieldCapacity) ! "effective" water table thickness (m) xTran = tran0*(xDepth/soilDepth)**zScale_TOPMODEL ! transmissivity for the entire aquifer (m2 s-1) xFlow = xTran*tan_slope*contourLength/HRUarea ! total column outflow (m s-1) print*, 'ixSaturation = ', ixSaturation write(*,'(a,1x,5(f30.20,1x))') 'tran0, soilDepth = ', tran0, soilDepth write(*,'(a,1x,5(f30.20,1x))') 'surfaceHydCond, zScale_TOPMODEL = ', surfaceHydCond, zScale_TOPMODEL write(*,'(a,1x,5(f30.20,1x))') 'xDepth, zActive(ixSaturation) = ', xDepth, zActive(ixSaturation) write(*,'(a,1x,5(f30.20,1x))') 'xTran, trTotal(ixSaturation) = ', xTran, trTotal(ixSaturation) write(*,'(a,1x,5(f30.20,1x))') 'xFlow, totalColumnOutflow = ', xFlow, sum(mLayerColumnOutflow(:))/HRUarea !pause 'check groundwater' end if ! *********************************************************************************************************************** ! (2) compute the derivative in the baseflow flux w.r.t. volumetric liquid water content (m s-1) ! *********************************************************************************************************************** ! initialize the derivative matrix dBaseflow_dVolLiq(:,:) = 0._dp ! check if derivatives are actually required if(.not.derivDesired) return ! compute ratio of hillslope width to hillslope area (m m-2) length2area = tan_slope*contourLength/HRUarea ! compute the ratio of layer depth to maximum water holding capacity (-) depth2capacity(1:nSoil) = mLayerDepth(1:nSoil)/sum( (theta_sat(1:nSoil) - fieldCapacity)*mLayerDepth(1:nSoil) ) ! compute the change in dimensionless flux w.r.t. change in dimensionless storage (-) dXdS(1:nSoil) = zScale_TOPMODEL*(zActive(1:nSoil)/SoilDepth)**(zScale_TOPMODEL - 1._dp) ! loop through soil layers do iLayer=1,nSoil ! compute diagonal terms (s-1) dBaseflow_dVolLiq(iLayer,iLayer) = tran0*dXdS(iLayer)*depth2capacity(iLayer)*length2area ! compute off-diagonal terms do jLayer=iLayer+1,nSoil ! (only dependent on layers below) dBaseflow_dVolLiq(iLayer,jLayer) = tran0*(dXdS(iLayer) - dXdS(iLayer+1))*depth2capacity(jLayer)*length2area end do ! looping through soil layers end do ! looping through soil layers ! compute the derivative in the exfiltration flux w.r.t. volumetric liquid water content (m s-1) if(qbTotal < 0._dp)then do iLayer=1,nSoil dExfiltrate_dVolLiq(iLayer) = dBaseflow_dVolLiq(iLayer,iLayer)*logF + dLogFunc_dLiq(iLayer)*qbTotal end do ! looping through soil layers dBaseflow_dVolLiq(1,1:nSoil) = dBaseflow_dVolLiq(1,1:nSoil) - dExfiltrate_dVolLiq(1:nSoil) end if ! end association to data in structures end associate end subroutine computeBaseflow end module groundwatr_module