From 0fc8b9cc56e261e8b761385048a902bfb0ad8ac9 Mon Sep 17 00:00:00 2001
From: Kyle <kyle.c.klenk@gmail.com>
Date: Tue, 6 Sep 2022 21:30:21 +0000
Subject: [PATCH] updated up to soilLiqFlx in computFlux.f90

---
 build/source/engine/computFlux.f90            |  309 +-
 build/source/engine/read_paramActors.f90      |    5 -
 build/source/engine/soilLiqFlx.f90            | 3613 +++++++++--------
 build/source/engine/soilLiqFlx_old.f90        | 1759 ++++++++
 build/source/engine/ssdNrgFlux.f90            | 1245 ++++--
 build/source/engine/ssdNrgFlux_old.f90        |  307 ++
 .../source/engine/sundials/computEnthalpy.f90 |    2 +-
 .../source/engine/sundials/computHeatCap.f90  |   24 +-
 .../engine/sundials/soil_utilsSundials.f90    |    7 +-
 .../engine/sundials/updatStateSundials.f90    |    2 -
 .../engine/sundials/updateVars4JacDAE.f90     |    2 -
 .../engine/sundials/updateVarsSundials.f90    |    1 -
 .../engine/sundials/varExtrSundials.f90       |   10 -
 13 files changed, 5121 insertions(+), 2165 deletions(-)
 mode change 100755 => 100644 build/source/engine/soilLiqFlx.f90
 create mode 100755 build/source/engine/soilLiqFlx_old.f90
 mode change 100755 => 100644 build/source/engine/ssdNrgFlux.f90
 create mode 100755 build/source/engine/ssdNrgFlux_old.f90

diff --git a/build/source/engine/computFlux.f90 b/build/source/engine/computFlux.f90
index 319abc7..e8b3312 100755
--- a/build/source/engine/computFlux.f90
+++ b/build/source/engine/computFlux.f90
@@ -209,6 +209,9 @@ subroutine computFlux(&
   logical(lgt)                    :: doVegNrgFlux                ! flag to compute the energy flux over vegetation
   real(dp),dimension(nSoil)       :: dHydCond_dMatric            ! derivative in hydraulic conductivity w.r.t matric head (s-1)
   character(LEN=256)              :: cmessage                    ! error message of downwind routine
+  real(dp)                        :: above_soilLiqFluxDeriv      ! derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+  real(dp)                        :: above_soildLiq_dTk          ! derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+  real(dp)                        :: above_soilFracLiq           ! fraction of liquid water layer above soil (canopy or snow) (-)
   ! --------------------------------------------------------------
   ! initialize error control
   err=0; message='computFlux/'
@@ -298,7 +301,9 @@ subroutine computFlux(&
   scalarSoilControl            => diag_data%var(iLookDIAG%scalarSoilControl )%dat(1)              ,&  ! intent(out): [dp] soil control on infiltration, zero or one
   scalarMaxInfilRate           => flux_data%var(iLookFLUX%scalarMaxInfilRate)%dat(1)              ,&  ! intent(out): [dp] maximum infiltration rate (m s-1)
   scalarInfiltration           => flux_data%var(iLookFLUX%scalarInfiltration)%dat(1)              ,&  ! intent(out): [dp] infiltration of water into the soil profile (m s-1)
-
+  scalarFracLiqVeg             => diag_data%var(iLookDIAG%scalarFracLiqVeg)%dat(1)                ,& ! intent(inout): [dp] fraction of liquid water on vegetation (-)
+  mLayerFracLiqSnow            => diag_data%var(iLookDIAG%mLayerFracLiqSnow)%dat                  ,& ! intent(inout): [dp(:)] fraction of liquid water in each snow layer (-)
+ 
   ! boundary fluxes in the soil domain
   scalarThroughfallRain        => flux_data%var(iLookFLUX%scalarThroughfallRain)%dat(1)           ,&  ! intent(out): [dp] rain that reaches the ground without ever touching the canopy (kg m-2 s-1)
   scalarCanopyLiqDrainage      => flux_data%var(iLookFLUX%scalarCanopyLiqDrainage)%dat(1)         ,&  ! intent(out): [dp] drainage of liquid water from the vegetation canopy (kg m-2 s-1)
@@ -356,6 +361,10 @@ subroutine computFlux(&
   dNrgFlux_dTempAbove          => deriv_data%var(iLookDERIV%dNrgFlux_dTempAbove         )%dat     ,&  ! intent(out): [dp(:)] derivatives in the flux w.r.t. temperature in the layer above
   dNrgFlux_dTempBelow          => deriv_data%var(iLookDERIV%dNrgFlux_dTempBelow         )%dat     ,&  ! intent(out): [dp(:)] derivatives in the flux w.r.t. temperature in the layer below
 
+  ! derivatives in energy fluxes at the interface of snow+soil layers w.r.t. water state in layers above and below
+  dNrgFlux_dWatAbove           => deriv_data%var(iLookDERIV%dNrgFlux_dWatAbove          )%dat     ,& ! intent(out): [dp(:)]  derivatives in the flux w.r.t. water state in the layer above
+  dNrgFlux_dWatBelow           => deriv_data%var(iLookDERIV%dNrgFlux_dWatBelow          )%dat     ,& ! intent(out): [dp(:)]  derivatives in the flux w.r.t. water state in the layer below
+
   ! derivative in liquid water fluxes at the interface of snow layers w.r.t. volumetric liquid water content in the layer above
   iLayerLiqFluxSnowDeriv       => deriv_data%var(iLookDERIV%iLayerLiqFluxSnowDeriv      )%dat     ,&  ! intent(out): [dp(:)] derivative in vertical liquid water flux at layer interfaces
 
@@ -363,6 +372,7 @@ subroutine computFlux(&
   dVolTot_dPsi0                => deriv_data%var(iLookDERIV%dVolTot_dPsi0               )%dat     ,&  ! intent(out): [dp(:)] derivative in total water content w.r.t. total water matric potential
   dq_dHydStateAbove            => deriv_data%var(iLookDERIV%dq_dHydStateAbove           )%dat     ,&  ! intent(out): [dp(:)] change in flux at layer interfaces w.r.t. states in the layer above
   dq_dHydStateBelow            => deriv_data%var(iLookDERIV%dq_dHydStateBelow           )%dat     ,&  ! intent(out): [dp(:)] change in flux at layer interfaces w.r.t. states in the layer below
+  dq_dHydStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dHydStateLayerSurfVec    )%dat     ,&  ! intent(out): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
   mLayerdTheta_dPsi            => deriv_data%var(iLookDERIV%mLayerdTheta_dPsi           )%dat     ,&  ! intent(out): [dp(:)] derivative in the soil water characteristic w.r.t. psi
   mLayerdPsi_dTheta            => deriv_data%var(iLookDERIV%mLayerdPsi_dTheta           )%dat     ,&  ! intent(out): [dp(:)] derivative in the soil water characteristic w.r.t. theta
   dCompress_dPsi               => deriv_data%var(iLookDERIV%dCompress_dPsi              )%dat     ,&  ! intent(out): [dp(:)] derivative in compressibility w.r.t matric head
@@ -372,8 +382,21 @@ subroutine computFlux(&
 
   ! derivative in liquid water fluxes for the soil domain w.r.t energy state variables
   dq_dNrgStateAbove            => deriv_data%var(iLookDERIV%dq_dNrgStateAbove           )%dat     ,&  ! intent(out): [dp(:)] change in flux at layer interfaces w.r.t. states in the layer above
-  dq_dNrgStateBelow            => deriv_data%var(iLookDERIV%dq_dNrgStateBelow           )%dat      &  ! intent(out): [dp(:)] change in flux at layer interfaces w.r.t. states in the layer below
-
+  dq_dNrgStateBelow            => deriv_data%var(iLookDERIV%dq_dNrgStateBelow           )%dat     ,&  ! intent(out): [dp(:)] change in flux at layer interfaces w.r.t. states in the layer below
+  dq_dNrgStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dNrgStateLayerSurfVec    )%dat     ,&  ! intent(out): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
+ 
+  ! derivatives in soil transpiration w.r.t. canopy state variables
+  mLayerdTrans_dTCanair        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanair       )%dat     ,&  !intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
+  mLayerdTrans_dTCanopy        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanopy       )%dat     ,&  ! intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy temperature
+  mLayerdTrans_dTGround        => deriv_data%var(iLookDERIV%mLayerdTrans_dTGround       )%dat     ,&  ! intent(out): derivatives in the soil layer transpiration flux w.r.t. ground temperature
+  mLayerdTrans_dCanWat         => deriv_data%var(iLookDERIV%mLayerdTrans_dCanWat        )%dat     ,&  ! intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy total water
+ 
+  ! derivatives in aquifer transpiration w.r.t. canopy state variables
+  dAquiferTrans_dTCanair       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanair      )%dat(1)  ,&  !intent(out): derivatives in the aquifer transpiration flux w.r.t. canopy air temperature
+  dAquiferTrans_dTCanopy       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanopy      )%dat(1)  ,&  ! intent(out): derivatives in the aquifer transpiration flux w.r.t. canopy temperature
+  dAquiferTrans_dTGround       => deriv_data%var(iLookDERIV%dAquiferTrans_dTGround      )%dat(1)  ,&  ! intent(out): derivatives in the aquifer transpiration flux w.r.t. ground temperature
+  dAquiferTrans_dCanWat        => deriv_data%var(iLookDERIV%dAquiferTrans_dCanWat       )%dat(1)   &  ! intent(out): derivatives in the aquifer transpiration flux w.r.t. canopy total water
+ 
   )  ! association to data in structures
 
   ! *****
@@ -477,126 +500,71 @@ subroutine computFlux(&
           ! output: error control
           err,cmessage)                             ! intent(out): error control
 
-    ! ! calculate the energy fluxes over vegetation
-    ! call vegNrgFlux(&
-    !                 ! input: model control
-    !                 firstSubStep,                           & ! intent(in): flag to indicate if we are processing the first sub-step
-    !                 firstFluxCall,                          & ! intent(in): flag to indicate if we are processing the first flux call
-    !                 computeVegFlux,                         & ! intent(in): flag to indicate if we need to compute fluxes over vegetation
-    !                 requireLWBal,                           & ! intent(in): flag to indicate if we need longwave to be balanced
-    !                 ! input: model state variables
-    !                 upperBoundTemp,                         & ! intent(in): temperature of the upper boundary (K) --> NOTE: use air temperature
-    !                 scalarCanairTempTrial,                  & ! intent(in): trial value of the canopy air space temperature (K)
-    !                 scalarCanopyTempTrial,                  & ! intent(in): trial value of canopy temperature (K)
-    !                 mLayerTempTrial(1),                     & ! intent(in): trial value of ground temperature (K)
-    !                 scalarCanopyIceTrial,                   & ! intent(in): trial value of mass of ice on the vegetation canopy (kg m-2)
-    !                 scalarCanopyLiqTrial,                   & ! intent(in): trial value of mass of liquid water on the vegetation canopy (kg m-2)
-    !                 ! input: model derivatives
-    !                 dCanLiq_dTcanopy,                       & ! intent(in): derivative in canopy liquid storage w.r.t. canopy temperature (kg m-2 K-1)
-    !                 ! input/output: data structures
-    !                 type_data,                              & ! intent(in):    type of vegetation and soil
-    !                 forc_data,                              & ! intent(in):    model forcing data
-    !                 mpar_data,                              & ! intent(in):    model parameters
-    !                 indx_data,                              & ! intent(in):    index data
-    !                 prog_data,                              & ! intent(in):    model prognostic variables for a local HRU
-    !                 diag_data,                              & ! intent(inout): model diagnostic variables for a local HRU
-    !                 flux_data,                              & ! intent(inout): model fluxes for a local HRU
-    !                 bvar_data,                              & ! intent(in):    model variables for the local basin
-    !                 model_decisions,                        & ! intent(in):    model decisions
-    !                 ! output: liquid water fluxes associated with evaporation/transpiration
-    !                 scalarCanopyTranspiration,              & ! intent(out): canopy transpiration (kg m-2 s-1)
-    !                 scalarCanopyEvaporation,                & ! intent(out): canopy evaporation/condensation (kg m-2 s-1)
-    !                 scalarGroundEvaporation,                & ! intent(out): ground evaporation/condensation -- below canopy or non-vegetated (kg m-2 s-1)
-    !                 ! output: fluxes
-    !                 scalarCanairNetNrgFlux,                 & ! intent(out): net energy flux for the canopy air space (W m-2)
-    !                 scalarCanopyNetNrgFlux,                 & ! intent(out): net energy flux for the vegetation canopy (W m-2)
-    !                 scalarGroundNetNrgFlux,                 & ! intent(out): net energy flux for the ground surface (W m-2)
-    !                 ! output: flux derivatives
-    !                 dCanairNetFlux_dCanairTemp,             & ! intent(out): derivative in net canopy air space flux w.r.t. canopy air temperature (W m-2 K-1)
-    !                 dCanairNetFlux_dCanopyTemp,             & ! intent(out): derivative in net canopy air space flux w.r.t. canopy temperature (W m-2 K-1)
-    !                 dCanairNetFlux_dGroundTemp,             & ! intent(out): derivative in net canopy air space flux w.r.t. ground temperature (W m-2 K-1)
-    !                 dCanopyNetFlux_dCanairTemp,             & ! intent(out): derivative in net canopy flux w.r.t. canopy air temperature (W m-2 K-1)
-    !                 dCanopyNetFlux_dCanopyTemp,             & ! intent(out): derivative in net canopy flux w.r.t. canopy temperature (W m-2 K-1)
-    !                 dCanopyNetFlux_dGroundTemp,             & ! intent(out): derivative in net canopy flux w.r.t. ground temperature (W m-2 K-1)
-    !                 dGroundNetFlux_dCanairTemp,             & ! intent(out): derivative in net ground flux w.r.t. canopy air temperature (W m-2 K-1)
-    !                 dGroundNetFlux_dCanopyTemp,             & ! intent(out): derivative in net ground flux w.r.t. canopy temperature (W m-2 K-1)
-    !                 dGroundNetFlux_dGroundTemp,             & ! intent(out): derivative in net ground flux w.r.t. ground temperature (W m-2 K-1)
-    !                 ! output: liquid water flux derivarives (canopy evap)
-    !                 dCanopyEvaporation_dCanWat,             & ! intent(out): derivative in canopy evaporation w.r.t. canopy liquid water content (s-1)
-    !                 dCanopyEvaporation_dTCanair,            & ! intent(out): derivative in canopy evaporation w.r.t. canopy air temperature (kg m-2 s-1 K-1)
-    !                 dCanopyEvaporation_dTCanopy,            & ! intent(out): derivative in canopy evaporation w.r.t. canopy temperature (kg m-2 s-1 K-1)
-    !                 dCanopyEvaporation_dTGround,            & ! intent(out): derivative in canopy evaporation w.r.t. ground temperature (kg m-2 s-1 K-1)
-    !                 ! output: liquid water flux derivarives (ground evap)
-    !                 dGroundEvaporation_dCanWat,             & ! intent(out): derivative in ground evaporation w.r.t. canopy liquid water content (s-1)
-    !                 dGroundEvaporation_dTCanair,            & ! intent(out): derivative in ground evaporation w.r.t. canopy air temperature (kg m-2 s-1 K-1)
-    !                 dGroundEvaporation_dTCanopy,            & ! intent(out): derivative in ground evaporation w.r.t. canopy temperature (kg m-2 s-1 K-1)
-    !                 dGroundEvaporation_dTGround,            & ! intent(out): derivative in ground evaporation w.r.t. ground temperature (kg m-2 s-1 K-1)
-    !                 ! output: cross derivative terms
-    !                 dCanopyNetFlux_dCanWat,                 & ! intent(out): derivative in net canopy fluxes w.r.t. canopy liquid water content (J kg-1 s-1)
-    !                 dGroundNetFlux_dCanWat,                 & ! intent(out): derivative in net ground fluxes w.r.t. canopy liquid water content (J kg-1 s-1)
-    !                 ! output: error control
-    !                 err,cmessage)                             ! intent(out): error control
-    ! if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-
-  ! check fluxes
-  if(globalPrintFlag)then
-   print*, '**'
-   write(*,'(a,1x,10(f30.20))') 'canopyDepth           = ',  canopyDepth
-   write(*,'(a,1x,10(f30.20))') 'mLayerDepth(1:2)      = ',  mLayerDepth(1:2)
-   write(*,'(a,1x,10(f30.20))') 'scalarCanairTempTrial = ',  scalarCanairTempTrial   ! trial value of the canopy air space temperature (K)
-   write(*,'(a,1x,10(f30.20))') 'scalarCanopyTempTrial = ',  scalarCanopyTempTrial   ! trial value of canopy temperature (K)
-   write(*,'(a,1x,10(f30.20))') 'mLayerTempTrial(1:2)  = ',  mLayerTempTrial(1:2)    ! trial value of ground temperature (K)
-   write(*,'(a,1x,10(f30.20))') 'scalarCanairNetNrgFlux = ', scalarCanairNetNrgFlux
-   write(*,'(a,1x,10(f30.20))') 'scalarCanopyNetNrgFlux = ', scalarCanopyNetNrgFlux
-   write(*,'(a,1x,10(f30.20))') 'scalarGroundNetNrgFlux = ', scalarGroundNetNrgFlux
-   write(*,'(a,1x,10(f30.20))') 'dGroundNetFlux_dGroundTemp = ', dGroundNetFlux_dGroundTemp
-  endif ! if checking fluxes
-
- endif ! if calculating the energy fluxes over vegetation
-
- ! *****
- ! * CALCULATE ENERGY FLUXES THROUGH THE SNOW-SOIL DOMAIN...
- ! **********************************************************
-
- ! check the need to compute energy fluxes throughout the snow+soil domain
- if(nSnowSoilNrg>0)then
+    ! check fluxes
+    if(globalPrintFlag)then
+      print*, '**'
+      write(*,'(a,1x,10(f30.20))') 'canopyDepth           = ',  canopyDepth
+      write(*,'(a,1x,10(f30.20))') 'mLayerDepth(1:2)      = ',  mLayerDepth(1:2)
+      write(*,'(a,1x,10(f30.20))') 'scalarCanairTempTrial = ',  scalarCanairTempTrial   ! trial value of the canopy air space temperature (K)
+      write(*,'(a,1x,10(f30.20))') 'scalarCanopyTempTrial = ',  scalarCanopyTempTrial   ! trial value of canopy temperature (K)
+      write(*,'(a,1x,10(f30.20))') 'mLayerTempTrial(1:2)  = ',  mLayerTempTrial(1:2)    ! trial value of ground temperature (K)
+      write(*,'(a,1x,10(f30.20))') 'scalarCanairNetNrgFlux = ', scalarCanairNetNrgFlux
+      write(*,'(a,1x,10(f30.20))') 'scalarCanopyNetNrgFlux = ', scalarCanopyNetNrgFlux
+      write(*,'(a,1x,10(f30.20))') 'scalarGroundNetNrgFlux = ', scalarGroundNetNrgFlux
+      write(*,'(a,1x,10(f30.20))') 'dGroundNetFlux_dGroundTemp = ', dGroundNetFlux_dGroundTemp
+    endif ! if checking fluxes
+
+  endif ! if calculating the energy fluxes over vegetation
 
-  ! calculate energy fluxes at layer interfaces through the snow and soil domain
-  call ssdNrgFlux(&
-                  ! input: model control
-                  (scalarSolution .and. .not.firstFluxCall), & ! intent(in): flag to indicate the scalar solution
-                  ! input: fluxes and derivatives at the upper boundary
-                  scalarGroundNetNrgFlux,                    & ! intent(in): total flux at the ground surface (W m-2)
-                  dGroundNetFlux_dGroundTemp,                & ! intent(in): derivative in total ground surface flux w.r.t. ground temperature (W m-2 K-1)
-                  ! input: liquid water fluxes throughout the snow and soil domains
-                  iLayerLiqFluxSnow,                         & ! intent(in): liquid flux at the interface of each snow layer (m s-1)
-                  iLayerLiqFluxSoil,                         & ! intent(in): liquid flux at the interface of each soil layer (m s-1)
-                  ! input: trial value of model state variabes
-                  mLayerTempTrial,                           & ! intent(in): trial temperature at the current iteration (K)
-                  mLayerMatricHeadTrial,                     & ! intent(in): trial value for the total water matric potential in each soil layer (m)
-                  mLayerVolFracLiqTrial,                     & ! intent(in): trial volumetric fraction of liquid water at the current iteration(-)
-                  mLayerVolFracIceTrial,                     & ! intent(in): trial volumetric fraction of ice water at the current iteration(-)
-                  ! input-output: data structures
-                  mpar_data,                                 & ! intent(in):    model parameters
-                  indx_data,                                 & ! intent(in):    model indices
-                  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: fluxes and derivatives at all layer interfaces
-                  iLayerNrgFlux,                             & ! intent(out): energy flux at the layer interfaces (W m-2)
-                  dNrgFlux_dTempAbove,                       & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (W m-2 K-1)
-                  dNrgFlux_dTempBelow,                       & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (W m-2 K-1)
-                  ! output: error control
-                  err,cmessage)                                ! intent(out): error control
-  if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-
-  ! calculate net energy fluxes for each snow and soil layer (J m-3 s-1)
-  do iLayer=1,nLayers
-   mLayerNrgFlux(iLayer) = -(iLayerNrgFlux(iLayer) - iLayerNrgFlux(iLayer-1))/mLayerDepth(iLayer)
-   if(globalPrintFlag)then
-    if(iLayer < 10) write(*,'(a,1x,i4,1x,10(f25.15,1x))') 'iLayer, iLayerNrgFlux(iLayer-1:iLayer), mLayerNrgFlux(iLayer)   = ', iLayer, iLayerNrgFlux(iLayer-1:iLayer), mLayerNrgFlux(iLayer)
-   endif
-  end do
+  ! *****
+  ! * CALCULATE ENERGY FLUXES THROUGH THE SNOW-SOIL DOMAIN...
+  ! **********************************************************
+
+  ! check the need to compute energy fluxes throughout the snow+soil domain
+  if(nSnowSoilNrg>0)then
+
+    ! calculate energy fluxes at layer interfaces through the snow and soil domain
+    call ssdNrgFlux(&
+                    ! input: model control
+                    (scalarSolution .and. .not.firstFluxCall), & ! intent(in): flag to indicate the scalar solution
+                    .true.,                                    & ! intent(in):    flag indicating if derivatives are desired     
+                    ! input: fluxes and derivatives at the upper boundary
+                    scalarGroundNetNrgFlux,                    & ! intent(in): total flux at the ground surface (W m-2)
+                    dGroundNetFlux_dGroundTemp,                & ! intent(in): derivative in total ground surface flux w.r.t. ground temperature (W m-2 K-1)
+                    ! input: liquid water fluxes throughout the snow and soil domains
+                    iLayerLiqFluxSnow,                         & ! intent(in): liquid flux at the interface of each snow layer (m s-1)
+                    iLayerLiqFluxSoil,                         & ! intent(in): liquid flux at the interface of each soil layer (m s-1)
+                    ! input: trial value of model state variabes
+                    mLayerTempTrial,                           & ! intent(in): trial temperature at the current iteration (K)
+                    mLayerMatricHeadTrial,                     & ! intent(in): trial value for the total water matric potential in each soil layer (m)
+                    mLayerVolFracLiqTrial,                     & ! intent(in): trial volumetric fraction of liquid water at the current iteration(-)
+                    mLayerVolFracIceTrial,                     & ! intent(in): trial volumetric fraction of ice water at the current iteration(-)
+                    ! input: pre-computed derivatives
+                    mLayerdTheta_dTk,                          & ! intent(in):    derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                    mLayerFracLiqSnow,                         & ! intent(in):    fraction of liquid water (-)
+                    ! input-output: data structures
+                    mpar_data,                                 & ! intent(in):    model parameters
+                    indx_data,                                 & ! intent(in):    model indices
+                    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: fluxes and derivatives at all layer interfaces
+                    iLayerNrgFlux,                             & ! intent(out): energy flux at the layer interfaces (W m-2)
+                    dNrgFlux_dTempAbove,                       & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (W m-2 K-1)
+                    dNrgFlux_dTempBelow,                       & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (W m-2 K-1)
+                    dNrgFlux_dWatAbove,                        & ! intent(out): derivatives in the flux w.r.t. water state in the layer above
+                    dNrgFlux_dWatBelow,                        & ! intent(out): derivatives in the flux w.r.t. water state in the layer below
+                    ! output: error control
+                    err,cmessage)                                ! intent(out): error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+
+    ! calculate net energy fluxes for each snow and soil layer (J m-3 s-1)
+    do iLayer=1,nLayers
+      mLayerNrgFlux(iLayer) = -(iLayerNrgFlux(iLayer) - iLayerNrgFlux(iLayer-1))/mLayerDepth(iLayer)
+      if(globalPrintFlag)then
+        if(iLayer < 10) write(*,'(a,1x,i4,1x,10(f25.15,1x))') 'iLayer, iLayerNrgFlux(iLayer-1:iLayer), mLayerNrgFlux(iLayer)   = ', iLayer, iLayerNrgFlux(iLayer-1:iLayer), mLayerNrgFlux(iLayer)
+      endif
+    end do
 
  endif  ! if computing energy fluxes throughout the snow+soil domain
 
@@ -688,14 +656,34 @@ subroutine computFlux(&
   ! compute drainage from the soil zone (needed for mass balance checks)
   scalarSnowDrainage = iLayerLiqFluxSnow(nSnow)
 
+    ! save bottom layer of snow derivatives
+  above_soilLiqFluxDeriv = iLayerLiqFluxSnowDeriv(nSnow) ! derivative in vertical liquid water flux at bottom snow layer interface
+  above_soildLiq_dTk     = mLayerdTheta_dTk(nSnow)  ! derivative in volumetric liquid water content in bottom snow layer w.r.t. temperature
+  above_soilFracLiq      = mLayerFracLiqSnow(nSnow) ! fraction of liquid water in bottom snow layer (-)
+
  else
 
   ! define forcing for the soil domain for the case of no snow layers
   ! NOTE: in case where nSnowOnlyHyd==0 AND snow layers exist, then scalarRainPlusMelt is taken from the previous flux evaluation
-  if(nSnow==0)then
-   scalarRainPlusMelt = (scalarThroughfallRain + scalarCanopyLiqDrainage)/iden_water &  ! liquid flux from the canopy (m s-1)
-                         + drainageMeltPond/iden_water  ! melt of the snow without a layer (m s-1)
-  endif  ! if no snow layers
+  if(nSnow==0)then !no snow layers
+    scalarRainPlusMelt = (scalarThroughfallRain + scalarCanopyLiqDrainage)/iden_water &  ! liquid flux from the canopy (m s-1)
+                          + drainageMeltPond/iden_water  ! melt of the snow without a layer (m s-1)
+ 
+    if(ixVegHyd/=integerMissing)then
+     ! save canopy derivatives
+     above_soilLiqFluxDeriv = scalarCanopyLiqDeriv/iden_water ! derivative in (throughfall + drainage) w.r.t. canopy liquid water
+     above_soildLiq_dTk     = dCanLiq_dTcanopy     ! derivative of canopy liquid storage w.r.t. temperature
+     above_soilFracLiq      = scalarFracLiqVeg     ! fraction of liquid water in canopy (-)
+    else
+     above_soilLiqFluxDeriv = 0._rkind
+     above_soildLiq_dTk     = 0._rkind
+     above_soilFracLiq      = 0._rkind
+    endif
+   else ! snow layers, take from previous flux calculation
+    above_soilLiqFluxDeriv = iLayerLiqFluxSnowDeriv(nSnow) ! derivative in vertical liquid water flux at bottom snow layer interface
+    above_soildLiq_dTk     = mLayerdTheta_dTk(nSnow)  ! derivative in volumetric liquid water content in bottom snow layer w.r.t. temperature
+    above_soilFracLiq      = mLayerFracLiqSnow(nSnow) ! fraction of liquid water in bottom snow layer (-)
+   endif  ! snow layers or not
 
  endif
 
@@ -721,6 +709,13 @@ subroutine computFlux(&
                   ! input: pre-computed deriavatives
                   mLayerdTheta_dTk(nSnow+1:nLayers),         & ! intent(in):    derivative in volumetric liquid water content w.r.t. temperature (K-1)
                   dPsiLiq_dTemp(1:nSoil),                    & ! intent(in):    derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                  dCanopyTrans_dCanWat,                      & ! intent(in):    derivative in canopy transpiration w.r.t. canopy total water content (s-1)
+                  dCanopyTrans_dTCanair,                     & ! intent(in):    derivative in canopy transpiration w.r.t. canopy air temperature (kg m-2 s-1 K-1)
+                  dCanopyTrans_dTCanopy,                     & ! intent(in):    derivative in canopy transpiration w.r.t. canopy temperature (kg m-2 s-1 K-1)
+                  dCanopyTrans_dTGround,                     & ! intent(in):    derivative in canopy transpiration w.r.t. ground temperature (kg m-2 s-1 K-1)
+                  above_soilLiqFluxDeriv,                    & ! intent(in): derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+                  above_soildLiq_dTk,                        & ! intent(in): derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+                  above_soilFracLiq,                         & ! intent(in): fraction of liquid water layer above soil (canopy or snow) (-)
                   ! input: fluxes
                   scalarCanopyTranspiration,                 & ! intent(in):    canopy transpiration (kg m-2 s-1)
                   scalarGroundEvaporation,                   & ! intent(in):    ground evaporation (kg m-2 s-1)
@@ -748,12 +743,72 @@ subroutine computFlux(&
                   ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
                   dq_dHydStateAbove,                         & ! intent(inout): derivatives in the flux w.r.t. matric head in the layer above (s-1)
                   dq_dHydStateBelow,                         & ! intent(inout): derivatives in the flux w.r.t. matric head in the layer below (s-1)
+                  dq_dHydStateLayerSurfVec,                  & ! intent(inout): derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer  (m s-1 or s-1)
                   ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
                   dq_dNrgStateAbove,                         & ! intent(inout): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
                   dq_dNrgStateBelow,                         & ! intent(inout): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                  dq_dNrgStateLayerSurfVec,                  & ! intent(inout): derivative in surface infiltration w.r.t. energy state in above soil snow or canopy and every soil layer (m s-1 K-1)
+                  ! output: derivatives in transpiration w.r.t. canopy state variables
+                  mLayerdTrans_dTCanair,                     & ! intent(inout): derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
+                  mLayerdTrans_dTCanopy,                     & ! intent(inout): derivatives in the soil layer transpiration flux w.r.t. canopy temperature
+                  mLayerdTrans_dTGround,                     & ! intent(inout): derivatives in the soil layer transpiration flux w.r.t. ground temperature
+                  mLayerdTrans_dCanWat,                      & ! intent(inout): derivatives in the soil layer transpiration flux w.r.t. canopy total water
                   ! output: error control
                   err,cmessage)                                ! intent(out): error control
-  if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+  if(err/=0)then
+    message=trim(message)//trim(cmessage)
+    print*, message
+    return
+  endif
+
+  ! calculate the liquid flux through soil
+  ! call soilLiqFlx(&
+  !                 ! input: model control
+  !                 nSoil,                                     & ! intent(in):    number of soil layers
+  !                 firstSplitOper,                            & ! intent(in):    flag indicating first flux call in a splitting operation
+  !                 (scalarSolution .and. .not.firstFluxCall), & ! intent(in):    flag to indicate the scalar solution
+  !                 .true.,                                    & ! intent(in):    flag indicating if derivatives are desired
+  !                 ! input: trial state variables
+  !                 mLayerTempTrial(nSnow+1:nLayers),          & ! intent(in):    trial temperature at the current iteration (K)
+  !                 mLayerMatricHeadLiqTrial(1:nSoil),         & ! intent(in):    liquid water matric potential (m)
+  !                 mLayerVolFracLiqTrial(nSnow+1:nLayers),    & ! intent(in):    volumetric fraction of liquid water (-)
+  !                 mLayerVolFracIceTrial(nSnow+1:nLayers),    & ! intent(in):    volumetric fraction of ice (-)
+  !                 ! input: pre-computed deriavatives
+  !                 mLayerdTheta_dTk(nSnow+1:nLayers),         & ! intent(in):    derivative in volumetric liquid water content w.r.t. temperature (K-1)
+  !                 dPsiLiq_dTemp(1:nSoil),                    & ! intent(in):    derivative in liquid water matric potential w.r.t. temperature (m K-1)
+  !                 ! input: fluxes
+  !                 scalarCanopyTranspiration,                 & ! intent(in):    canopy transpiration (kg m-2 s-1)
+  !                 scalarGroundEvaporation,                   & ! intent(in):    ground evaporation (kg m-2 s-1)
+  !                 scalarRainPlusMelt,                        & ! intent(in):    rain plus melt (m s-1)
+  !                 ! input-output: data structures
+  !                 mpar_data,                                 & ! intent(in):    model parameters
+  !                 indx_data,                                 & ! intent(in):    model indices
+  !                 prog_data,                                 & ! intent(inout): model prognostic variables for a local HRU
+  !                 diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
+  !                 flux_data,                                 & ! intent(inout): model fluxes for a local HRU
+  !                 ! output: diagnostic variables for surface runoff
+  !                 scalarMaxInfilRate,                        & ! intent(inout): maximum infiltration rate (m s-1)
+  !                 scalarInfilArea,                           & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+  !                 scalarFrozenArea,                          & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+  !                 scalarSurfaceRunoff,                       & ! intent(inout): surface runoff (m s-1)
+  !                 ! output: diagnostic variables for model layers
+  !                 mLayerdTheta_dPsi,                         & ! intent(inout): derivative in the soil water characteristic w.r.t. psi (m-1)
+  !                 mLayerdPsi_dTheta,                         & ! intent(inout): derivative in the soil water characteristic w.r.t. theta (m)
+  !                 dHydCond_dMatric,                          & ! intent(inout): derivative in hydraulic conductivity w.r.t matric head (s-1)
+  !                 ! output: fluxes
+  !                 scalarInfiltration,                        & ! intent(inout): surface infiltration rate (m s-1) -- controls on infiltration only computed for iter==1
+  !                 iLayerLiqFluxSoil,                         & ! intent(inout): liquid fluxes at layer interfaces (m s-1)
+  !                 mLayerTranspire,                           & ! intent(inout): transpiration loss from each soil layer (m s-1)
+  !                 mLayerHydCond,                             & ! intent(inout): hydraulic conductivity in each layer (m s-1)
+  !                 ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+  !                 dq_dHydStateAbove,                         & ! intent(inout): derivatives in the flux w.r.t. matric head in the layer above (s-1)
+  !                 dq_dHydStateBelow,                         & ! intent(inout): derivatives in the flux w.r.t. matric head in the layer below (s-1)
+  !                 ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+  !                 dq_dNrgStateAbove,                         & ! intent(inout): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+  !                 dq_dNrgStateBelow,                         & ! intent(inout): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+  !                 ! output: error control
+  !                 err,cmessage)                                ! intent(out): error control
+  ! if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
 
 !   print*, "After soil Liq call ", flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat
 
diff --git a/build/source/engine/read_paramActors.f90 b/build/source/engine/read_paramActors.f90
index 661ffe6..356246f 100755
--- a/build/source/engine/read_paramActors.f90
+++ b/build/source/engine/read_paramActors.f90
@@ -51,7 +51,6 @@ contains
 subroutine read_param(indxHRU,indxGRU,mparStruct,bparStruct,dparStruct,err)
    USE globalData,only:outputStructure
    USE globalData,only:mpar_meta,bpar_meta
-   USE globalData,only:localParFallback                        ! local column default parameters
 
    implicit none
    ! define input
@@ -72,10 +71,6 @@ subroutine read_param(indxHRU,indxGRU,mparStruct,bparStruct,dparStruct,err)
       dparStruct%var(:) = outputStructure(1)%dparStruct(1)%gru(indxGRU)%hru(indxHRU)%var(:)
    ! end do
 
-   ! do iVar=1, size(localParFallback)
-   !    mparStruct%var(iVar)%dat(:) = dparStruct%var(iVar)
-   ! end do
-
    ! populate parameter structures
    do iVar=1, size(mpar_meta)
       mparStruct%var(iVar)%dat(:) = outputStructure(1)%mparStruct(1)%gru(indxGRU)%hru(indxHRU)%var(iVar)%dat(:)
diff --git a/build/source/engine/soilLiqFlx.f90 b/build/source/engine/soilLiqFlx.f90
old mode 100755
new mode 100644
index e5c57fe..06cf0bf
--- a/build/source/engine/soilLiqFlx.f90
+++ b/build/source/engine/soilLiqFlx.f90
@@ -19,1741 +19,1924 @@
 ! along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 module soilLiqFlx_module
-! -----------------------------------------------------------------------------------------------------------
-
-! data types
-USE nrtype
-USE data_types,only:var_d                  ! x%var(:)       (dp)
-USE data_types,only:var_ilength            ! x%var(:)%dat   (i4b)
-USE data_types,only:var_dlength            ! x%var(:)%dat   (dp)
-
-! missing values
-USE globalData,only:integerMissing  ! missing integer
-USE globalData,only:realMissing     ! missing real number
-
-! physical constants
-USE multiconst,only:&
-                    LH_fus,  & ! latent heat of fusion         (J kg-1)
-                    LH_vap,  & ! latent heat of vaporization   (J kg-1)
-                    LH_sub,  & ! latent heat of sublimation    (J kg-1)
-                    gravity, & ! gravitational acceleteration  (m s-2)
-                    Tfreeze, & ! freezing point of pure water  (K)
-                    iden_air,& ! intrinsic density of air      (kg m-3)
-                    iden_ice,& ! intrinsic density of ice      (kg m-3)
-                    iden_water ! intrinsic density of water    (kg m-3)
-
-! named variables
-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
-USE var_lookup,only:iLookINDEX             ! named variables for structure elements
-
-! model decisions
-USE globalData,only:model_decisions        ! model decision structure
-USE var_lookup,only:iLookDECISIONS         ! named variables for elements of the decision structure
-
-! provide access to look-up values for model decisions
-USE mDecisions_module,only:  &
- ! look-up values for method used to compute derivative
- numerical,                  & ! numerical solution
- analytical,                 & ! analytical solution
- ! look-up values for the form of Richards' equation
- moisture,                   & ! moisture-based form of Richards' equation
- mixdform,                   & ! mixed form of Richards' equation
- ! look-up values for the type of hydraulic conductivity profile
- constant,                   & ! constant hydraulic conductivity with depth
- powerLaw_profile,           & ! power-law profile
- ! look-up values for the choice of groundwater parameterization
- qbaseTopmodel,              & ! TOPMODEL-ish baseflow parameterization
- bigBucket,                  & ! a big bucket (lumped aquifer model)
- noExplicit,                 & ! no explicit groundwater parameterization
- ! look-up values for the choice of boundary conditions for hydrology
- prescribedHead,             & ! prescribed head (volumetric liquid water content for mixed form of Richards' eqn)
- funcBottomHead,             & ! function of matric head in the lower-most layer
- freeDrainage,               & ! free drainage
- liquidFlux,                 & ! liquid water flux
- zeroFlux                      ! zero flux
-
-! -----------------------------------------------------------------------------------------------------------
-implicit none
-private
-public::soilLiqFlx
-! constant parameters
-real(dp),parameter     :: verySmall=1.e-12_dp       ! a very small number (used to avoid divide by zero)
-real(dp),parameter     :: dx=1.e-8_dp               ! finite difference increment
-contains
-
-
- ! ***************************************************************************************************************
- ! public subroutine soilLiqFlx: compute liquid water fluxes and their derivatives
- ! ***************************************************************************************************************
- subroutine soilLiqFlx(&
-                       ! input: model control
-                       nSoil,                        & ! intent(in): number of soil layers
-                       doInfiltrate,                 & ! intent(in): flag to compute infiltration
-                       scalarSolution,               & ! intent(in):    flag to indicate the scalar solution
-                       deriv_desired,                & ! intent(in): flag indicating if derivatives are desired
-                       ! input: trial state variables
-                       mLayerTempTrial,              & ! intent(in): temperature (K)
-                       mLayerMatricHeadTrial,        & ! intent(in): matric head (m)
-                       mLayerVolFracLiqTrial,        & ! intent(in): volumetric fraction of liquid water (-)
-                       mLayerVolFracIceTrial,        & ! intent(in): volumetric fraction of ice (-)
-                       ! input: pre-computed derivatives
-                       mLayerdTheta_dTk,             & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
-                       dPsiLiq_dTemp,                & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
-                       ! input: fluxes
-                       scalarCanopyTranspiration,    & ! intent(in): canopy transpiration (kg m-2 s-1)
-                       scalarGroundEvaporation,      & ! intent(in): ground evaporation (kg m-2 s-1)
-                       scalarRainPlusMelt,           & ! intent(in): rain plus melt (m s-1)
-                       ! input-output: data structures
-                       mpar_data,                    & ! intent(in):    model parameters
-                       indx_data,                    & ! intent(in):    model indices
-                       prog_data,                    & ! intent(in):    model prognostic variables for a local HRU
-                       diag_data,                    & ! intent(inout): model diagnostic variables for a local HRU
-                       flux_data,                    & ! intent(inout): model fluxes for a local HRU
-                       ! output: diagnostic variables for surface runoff
-                       xMaxInfilRate,                & ! intent(inout): maximum infiltration rate (m s-1)
-                       scalarInfilArea,              & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
-                       scalarFrozenArea,             & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
-                       scalarSurfaceRunoff,          & ! intent(out): surface runoff (m s-1)
-                       ! output: diagnostic variables for model layers
-                       mLayerdTheta_dPsi,            & ! intent(out): derivative in the soil water characteristic w.r.t. psi (m-1)
-                       mLayerdPsi_dTheta,            & ! intent(out): derivative in the soil water characteristic w.r.t. theta (m)
-                       dHydCond_dMatric,             & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (s-1)
-                       ! output: fluxes
-                       scalarSurfaceInfiltration,    & ! intent(out): surface infiltration rate (m s-1)
-                       iLayerLiqFluxSoil,            & ! intent(out): liquid fluxes at layer interfaces (m s-1)
-                       mLayerTranspire,              & ! intent(out): transpiration loss from each soil layer (m s-1)
-                       mLayerHydCond,                & ! intent(out): hydraulic conductivity in each soil layer (m s-1)
-                       ! output: derivatives in fluxes w.r.t. hydrology state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
-                       dq_dHydStateAbove,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer above (m s-1)
-                       dq_dHydStateBelow,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer below (m s-1)
-                       ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
-                       dq_dNrgStateAbove,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
-                       dq_dNrgStateBelow,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
-                       ! output: error control
-                       err,message)                    ! intent(out): error control
- ! utility modules
- USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water
- USE soil_utils_module,only:matricHead      ! compute matric head (m)
- USE soil_utils_module,only:dTheta_dPsi     ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
- USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
- USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head
- USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content
- USE soil_utils_module,only:hydCondMP_liq   ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- implicit none
- ! input: model control
- integer(i4b),intent(in)          :: nSoil                         ! number of soil layers
- logical(lgt),intent(in)          :: doInfiltrate                  ! flag to compute infiltration
- logical(lgt),intent(in)          :: scalarSolution                ! flag to denote if implementing the scalar solution
- logical(lgt),intent(in)          :: deriv_desired                 ! flag indicating if derivatives are desired
- ! input: trial model state variables
- real(dp),intent(in)              :: mLayerTempTrial(:)            ! temperature in each layer at the current iteration (m)
- real(dp),intent(in)              :: mLayerMatricHeadTrial(:)      ! matric head in each layer at the current iteration (m)
- real(dp),intent(in)              :: mLayerVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the current iteration (-)
- real(dp),intent(in)              :: mLayerVolFracIceTrial(:)      ! volumetric fraction of ice at the current iteration (-)
- ! input: pre-computed derivatves
- real(dp),intent(in)              :: mLayerdTheta_dTk(:)           ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
- real(dp),intent(in)              :: dPsiLiq_dTemp(:)              ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
- ! input: model fluxes
- real(dp),intent(in)              :: scalarCanopyTranspiration     ! canopy transpiration (kg m-2 s-1)
- real(dp),intent(in)              :: scalarGroundEvaporation       ! ground evaporation (kg m-2 s-1)
- real(dp),intent(in)              :: scalarRainPlusMelt            ! rain plus melt (m s-1)
- ! input-output: data structures
- type(var_dlength),intent(in)     :: mpar_data                     ! model parameters
- type(var_ilength),intent(in)     :: indx_data                     ! state vector geometry
- type(var_dlength),intent(in)     :: prog_data                     ! prognostic variables for a local HRU
- type(var_dlength),intent(inout)  :: diag_data                     ! diagnostic variables for a local HRU
- type(var_dlength),intent(inout)  :: flux_data                     ! model fluxes for a local HRU
- ! output: diagnostic variables for surface runoff
- real(dp),intent(inout)           :: xMaxInfilRate                 ! maximum infiltration rate (m s-1)
- real(dp),intent(inout)           :: scalarInfilArea               ! fraction of unfrozen area where water can infiltrate (-)
- real(dp),intent(inout)           :: scalarFrozenArea              ! fraction of area that is considered impermeable due to soil ice (-)
- real(dp),intent(inout)           :: scalarSurfaceRunoff           ! surface runoff (m s-1)
- ! output: diagnostic variables for each layer
- real(dp),intent(inout)           :: mLayerdTheta_dPsi(:)          ! derivative in the soil water characteristic w.r.t. psi (m-1)
- real(dp),intent(inout)           :: mLayerdPsi_dTheta(:)          ! derivative in the soil water characteristic w.r.t. theta (m)
- real(dp),intent(inout)           :: dHydCond_dMatric(:)           ! derivative in hydraulic conductivity w.r.t matric head (s-1)
- ! output: liquid fluxes
- real(dp),intent(inout)           :: scalarSurfaceInfiltration     ! surface infiltration rate (m s-1)
- real(dp),intent(inout)           :: iLayerLiqFluxSoil(0:)         ! liquid flux at soil layer interfaces (m s-1)
- real(dp),intent(inout)           :: mLayerTranspire(:)            ! transpiration loss from each soil layer (m s-1)
- real(dp),intent(inout)           :: mLayerHydCond(:)              ! hydraulic conductivity in each soil layer (m s-1)
- ! output: derivatives in fluxes w.r.t. state variables in the layer above and layer below (m s-1)
- real(dp),intent(inout)           :: dq_dHydStateAbove(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer above
- real(dp),intent(inout)           :: dq_dHydStateBelow(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer below
- ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
- real(dp),intent(inout)           :: dq_dNrgStateAbove(0:)         ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
- real(dp),intent(inout)           :: dq_dNrgStateBelow(0:)         ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)         :: err                           ! error code
- character(*),intent(out)         :: message                       ! error message
- ! -----------------------------------------------------------------------------------------------------------------------------------------------------
- ! local variables: general
- character(LEN=256)               :: cmessage                     ! error message of downwind routine
- integer(i4b)                     :: ibeg,iend                    ! start and end indices of the soil layers in concatanated snow-soil vector
- logical(lgt)                     :: desireAnal                   ! flag to identify if analytical derivatives are desired
- integer(i4b)                     :: iLayer,iSoil                 ! index of soil layer
- integer(i4b)                     :: ixLayerDesired(1)            ! layer desired (scalar solution)
- integer(i4b)                     :: ixTop                        ! top layer in subroutine call
- integer(i4b)                     :: ixBot                        ! bottom layer in subroutine call
- ! additional variables to compute numerical derivatives
- integer(i4b)                     :: nFlux                        ! number of flux calculations required (>1 = numerical derivatives with one-sided finite differences)
- integer(i4b)                     :: itry                         ! index of different flux calculations
- integer(i4b),parameter           :: unperturbed=0                ! named variable to identify the case of unperturbed state variables
- integer(i4b),parameter           :: perturbState=1               ! named variable to identify the case where we perturb the state in the current layer
- integer(i4b),parameter           :: perturbStateAbove=2          ! named variable to identify the case where we perturb the state layer above
- integer(i4b),parameter           :: perturbStateBelow=3          ! named variable to identify the case where we perturb the state layer below
- integer(i4b)                     :: ixPerturb                    ! index of element in 2-element vector to perturb
- integer(i4b)                     :: ixOriginal                   ! index of perturbed element in the original vector
- real(dp)                         :: scalarVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
- real(dp)                         :: scalarMatricHeadTrial        ! trial value of matric head (m)
- real(dp)                         :: scalarHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
- real(dp)                         :: scalarHydCondMicro           ! trial value of hydraulic conductivity of micropores (m s-1)
- real(dp)                         :: scalarHydCondMacro           ! trial value of hydraulic conductivity of macropores (m s-1)
- real(dp)                         :: scalarFlux                   ! vertical flux (m s-1)
- real(dp)                         :: scalarFlux_dStateAbove       ! vertical flux with perturbation to the state above (m s-1)
- real(dp)                         :: scalarFlux_dStateBelow       ! vertical flux with perturbation to the state below (m s-1)
- ! transpiration sink term
- real(dp),dimension(nSoil)        :: mLayerTranspireFrac          ! fraction of transpiration allocated to each soil layer (-)
- ! diagnostic variables
- real(dp),dimension(nSoil)        :: iceImpedeFac                 ! ice impedence factor at layer mid-points (-)
- real(dp),dimension(nSoil)        :: mLayerDiffuse                ! diffusivity at layer mid-point (m2 s-1)
- real(dp),dimension(nSoil)        :: dHydCond_dVolLiq             ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
- real(dp),dimension(nSoil)        :: dDiffuse_dVolLiq             ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
- real(dp),dimension(nSoil)        :: dHydCond_dTemp               ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
- real(dp),dimension(0:nSoil)      :: iLayerHydCond                ! hydraulic conductivity at layer interface (m s-1)
- real(dp),dimension(0:nSoil)      :: iLayerDiffuse                ! diffusivity at layer interface (m2 s-1)
- ! compute surface flux
- integer(i4b)                     :: nRoots                       ! number of soil layers with roots
- integer(i4b)                     :: ixIce                        ! index of the lowest soil layer that contains ice
- real(dp),dimension(0:nSoil)      :: iLayerHeight                 ! height of the layer interfaces (m)
- ! compute fluxes and derivatives at layer interfaces
- real(dp),dimension(2)            :: vectorVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
- real(dp),dimension(2)            :: vectorMatricHeadTrial        ! trial value of matric head (m)
- real(dp),dimension(2)            :: vectorHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
- real(dp),dimension(2)            :: vectorDiffuseTrial           ! trial value of hydraulic diffusivity (m2 s-1)
- real(dp)                         :: scalardPsi_dTheta            ! derivative in soil water characteristix, used for perturbations when computing numerical derivatives
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='soilLiqFlx/'
-
- ! get indices for the data structures
- ibeg = indx_data%var(iLookINDEX%nSnow)%dat(1) + 1
- iend = indx_data%var(iLookINDEX%nSnow)%dat(1) + indx_data%var(iLookINDEX%nSoil)%dat(1)
-
- ! get a copy of iLayerHeight
- ! NOTE: performance hit, though cannot define the shape (0:) with the associate construct
- iLayerHeight(0:nSoil) = prog_data%var(iLookPROG%iLayerHeight)%dat(ibeg-1:iend)  ! height of the layer interfaces (m)
-
- ! make association between local variables and the information in the data structures
- associate(&
-  ! input: model control
-  ixDerivMethod          => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision,   & ! intent(in): index of the method used to calculate flux derivatives
-  ixRichards             => model_decisions(iLookDECISIONS%f_Richards)%iDecision,   & ! intent(in): index of the form of Richards' equation
-  ixBcUpperSoilHydrology => model_decisions(iLookDECISIONS%bcUpprSoiH)%iDecision,   & ! intent(in): index of the upper boundary conditions for soil hydrology
-  ixBcLowerSoilHydrology => model_decisions(iLookDECISIONS%bcLowrSoiH)%iDecision,   & ! intent(in): index of the lower boundary conditions for soil hydrology
-  ! input: model indices
-  ixMatricHead           => indx_data%var(iLookINDEX%ixMatricHead)%dat,             & ! intent(in): indices of soil layers where matric head is the state variable
-  ixSoilOnlyHyd          => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat,            & ! intent(in): index in the state subset for hydrology state variables in the soil domain
-  ! input: model coordinate variables -- NOTE: use of ibeg and iend
-  mLayerDepth            => prog_data%var(iLookPROG%mLayerDepth)%dat(ibeg:iend),    & ! intent(in): depth of the layer (m)
-  mLayerHeight           => prog_data%var(iLookPROG%mLayerHeight)%dat(ibeg:iend),   & ! intent(in): height of the layer mid-point (m)
-  ! input: upper boundary conditions
-  upperBoundHead         => mpar_data%var(iLookPARAM%upperBoundHead)%dat(1),        & ! intent(in): upper boundary condition for matric head (m)
-  upperBoundTheta        => mpar_data%var(iLookPARAM%upperBoundTheta)%dat(1),       & ! intent(in): upper boundary condition for volumetric liquid water content (-)
-  ! input: lower boundary conditions
-  lowerBoundHead         => mpar_data%var(iLookPARAM%lowerBoundHead)%dat(1),        & ! intent(in): lower boundary condition for matric head (m)
-  lowerBoundTheta        => mpar_data%var(iLookPARAM%lowerBoundTheta)%dat(1),       & ! intent(in): lower boundary condition for volumetric liquid water content (-)
-  ! input: vertically variable soil parameters
-  vGn_m                  => diag_data%var(iLookDIAG%scalarVGn_m)%dat,               & ! intent(in): van Genutchen "m" parameter (-)
-  vGn_n                  => mpar_data%var(iLookPARAM%vGn_n)%dat,                    & ! intent(in): van Genutchen "n" parameter (-)
-  vGn_alpha              => mpar_data%var(iLookPARAM%vGn_alpha)%dat,                & ! intent(in): van Genutchen "alpha" parameter (m-1)
-  theta_sat              => mpar_data%var(iLookPARAM%theta_sat)%dat,                & ! intent(in): soil porosity (-)
-  theta_res              => mpar_data%var(iLookPARAM%theta_res)%dat,                & ! intent(in): soil residual volumetric water content (-)
-  ! input: vertically constant soil parameters
-  wettingFrontSuction    => mpar_data%var(iLookPARAM%wettingFrontSuction)%dat(1),   & ! intent(in): Green-Ampt wetting front suction (m)
-  rootingDepth           => mpar_data%var(iLookPARAM%rootingDepth)%dat(1),          & ! intent(in): rooting depth (m)
-  kAnisotropic           => mpar_data%var(iLookPARAM%kAnisotropic)%dat(1),          & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
-  zScale_TOPMODEL        => mpar_data%var(iLookPARAM%zScale_TOPMODEL)%dat(1),       & ! intent(in): TOPMODEL scaling factor (m)
-  qSurfScale             => mpar_data%var(iLookPARAM%qSurfScale)%dat(1),            & ! intent(in): scaling factor in the surface runoff parameterization (-)
-  f_impede               => mpar_data%var(iLookPARAM%f_impede)%dat(1),              & ! intent(in): ice impedence factor (-)
-  soilIceScale           => mpar_data%var(iLookPARAM%soilIceScale)%dat(1),          & ! intent(in): scaling factor for depth of soil ice, used to get frozen fraction (m)
-  soilIceCV              => mpar_data%var(iLookPARAM%soilIceCV)%dat(1),             & ! intent(in): CV of depth of soil ice, used to get frozen fraction (-)
-  theta_mp               => mpar_data%var(iLookPARAM%theta_mp)%dat(1),              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
-  mpExp                  => mpar_data%var(iLookPARAM%mpExp)%dat(1),                 & ! intent(in): empirical exponent in macropore flow equation (-)
-  ! input: saturated hydraulic conductivity
-  mLayerSatHydCondMP     => flux_data%var(iLookFLUX%mLayerSatHydCondMP)%dat,        & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
-  mLayerSatHydCond       => flux_data%var(iLookFLUX%mLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
-  iLayerSatHydCond       => flux_data%var(iLookFLUX%iLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the interface of each layer (m s-1)
-  ! input: factors limiting transpiration (from vegFlux routine)
-  mLayerRootDensity      => diag_data%var(iLookDIAG%mLayerRootDensity)%dat,         & ! intent(in): root density in each layer (-)
-  scalarTranspireLim     => diag_data%var(iLookDIAG%scalarTranspireLim)%dat(1),     & ! intent(in): weighted average of the transpiration limiting factor (-)
-  mLayerTranspireLim     => diag_data%var(iLookDIAG%mLayerTranspireLim)%dat         & ! intent(in): transpiration limiting factor in each layer (-)
- )  ! associating local variables with the information in the data structures
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! preliminaries
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
-
- ! define the pethod to compute derivatives
- !print*, 'numerical derivatives = ', (ixDerivMethod==numerical)
-
- ! numerical derivatives are not implemented yet
- if(ixDerivMethod==numerical)then
-  message=trim(message)//'numerical derivates do not account for the cross derivatives between hydrology and thermodynamics'
-  err=20; return
- end if
-
- ! check the need to compute analytical derivatives
- if(deriv_desired .and. ixDerivMethod==analytical)then
-  desireAnal = .true.
- else
-  desireAnal = .false.
- end if
-
- ! check the need to compute numerical derivatives
- if(deriv_desired .and. ixDerivMethod==numerical)then
-  nFlux=3  ! compute the derivatives using one-sided finite differences
- else
-  nFlux=0  ! compute analytical derivatives
- end if
-
- ! get the indices for the soil layers
- if(scalarSolution)then
-  ixLayerDesired = pack(ixMatricHead, ixSoilOnlyHyd/=integerMissing)
-  ixTop = ixLayerDesired(1)
-  ixBot = ixLayerDesired(1)
- else
-  ixTop = 1
-  ixBot = nSoil
- endif
-
- ! identify the number of layers that contain roots
- nRoots = count(iLayerHeight(0:nSoil-1) < rootingDepth-verySmall)
- if(nRoots==0)then
-  message=trim(message)//'no layers with roots'
-  err=20; return
- endif
-
- ! identify lowest soil layer with ice
- ! NOTE: cannot use count because there may be an unfrozen wedge
- ixIce = 0  ! initialize the index of the ice layer (0 means no ice in the soil profile)
- do iLayer=1,nSoil ! (loop through soil layers)
-  if(mLayerVolFracIceTrial(iLayer) > verySmall) ixIce = iLayer
- end do
- !if(ixIce==nSoil)then; err=20; message=trim(message)//'ice extends to the bottom of the soil profile'; return; end if
-
- ! *************************************************************************************************************************************************
- ! *************************************************************************************************************************************************
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! compute the transpiration sink term
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
-
- ! check the need to compute transpiration (NOTE: intent=inout)
- if( .not. (scalarSolution .and. ixTop>1) )then
-
-  ! compute the fraction of transpiration loss from each soil layer
-  if(scalarTranspireLim > tiny(scalarTranspireLim))then ! (transpiration may be non-zero even if the soil moisture limiting factor is zero)
-   mLayerTranspireFrac(:) = mLayerRootDensity(:)*mLayerTranspireLim(:)/scalarTranspireLim
-  else ! (possible for there to be non-zero conductance and therefore transpiration in this case)
-   mLayerTranspireFrac(:) = mLayerRootDensity(:) / sum(mLayerRootDensity)
-  end if
-
-  ! check fractions sum to one
-  if(abs(sum(mLayerTranspireFrac) - 1._dp) > verySmall)then
-   message=trim(message)//'fraction transpiration in soil layers does not sum to one'
-   err=20; return
-  endif
-
-  ! compute transpiration loss from each soil layer (kg m-2 s-1 --> m s-1)
-  mLayerTranspire = mLayerTranspireFrac(:)*scalarCanopyTranspiration/iden_water
-
-  ! special case of prescribed head -- no transpiration
-  if(ixBcUpperSoilHydrology==prescribedHead) mLayerTranspire(:) = 0._dp
-
- endif  ! if need to compute transpiration
-
- ! *************************************************************************************************************************************************
- ! *************************************************************************************************************************************************
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! compute diagnostic variables at the nodes throughout the soil profile
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- do iSoil=ixTop,min(ixBot+1,nSoil) ! (loop through soil layers)
-
-  call diagv_node(&
-                  ! input: model control
-                  desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
-                  ixRichards,                      & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
-                  ! input: state variables
-                  mLayerTempTrial(iSoil),          & ! intent(in): temperature (K)
-                  mLayerMatricHeadTrial(iSoil),    & ! intent(in): matric head in each layer (m)
-                  mLayerVolFracLiqTrial(iSoil),    & ! intent(in): volumetric liquid water content in each soil layer (-)
-                  mLayerVolFracIceTrial(iSoil),    & ! intent(in): volumetric ice content in each soil layer (-)
-                  ! input: pre-computed deriavatives
-                  mLayerdTheta_dTk(iSoil),         & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
-                  dPsiLiq_dTemp(iSoil),            & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
-                  ! input: soil parameters
-                  vGn_alpha(iSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                  vGn_n(iSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
-                  VGn_m(iSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
-                  mpExp,                           & ! intent(in): empirical exponent in macropore flow equation (-)
-                  theta_sat(iSoil),                & ! intent(in): soil porosity (-)
-                  theta_res(iSoil),                & ! intent(in): soil residual volumetric water content (-)
-                  theta_mp,                        & ! intent(in): volumetric liquid water content when macropore flow begins (-)
-                  f_impede,                        & ! intent(in): ice impedence factor (-)
-                  ! input: saturated hydraulic conductivity
-                  mLayerSatHydCond(iSoil),         & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
-                  mLayerSatHydCondMP(iSoil),       & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
-                  ! output: derivative in the soil water characteristic
-                  mLayerdPsi_dTheta(iSoil),        & ! intent(out): derivative in the soil water characteristic
-                  mLayerdTheta_dPsi(iSoil),        & ! intent(out): derivative in the soil water characteristic
-                  ! output: transmittance
-                  mLayerHydCond(iSoil),            & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
-                  mLayerDiffuse(iSoil),            & ! intent(out): diffusivity at layer mid-points (m2 s-1)
-                  iceImpedeFac(iSoil),             & ! intent(out): ice impedence factor in each layer (-)
-                  ! output: transmittance derivatives
-                  dHydCond_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
-                  dDiffuse_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
-                  dHydCond_dMatric(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
-                  dHydCond_dTemp(iSoil),           & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                  ! output: error control
-                  err,cmessage)                      ! intent(out): error control
-  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
-
- end do  ! (looping through soil layers)
-
- ! *************************************************************************************************************************************************
- ! *************************************************************************************************************************************************
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
-
- ! set derivative w.r.t. state above to zero (does not exist)
- dq_dHydStateAbove(0) = 0._dp
- dq_dNrgStateAbove(0) = 0._dp
-
- ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
- do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
-
-  ! =====
-  ! get input state variables...
-  ! ============================
-  ! identify the type of perturbation
-  select case(itry)
-
-   ! skip undesired perturbations
-   case(perturbStateAbove); cycle  ! cannot perturb state above (does not exist) -- so keep cycling
-   case(perturbState); cycle       ! perturbing the layer below the flux at the top interface
-
-   ! un-perturbed case
-   case(unperturbed)
-    scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
-    scalarMatricHeadTrial = mLayerMatricHeadTrial(1)
-
-   ! perturb soil state (one-sided finite differences)
-   case(perturbStateBelow)
-    ! (perturbation depends on the form of Richards' equation)
-    select case(ixRichards)
-     case(moisture)
-      scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1) + dx
-      scalarMatricHeadTrial = mLayerMatricHeadTrial(1)
-     case(mixdform)
-      scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
-      scalarMatricHeadTrial = mLayerMatricHeadTrial(1) + dx
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select ! (form of Richards' equation
-   ! check for an unknown perturbation
-   case default; err=10; message=trim(message)//"unknown perturbation"; return
-
-  end select ! (type of perturbation)
-
-  ! =====
-  ! compute surface flux and its derivative...
-  ! ==========================================
-
-  call surfaceFlx(&
-                  ! input: model control
-                  doInfiltrate,                       & ! intent(in): flag indicating if desire to compute infiltration
-                  desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
-                  ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
-                  ixBcUpperSoilHydrology,             & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
-                  nRoots,                             & ! intent(in): number of layers that contain roots
-                  ixIce,                              & ! intent(in): index of lowest ice layer
-                  ! input: state variables
-                  scalarMatricHeadTrial,              & ! intent(in): matric head in the upper-most soil layer (m)
-                  scalarVolFracLiqTrial,              & ! intent(in): volumetric liquid water content the upper-most soil layer (-)
-                  mLayerVolFracLiqTrial,              & ! intent(in): volumetric liquid water content in each soil layer (-)
-                  mLayerVolFracIceTrial,              & ! intent(in): volumetric ice content in each soil layer (-)
-                  ! input: depth of upper-most soil layer (m)
-                  mLayerDepth,                        & ! intent(in): depth of each soil layer (m)
-                  iLayerHeight,                       & ! intent(in): height at the interface of each layer (m)
-                  ! input: boundary conditions
-                  upperBoundHead,                     & ! intent(in): upper boundary condition (m)
-                  upperBoundTheta,                    & ! intent(in): upper boundary condition (-)
-                  ! input: flux at the upper boundary
-                  scalarRainPlusMelt,                 & ! intent(in): rain plus melt (m s-1)
-                  ! input: transmittance
-                  iLayerSatHydCond(0),                & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
-                  dHydCond_dTemp(1),                  & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                  iceImpedeFac(1),                    & ! intent(in): ice impedence factor in the upper-most soil layer (-)
-                  ! input: soil parameters
-                  vGn_alpha(1),                       & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                  vGn_n(1),                           & ! intent(in): van Genutchen "n" parameter (-)
-                  VGn_m(1),                           & ! intent(in): van Genutchen "m" parameter (-)
-                  theta_sat(1),                       & ! intent(in): soil porosity (-)
-                  theta_res(1),                       & ! intent(in): soil residual volumetric water content (-)
-                  qSurfScale,                         & ! intent(in): scaling factor in the surface runoff parameterization (-)
-                  zScale_TOPMODEL,                    & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
-                  rootingDepth,                       & ! intent(in): rooting depth (m)
-                  wettingFrontSuction,                & ! intent(in): Green-Ampt wetting front suction (m)
-                  soilIceScale,                       & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
-                  soilIceCV,                          & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
-                  ! input-output: hydraulic conductivity and diffusivity at the surface
-                  iLayerHydCond(0),                   & ! intent(inout): hydraulic conductivity at the surface (m s-1)
-                  iLayerDiffuse(0),                   & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
-                  ! input-output: fluxes at layer interfaces and surface runoff
-                  xMaxInfilRate,                      & ! intent(inout): maximum infiltration rate (m s-1)
-                  scalarInfilArea,                    & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
-                  scalarFrozenArea,                   & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
-                  scalarSurfaceRunoff,                & ! intent(out): surface runoff (m s-1)
-                  scalarSurfaceInfiltration,          & ! intent(out): surface infiltration (m s-1)
-                  ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
-                  dq_dHydStateBelow(0),               & ! intent(inout): derivative in surface infiltration w.r.t. hydrology state variable in the upper-most soil layer (m s-1 or s-1)
-                  dq_dNrgStateBelow(0),               & ! intent(out):   derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
-                  ! output: error control
-                  err,cmessage)                         ! intent(out): error control
-  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
-  ! print*, "scalarGroundEvaporation =", scalarGroundEvaporation
-  ! include base soil evaporation as the upper boundary flux
-  iLayerLiqFluxSoil(0) = scalarGroundEvaporation/iden_water + scalarSurfaceInfiltration
-
-  ! get copies of surface flux to compute numerical derivatives
-  if(deriv_desired .and. ixDerivMethod==numerical)then
-   select case(itry)
-    case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(0)
-    case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(0)
-    case default; err=10; message=trim(message)//"unknown perturbation"; return
-   end select
-  end if
-
-  ! write(*,'(a,1x,10(f30.15))') 'scalarRainPlusMelt, scalarSurfaceInfiltration = ', scalarRainPlusMelt, scalarSurfaceInfiltration
-
- end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
-
- ! compute numerical derivatives
- if(deriv_desired .and. ixDerivMethod==numerical)then
-  dq_dHydStateBelow(0) = (scalarFlux_dStateBelow - scalarFlux)/dx ! change in surface flux w.r.t. change in the soil moisture in the top soil layer (m s-1)
- end if
-!  print*, 'scalarSurfaceInfiltration, iLayerLiqFluxSoil(0) = ', scalarSurfaceInfiltration, iLayerLiqFluxSoil(0)
- !print*, '(ixDerivMethod==numerical), dq_dHydStateBelow(0) = ', (ixDerivMethod==numerical), dq_dHydStateBelow(0)
- !pause
-
- ! *************************************************************************************************************************************************
- ! *************************************************************************************************************************************************
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! * compute fluxes and derivatives at layer interfaces...
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
-
- ! NOTE: computing flux at the bottom of the layer
-
- ! loop through soil layers
- do iLayer=ixTop,min(ixBot,nSoil-1)
-
-  ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
-  do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
-
-   ! =====
-   ! determine layer to perturb
-   ! ============================
-   select case(itry)
-    ! skip undesired perturbations
-    case(perturbState); cycle       ! perturbing the layers above and below the flux at the interface
-    ! identify the index for the perturbation
-    case(unperturbed);       ixPerturb = 0
-    case(perturbStateAbove); ixPerturb = 1
-    case(perturbStateBelow); ixPerturb = 2
-    case default; err=10; message=trim(message)//"unknown perturbation"; return
-   end select ! (identifying layer to of perturbation)
-   ! determine the index in the original vector
-   ixOriginal = iLayer + (ixPerturb-1)
-
-   ! =====
-   ! get input state variables...
-   ! ============================
-   ! start with the un-perturbed case
-   vectorVolFracLiqTrial(1:2) = mLayerVolFracLiqTrial(iLayer:iLayer+1)
-   vectorMatricHeadTrial(1:2) = mLayerMatricHeadTrial(iLayer:iLayer+1)
-   ! make appropriate perturbations
-   if(ixPerturb > 0)then
-    select case(ixRichards)
-     case(moisture); vectorVolFracLiqTrial(ixPerturb) = vectorVolFracLiqTrial(ixPerturb) + dx
-     case(mixdform); vectorMatricHeadTrial(ixPerturb) = vectorMatricHeadTrial(ixPerturb) + dx
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select ! (form of Richards' equation)
-   end if
-
-   ! =====
-   ! get hydraulic conductivty...
-   ! ============================
-   ! start with the un-perturbed case
-   vectorHydCondTrial(1:2) = mLayerHydCond(iLayer:iLayer+1)
-   vectorDiffuseTrial(1:2) = mLayerDiffuse(iLayer:iLayer+1)
-   ! make appropriate perturbations
-   if(ixPerturb > 0)then
-    select case(ixRichards)
-     case(moisture)
-      scalardPsi_dTheta             = dPsi_dTheta(vectorVolFracLiqTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
-      vectorHydCondTrial(ixPerturb) = hydCond_liq(vectorVolFracLiqTrial(ixPerturb),mLayerSatHydCond(ixOriginal),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
-      vectorDiffuseTrial(ixPerturb) = scalardPsi_dTheta * vectorHydCondTrial(ixPerturb)
-     case(mixdform)
-      scalarVolFracLiqTrial = volFracLiq(vectorMatricHeadTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
-      scalarHydCondMicro    = hydCond_psi(vectorMatricHeadTrial(ixPerturb),mLayerSatHydCond(ixOriginal),vGn_alpha(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
-      scalarHydCondMacro    = hydCondMP_liq(scalarVolFracLiqTrial,theta_sat(ixPerturb),theta_mp,mpExp,mLayerSatHydCondMP(ixOriginal),mLayerSatHydCond(ixOriginal))
-      vectorHydCondTrial(ixPerturb) = scalarHydCondMicro + scalarHydCondMacro
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select ! (form of Richards' equation)
-   end if
-
-   ! =====
-   ! compute vertical flux at layer interface and its derivative w.r.t. the state above and the state below...
-   ! =========================================================================================================
-
-   ! NOTE: computing flux at the bottom of the layer
-
-   call iLayerFlux(&
-                   ! input: model control
-                   desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
-                   ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
-                   ! input: state variables (adjacent layers)
-                   vectorMatricHeadTrial,              & ! intent(in): matric head at the soil nodes (m)
-                   vectorVolFracLiqTrial,              & ! intent(in): volumetric liquid water content at the soil nodes (-)
-                   ! input: model coordinate variables (adjacent layers)
-                   mLayerHeight(iLayer:iLayer+1),      & ! intent(in): height of the soil nodes (m)
-                   ! input: temperature derivatives
-                   dPsiLiq_dTemp(iLayer:iLayer+1),     & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
-                   dHydCond_dTemp(iLayer:iLayer+1),    & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                   ! input: transmittance (adjacent layers)
-                   vectorHydCondTrial,                 & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
-                   vectorDiffuseTrial,                 & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
-                   ! input: transmittance derivatives (adjacent layers)
-                   dHydCond_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
-                   dDiffuse_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
-                   dHydCond_dMatric(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in matric head (s-1)
-                   ! output: tranmsmittance at the layer interface (scalars)
-                   iLayerHydCond(iLayer),              & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
-                   iLayerDiffuse(iLayer),              & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
-                   ! output: vertical flux at the layer interface (scalars)
-                   iLayerLiqFluxSoil(iLayer),          & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
-                   ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
-                   dq_dHydStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
-                   dq_dHydStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
-                   ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
-                   dq_dNrgStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
-                   dq_dNrgStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
-                   ! output: error control
-                   err,cmessage)                         ! intent(out): error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
-
-   ! compute total vertical flux, to compute derivatives
-   if(deriv_desired .and. ixDerivMethod==numerical)then
-    select case(itry)
-     case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(iLayer)
-     case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(iLayer)
-     case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(iLayer)
-     case default; err=10; message=trim(message)//"unknown perturbation"; return
-    end select
-   end if
-
-  end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
-
-  ! compute numerical derivatives
-  if(deriv_desired .and. ixDerivMethod==numerical)then
-   dq_dHydStateAbove(iLayer) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
-   dq_dHydStateBelow(iLayer) = (scalarFlux_dStateBelow - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
-  end if
-
-  ! check
-  !if(iLayer==6) write(*,'(a,i4,1x,10(e25.15,1x))') 'iLayer, vectorMatricHeadTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer) = ',&
-  !                                                  iLayer, vectorMatricHeadTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer)
-  !if(iLayer==1) write(*,'(a,i4,1x,L1,1x,2(e15.5,1x))') 'iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer) = ', &
-  !                                                      iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer)
-  !pause
-
- end do  ! (looping through soil layers)
-
- ! add infiltration to the upper-most unfrozen layer
- ! NOTE: this is done here rather than in surface runoff
- !iLayerLiqFluxSoil(ixIce) = iLayerLiqFluxSoil(ixIce) + scalarSurfaceInfiltration
-
- ! *************************************************************************************************************************************************
- ! *************************************************************************************************************************************************
-
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
- ! * compute drainage flux from the bottom of the soil profile, and its derivative
- ! -------------------------------------------------------------------------------------------------------------------------------------------------
-
- ! define the need to compute drainage
- if( .not. (scalarSolution .and. ixTop<nSoil) )then
-
-  ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
-  do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
-
-   ! =====
-   ! get input state variables...
-   ! ============================
-   ! identify the type of perturbation
-   select case(itry)
-
-    ! skip undesired perturbations
-    case(perturbStateBelow); cycle   ! only perturb soil state at this time (perhaps perturb aquifer state later)
-    case(perturbState); cycle        ! here pertubing the state above the flux at the interface
-
-    ! un-perturbed case
-    case(unperturbed)
-     scalarVolFracLiqTrial   = mLayerVolFracLiqTrial(nSoil)
-     scalarMatricHeadTrial   = mLayerMatricHeadTrial(nSoil)
-
-    ! perturb soil state (one-sided finite differences)
-    case(perturbStateAbove)
-     select case(ixRichards)  ! (perturbation depends on the form of Richards' equation)
-      case(moisture)
-       scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil) + dx
-       scalarMatricHeadTrial = mLayerMatricHeadTrial(nSoil)
-      case(mixdform)
-       scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil)
-       scalarMatricHeadTrial = mLayerMatricHeadTrial(nSoil) + dx
-      case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-     end select ! (form of Richards' equation)
-
-   end select ! (type of perturbation)
-
-   ! =====
-   ! get hydraulic conductivty...
-   ! ============================
-   select case(itry)
-
-    ! compute perturbed value of hydraulic conductivity
-    case(perturbStateAbove)
-     select case(ixRichards)
-      case(moisture); scalarHydCondTrial = hydCond_liq(scalarVolFracLiqTrial,mLayerSatHydCond(nSoil),theta_res(nSoil),theta_sat(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
-      case(mixdform); scalarHydCondTrial = hydCond_psi(scalarMatricHeadTrial,mLayerSatHydCond(nSoil),vGn_alpha(nSoil),vGn_n(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
-     end select
-
-    ! (use un-perturbed value)
-    case default
-     scalarHydCondTrial = mLayerHydCond(nSoil)        ! hydraulic conductivity at the mid-point of the lowest unsaturated soil layer (m s-1)
-
-   end select ! (re-computing hydraulic conductivity)
-
-   ! =====
-   ! compute drainage flux and its derivative...
-   ! ===========================================
-
-   call qDrainFlux(&
-                   ! input: model control
-                   desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
-                   ixRichards,                      & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
-                   ixBcLowerSoilHydrology,          & ! intent(in): index defining the type of boundary conditions
-                   ! input: state variables
-                   scalarMatricHeadTrial,           & ! intent(in): matric head in the lowest unsaturated node (m)
-                   scalarVolFracLiqTrial,           & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
-                   ! input: model coordinate variables
-                   mLayerDepth(nSoil),              & ! intent(in): depth of the lowest unsaturated soil layer (m)
-                   mLayerHeight(nSoil),             & ! intent(in): height of the lowest unsaturated soil node (m)
-                   ! input: boundary conditions
-                   lowerBoundHead,                  & ! intent(in): lower boundary condition (m)
-                   lowerBoundTheta,                 & ! intent(in): lower boundary condition (-)
-                   ! input: derivative in the soil water characteristic
-                   mLayerdPsi_dTheta(nSoil),        & ! intent(in): derivative in the soil water characteristic
-                   ! input: transmittance
-                   iLayerSatHydCond(0),             & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
-                   iLayerSatHydCond(nSoil),         & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
-                   scalarHydCondTrial,              & ! intent(in): hydraulic conductivity at the node itself (m s-1)
-                   iceImpedeFac(nSoil),             & ! intent(in): ice impedence factor in the lower-most soil layer (-)
-                   ! input: transmittance derivatives
-                   dHydCond_dVolLiq(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
-                   dHydCond_dMatric(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
-                   dHydCond_dTemp(nSoil),           & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                   ! input: soil parameters
-                   vGn_alpha(nSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                   vGn_n(nSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
-                   VGn_m(nSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
-                   theta_sat(nSoil),                & ! intent(in): soil porosity (-)
-                   theta_res(nSoil),                & ! intent(in): soil residual volumetric water content (-)
-                   kAnisotropic,                    & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
-                   zScale_TOPMODEL,                 & ! intent(in): TOPMODEL scaling factor (m)
-                   ! output: hydraulic conductivity and diffusivity at the surface
-                   iLayerHydCond(nSoil),            & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
-                   iLayerDiffuse(nSoil),            & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
-                   ! output: drainage flux
-                   iLayerLiqFluxSoil(nSoil),        & ! intent(out): drainage flux (m s-1)
-                   ! output: derivatives in drainage flux
-                   dq_dHydStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in hydrology state in lowest unsaturated node (m s-1 or s-1)
-                   dq_dNrgStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in energy state in lowest unsaturated node (m s-1 or s-1)
-                   ! output: error control
-                   err,cmessage)                ! intent(out): error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
-
-   ! get copies of drainage flux to compute derivatives
-   if(deriv_desired .and. ixDerivMethod==numerical)then
-    select case(itry)
-     case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(nSoil)
-     case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(nSoil)
-     case(perturbStateBelow); err=20; message=trim(message)//'lower state should never be perturbed when computing drainage do not expect to get here'; return
-     case default; err=10; message=trim(message)//"unknown perturbation"; return
-    end select
-   end if
-
-  end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
-
-  ! compute numerical derivatives
-  ! NOTE: drainage derivatives w.r.t. state below are *actually* w.r.t. water table depth, so need to be corrected for aquifer storage
-  !       (note also negative sign to account for inverse relationship between water table depth and aquifer storage)
-  if(deriv_desired .and. ixDerivMethod==numerical)then
-   dq_dHydStateAbove(nSoil) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in state in lowest unsaturated node (m s-1 or s-1)
-  end if
-
-  ! no dependence on the aquifer for drainage
-  dq_dHydStateBelow(nSoil) = 0._dp  ! keep this here in case we want to couple some day....
-  dq_dNrgStateBelow(nSoil) = 0._dp  ! keep this here in case we want to couple some day....
-
-  ! print drainage
-  !print*, 'iLayerLiqFluxSoil(nSoil) = ', iLayerLiqFluxSoil(nSoil)
-
- endif  ! if computing drainage
- ! end of drainage section
-
- ! *****************************************************************************************************************************************************************
- ! *****************************************************************************************************************************************************************
-
- ! end association between local variables and the information in the data structures
- end associate
-
- end subroutine soilLiqFlx
-
- ! ***************************************************************************************************************
- ! private subroutine diagv_node: compute transmittance and derivatives for model nodes
- ! ***************************************************************************************************************
- subroutine diagv_node(&
-                       ! input: model control
-                       deriv_desired,         & ! intent(in): flag indicating if derivatives are desired
-                       ixRichards,            & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
-                       ! input: state variables
-                       scalarTempTrial,       & ! intent(in): temperature (K)
-                       scalarMatricHeadTrial, & ! intent(in): matric head in a given layer (m)
-                       scalarVolFracLiqTrial, & ! intent(in): volumetric liquid water content in a given soil layer (-)
-                       scalarVolFracIceTrial, & ! intent(in): volumetric ice content in a given soil layer (-)
-                       ! input: pre-computed deriavatives
-                       dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
-                       dPsiLiq_dTemp,         & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
-                       ! input: soil parameters
-                       vGn_alpha,             & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                       vGn_n,                 & ! intent(in): van Genutchen "n" parameter (-)
-                       VGn_m,                 & ! intent(in): van Genutchen "m" parameter (-)
-                       mpExp,                 & ! intent(in): empirical exponent in macropore flow equation (-)
-                       theta_sat,             & ! intent(in): soil porosity (-)
-                       theta_res,             & ! intent(in): soil residual volumetric water content (-)
-                       theta_mp,              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
-                       f_impede,              & ! intent(in): ice impedence factor (-)
-                       ! input: saturated hydraulic conductivity
-                       scalarSatHydCond,      & ! intent(in): saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
-                       scalarSatHydCondMP,    & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
-                       ! output: derivative in the soil water characteristic
-                       scalardPsi_dTheta,     & ! derivative in the soil water characteristic
-                       scalardTheta_dPsi,     & ! derivative in the soil water characteristic
-                       ! output: transmittance
-                       scalarHydCond,         & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
-                       scalarDiffuse,         & ! intent(out): diffusivity at layer mid-points (m2 s-1)
-                       iceImpedeFac,          & ! intent(out): ice impedence factor in each layer (-)
-                       ! output: transmittance derivatives
-                       dHydCond_dVolLiq,      & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
-                       dDiffuse_dVolLiq,      & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
-                       dHydCond_dMatric,      & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
-                       dHydCond_dTemp,        & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                       ! output: error control
-                       err,message)             ! intent(out): error control
- USE soil_utils_module,only:iceImpede           ! compute the ice impedence factor
- USE soil_utils_module,only:volFracLiq          ! compute volumetric fraction of liquid water as a function of matric head
- USE soil_utils_module,only:matricHead          ! compute matric head (m)
- USE soil_utils_module,only:hydCond_psi         ! compute hydraulic conductivity as a function of matric head
- USE soil_utils_module,only:hydCond_liq         ! compute hydraulic conductivity as a function of volumetric liquid water content
- USE soil_utils_module,only:hydCondMP_liq       ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
- USE soil_utils_module,only:dTheta_dPsi         ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
- USE soil_utils_module,only:dPsi_dTheta         ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
- USE soil_utils_module,only:dPsi_dTheta2        ! compute derivative in dPsi_dTheta (m)
- USE soil_utils_module,only:dHydCond_dLiq       ! compute derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
- USE soil_utils_module,only:dHydCond_dPsi       ! compute derivative in hydraulic conductivity w.r.t. matric head (s-1)
- USE soil_utils_module,only:dIceImpede_dTemp    ! compute the derivative in the ice impedance factor w.r.t. temperature (K-1)
- ! compute hydraulic transmittance and derivatives for all layers
- implicit none
- ! input: model control
- logical(lgt),intent(in)       :: deriv_desired             ! flag indicating if derivatives are desired
- integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
- ! input: state and diagnostic variables
- real(dp),intent(in)           :: scalarTempTrial           ! temperature in each layer (K)
- real(dp),intent(in)           :: scalarMatricHeadTrial     ! matric head in each layer (m)
- real(dp),intent(in)           :: scalarVolFracLiqTrial     ! volumetric fraction of liquid water in a given layer (-)
- real(dp),intent(in)           :: scalarVolFracIceTrial     ! volumetric fraction of ice in a given layer (-)
- ! input: pre-computed deriavatives
- real(dp),intent(in)           :: dTheta_dTk                ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
- real(dp),intent(in)           :: dPsiLiq_dTemp             ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
- ! input: soil parameters
- real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
- real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
- real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
- real(dp),intent(in)           :: mpExp                     ! empirical exponent in macropore flow equation (-)
- real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
- real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
- real(dp),intent(in)           :: theta_mp                  ! volumetric liquid water content when macropore flow begins (-)
- real(dp),intent(in)           :: f_impede                  ! ice impedence factor (-)
- ! input: saturated hydraulic conductivity
- real(dp),intent(in)           :: scalarSatHydCond          ! saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
- real(dp),intent(in)           :: scalarSatHydCondMP        ! saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
- ! output: derivative in the soil water characteristic
- real(dp),intent(out)          :: scalardPsi_dTheta         ! derivative in the soil water characteristic
- real(dp),intent(out)          :: scalardTheta_dPsi         ! derivative in the soil water characteristic
- ! output: transmittance
- real(dp),intent(out)          :: scalarHydCond             ! hydraulic conductivity at layer mid-points (m s-1)
- real(dp),intent(out)          :: scalarDiffuse             ! diffusivity at layer mid-points (m2 s-1)
- real(dp),intent(out)          :: iceImpedeFac              ! ice impedence factor in each layer (-)
- ! output: transmittance derivatives
- real(dp),intent(out)          :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
- real(dp),intent(out)          :: dDiffuse_dVolLiq          ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
- real(dp),intent(out)          :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t matric head (s-1)
- real(dp),intent(out)          :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)      :: err                       ! error code
- character(*),intent(out)      :: message                   ! error message
- ! local variables
- real(dp)                      :: localVolFracLiq           ! local volumetric fraction of liquid water
- real(dp)                      :: scalarHydCondMP           ! hydraulic conductivity of macropores at layer mid-points (m s-1)
- real(dp)                      :: dIceImpede_dT             ! derivative in ice impedance factor w.r.t. temperature (K-1)
- real(dp)                      :: dHydCondMacro_dVolLiq     ! derivative in hydraulic conductivity of macropores w.r.t volumetric liquid water content (m s-1)
- real(dp)                      :: dHydCondMacro_dMatric     ! derivative in hydraulic conductivity of macropores w.r.t matric head (s-1)
- real(dp)                      :: dHydCondMicro_dMatric     ! derivative in hydraulic conductivity of micropores w.r.t matric head (s-1)
- real(dp)                      :: dHydCondMicro_dTemp       ! derivative in hydraulic conductivity of micropores w.r.t temperature (m s-1 K-1)
- real(dp)                      :: dPsi_dTheta2a             ! derivative in dPsi_dTheta (analytical)
- real(dp)                      :: dIceImpede_dLiq           ! derivative in ice impedence factor w.r.t. volumetric liquid water content (-)
- real(dp)                      :: hydCond_noIce             ! hydraulic conductivity in the absence of ice (m s-1)
- real(dp)                      :: dK_dLiq__noIce            ! derivative in hydraulic conductivity w.r.t volumetric liquid water content, in the absence of ice (m s-1)
- real(dp)                      :: dK_dPsi__noIce            ! derivative in hydraulic conductivity w.r.t matric head, in the absence of ice (s-1)
- real(dp)                      :: relSatMP                  ! relative saturation of macropores (-)
- ! local variables to test the derivative
- logical(lgt),parameter        :: testDeriv=.false.         ! local flag to test the derivative
- real(dp)                      :: xConst                    ! LH_fus/(gravity*Tfreeze), used in freezing point depression equation (m K-1)
- real(dp)                      :: vTheta                    ! volumetric fraction of total water (-)
- real(dp)                      :: volLiq                    ! volumetric fraction of liquid water (-)
- real(dp)                      :: volIce                    ! volumetric fraction of ice (-)
- real(dp)                      :: volFracLiq1,volFracLiq2   ! different trial values of volumetric liquid water content (-)
- real(dp)                      :: effSat                    ! effective saturation (-)
- real(dp)                      :: psiLiq                    ! liquid water matric potential (m)
- real(dp)                      :: hydCon                    ! hydraulic conductivity (m s-1)
- real(dp)                      :: hydIce                    ! hydraulic conductivity after accounting for ice impedance (-)
- real(dp),parameter            :: dx = 1.e-8_dp             ! finite difference increment (m)
- ! initialize error control
- err=0; message="diagv_node/"
-
- ! *****
- ! compute the derivative in the soil water characteristic
- select case(ixRichards)
-  case(moisture)
-   scalardPsi_dTheta = dPsi_dTheta(scalarvolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-   scalardTheta_dPsi = realMissing  ! (deliberately cause problems if this is ever used)
-  case(mixdform)
-   scalardTheta_dPsi = dTheta_dPsi(scalarMatricHeadTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-   scalardPsi_dTheta = dPsi_dTheta(scalarvolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-   if(testDeriv)then
-    volFracLiq1 = volFracLiq(scalarMatricHeadTrial,   vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-    volFracLiq2 = volFracLiq(scalarMatricHeadTrial+dx,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-   end if  ! (testing the derivative)
-  case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
- end select
-
- ! *****
- ! compute hydraulic conductivity and its derivative in each soil layer
-
- ! compute the ice impedence factor and its derivative w.r.t. volumetric liquid water content (-)
- call iceImpede(scalarVolFracIceTrial,f_impede, &  ! input
-                iceImpedeFac,dIceImpede_dLiq)      ! output
-
- select case(ixRichards)
-  ! ***** moisture-based form of Richards' equation
-  case(moisture)
-   ! haven't included macropores yet
-   err=20; message=trim(message)//'still need to include macropores for the moisture-based form of Richards eqn'; return
-   ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
-   hydCond_noIce = hydCond_liq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m)
-   scalarHydCond = hydCond_noIce*iceImpedeFac
-   scalarDiffuse = scalardPsi_dTheta * scalarHydCond
-   ! compute derivative in hydraulic conductivity (m s-1) and hydraulic diffusivity (m2 s-1)
-   if(deriv_desired)then
-    if(scalarVolFracIceTrial > epsilon(iceImpedeFac))then
-     dK_dLiq__noIce   = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)  ! [.true. = analytical]
-     dHydCond_dVolLiq = hydCond_noIce*dIceImpede_dLiq + dK_dLiq__noIce*iceImpedeFac
-    else
-     dHydCond_dVolLiq = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)
-    end if
-    dPsi_dTheta2a    = dPsi_dTheta2(scalarVolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m,.true.)   ! [.true. = analytical] compute derivative in dPsi_dTheta (m)
-    dDiffuse_dVolLiq = dHydCond_dVolLiq*scalardPsi_dTheta + scalarHydCond*dPsi_dTheta2a
-    dHydCond_dMatric = realMissing ! not used, so cause problems
-   end if
-
-  ! ***** mixed form of Richards' equation -- just compute hydraulic condictivity
-  case(mixdform)
-   ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
-   hydCond_noIce = hydCond_psi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
-   scalarDiffuse = realMissing ! not used, so cause problems
-   ! compute the hydraulic conductivity of macropores (m s-1)
-   localVolFracLiq = volFracLiq(scalarMatricHeadTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-   scalarHydCondMP = hydCondMP_liq(localVolFracLiq,theta_sat,theta_mp,mpExp,scalarSatHydCondMP,scalarSatHydCond)
-   scalarHydCond   = hydCond_noIce*iceImpedeFac + scalarHydCondMP
-
-   ! compute derivative in hydraulic conductivity (m s-1)
-   if(deriv_desired)then
-    ! (compute derivative for macropores)
-    if(localVolFracLiq > theta_mp)then
-     relSatMP              = (localVolFracLiq - theta_mp)/(theta_sat - theta_mp)
-     dHydCondMacro_dVolLiq = ((scalarSatHydCondMP - scalarSatHydCond)/(theta_sat - theta_mp))*mpExp*(relSatMP**(mpExp - 1._dp))
-     dHydCondMacro_dMatric = scalardTheta_dPsi*dHydCondMacro_dVolLiq
-    else
-     dHydCondMacro_dVolLiq = 0._dp
-     dHydCondMacro_dMatric = 0._dp
-    end if
-    ! (compute derivatives for micropores)
-    if(scalarVolFracIceTrial > verySmall)then
-     dK_dPsi__noIce        = dHydCond_dPsi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)  ! analytical
-     dHydCondMicro_dTemp   = dPsiLiq_dTemp*dK_dPsi__noIce  ! m s-1 K-1
-     dHydCondMicro_dMatric = hydCond_noIce*dIceImpede_dLiq*scalardTheta_dPsi + dK_dPsi__noIce*iceImpedeFac
-    else
-     dHydCondMicro_dTemp   = 0._dp
-     dHydCondMicro_dMatric = dHydCond_dPsi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)
-    end if
-    ! (combine derivatives)
-    dHydCond_dMatric = dHydCondMicro_dMatric + dHydCondMacro_dMatric
-
-    ! (compute analytical derivative for change in ice impedance factor w.r.t. temperature)
-    call dIceImpede_dTemp(scalarVolFracIceTrial, & ! intent(in): trial value of volumetric ice content (-)
-                          dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
-                          f_impede,              & ! intent(in): ice impedance parameter (-)
-                          dIceImpede_dT          ) ! intent(out): derivative in ice impedance factor w.r.t. temperature (K-1)
-    ! (compute derivative in hydraulic conductivity w.r.t. temperature)
-    dHydCond_dTemp = hydCond_noIce*dIceImpede_dT + dHydCondMicro_dTemp*iceImpedeFac
-    ! (test derivative)
-    if(testDeriv)then
-     xConst = LH_fus/(gravity*Tfreeze)                            ! m K-1 (NOTE: J = kg m2 s-2)
-     vTheta = scalarVolFracIceTrial + scalarVolFracLiqTrial
-     volLiq = volFracLiq(xConst*(scalarTempTrial+dx - Tfreeze),vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-     volIce = vTheta - volLiq
-     effSat = (volLiq - theta_res)/(theta_sat - volIce - theta_res)
-     psiLiq = matricHead(effSat,vGn_alpha,0._dp,1._dp,vGn_n,vGn_m)  ! use effective saturation, so theta_res=0 and theta_sat=1
-     hydCon = hydCond_psi(psiLiq,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
-     call iceImpede(volIce,f_impede,iceImpedeFac,dIceImpede_dLiq)
-     hydIce = hydCon*iceImpedeFac
-     print*, 'test derivative: ', (psiLiq - scalarMatricHeadTrial)/dx, dPsiLiq_dTemp
-     print*, 'test derivative: ', (hydCon - hydCond_noIce)/dx, dHydCondMicro_dTemp
-     print*, 'test derivative: ', (hydIce - scalarHydCond)/dx, dHydCond_dTemp
-     print*, 'press any key to continue'; read(*,*) ! (alternative to the deprecated 'pause' statement)
-    end if  ! testing the derivative
-    ! (set values that are not used to missing)
-    dHydCond_dVolLiq = realMissing ! not used, so cause problems
-    dDiffuse_dVolLiq = realMissing ! not used, so cause problems
-   end if
-
-  case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-
- end select
-
- ! if derivatives are not desired, then set values to missing
- if(.not.deriv_desired)then
-  dHydCond_dVolLiq   = realMissing ! not used, so cause problems
-  dDiffuse_dVolLiq   = realMissing ! not used, so cause problems
-  dHydCond_dMatric   = realMissing ! not used, so cause problems
- end if
-
- end subroutine diagv_node
-
-
- ! ***************************************************************************************************************
- ! private subroutine surfaceFlx: compute the surface flux and its derivative
- ! ***************************************************************************************************************
- subroutine surfaceFlx(&
-                       ! input: model control
-                       doInfiltration,            & ! intent(in): flag indicating if desire to compute infiltration
-                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
-                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
-                       bc_upper,                  & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
-                       nRoots,                    & ! intent(in): number of layers that contain roots
-                       ixIce,                     & ! intent(in): index of lowest ice layer
-                       ! input: state variables
-                       scalarMatricHead,          & ! intent(in): matric head in the upper-most soil layer (m)
-                       scalarVolFracLiq,          & ! intent(in): volumetric liquid water content in the upper-most soil layer (-)
-                       mLayerVolFracLiq,          & ! intent(in): volumetric liquid water content in each soil layer (-)
-                       mLayerVolFracIce,          & ! intent(in): volumetric ice content in each soil layer (-)
-                       ! input: depth of upper-most soil layer (m)
-                       mLayerDepth,               & ! intent(in): depth of each soil layer (m)
-                       iLayerHeight,              & ! intent(in): height at the interface of each layer (m)
-                       ! input: boundary conditions
-                       upperBoundHead,            & ! intent(in): upper boundary condition (m)
-                       upperBoundTheta,           & ! intent(in): upper boundary condition (-)
-                       ! input: flux at the upper boundary
-                       scalarRainPlusMelt,        & ! intent(in): rain plus melt (m s-1)
-                       ! input: transmittance
-                       surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
-                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
-                       iceImpedeFac,              & ! intent(in): ice impedence factor in the upper-most soil layer (-)
-                       ! input: soil parameters
-                       vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                       vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
-                       VGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
-                       theta_sat,                 & ! intent(in): soil porosity (-)
-                       theta_res,                 & ! intent(in): soil residual volumetric water content (-)
-                       qSurfScale,                & ! intent(in): scaling factor in the surface runoff parameterization (-)
-                       zScale_TOPMODEL,           & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
-                       rootingDepth,              & ! intent(in): rooting depth (m)
-                       wettingFrontSuction,       & ! intent(in): Green-Ampt wetting front suction (m)
-                       soilIceScale,              & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
-                       soilIceCV,                 & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
-                       ! input-output: hydraulic conductivity and diffusivity at the surface
-                       surfaceHydCond,            & ! intent(inout): hydraulic conductivity at the surface (m s-1)
-                       surfaceDiffuse,            & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
-                       ! input-output: fluxes at layer interfaces and surface runoff
-                       xMaxInfilRate,             & ! intent(inout): maximum infiltration rate (m s-1)
-                       scalarInfilArea,           & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
-                       scalarFrozenArea,          & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
-                       scalarSurfaceRunoff,       & ! intent(out): surface runoff (m s-1)
-                       scalarSurfaceInfiltration, & ! intent(out): surface infiltration (m s-1)
-                       ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
-                       dq_dHydState,              & ! intent(inout): derivative in surface infiltration w.r.t. state variable in the upper-most soil layer (m s-1 or s-1)
-                       dq_dNrgState,              & ! intent(out):   derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
-                       ! output: error control
-                       err,message)                 ! intent(out): error control
- 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 (m s-1)
- USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
- USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
- USE soil_utils_module,only:gammp           ! compute the cumulative probabilty based on the Gamma distribution
- ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
- implicit none
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! input: model control
- logical(lgt),intent(in)       :: doInfiltration            ! flag indicating if desire to compute infiltration
- logical(lgt),intent(in)       :: deriv_desired             ! flag to indicate if derivatives are desired
- integer(i4b),intent(in)       :: bc_upper                  ! index defining the type of boundary conditions
- integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
- integer(i4b),intent(in)       :: nRoots                    ! number of layers that contain roots
- integer(i4b),intent(in)       :: ixIce                     ! index of lowest ice layer
- ! input: state and diagnostic variables
- real(dp),intent(in)           :: scalarMatricHead          ! matric head in the upper-most soil layer (m)
- real(dp),intent(in)           :: scalarVolFracLiq          ! volumetric liquid water content in the upper-most soil layer (-)
- real(dp),intent(in)           :: mLayerVolFracLiq(:)       ! volumetric liquid water content in each soil layer (-)
- real(dp),intent(in)           :: mLayerVolFracIce(:)       ! volumetric ice content in each soil layer (-)
- ! input: depth of upper-most soil layer (m)
- real(dp),intent(in)           :: mLayerDepth(:)            ! depth of upper-most soil layer (m)
- real(dp),intent(in)           :: iLayerHeight(0:)          ! height at the interface of each layer (m)
- ! input: diriclet boundary conditions
- real(dp),intent(in)           :: upperBoundHead            ! upper boundary condition for matric head (m)
- real(dp),intent(in)           :: upperBoundTheta           ! upper boundary condition for volumetric liquid water content (-)
- ! input: flux at the upper boundary
- real(dp),intent(in)           :: scalarRainPlusMelt        ! rain plus melt, used as input to the soil zone before computing surface runoff (m s-1)
- ! input: transmittance
- real(dp),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
- real(dp),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
- real(dp),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
- ! input: soil parameters
- real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
- real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
- real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
- real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
- real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
- real(dp),intent(in)           :: qSurfScale                ! scaling factor in the surface runoff parameterization (-)
- real(dp),intent(in)           :: zScale_TOPMODEL           ! scaling factor used to describe decrease in hydraulic conductivity with depth (m)
- real(dp),intent(in)           :: rootingDepth              ! rooting depth (m)
- real(dp),intent(in)           :: wettingFrontSuction       ! Green-Ampt wetting front suction (m)
- real(dp),intent(in)           :: soilIceScale              ! soil ice scaling factor in Gamma distribution used to define frozen area (m)
- real(dp),intent(in)           :: soilIceCV                 ! soil ice CV in Gamma distribution used to define frozen area (-)
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! input-output: hydraulic conductivity and diffusivity at the surface
- ! NOTE: intent(inout) because infiltration may only be computed for the first iteration
- real(dp),intent(inout)        :: surfaceHydCond            ! hydraulic conductivity (m s-1)
- real(dp),intent(inout)        :: surfaceDiffuse            ! hydraulic diffusivity at the surface (m
- ! output: surface runoff and infiltration flux (m s-1)
- real(dp),intent(inout)        :: xMaxInfilRate             ! maximum infiltration rate (m s-1)
- real(dp),intent(inout)        :: scalarInfilArea           ! fraction of unfrozen area where water can infiltrate (-)
- real(dp),intent(inout)        :: scalarFrozenArea          ! fraction of area that is considered impermeable due to soil ice (-)
- real(dp),intent(out)          :: scalarSurfaceRunoff       ! surface runoff (m s-1)
- real(dp),intent(out)          :: scalarSurfaceInfiltration ! surface infiltration (m s-1)
- ! output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
- real(dp),intent(out)          :: dq_dHydState              ! derivative in surface infiltration w.r.t. state variable in the upper-most soil layer (m s-1 or s-1)
- real(dp),intent(out)          :: dq_dNrgState              ! derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)      :: err                       ! error code
- character(*),intent(out)      :: message                   ! error message
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! local variables
- ! (general)
- integer(i4b)                  :: iLayer                    ! index of soil layer
- ! (head boundary condition)
- real(dp)                      :: cFlux                     ! capillary flux (m s-1)
- real(dp)                      :: dNum                      ! numerical derivative
- ! (simplified Green-Ampt infiltration)
- real(dp)                      :: rootZoneLiq               ! depth of liquid water in the root zone (m)
- real(dp)                      :: rootZoneIce               ! depth of ice in the root zone (m)
- real(dp)                      :: availCapacity             ! available storage capacity in the root zone (m)
- real(dp)                      :: depthWettingFront         ! depth to the wetting front (m)
- real(dp)                      :: hydCondWettingFront       ! hydraulic conductivity at the wetting front (m s-1)
- ! (saturated area associated with variable storage capacity)
- real(dp)                      :: fracCap                   ! fraction of pore space filled with liquid water and ice (-)
- real(dp)                      :: fInfRaw                   ! infiltrating area before imposing solution constraints (-)
- real(dp),parameter            :: maxFracCap=0.995_dp       ! maximum fraction capacity -- used to avoid numerical problems associated with an enormous derivative
- real(dp),parameter            :: scaleFactor=0.000001_dp   ! scale factor for the smoothing function (-)
- real(dp),parameter            :: qSurfScaleMax=1000._dp    ! maximum surface runoff scaling factor (-)
- ! (fraction of impermeable area associated with frozen ground)
- real(dp)                      :: alpha                     ! shape parameter in the Gamma distribution
- real(dp)                      :: xLimg                     ! upper limit of the integral
- ! initialize error control
- err=0; message="surfaceFlx/"
-
- ! compute derivative in the energy state
- ! NOTE: revisit the need to do this
- dq_dNrgState = 0._dp
-
- ! *****
- ! compute the surface flux and its derivative
- select case(bc_upper)
-
-  ! *****
-  ! head condition
-  case(prescribedHead)
-
-   ! surface runoff iz zero for the head condition
-   scalarSurfaceRunoff = 0._dp
-
-   ! compute transmission and the capillary flux
-   select case(ixRichards)  ! (form of Richards' equation)
-    case(moisture)
-     ! compute the hydraulic conductivity and diffusivity at the boundary
-     surfaceHydCond = hydCond_liq(upperBoundTheta,surfaceSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
-     surfaceDiffuse = dPsi_dTheta(upperBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * surfaceHydCond
-     ! compute the capillary flux
-     cflux = -surfaceDiffuse*(scalarVolFracLiq - upperBoundTheta) / (mLayerDepth(1)*0.5_dp)
-    case(mixdform)
-     ! compute the hydraulic conductivity and diffusivity at the boundary
-     surfaceHydCond = hydCond_psi(upperBoundHead,surfaceSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
-     surfaceDiffuse = realMissing
-     ! compute the capillary flux
-     cflux = -surfaceHydCond*(scalarMatricHead - upperBoundHead) / (mLayerDepth(1)*0.5_dp)
-    case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-   end select  ! (form of Richards' eqn)
-   ! compute the total flux
-   scalarSurfaceInfiltration = cflux + surfaceHydCond
-   ! compute the derivative
-   if(deriv_desired)then
-    ! compute the hydrology derivative
-    select case(ixRichards)  ! (form of Richards' equation)
-     case(moisture); dq_dHydState = -surfaceDiffuse/(mLayerDepth(1)/2._dp)
-     case(mixdform); dq_dHydState = -surfaceHydCond/(mLayerDepth(1)/2._dp)
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select
-    ! compute the energy derivative
-    dq_dNrgState = -(dHydCond_dTemp/2._dp)*(scalarMatricHead - upperBoundHead)/(mLayerDepth(1)*0.5_dp) + dHydCond_dTemp/2._dp
-    ! compute the numerical derivative
-    !cflux = -surfaceHydCond*((scalarMatricHead+dx) - upperBoundHead) / (mLayerDepth(1)*0.5_dp)
-    !surfaceInfiltration1 = cflux + surfaceHydCond
-    !dNum  = (surfaceInfiltration1 - scalarSurfaceInfiltration)/dx
-   else
-    dq_dHydState = 0._dp
-    dNum         = 0._dp
-   end if
-   !write(*,'(a,1x,10(e30.20,1x))') 'scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum = ', &
-   !                                 scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum
-
-  ! *****
-  ! flux condition
-  case(liquidFlux)
-
-   ! force infiltration to be constant over the iterations
-   if(doInfiltration)then
-
-    ! define the storage in the root zone (m)
-    rootZoneLiq = 0._dp
-    rootZoneIce = 0._dp
-    ! (process layers where the roots extend to the bottom of the layer)
-    if(nRoots > 1)then
-     do iLayer=1,nRoots-1
-      rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(iLayer)*mLayerDepth(iLayer)
-      rootZoneIce = rootZoneIce + mLayerVolFracIce(iLayer)*mLayerDepth(iLayer)
+    ! -----------------------------------------------------------------------------------------------------------
+    
+    ! data types
+    USE nrtype
+    USE data_types,only:var_d                  ! x%var(:)       (rkind)
+    USE data_types,only:var_ilength            ! x%var(:)%dat   (i4b)
+    USE data_types,only:var_dlength            ! x%var(:)%dat   (rkind)
+    
+    ! missing values
+    USE globalData,only:integerMissing  ! missing integer
+    USE globalData,only:realMissing     ! missing real number
+    
+    ! physical constants
+    USE multiconst,only:&
+                        LH_fus,  & ! latent heat of fusion         (J kg-1)
+                        LH_vap,  & ! latent heat of vaporization   (J kg-1)
+                        LH_sub,  & ! latent heat of sublimation    (J kg-1)
+                        gravity, & ! gravitational acceleteration  (m s-2)
+                        Tfreeze, & ! freezing point of pure water  (K)
+                        iden_air,& ! intrinsic density of air      (kg m-3)
+                        iden_ice,& ! intrinsic density of ice      (kg m-3)
+                        iden_water ! intrinsic density of water    (kg m-3)
+    
+    ! named variables
+    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
+    USE var_lookup,only:iLookINDEX             ! named variables for structure elements
+    
+    ! model decisions
+    USE globalData,only:model_decisions        ! model decision structure
+    USE var_lookup,only:iLookDECISIONS         ! named variables for elements of the decision structure
+    
+    ! provide access to look-up values for model decisions
+    USE mDecisions_module,only:  &
+     ! look-up values for method used to compute derivative
+     numerical,                  & ! numerical solution
+     analytical,                 & ! analytical solution
+     ! look-up values for the form of Richards' equation
+     moisture,                   & ! moisture-based form of Richards' equation
+     mixdform,                   & ! mixed form of Richards' equation
+     ! look-up values for the type of hydraulic conductivity profile
+     constant,                   & ! constant hydraulic conductivity with depth
+     powerLaw_profile,           & ! power-law profile
+     ! look-up values for the choice of groundwater parameterization
+     qbaseTopmodel,              & ! TOPMODEL-ish baseflow parameterization
+     bigBucket,                  & ! a big bucket (lumped aquifer model)
+     noExplicit,                 & ! no explicit groundwater parameterization
+     ! look-up values for the choice of boundary conditions for hydrology
+     prescribedHead,             & ! prescribed head (volumetric liquid water content for mixed form of Richards' eqn)
+     funcBottomHead,             & ! function of matric head in the lower-most layer
+     freeDrainage,               & ! free drainage
+     liquidFlux,                 & ! liquid water flux
+     zeroFlux                      ! zero flux
+    
+    ! -----------------------------------------------------------------------------------------------------------
+    implicit none
+    private
+    public::soilLiqFlx
+    ! constant parameters
+    real(rkind),parameter     :: verySmall=1.e-12_rkind       ! a very small number (used to avoid divide by zero)
+    real(rkind),parameter     :: dx=1.e-8_rkind               ! finite difference increment
+    contains
+    
+    
+     ! ***************************************************************************************************************
+     ! public subroutine soilLiqFlx: compute liquid water fluxes and their derivatives
+     ! ***************************************************************************************************************
+     subroutine soilLiqFlx(&
+                           ! input: model control
+                           nSoil,                        & ! intent(in): number of soil layers
+                           doInfiltrate,                 & ! intent(in): flag to compute infiltration
+                           scalarSolution,               & ! intent(in):    flag to indicate the scalar solution
+                           deriv_desired,                & ! intent(in): flag indicating if derivatives are desired
+                           ! input: trial state variables
+                           mLayerTempTrial,              & ! intent(in): temperature (K)
+                           mLayerMatricHeadLiqTrial,     & ! intent(in): liquid matric head (m)
+                           mLayerVolFracLiqTrial,        & ! intent(in): volumetric fraction of liquid water (-)
+                           mLayerVolFracIceTrial,        & ! intent(in): volumetric fraction of ice (-)
+                           ! input: pre-computed derivatives
+                           mLayerdTheta_dTk,             & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           dPsiLiq_dTemp,                & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                           dCanopyTrans_dCanWat,         & ! intent(in): derivative in canopy transpiration w.r.t. canopy total water content (s-1)
+                           dCanopyTrans_dTCanair,        & ! intent(in): derivative in canopy transpiration w.r.t. canopy air temperature (kg m-2 s-1 K-1)
+                           dCanopyTrans_dTCanopy,        & ! intent(in): derivative in canopy transpiration w.r.t. canopy temperature (kg m-2 s-1 K-1)
+                           dCanopyTrans_dTGround,        & ! intent(in): derivative in canopy transpiration w.r.t. ground temperature (kg m-2 s-1 K-1)
+                           above_soilLiqFluxDeriv,       & ! intent(in): derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+                           above_soildLiq_dTk,           & ! intent(in): derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+                           above_soilFracLiq,            & ! intent(in): fraction of liquid water layer above soil (canopy or snow) (-)
+                           ! input: fluxes
+                           scalarCanopyTranspiration,    & ! intent(in): canopy transpiration (kg m-2 s-1)
+                           scalarGroundEvaporation,      & ! intent(in): ground evaporation (kg m-2 s-1)
+                           scalarRainPlusMelt,           & ! intent(in): rain plus melt (m s-1)
+                           ! input-output: data structures
+                           mpar_data,                    & ! intent(in):    model parameters
+                           indx_data,                    & ! intent(in):    model indices
+                           prog_data,                    & ! intent(in):    model prognostic variables for a local HRU
+                           diag_data,                    & ! intent(inout): model diagnostic variables for a local HRU
+                           flux_data,                    & ! intent(inout): model fluxes for a local HRU
+                           ! output: diagnostic variables for surface runoff
+                           xMaxInfilRate,                & ! intent(inout): maximum infiltration rate (m s-1)
+                           scalarInfilArea,              & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                           scalarFrozenArea,             & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                           scalarSurfaceRunoff,          & ! intent(out): surface runoff (m s-1)
+                           ! output: diagnostic variables for model layers
+                           mLayerdTheta_dPsi,            & ! intent(out): derivative in the soil water characteristic w.r.t. psi (m-1)
+                           mLayerdPsi_dTheta,            & ! intent(out): derivative in the soil water characteristic w.r.t. theta (m)
+                           dHydCond_dMatric,             & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (s-1)
+                           ! output: fluxes
+                           scalarSurfaceInfiltration,    & ! intent(out): surface infiltration rate (m s-1)
+                           iLayerLiqFluxSoil,            & ! intent(out): liquid fluxes at layer interfaces (m s-1)
+                           mLayerTranspire,              & ! intent(out): transpiration loss from each soil layer (m s-1)
+                           mLayerHydCond,                & ! intent(out): hydraulic conductivity in each soil layer (m s-1)
+                           ! output: derivatives in fluxes w.r.t. hydrology state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+                           dq_dHydStateAbove,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer above (m s-1)
+                           dq_dHydStateBelow,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer below (m s-1)
+                           dq_dHydStateLayerSurfVec,     & ! intent(out): derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer  (m s-1 or s-1)
+                           ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+                           dq_dNrgStateAbove,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                           dq_dNrgStateBelow,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                           dq_dNrgStateLayerSurfVec,     & ! intent(out): derivative in surface infiltration w.r.t. energy state in above soil snow or canopy and every soil layer (m s-1 K-1)
+                           ! output: derivatives in transpiration w.r.t. canopy state variables
+                           mLayerdTrans_dTCanair,        & ! intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
+                           mLayerdTrans_dTCanopy,        & ! intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy temperature
+                           mLayerdTrans_dTGround,        & ! intent(out): derivatives in the soil layer transpiration flux w.r.t. ground temperature
+                           mLayerdTrans_dCanWat,         & ! intent(out): derivatives in the soil layer transpiration flux w.r.t. canopy total water
+                           ! output: error control
+                           err,message)                    ! intent(out): error control
+     ! utility modules
+     USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water
+     USE soil_utils_module,only:matricHead      ! compute matric head (m)
+     USE soil_utils_module,only:dTheta_dPsi     ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
+     USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+     USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head
+     USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content
+     USE soil_utils_module,only:hydCondMP_liq   ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     implicit none
+     ! input: model control
+     integer(i4b),intent(in)          :: nSoil                         ! number of soil layers
+     logical(lgt),intent(in)          :: doInfiltrate                  ! flag to compute infiltration
+     logical(lgt),intent(in)          :: scalarSolution                ! flag to denote if implementing the scalar solution
+     logical(lgt),intent(in)          :: deriv_desired                 ! flag indicating if derivatives are desired
+     ! input: trial model state variables
+     real(rkind),intent(in)              :: mLayerTempTrial(:)            ! temperature in each layer at the current iteration (m)
+     real(rkind),intent(in)              :: mLayerMatricHeadLiqTrial(:)   ! liquid matric head in each layer at the current iteration (m)
+     real(rkind),intent(in)              :: mLayerVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the current iteration (-)
+     real(rkind),intent(in)              :: mLayerVolFracIceTrial(:)      ! volumetric fraction of ice at the current iteration (-)
+     ! input: pre-computed derivatves
+     real(rkind),intent(in)              :: mLayerdTheta_dTk(:)           ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+     real(rkind),intent(in)              :: dPsiLiq_dTemp(:)              ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+     real(rkind),intent(in)              :: dCanopyTrans_dCanWat          ! derivative in canopy transpiration w.r.t. canopy total water content (s-1)
+     real(rkind),intent(in)              :: dCanopyTrans_dTCanair         ! derivative in canopy transpiration w.r.t. canopy air temperature (kg m-2 s-1 K-1)
+     real(rkind),intent(in)              :: dCanopyTrans_dTCanopy         ! derivative in canopy transpiration w.r.t. canopy temperature (kg m-2 s-1 K-1)
+     real(rkind),intent(in)              :: dCanopyTrans_dTGround         ! derivative in canopy transpiration w.r.t. ground temperature (kg m-2 s-1 K-1)
+     real(rkind),intent(in)              :: above_soilLiqFluxDeriv        ! derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+     real(rkind),intent(in)              :: above_soildLiq_dTk            ! derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+     real(rkind),intent(in)              :: above_soilFracLiq             ! fraction of liquid water layer above soil (canopy or snow) (-)
+     ! input: model fluxes
+     real(rkind),intent(in)              :: scalarCanopyTranspiration     ! canopy transpiration (kg m-2 s-1)
+     real(rkind),intent(in)              :: scalarGroundEvaporation       ! ground evaporation (kg m-2 s-1)
+     real(rkind),intent(in)              :: scalarRainPlusMelt            ! rain plus melt (m s-1)
+     ! input-output: data structures
+     type(var_dlength),intent(in)        :: mpar_data                     ! model parameters
+     type(var_ilength),intent(in)        :: indx_data                     ! state vector geometry
+     type(var_dlength),intent(in)        :: prog_data                     ! prognostic variables for a local HRU
+     type(var_dlength),intent(inout)     :: diag_data                     ! diagnostic variables for a local HRU
+     type(var_dlength),intent(inout)     :: flux_data                     ! model fluxes for a local HRU
+     ! output: diagnostic variables for surface runoff
+     real(rkind),intent(inout)           :: xMaxInfilRate                 ! maximum infiltration rate (m s-1)
+     real(rkind),intent(inout)           :: scalarInfilArea               ! fraction of unfrozen area where water can infiltrate (-)
+     real(rkind),intent(inout)           :: scalarFrozenArea              ! fraction of area that is considered impermeable due to soil ice (-)
+     real(rkind),intent(inout)           :: scalarSurfaceRunoff           ! surface runoff (m s-1)
+     ! output: diagnostic variables for each layer
+     real(rkind),intent(inout)           :: mLayerdTheta_dPsi(:)          ! derivative in the soil water characteristic w.r.t. psi (m-1)
+     real(rkind),intent(inout)           :: mLayerdPsi_dTheta(:)          ! derivative in the soil water characteristic w.r.t. theta (m)
+     real(rkind),intent(inout)           :: dHydCond_dMatric(:)           ! derivative in hydraulic conductivity w.r.t matric head (s-1)
+     ! output: liquid fluxes
+     real(rkind),intent(inout)           :: scalarSurfaceInfiltration     ! surface infiltration rate (m s-1)
+     real(rkind),intent(inout)           :: iLayerLiqFluxSoil(0:)         ! liquid flux at soil layer interfaces (m s-1)
+     real(rkind),intent(inout)           :: mLayerTranspire(:)            ! transpiration loss from each soil layer (m s-1)
+     real(rkind),intent(inout)           :: mLayerHydCond(:)              ! hydraulic conductivity in each soil layer (m s-1)
+     ! output: derivatives in fluxes w.r.t. state variables in the layer above and layer below (m s-1)
+     real(rkind),intent(inout)           :: dq_dHydStateAbove(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer above
+     real(rkind),intent(inout)           :: dq_dHydStateBelow(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer below
+     real(rkind),intent(inout)           :: dq_dHydStateLayerSurfVec(0:)  ! derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer  (m s-1 or s-1)
+     ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+     real(rkind),intent(inout)           :: dq_dNrgStateAbove(0:)         ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+     real(rkind),intent(inout)           :: dq_dNrgStateBelow(0:)         ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+     real(rkind),intent(inout)           :: dq_dNrgStateLayerSurfVec(0:)  ! derivative in surface infiltration w.r.t. temperature in above soil snow or canopy and every soil layer  (m s-1 or s-1)
+     ! output: derivatives in transpiration w.r.t. canopy state variables
+     real(rkind),intent(inout)           :: mLayerdTrans_dTCanair(:)      ! derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
+     real(rkind),intent(inout)           :: mLayerdTrans_dTCanopy(:)      ! derivatives in the soil layer transpiration flux w.r.t. canopy temperature
+     real(rkind),intent(inout)           :: mLayerdTrans_dTGround(:)      ! derivatives in the soil layer transpiration flux w.r.t. ground temperature
+     real(rkind),intent(inout)           :: mLayerdTrans_dCanWat(:)       ! derivatives in the soil layer transpiration flux w.r.t. canopy total water
+     ! output: error control
+     integer(i4b),intent(out)         :: err                           ! error code
+     character(*),intent(out)         :: message                       ! error message
+     ! -----------------------------------------------------------------------------------------------------------------------------------------------------
+     ! local variables: general
+     character(LEN=256)               :: cmessage                     ! error message of downwind routine
+     integer(i4b)                     :: ibeg,iend                    ! start and end indices of the soil layers in concatanated snow-soil vector
+     logical(lgt)                     :: desireAnal                   ! flag to identify if analytical derivatives are desired
+     integer(i4b)                     :: iLayer,iSoil                 ! index of soil layer
+     integer(i4b)                     :: ixLayerDesired(1)            ! layer desired (scalar solution)
+     integer(i4b)                     :: ixTop                        ! top layer in subroutine call
+     integer(i4b)                     :: ixBot                        ! bottom layer in subroutine call
+     ! additional variables to compute numerical derivatives
+     integer(i4b)                     :: nFlux                        ! number of flux calculations required (>1 = numerical derivatives with one-sided finite differences)
+     integer(i4b)                     :: itry                         ! index of different flux calculations
+     integer(i4b),parameter           :: unperturbed=0                ! named variable to identify the case of unperturbed state variables
+     integer(i4b),parameter           :: perturbState=1               ! named variable to identify the case where we perturb the state in the current layer
+     integer(i4b),parameter           :: perturbStateAbove=2          ! named variable to identify the case where we perturb the state layer above
+     integer(i4b),parameter           :: perturbStateBelow=3          ! named variable to identify the case where we perturb the state layer below
+     integer(i4b)                     :: ixPerturb                    ! index of element in 2-element vector to perturb
+     integer(i4b)                     :: ixOriginal                   ! index of perturbed element in the original vector
+     real(rkind)                         :: scalarVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
+     real(rkind)                         :: scalarMatricHeadLiqTrial     ! trial value of liquid matric head (m)
+     real(rkind)                         :: scalarHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
+     real(rkind)                         :: scalarHydCondMicro           ! trial value of hydraulic conductivity of micropores (m s-1)
+     real(rkind)                         :: scalarHydCondMacro           ! trial value of hydraulic conductivity of macropores (m s-1)
+     real(rkind)                         :: scalarFlux                   ! vertical flux (m s-1)
+     real(rkind)                         :: scalarFlux_dStateAbove       ! vertical flux with perturbation to the state above (m s-1)
+     real(rkind)                         :: scalarFlux_dStateBelow       ! vertical flux with perturbation to the state below (m s-1)
+     ! transpiration sink term
+     real(rkind),dimension(nSoil)        :: mLayerTranspireFrac          ! fraction of transpiration allocated to each soil layer (-)
+     ! diagnostic variables
+     real(rkind),dimension(nSoil)        :: iceImpedeFac                 ! ice impedence factor at layer mid-points (-)
+     real(rkind),dimension(nSoil)        :: mLayerDiffuse                ! diffusivity at layer mid-point (m2 s-1)
+     real(rkind),dimension(nSoil)        :: dHydCond_dVolLiq             ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+     real(rkind),dimension(nSoil)        :: dDiffuse_dVolLiq             ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+     real(rkind),dimension(nSoil)        :: dHydCond_dTemp               ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+     real(rkind),dimension(0:nSoil)      :: iLayerHydCond                ! hydraulic conductivity at layer interface (m s-1)
+     real(rkind),dimension(0:nSoil)      :: iLayerDiffuse                ! diffusivity at layer interface (m2 s-1)
+     ! compute surface flux
+     integer(i4b)                     :: nRoots                       ! number of soil layers with roots
+     integer(i4b)                     :: ixIce                        ! index of the lowest soil layer that contains ice
+     real(rkind),dimension(0:nSoil)      :: iLayerHeight                 ! height of the layer interfaces (m)
+     ! compute fluxes and derivatives at layer interfaces
+     real(rkind),dimension(2)            :: vectorVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
+     real(rkind),dimension(2)            :: vectorMatricHeadLiqTrial     ! trial value of liquid matric head (m)
+     real(rkind),dimension(2)            :: vectorHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
+     real(rkind),dimension(2)            :: vectorDiffuseTrial           ! trial value of hydraulic diffusivity (m2 s-1)
+     real(rkind)                         :: scalardPsi_dTheta            ! derivative in soil water characteristix, used for perturbations when computing numerical derivatives
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! initialize error control
+     err=0; message='soilLiqFlx/'
+    
+     ! get indices for the data structures
+     ibeg = indx_data%var(iLookINDEX%nSnow)%dat(1) + 1
+     iend = indx_data%var(iLookINDEX%nSnow)%dat(1) + indx_data%var(iLookINDEX%nSoil)%dat(1)
+    
+     ! get a copy of iLayerHeight
+     ! NOTE: performance hit, though cannot define the shape (0:) with the associate construct
+     iLayerHeight(0:nSoil) = prog_data%var(iLookPROG%iLayerHeight)%dat(ibeg-1:iend)  ! height of the layer interfaces (m)
+    
+     ! make association between local variables and the information in the data structures
+     associate(&
+      ! input: model control
+      ixDerivMethod          => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision,   & ! intent(in): index of the method used to calculate flux derivatives
+      ixRichards             => model_decisions(iLookDECISIONS%f_Richards)%iDecision,   & ! intent(in): index of the form of Richards' equation
+      ixBcUpperSoilHydrology => model_decisions(iLookDECISIONS%bcUpprSoiH)%iDecision,   & ! intent(in): index of the upper boundary conditions for soil hydrology
+      ixBcLowerSoilHydrology => model_decisions(iLookDECISIONS%bcLowrSoiH)%iDecision,   & ! intent(in): index of the lower boundary conditions for soil hydrology
+      ! input: model indices
+      ixMatricHead           => indx_data%var(iLookINDEX%ixMatricHead)%dat,             & ! intent(in): indices of soil layers where matric head is the state variable
+      ixSoilOnlyHyd          => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat,            & ! intent(in): index in the state subset for hydrology state variables in the soil domain
+      ! input: model coordinate variables -- NOTE: use of ibeg and iend
+      mLayerDepth            => prog_data%var(iLookPROG%mLayerDepth)%dat(ibeg:iend),    & ! intent(in): depth of the layer (m)
+      mLayerHeight           => prog_data%var(iLookPROG%mLayerHeight)%dat(ibeg:iend),   & ! intent(in): height of the layer mid-point (m)
+      ! input: upper boundary conditions
+      upperBoundHead         => mpar_data%var(iLookPARAM%upperBoundHead)%dat(1),        & ! intent(in): upper boundary condition for matric head (m)
+      upperBoundTheta        => mpar_data%var(iLookPARAM%upperBoundTheta)%dat(1),       & ! intent(in): upper boundary condition for volumetric liquid water content (-)
+      ! input: lower boundary conditions
+      lowerBoundHead         => mpar_data%var(iLookPARAM%lowerBoundHead)%dat(1),        & ! intent(in): lower boundary condition for matric head (m)
+      lowerBoundTheta        => mpar_data%var(iLookPARAM%lowerBoundTheta)%dat(1),       & ! intent(in): lower boundary condition for volumetric liquid water content (-)
+      ! input: vertically variable soil parameters
+      vGn_m                  => diag_data%var(iLookDIAG%scalarVGn_m)%dat,               & ! intent(in): van Genutchen "m" parameter (-)
+      vGn_n                  => mpar_data%var(iLookPARAM%vGn_n)%dat,                    & ! intent(in): van Genutchen "n" parameter (-)
+      vGn_alpha              => mpar_data%var(iLookPARAM%vGn_alpha)%dat,                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+      theta_sat              => mpar_data%var(iLookPARAM%theta_sat)%dat,                & ! intent(in): soil porosity (-)
+      theta_res              => mpar_data%var(iLookPARAM%theta_res)%dat,                & ! intent(in): soil residual volumetric water content (-)
+      ! input: vertically constant soil parameters
+      wettingFrontSuction    => mpar_data%var(iLookPARAM%wettingFrontSuction)%dat(1),   & ! intent(in): Green-Ampt wetting front suction (m)
+      rootingDepth           => mpar_data%var(iLookPARAM%rootingDepth)%dat(1),          & ! intent(in): rooting depth (m)
+      kAnisotropic           => mpar_data%var(iLookPARAM%kAnisotropic)%dat(1),          & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+      zScale_TOPMODEL        => mpar_data%var(iLookPARAM%zScale_TOPMODEL)%dat(1),       & ! intent(in): TOPMODEL scaling factor (m)
+      qSurfScale             => mpar_data%var(iLookPARAM%qSurfScale)%dat(1),            & ! intent(in): scaling factor in the surface runoff parameterization (-)
+      f_impede               => mpar_data%var(iLookPARAM%f_impede)%dat(1),              & ! intent(in): ice impedence factor (-)
+      soilIceScale           => mpar_data%var(iLookPARAM%soilIceScale)%dat(1),          & ! intent(in): scaling factor for depth of soil ice, used to get frozen fraction (m)
+      soilIceCV              => mpar_data%var(iLookPARAM%soilIceCV)%dat(1),             & ! intent(in): CV of depth of soil ice, used to get frozen fraction (-)
+      theta_mp               => mpar_data%var(iLookPARAM%theta_mp)%dat(1),              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+      mpExp                  => mpar_data%var(iLookPARAM%mpExp)%dat(1),                 & ! intent(in): empirical exponent in macropore flow equation (-)
+      ! input: saturated hydraulic conductivity
+      mLayerSatHydCondMP     => flux_data%var(iLookFLUX%mLayerSatHydCondMP)%dat,        & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
+      mLayerSatHydCond       => flux_data%var(iLookFLUX%mLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
+      iLayerSatHydCond       => flux_data%var(iLookFLUX%iLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the interface of each layer (m s-1)
+      ! input: factors limiting transpiration (from vegFlux routine)
+      mLayerRootDensity      => diag_data%var(iLookDIAG%mLayerRootDensity)%dat,         & ! intent(in): root density in each layer (-)
+      scalarTranspireLim     => diag_data%var(iLookDIAG%scalarTranspireLim)%dat(1),     & ! intent(in): weighted average of the transpiration limiting factor (-)
+      mLayerTranspireLim     => diag_data%var(iLookDIAG%mLayerTranspireLim)%dat         & ! intent(in): transpiration limiting factor in each layer (-)
+     )  ! associating local variables with the information in the data structures
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! preliminaries
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+    
+     ! define the pethod to compute derivatives
+     !print*, 'numerical derivatives = ', (ixDerivMethod==numerical)
+    
+     ! numerical derivatives are not implemented yet
+     if(ixDerivMethod==numerical)then
+      message=trim(message)//'numerical derivates do not account for the cross derivatives between hydrology and thermodynamics'
+      err=20; return
+     end if
+    
+     ! check the need to compute analytical derivatives
+     if(deriv_desired .and. ixDerivMethod==analytical)then
+      desireAnal = .true.
+     else
+      desireAnal = .false.
+     end if
+    
+     ! check the need to compute numerical derivatives
+     if(deriv_desired .and. ixDerivMethod==numerical)then
+      nFlux=3  ! compute the derivatives using one-sided finite differences
+     else
+      nFlux=0  ! compute analytical derivatives
+     end if
+    
+     ! get the indices for the soil layers
+     if(scalarSolution)then
+      ixLayerDesired = pack(ixMatricHead, ixSoilOnlyHyd/=integerMissing)
+      ixTop = ixLayerDesired(1)
+      ixBot = ixLayerDesired(1)
+     else
+      ixTop = 1
+      ixBot = nSoil
+     endif
+    
+     ! identify the number of layers that contain roots
+     nRoots = count(iLayerHeight(0:nSoil-1) < rootingDepth-verySmall)
+     if(nRoots==0)then
+      message=trim(message)//'no layers with roots'
+      err=20; return
+     endif
+    
+     ! identify lowest soil layer with ice
+     ! NOTE: cannot use count because there may be an unfrozen wedge
+     ixIce = 0  ! initialize the index of the ice layer (0 means no ice in the soil profile)
+     do iLayer=1,nSoil ! (loop through soil layers)
+      if(mLayerVolFracIceTrial(iLayer) > verySmall) ixIce = iLayer
      end do
-    end if
-    ! (process layers where the roots end in the current layer)
-    rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
-    rootZoneIce = rootZoneIce + mLayerVolFracIce(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
-
-    ! define available capacity to hold water (m)
-    availCapacity = theta_sat*rootingDepth - rootZoneIce
-    if(rootZoneLiq > availCapacity+verySmall)then
-     message=trim(message)//'liquid water in the root zone exceeds capacity'
-     err=20; return
-    end if
-
-    ! define the depth to the wetting front (m)
-    depthWettingFront = (rootZoneLiq/availCapacity)*rootingDepth
-
-    ! define the hydraulic conductivity at depth=depthWettingFront (m s-1)
-    hydCondWettingFront =  surfaceSatHydCond * ( (1._dp - depthWettingFront/sum(mLayerDepth))**(zScale_TOPMODEL - 1._dp) )
-
-    ! define the maximum infiltration rate (m s-1)
-    xMaxInfilRate = hydCondWettingFront*( (wettingFrontSuction + depthWettingFront)/depthWettingFront )  ! maximum infiltration rate (m s-1)
-    !write(*,'(a,1x,f9.3,1x,10(e20.10,1x))') 'depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate = ', depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate
-
-    ! define the infiltrating area for the non-frozen part of the cell/basin
-    if(qSurfScale < qSurfScaleMax)then
-     fracCap         = rootZoneLiq/(maxFracCap*availCapacity)                              ! fraction of available root zone filled with water
-     fInfRaw         = 1._dp - exp(-qSurfScale*(1._dp - fracCap))                          ! infiltrating area -- allowed to violate solution constraints
-     scalarInfilArea = min(0.5_dp*(fInfRaw + sqrt(fInfRaw**2._dp + scaleFactor)), 1._dp)   ! infiltrating area -- constrained
-    else
-     scalarInfilArea = 1._dp
-    endif
-
-    ! check to ensure we are not infiltrating into a fully saturated column
-    if(ixIce<nRoots)then
-     if(sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) > 0.9999_dp*theta_sat*sum(mLayerDepth(ixIce+1:nRoots))) scalarInfilArea=0._dp
-     !print*, 'ixIce, nRoots, scalarInfilArea = ', ixIce, nRoots, scalarInfilArea
-     !print*, 'sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) = ', sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots))
-     !print*, 'theta_sat*sum(mLayerDepth(ixIce+1:nRoots)) = ', theta_sat*sum(mLayerDepth(ixIce+1:nRoots))
-    endif
-
-    ! define the impermeable area due to frozen ground
-    if(rootZoneIce > tiny(rootZoneIce))then  ! (avoid divide by zero)
-     alpha            = 1._dp/(soilIceCV**2._dp)        ! shape parameter in the Gamma distribution
-     xLimg            = alpha*soilIceScale/rootZoneIce  ! upper limit of the integral
-     !scalarFrozenArea = 1._dp - gammp(alpha,xLimg)      ! fraction of frozen area
-     scalarFrozenArea = 0._dp
-    else
-     scalarFrozenArea = 0._dp
-    end if
-    !print*, 'scalarFrozenArea, rootZoneIce = ', scalarFrozenArea, rootZoneIce
-
-   end if ! (if desire to compute infiltration)
-
-   ! compute infiltration (m s-1)
-   scalarSurfaceInfiltration = (1._dp - scalarFrozenArea)*scalarInfilArea*min(scalarRainPlusMelt,xMaxInfilRate)
-
-   ! compute surface runoff (m s-1)
-   scalarSurfaceRunoff = scalarRainPlusMelt - scalarSurfaceInfiltration
-   !print*, 'scalarRainPlusMelt, xMaxInfilRate = ', scalarRainPlusMelt, xMaxInfilRate
-   !print*, 'scalarSurfaceInfiltration, scalarSurfaceRunoff = ', scalarSurfaceInfiltration, scalarSurfaceRunoff
-   !print*, '(1._dp - scalarFrozenArea), (1._dp - scalarFrozenArea)*scalarInfilArea = ', (1._dp - scalarFrozenArea), (1._dp - scalarFrozenArea)*scalarInfilArea
-
-   ! set surface hydraulic conductivity and diffusivity to missing (not used for flux condition)
-   surfaceHydCond = realMissing
-   surfaceDiffuse = realMissing
-
-   ! set numerical derivative to zero
-   ! NOTE 1: Depends on multiple soil layers and does not jive with the current tridiagonal matrix
-   ! NOTE 2: Need to define the derivative at every call, because intent(out)
-   dq_dHydState = 0._dp
-   dq_dNrgState = 0._dp
-
-  ! ***** error check
-  case default; err=20; message=trim(message)//'unknown upper boundary condition for soil hydrology'; return
-
- end select  ! (type of upper boundary condition)
-
- end subroutine surfaceFlx
-
-
- ! ***************************************************************************************************************
- ! private subroutine iLayerFlux: compute the fluxes and derivatives at layer interfaces
- ! ***************************************************************************************************************
- subroutine iLayerFlux(&
+     !if(ixIce==nSoil)then; err=20; message=trim(message)//'ice extends to the bottom of the soil profile'; return; end if
+    
+     ! *************************************************************************************************************************************************
+     ! *************************************************************************************************************************************************
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! compute the transpiration sink term
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+    
+     ! check the need to compute transpiration (NOTE: intent=inout)
+     if( .not. (scalarSolution .and. ixTop>1) )then
+    
+      ! compute the fraction of transpiration loss from each soil layer
+      if(scalarTranspireLim > tiny(scalarTranspireLim))then ! (transpiration may be non-zero even if the soil moisture limiting factor is zero)
+       mLayerTranspireFrac(:) = mLayerRootDensity(:)*mLayerTranspireLim(:)/scalarTranspireLim
+      else ! (possible for there to be non-zero conductance and therefore transpiration in this case)
+       mLayerTranspireFrac(:) = mLayerRootDensity(:) / sum(mLayerRootDensity)
+      end if
+    
+      ! check fractions sum to one
+      if(abs(sum(mLayerTranspireFrac) - 1._rkind) > verySmall)then
+       message=trim(message)//'fraction transpiration in soil layers does not sum to one'
+       err=20; return
+      endif
+    
+      ! compute transpiration loss from each soil layer (kg m-2 s-1 --> m s-1)
+      mLayerTranspire(:) = mLayerTranspireFrac(:)*scalarCanopyTranspiration/iden_water
+      ! derivatives in transpiration w.r.t. canopy state variables
+      mLayerdTrans_dCanWat(:)  = mLayerTranspireFrac(:)*dCanopyTrans_dCanWat /iden_water
+      mLayerdTrans_dTCanair(:) = mLayerTranspireFrac(:)*dCanopyTrans_dTCanair/iden_water
+      mLayerdTrans_dTCanopy(:) = mLayerTranspireFrac(:)*dCanopyTrans_dTCanopy/iden_water
+      mLayerdTrans_dTGround(:) = mLayerTranspireFrac(:)*dCanopyTrans_dTGround/iden_water
+    
+      ! special case of prescribed head -- no transpiration
+      if(ixBcUpperSoilHydrology==prescribedHead) then
+       mLayerTranspire(:)      = 0._rkind
+       ! derivatives in transpiration w.r.t. canopy state variables
+       mLayerdTrans_dCanWat(:) = 0._rkind
+       mLayerdTrans_dTCanair(:)= 0._rkind
+       mLayerdTrans_dTCanopy(:)= 0._rkind
+       mLayerdTrans_dTGround(:)= 0._rkind
+      endif
+    
+     endif  ! if need to compute transpiration
+    
+     ! *************************************************************************************************************************************************
+     ! *************************************************************************************************************************************************
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! compute diagnostic variables at the nodes throughout the soil profile
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     do iSoil=ixTop,min(ixBot+1,nSoil) ! (loop through soil layers)
+    
+      call diagv_node(&
+                      ! input: model control
+                      desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
+                      ixRichards,                      & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
+                      ! input: state variables
+                      mLayerTempTrial(iSoil),          & ! intent(in): temperature (K)
+                      mLayerMatricHeadLiqTrial(iSoil), & ! intent(in): liquid  matric head in each layer (m)
+                      mLayerVolFracLiqTrial(iSoil),    & ! intent(in): volumetric liquid water content in each soil layer (-)
+                      mLayerVolFracIceTrial(iSoil),    & ! intent(in): volumetric ice content in each soil layer (-)
+                      ! input: pre-computed deriavatives
+                      mLayerdTheta_dTk(iSoil),         & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                      dPsiLiq_dTemp(iSoil),            & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                      ! input: soil parameters
+                      vGn_alpha(iSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                      vGn_n(iSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
+                      vGn_m(iSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
+                      mpExp,                           & ! intent(in): empirical exponent in macropore flow equation (-)
+                      theta_sat(iSoil),                & ! intent(in): soil porosity (-)
+                      theta_res(iSoil),                & ! intent(in): soil residual volumetric water content (-)
+                      theta_mp,                        & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+                      f_impede,                        & ! intent(in): ice impedence factor (-)
+                      ! input: saturated hydraulic conductivity
+                      mLayerSatHydCond(iSoil),         & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
+                      mLayerSatHydCondMP(iSoil),       & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
+                      ! output: derivative in the soil water characteristic
+                      mLayerdPsi_dTheta(iSoil),        & ! intent(out): derivative in the soil water characteristic
+                      mLayerdTheta_dPsi(iSoil),        & ! intent(out): derivative in the soil water characteristic
+                      ! output: transmittance
+                      mLayerHydCond(iSoil),            & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
+                      mLayerDiffuse(iSoil),            & ! intent(out): diffusivity at layer mid-points (m2 s-1)
+                      iceImpedeFac(iSoil),             & ! intent(out): ice impedence factor in each layer (-)
+                      ! output: transmittance derivatives
+                      dHydCond_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+                      dDiffuse_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+                      dHydCond_dMatric(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
+                      dHydCond_dTemp(iSoil),           & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                      ! output: error control
+                      err,cmessage)                      ! intent(out): error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+     end do  ! (looping through soil layers)
+    
+     ! *************************************************************************************************************************************************
+     ! *************************************************************************************************************************************************
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+    
+     ! set derivative w.r.t. state above to zero (does not exist)
+     dq_dHydStateAbove(0) = 0._rkind
+     dq_dNrgStateAbove(0) = 0._rkind
+    
+     ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+     do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+    
+      ! =====
+      ! get input state variables...
+      ! ============================
+      ! identify the type of perturbation
+      ! Currently we are ignoring the perturbations in the non-surface layers and with temperature
+      select case(itry)
+    
+       ! skip undesired perturbations
+       case(perturbStateAbove); cycle  ! cannot perturb state above (does not exist) -- so keep cycling
+       case(perturbState); cycle       ! perturbing the layer below the flux at the top interface
+    
+       ! un-perturbed case
+       case(unperturbed)
+        scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
+        scalarMatricHeadLiqTrial = mLayerMatricHeadLiqTrial(1)
+    
+       ! perturb soil state (one-sided finite differences)
+       case(perturbStateBelow)
+        ! (perturbation depends on the form of Richards' equation)
+        select case(ixRichards)
+         case(moisture)
+          scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1) + dx
+          scalarMatricHeadLiqTrial = mLayerMatricHeadLiqTrial(1)
+         case(mixdform)
+          scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
+          scalarMatricHeadLiqTrial = mLayerMatricHeadLiqTrial(1) + dx
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select ! (form of Richards' equation
+       ! check for an unknown perturbation
+       case default; err=10; message=trim(message)//"unknown perturbation"; return
+    
+      end select ! (type of perturbation)
+    
+      ! =====
+      ! compute surface flux and its derivative...
+      ! ==========================================
+    
+      call surfaceFlx(&
+                      ! input: model control
+                      doInfiltrate,                       & ! intent(in): flag indicating if desire to compute infiltration
+                      desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
+                      ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                      ixBcUpperSoilHydrology,             & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
+                      nRoots,                             & ! intent(in): number of layers that contain roots
+                      ixIce,                              & ! intent(in): index of lowest ice layer
+                      nSoil,                              & ! intent(in): number of soil layers
+                      ! input: state variables
+                      mLayerTempTrial,                    & ! intent(in): temperature (K)
+                      scalarMatricHeadLiqTrial,           & ! intent(in): liquid matric head in the upper-most soil layer (m)
+                      mLayerMatricHeadLiqTrial,           & ! intent(in): liquid matric head in each soil layer (m)
+                      scalarVolFracLiqTrial,              & ! intent(in): volumetric liquid water content the upper-most soil layer (-)
+                      mLayerVolFracLiqTrial,              & ! intent(in): volumetric liquid water content in each soil layer (-)
+                      mLayerVolFracIceTrial,              & ! intent(in): volumetric ice content in each soil layer (-)
+                      ! input: pre-computed deriavatives
+                      mLayerdTheta_dTk,                   & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                      mLayerdTheta_dPsi,                  & ! intent(in): derivative in the soil water characteristic w.r.t. psi (m-1)
+                      mLayerdPsi_dTheta,                  & ! intent(in): derivative in the soil water characteristic w.r.t. theta (m)
+                      above_soilLiqFluxDeriv,             & ! intent(in): derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+                      above_soildLiq_dTk,                 & ! intent(in): derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+                      above_soilFracLiq,                  & ! intent(in): fraction of liquid water layer above soil (canopy or snow) (-)
+                      ! input: depth of upper-most soil layer (m)
+                      mLayerDepth,                        & ! intent(in): depth of each soil layer (m)
+                      iLayerHeight,                       & ! intent(in): height at the interface of each layer (m)
+                      ! input: boundary conditions
+                      upperBoundHead,                     & ! intent(in): upper boundary condition (m)
+                      upperBoundTheta,                    & ! intent(in): upper boundary condition (-)
+                      ! input: flux at the upper boundary
+                      scalarRainPlusMelt,                 & ! intent(in): rain plus melt (m s-1)
+                      ! input: transmittance
+                      iLayerSatHydCond(0),                & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                      dHydCond_dTemp(1),                  & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                      iceImpedeFac(1),                    & ! intent(in): ice impedence factor in the upper-most soil layer (-)
+                      ! input: soil parameters
+                      vGn_alpha(1),                       & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                      vGn_n(1),                           & ! intent(in): van Genutchen "n" parameter (-)
+                      vGn_m(1),                           & ! intent(in): van Genutchen "m" parameter (-)
+                      theta_sat(1),                       & ! intent(in): soil porosity (-)
+                      theta_res(1),                       & ! intent(in): soil residual volumetric water content (-)
+                      qSurfScale,                         & ! intent(in): scaling factor in the surface runoff parameterization (-)
+                      zScale_TOPMODEL,                    & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+                      rootingDepth,                       & ! intent(in): rooting depth (m)
+                      wettingFrontSuction,                & ! intent(in): Green-Ampt wetting front suction (m)
+                      soilIceScale,                       & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
+                      soilIceCV,                          & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
+                      ! input-output: hydraulic conductivity and diffusivity at the surface
+                      iLayerHydCond(0),                   & ! intent(inout): hydraulic conductivity at the surface (m s-1)
+                      iLayerDiffuse(0),                   & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
+                      ! input-output: fluxes at layer interfaces and surface runoff
+                      xMaxInfilRate,                      & ! intent(inout): maximum infiltration rate (m s-1)
+                      scalarInfilArea,                    & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                      scalarFrozenArea,                   & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                      scalarSurfaceRunoff,                & ! intent(out): surface runoff (m s-1)
+                      scalarSurfaceInfiltration,          & ! intent(out): surface infiltration (m s-1)
+                      ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
+                      dq_dHydStateLayerSurfVec,           & ! intent(inout): derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer  (m s-1 or s-1)
+                      dq_dNrgStateLayerSurfVec,           & ! intent(inout): derivative in surface infiltration w.r.t. energy state in above soil snow or canopy and every soil layer (m s-1 K-1)
+                      ! output: error control
+                      err,cmessage)                         ! intent(out): error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+      ! include base soil evaporation as the upper boundary flux
+      iLayerLiqFluxSoil(0) = scalarGroundEvaporation/iden_water + scalarSurfaceInfiltration
+    
+      ! get copies of surface flux to compute numerical derivatives
+      if(deriv_desired .and. ixDerivMethod==numerical)then
+       select case(itry)
+        case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(0)
+        case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(0)
+        case default; err=10; message=trim(message)//"unknown perturbation"; return
+       end select
+      end if
+    
+      !write(*,'(a,1x,10(f30.15))') 'scalarRainPlusMelt, scalarSurfaceInfiltration = ', scalarRainPlusMelt, scalarSurfaceInfiltration
+    
+     end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+    
+     dq_dHydStateBelow(0) = 0._rkind ! contribution will be in dq_dHydStateLayerSurfVec(1)
+     dq_dNrgStateBelow(0) = 0._rkind ! contribution will be in dq_dNrgStateLayerSurfVec(1)
+    
+     ! compute numerical derivatives
+     if(deriv_desired .and. ixDerivMethod==numerical)then
+      dq_dHydStateLayerSurfVec(1) = (scalarFlux_dStateBelow - scalarFlux)/dx ! change in surface flux w.r.t. change in the soil moisture in the top soil layer (m s-1)
+      dq_dHydStateLayerSurfVec(1) = 0._rkind ! Did not yet compute this perturbation
+     end if
+     !print*, 'scalarSurfaceInfiltration, iLayerLiqFluxSoil(0) = ', scalarSurfaceInfiltration, iLayerLiqFluxSoil(0)
+     !print*, '(ixDerivMethod==numerical), dq_dHydStateBelow(0) = ', (ixDerivMethod==numerical), dq_dHydStateBelow(0)
+     !pause
+    
+     ! *************************************************************************************************************************************************
+     ! *************************************************************************************************************************************************
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! * compute fluxes and derivatives at layer interfaces...
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+    
+     ! NOTE: computing flux at the bottom of the layer
+    
+     ! loop through soil layers
+     do iLayer=ixTop,min(ixBot,nSoil-1)
+    
+      ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+      do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+    
+       ! =====
+       ! determine layer to perturb
+       ! ============================
+       select case(itry)
+        ! skip undesired perturbations
+        case(perturbState); cycle       ! perturbing the layers above and below the flux at the interface
+        ! identify the index for the perturbation
+        case(unperturbed);       ixPerturb = 0
+        case(perturbStateAbove); ixPerturb = 1
+        case(perturbStateBelow); ixPerturb = 2
+        case default; err=10; message=trim(message)//"unknown perturbation"; return
+       end select ! (identifying layer to of perturbation)
+       ! determine the index in the original vector
+       ixOriginal = iLayer + (ixPerturb-1)
+    
+       ! =====
+       ! get input state variables...
+       ! ============================
+       ! start with the un-perturbed case
+       vectorVolFracLiqTrial(1:2) = mLayerVolFracLiqTrial(iLayer:iLayer+1)
+       vectorMatricHeadLiqTrial(1:2) = mLayerMatricHeadLiqTrial(iLayer:iLayer+1)
+       ! make appropriate perturbations
+       if(ixPerturb > 0)then
+        select case(ixRichards)
+         case(moisture); vectorVolFracLiqTrial(ixPerturb) = vectorVolFracLiqTrial(ixPerturb) + dx
+         case(mixdform); vectorMatricHeadLiqTrial(ixPerturb) = vectorMatricHeadLiqTrial(ixPerturb) + dx
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select ! (form of Richards' equation)
+       end if
+    
+       ! =====
+       ! get hydraulic conductivty...
+       ! ============================
+       ! start with the un-perturbed case
+       vectorHydCondTrial(1:2) = mLayerHydCond(iLayer:iLayer+1)
+       vectorDiffuseTrial(1:2) = mLayerDiffuse(iLayer:iLayer+1)
+       ! make appropriate perturbations
+       if(ixPerturb > 0)then ! only recompute these if perturbed
+        select case(ixRichards)
+         case(moisture)
+          scalardPsi_dTheta             = dPsi_dTheta(vectorVolFracLiqTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
+          vectorHydCondTrial(ixPerturb) = hydCond_liq(vectorVolFracLiqTrial(ixPerturb),mLayerSatHydCond(ixOriginal),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
+          vectorDiffuseTrial(ixPerturb) = scalardPsi_dTheta * vectorHydCondTrial(ixPerturb)
+         case(mixdform)
+          scalarVolFracLiqTrial = volFracLiq(vectorMatricHeadLiqTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
+          scalarHydCondMicro    = hydCond_psi(vectorMatricHeadLiqTrial(ixPerturb),mLayerSatHydCond(ixOriginal),vGn_alpha(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
+          scalarHydCondMacro    = hydCondMP_liq(scalarVolFracLiqTrial,theta_sat(ixPerturb),theta_mp,mpExp,mLayerSatHydCondMP(ixOriginal),mLayerSatHydCond(ixOriginal))
+          vectorHydCondTrial(ixPerturb) = scalarHydCondMicro + scalarHydCondMacro
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select ! (form of Richards' equation)
+       endif ! (recompute if perturbed)
+    
+       ! =====
+       ! compute vertical flux at layer interface and its derivative w.r.t. the state above and the state below...
+       ! =========================================================================================================
+    
+       ! NOTE: computing flux at the bottom of the layer
+    
+       call iLayerFlux(&
                        ! input: model control
-                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
-                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                       desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
                        ! input: state variables (adjacent layers)
-                       nodeMatricHeadTrial,       & ! intent(in): matric head at the soil nodes (m)
-                       nodeVolFracLiqTrial,       & ! intent(in): volumetric liquid water content at the soil nodes (-)
+                       vectorMatricHeadLiqTrial,           & ! intent(in): liquid matric head at the soil nodes (m)
+                       vectorVolFracLiqTrial,              & ! intent(in): volumetric liquid water content at the soil nodes (-)
                        ! input: model coordinate variables (adjacent layers)
-                       nodeHeight,                & ! intent(in): height of the soil nodes (m)
+                       mLayerHeight(iLayer:iLayer+1),      & ! intent(in): height of the soil nodes (m)
                        ! input: temperature derivatives
-                       dPsiLiq_dTemp,             & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
-                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       dPsiLiq_dTemp(iLayer:iLayer+1),     & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                       dHydCond_dTemp(iLayer:iLayer+1),    & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
                        ! input: transmittance (adjacent layers)
-                       nodeHydCondTrial,          & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
-                       nodeDiffuseTrial,          & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
+                       vectorHydCondTrial,                 & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
+                       vectorDiffuseTrial,                 & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
                        ! input: transmittance derivatives (adjacent layers)
-                       dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
-                       dDiffuse_dVolLiq,          & ! intent(in): derivative in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
-                       dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in matric head (s-1)
+                       dHydCond_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
+                       dDiffuse_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
+                       dHydCond_dMatric(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in matric head (s-1)
                        ! output: tranmsmittance at the layer interface (scalars)
-                       iLayerHydCond,             & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
-                       iLayerDiffuse,             & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
+                       iLayerHydCond(iLayer),              & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
+                       iLayerDiffuse(iLayer),              & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
                        ! output: vertical flux at the layer interface (scalars)
-                       iLayerLiqFluxSoil,         & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
+                       iLayerLiqFluxSoil(iLayer),          & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
                        ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
-                       dq_dHydStateAbove,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
-                       dq_dHydStateBelow,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+                       dq_dHydStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+                       dq_dHydStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
                        ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
-                       dq_dNrgStateAbove,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
-                       dq_dNrgStateBelow,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                       dq_dNrgStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                       dq_dNrgStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
                        ! output: error control
-                       err,message)                 ! intent(out): error control
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- ! input: model control
- logical(lgt),intent(in)       :: deriv_desired               ! flag indicating if derivatives are desired
- integer(i4b),intent(in)       :: ixRichards                  ! index defining the option for Richards' equation (moisture or mixdform)
- ! input: state variables
- real(dp),intent(in)           :: nodeMatricHeadTrial(:)      ! matric head at the soil nodes (m)
- real(dp),intent(in)           :: nodeVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the soil nodes (-)
- ! input: model coordinate variables
- real(dp),intent(in)           :: nodeHeight(:)               ! height at the mid-point of the lower layer (m)
- ! input: temperature derivatives
- real(dp),intent(in)           :: dPsiLiq_dTemp(:)            ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
- real(dp),intent(in)           :: dHydCond_dTemp(:)           ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
- ! input: transmittance
- real(dp),intent(in)           :: nodeHydCondTrial(:)         ! hydraulic conductivity at layer mid-points (m s-1)
- real(dp),intent(in)           :: nodeDiffuseTrial(:)         ! diffusivity at layer mid-points (m2 s-1)
- ! input: transmittance derivatives
- real(dp),intent(in)           :: dHydCond_dVolLiq(:)         ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
- real(dp),intent(in)           :: dDiffuse_dVolLiq(:)         ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
- real(dp),intent(in)           :: dHydCond_dMatric(:)         ! derivative in hydraulic conductivity w.r.t matric head (m s-1)
- ! output: tranmsmittance at the layer interface (scalars)
- real(dp),intent(out)          :: iLayerHydCond               ! hydraulic conductivity at the interface between layers (m s-1)
- real(dp),intent(out)          :: iLayerDiffuse               ! hydraulic diffusivity at the interface between layers (m2 s-1)
- ! output: vertical flux at the layer interface (scalars)
- real(dp),intent(out)          :: iLayerLiqFluxSoil           ! vertical flux of liquid water at the layer interface (m s-1)
- ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
- real(dp),intent(out)          :: dq_dHydStateAbove           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
- real(dp),intent(out)          :: dq_dHydStateBelow           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
- ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
- real(dp),intent(out)          :: dq_dNrgStateAbove           ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
- real(dp),intent(out)          :: dq_dNrgStateBelow           ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)      :: err                         ! error code
- character(*),intent(out)      :: message                     ! error message
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- ! local variables (named variables to provide index of 2-element vectors)
- integer(i4b),parameter        :: ixUpper=1                   ! index of upper node in the 2-element vectors
- integer(i4b),parameter        :: ixLower=2                   ! index of lower node in the 2-element vectors
- logical(lgt),parameter        :: useGeometric=.false.        ! switch between the arithmetic and geometric mean
- ! local variables (Darcy flux)
- real(dp)                      :: dPsi                        ! spatial difference in matric head (m)
- real(dp)                      :: dLiq                        ! spatial difference in volumetric liquid water (-)
- real(dp)                      :: dz                          ! spatial difference in layer mid-points (m)
- real(dp)                      :: cflux                       ! capillary flux (m s-1)
- ! local variables (derivative in Darcy's flux)
- real(dp)                      :: dHydCondIface_dVolLiqAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer above
- real(dp)                      :: dHydCondIface_dVolLiqBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer below
- real(dp)                      :: dDiffuseIface_dVolLiqAbove  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer above
- real(dp)                      :: dDiffuseIface_dVolLiqBelow  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer below
- real(dp)                      :: dHydCondIface_dMatricAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer above
- real(dp)                      :: dHydCondIface_dMatricBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer below
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message="iLayerFlux/"
-
- ! *****
- ! compute the vertical flux of liquid water
- ! compute the hydraulic conductivity at the interface
- if(useGeometric)then
-  iLayerHydCond   = (nodeHydCondTrial(ixLower)   * nodeHydCondTrial(ixUpper))**0.5_dp
- else
-  iLayerHydCond   = (nodeHydCondTrial(ixLower)   + nodeHydCondTrial(ixUpper))*0.5_dp
- end if
- !write(*,'(a,1x,5(e20.10,1x))') 'in iLayerFlux: iLayerHydCond, iLayerHydCondMP = ', iLayerHydCond, iLayerHydCondMP
- ! compute the height difference between nodes
- dz = nodeHeight(ixLower) - nodeHeight(ixUpper)
- ! compute the capillary flux
- select case(ixRichards)  ! (form of Richards' equation)
-  case(moisture)
-   iLayerDiffuse = (nodeDiffuseTrial(ixLower) * nodeDiffuseTrial(ixUpper))**0.5_dp
-   dLiq          = nodeVolFracLiqTrial(ixLower) - nodeVolFracLiqTrial(ixUpper)
-   cflux         = -iLayerDiffuse * dLiq/dz
-  case(mixdform)
-   iLayerDiffuse = realMissing
-   dPsi          = nodeMatricHeadTrial(ixLower) - nodeMatricHeadTrial(ixUpper)
-   cflux         = -iLayerHydCond * dPsi/dz
-  case default; err=10; message=trim(message)//"unable to identify option for Richards' equation"; return
- end select
- ! compute the total flux (add gravity flux, positive downwards)
- iLayerLiqFluxSoil = cflux + iLayerHydCond
- !write(*,'(a,1x,10(e20.10,1x))') 'iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond = ', &
- !                                 iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond
-
- ! ** compute the derivatives
- if(deriv_desired)then
-  select case(ixRichards)  ! (form of Richards' equation)
-   case(moisture)
-    ! still need to implement arithmetric mean for the moisture-based form
-    if(.not.useGeometric)then
-     message=trim(message)//'only currently implemented for geometric mean -- change local flag'
-     err=20; return
-    end if
-    ! derivatives in hydraulic conductivity at the layer interface (m s-1)
-    dHydCondIface_dVolLiqAbove = dHydCond_dVolLiq(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_dp/max(iLayerHydCond,verySmall)
-    dHydCondIface_dVolLiqBelow = dHydCond_dVolLiq(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_dp/max(iLayerHydCond,verySmall)
-    ! derivatives in hydraulic diffusivity at the layer interface (m2 s-1)
-    dDiffuseIface_dVolLiqAbove = dDiffuse_dVolLiq(ixUpper)*nodeDiffuseTrial(ixLower) * 0.5_dp/max(iLayerDiffuse,verySmall)
-    dDiffuseIface_dVolLiqBelow = dDiffuse_dVolLiq(ixLower)*nodeDiffuseTrial(ixUpper) * 0.5_dp/max(iLayerDiffuse,verySmall)
-    ! derivatives in the flux w.r.t. volumetric liquid water content
-    dq_dHydStateAbove = -dDiffuseIface_dVolLiqAbove*dLiq/dz + iLayerDiffuse/dz + dHydCondIface_dVolLiqAbove
-    dq_dHydStateBelow = -dDiffuseIface_dVolLiqBelow*dLiq/dz - iLayerDiffuse/dz + dHydCondIface_dVolLiqBelow
-   case(mixdform)
-    ! derivatives in hydraulic conductivity
-    if(useGeometric)then
-     dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_dp/max(iLayerHydCond,verySmall)
-     dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_dp/max(iLayerHydCond,verySmall)
-    else
-     dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)/2._dp
-     dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)/2._dp
-    end if
-    ! derivatives in the flux w.r.t. matric head
-    dq_dHydStateAbove = -dHydCondIface_dMatricAbove*dPsi/dz + iLayerHydCond/dz + dHydCondIface_dMatricAbove
-    dq_dHydStateBelow = -dHydCondIface_dMatricBelow*dPsi/dz - iLayerHydCond/dz + dHydCondIface_dMatricBelow
-    ! derivative in the flux w.r.t. temperature
-    dq_dNrgStateAbove = -(dHydCond_dTemp(ixUpper)/2._dp)*dPsi/dz + iLayerHydCond*dPsiLiq_dTemp(ixUpper)/dz + dHydCond_dTemp(ixUpper)/2._dp
-    dq_dNrgStateBelow = -(dHydCond_dTemp(ixLower)/2._dp)*dPsi/dz - iLayerHydCond*dPsiLiq_dTemp(ixLower)/dz + dHydCond_dTemp(ixLower)/2._dp
-   case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-  end select
- else
-  dq_dHydStateAbove = realMissing
-  dq_dHydStateBelow = realMissing
- end if
-
- end subroutine iLayerFlux
-
-
- ! ***************************************************************************************************************
- ! private subroutine qDrainFlux: compute the drainage flux from the bottom of the soil profile and its derivative
- ! ***************************************************************************************************************
- subroutine qDrainFlux(&
+                       err,cmessage)                         ! intent(out): error control
+       if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+       ! compute total vertical flux, to compute derivatives
+       if(deriv_desired .and. ixDerivMethod==numerical)then
+        select case(itry)
+         case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(iLayer)
+         case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(iLayer)
+         case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(iLayer)
+         case default; err=10; message=trim(message)//"unknown perturbation"; return
+        end select
+       end if
+    
+      end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+    
+      ! compute numerical derivatives
+      if(deriv_desired .and. ixDerivMethod==numerical)then
+       dq_dHydStateAbove(iLayer) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
+       dq_dHydStateBelow(iLayer) = (scalarFlux_dStateBelow - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
+      end if
+    
+      ! check
+      !if(iLayer==6) write(*,'(a,i4,1x,10(e25.15,1x))') 'iLayer, vectorMatricHeadLiqTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer) = ',&
+      !                                                  iLayer, vectorMatricHeadLiqTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer)
+      !if(iLayer==1) write(*,'(a,i4,1x,L1,1x,2(e15.5,1x))') 'iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer) = ', &
+      !                                                      iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer)
+      !pause
+    
+     end do  ! (looping through soil layers)
+    
+     ! add infiltration to the upper-most unfrozen layer
+     ! NOTE: this is done here rather than in surface runoff
+     !iLayerLiqFluxSoil(ixIce) = iLayerLiqFluxSoil(ixIce) + scalarSurfaceInfiltration
+    
+     ! *************************************************************************************************************************************************
+     ! *************************************************************************************************************************************************
+    
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     ! * compute drainage flux from the bottom of the soil profile, and its derivative
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+    
+     ! define the need to compute drainage
+     if( .not. (scalarSolution .and. ixTop<nSoil) )then
+    
+      ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+      do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+    
+       ! =====
+       ! get input state variables...
+       ! ============================
+       ! identify the type of perturbation
+       select case(itry)
+    
+        ! skip undesired perturbations
+        case(perturbStateBelow); cycle   ! only perturb soil state at this time (perhaps perturb aquifer state later)
+        case(perturbState); cycle        ! here pertubing the state above the flux at the interface
+    
+        ! un-perturbed case
+        case(unperturbed)
+         scalarVolFracLiqTrial   = mLayerVolFracLiqTrial(nSoil)
+         scalarMatricHeadLiqTrial   = mLayerMatricHeadLiqTrial(nSoil)
+    
+        ! perturb soil state (one-sided finite differences)
+        case(perturbStateAbove)
+         select case(ixRichards)  ! (perturbation depends on the form of Richards' equation)
+          case(moisture)
+           scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil) + dx
+           scalarMatricHeadLiqTrial = mLayerMatricHeadLiqTrial(nSoil)
+          case(mixdform)
+           scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil)
+           scalarMatricHeadLiqTrial = mLayerMatricHeadLiqTrial(nSoil) + dx
+          case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+         end select ! (form of Richards' equation)
+    
+       end select ! (type of perturbation)
+    
+       ! =====
+       ! get hydraulic conductivty...
+       ! ============================
+       select case(itry)
+    
+        ! compute perturbed value of hydraulic conductivity
+        case(perturbStateAbove)
+         select case(ixRichards)
+          case(moisture); scalarHydCondTrial = hydCond_liq(scalarVolFracLiqTrial,mLayerSatHydCond(nSoil),theta_res(nSoil),theta_sat(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
+          case(mixdform); scalarHydCondTrial = hydCond_psi(scalarMatricHeadLiqTrial,mLayerSatHydCond(nSoil),vGn_alpha(nSoil),vGn_n(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
+         end select
+    
+        ! (use un-perturbed value)
+        case default
+         scalarHydCondTrial = mLayerHydCond(nSoil)        ! hydraulic conductivity at the mid-point of the lowest unsaturated soil layer (m s-1)
+    
+       end select ! (re-computing hydraulic conductivity)
+    
+       ! =====
+       ! compute drainage flux and its derivative...
+       ! ===========================================
+    
+       call qDrainFlux(&
                        ! input: model control
-                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
-                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
-                       bc_lower,                  & ! intent(in): index defining the type of boundary conditions
+                       desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,                      & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                       ixBcLowerSoilHydrology,          & ! intent(in): index defining the type of boundary conditions
                        ! input: state variables
-                       nodeMatricHead,            & ! intent(in): matric head in the lowest unsaturated node (m)
-                       nodeVolFracLiq,            & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
+                       scalarMatricHeadLiqTrial,        & ! intent(in): liquid matric head in the lowest unsaturated node (m)
+                       scalarVolFracLiqTrial,           & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
                        ! input: model coordinate variables
-                       nodeDepth,                 & ! intent(in): depth of the lowest unsaturated soil layer (m)
-                       nodeHeight,                & ! intent(in): height of the lowest unsaturated soil node (m)
+                       mLayerDepth(nSoil),              & ! intent(in): depth of the lowest unsaturated soil layer (m)
+                       mLayerHeight(nSoil),             & ! intent(in): height of the lowest unsaturated soil node (m)
                        ! input: boundary conditions
-                       lowerBoundHead,            & ! intent(in): lower boundary condition (m)
-                       lowerBoundTheta,           & ! intent(in): lower boundary condition (-)
-                       ! input: derivative in soil water characteristix
-                       node__dPsi_dTheta,         & ! intent(in): derivative of the soil moisture characteristic w.r.t. theta (m)
+                       lowerBoundHead,                  & ! intent(in): lower boundary condition (m)
+                       lowerBoundTheta,                 & ! intent(in): lower boundary condition (-)
+                       ! input: derivative in the soil water characteristic
+                       mLayerdPsi_dTheta(nSoil),        & ! intent(in): derivative in the soil water characteristic
                        ! input: transmittance
-                       surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
-                       bottomSatHydCond,          & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
-                       nodeHydCond,               & ! intent(in): hydraulic conductivity at the node itself (m s-1)
-                       iceImpedeFac,              & ! intent(in): ice impedence factor in the lower-most soil layer (-)
+                       iLayerSatHydCond(0),             & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                       iLayerSatHydCond(nSoil),         & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+                       scalarHydCondTrial,              & ! intent(in): hydraulic conductivity at the node itself (m s-1)
+                       iceImpedeFac(nSoil),             & ! intent(in): ice impedence factor in the lower-most soil layer (-)
                        ! input: transmittance derivatives
-                       dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
-                       dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
-                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       dHydCond_dVolLiq(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+                       dHydCond_dMatric(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
+                       dHydCond_dTemp(nSoil),           & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
                        ! input: soil parameters
-                       vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
-                       vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
-                       VGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
-                       theta_sat,                 & ! intent(in): soil porosity (-)
-                       theta_res,                 & ! intent(in): soil residual volumetric water content (-)
-                       kAnisotropic,              & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
-                       zScale_TOPMODEL,           & ! intent(in): TOPMODEL scaling factor (m)
+                       vGn_alpha(nSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                       vGn_n(nSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
+                       vGn_m(nSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
+                       theta_sat(nSoil),                & ! intent(in): soil porosity (-)
+                       theta_res(nSoil),                & ! intent(in): soil residual volumetric water content (-)
+                       kAnisotropic,                    & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+                       zScale_TOPMODEL,                 & ! intent(in): TOPMODEL scaling factor (m)
                        ! output: hydraulic conductivity and diffusivity at the surface
-                       bottomHydCond,             & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
-                       bottomDiffuse,             & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
-                       ! output: drainage flux from the bottom of the soil profile
-                       scalarDrainage,            & ! intent(out): drainage flux from the bottom of the soil profile (m s-1)
+                       iLayerHydCond(nSoil),            & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
+                       iLayerDiffuse(nSoil),            & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+                       ! output: drainage flux
+                       iLayerLiqFluxSoil(nSoil),        & ! intent(out): drainage flux (m s-1)
                        ! output: derivatives in drainage flux
-                       dq_dHydStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in hydrology state variable in lowest unsaturated node (m s-1 or s-1)
-                       dq_dNrgStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
+                       dq_dHydStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in hydrology state in lowest unsaturated node (m s-1 or s-1)
+                       dq_dNrgStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in energy state in lowest unsaturated node (m s-1 or s-1)
                        ! output: error control
-                       err,message)                 ! intent(out): error control
- USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water as a function of matric head (-)
- USE soil_utils_module,only:matricHead      ! compute matric head as a function of volumetric fraction of liquid water (m)
- USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head (m s-1)
- USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
- USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
- ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
- implicit none
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! input: model control
- logical(lgt),intent(in)       :: deriv_desired             ! flag to indicate if derivatives are desired
- integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
- integer(i4b),intent(in)       :: bc_lower                  ! index defining the type of boundary conditions
- ! input: state and diagnostic variables
- real(dp),intent(in)           :: nodeMatricHead            ! matric head in the lowest unsaturated node (m)
- real(dp),intent(in)           :: nodeVolFracLiq            ! volumetric liquid water content in the lowest unsaturated node (-)
- ! input: model coordinate variables
- real(dp),intent(in)           :: nodeDepth                 ! depth of the lowest unsaturated soil layer (m)
- real(dp),intent(in)           :: nodeHeight                ! height of the lowest unsaturated soil node (m)
- ! input: diriclet boundary conditions
- real(dp),intent(in)           :: lowerBoundHead            ! lower boundary condition for matric head (m)
- real(dp),intent(in)           :: lowerBoundTheta           ! lower boundary condition for volumetric liquid water content (-)
- ! input: derivative in soil water characteristix
- real(dp),intent(in)           :: node__dPsi_dTheta         ! derivative of the soil moisture characteristic w.r.t. theta (m)
- ! input: transmittance
- real(dp),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
- real(dp),intent(in)           :: bottomSatHydCond          ! saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
- real(dp),intent(in)           :: nodeHydCond               ! hydraulic conductivity at the node itself (m s-1)
- real(dp),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
- ! input: transmittance derivatives
- real(dp),intent(in)           :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
- real(dp),intent(in)           :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
- real(dp),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
- ! input: soil parameters
- real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
- real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
- real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
- real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
- real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
- real(dp),intent(in)           :: kAnisotropic              ! anisotropy factor for lateral hydraulic conductivity (-)
- real(dp),intent(in)           :: zScale_TOPMODEL           ! scale factor for TOPMODEL-ish baseflow parameterization (m)
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! output: hydraulic conductivity at the bottom of the unsaturated zone
- real(dp),intent(out)          :: bottomHydCond             ! hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
- real(dp),intent(out)          :: bottomDiffuse             ! hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
- ! output: drainage flux from the bottom of the soil profile
- real(dp),intent(out)          :: scalarDrainage            ! drainage flux from the bottom of the soil profile (m s-1)
- ! output: derivatives in drainage flux
- real(dp),intent(out)          :: dq_dHydStateUnsat         ! change in drainage flux w.r.t. change in state variable in lowest unsaturated node (m s-1 or s-1)
- real(dp),intent(out)          :: dq_dNrgStateUnsat         ! change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)      :: err                       ! error code
- character(*),intent(out)      :: message                   ! error message
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! local variables
- real(dp)                      :: zWater                    ! effective water table depth (m)
- real(dp)                      :: nodePsi                   ! matric head in the lowest unsaturated node (m)
- real(dp)                      :: cflux                     ! capillary flux (m s-1)
- ! -----------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message="qDrainFlux/"
-
- ! determine lower boundary condition
- select case(bc_lower)
-
-  ! ---------------------------------------------------------------------------------------------
-  ! * prescribed head
-  ! ---------------------------------------------------------------------------------------------
-  case(prescribedHead)
-
-   ! compute fluxes
-   select case(ixRichards)  ! (moisture-based form of Richards' equation)
-    case(moisture)
-     ! compute the hydraulic conductivity and diffusivity at the boundary
-     bottomHydCond = hydCond_liq(lowerBoundTheta,bottomSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
-     bottomDiffuse = dPsi_dTheta(lowerBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * bottomHydCond
-     ! compute the capillary flux
-     cflux = -bottomDiffuse*(lowerBoundTheta - nodeVolFracLiq) / (nodeDepth*0.5_dp)
-    case(mixdform)
-     ! compute the hydraulic conductivity and diffusivity at the boundary
-     bottomHydCond = hydCond_psi(lowerBoundHead,bottomSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
-     bottomDiffuse = realMissing
+                       err,cmessage)                ! intent(out): error control
+       if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+       ! get copies of drainage flux to compute derivatives
+       if(deriv_desired .and. ixDerivMethod==numerical)then
+        select case(itry)
+         case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(nSoil)
+         case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(nSoil)
+         case(perturbStateBelow); err=20; message=trim(message)//'lower state should never be perturbed when computing drainage do not expect to get here'; return
+         case default; err=10; message=trim(message)//"unknown perturbation"; return
+        end select
+       end if
+    
+      end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+    
+      ! compute numerical derivatives
+      ! NOTE: drainage derivatives w.r.t. state below are *actually* w.r.t. water table depth, so need to be corrected for aquifer storage
+      !       (note also negative sign to account for inverse relationship between water table depth and aquifer storage)
+      if(deriv_desired .and. ixDerivMethod==numerical)then
+       dq_dHydStateAbove(nSoil) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in state in lowest unsaturated node (m s-1 or s-1)
+      end if
+    
+      ! no dependence on the aquifer for drainage
+      dq_dHydStateBelow(nSoil) = 0._rkind  ! keep this here in case we want to couple some day....
+      dq_dNrgStateBelow(nSoil) = 0._rkind  ! keep this here in case we want to couple some day....
+    
+      ! print drainage
+      !print*, 'iLayerLiqFluxSoil(nSoil) = ', iLayerLiqFluxSoil(nSoil)
+    
+     endif  ! if computing drainage
+     ! end of drainage section
+    
+     ! *****************************************************************************************************************************************************************
+     ! *****************************************************************************************************************************************************************
+    
+     ! end association between local variables and the information in the data structures
+     end associate
+    
+     end subroutine soilLiqFlx
+    
+     ! ***************************************************************************************************************
+     ! private subroutine diagv_node: compute transmittance and derivatives for model nodes
+     ! ***************************************************************************************************************
+     subroutine diagv_node(&
+                           ! input: model control
+                           deriv_desired,         & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,            & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
+                           ! input: state variables
+                           scalarTempTrial,       & ! intent(in): temperature (K)
+                           scalarMatricHeadLiqTrial, & ! intent(in): liquid matric head in a given layer (m)
+                           scalarVolFracLiqTrial, & ! intent(in): volumetric liquid water content in a given soil layer (-)
+                           scalarVolFracIceTrial, & ! intent(in): volumetric ice content in a given soil layer (-)
+                           ! input: pre-computed deriavatives
+                           dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           dPsiLiq_dTemp,         & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                           ! input: soil parameters
+                           vGn_alpha,             & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                           vGn_n,                 & ! intent(in): van Genutchen "n" parameter (-)
+                           vGn_m,                 & ! intent(in): van Genutchen "m" parameter (-)
+                           mpExp,                 & ! intent(in): empirical exponent in macropore flow equation (-)
+                           theta_sat,             & ! intent(in): soil porosity (-)
+                           theta_res,             & ! intent(in): soil residual volumetric water content (-)
+                           theta_mp,              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+                           f_impede,              & ! intent(in): ice impedence factor (-)
+                           ! input: saturated hydraulic conductivity
+                           scalarSatHydCond,      & ! intent(in): saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
+                           scalarSatHydCondMP,    & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
+                           ! output: derivative in the soil water characteristic
+                           scalardPsi_dTheta,     & ! derivative in the soil water characteristic
+                           scalardTheta_dPsi,     & ! derivative in the soil water characteristic
+                           ! output: transmittance
+                           scalarHydCond,         & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
+                           scalarDiffuse,         & ! intent(out): diffusivity at layer mid-points (m2 s-1)
+                           iceImpedeFac,          & ! intent(out): ice impedence factor in each layer (-)
+                           ! output: transmittance derivatives
+                           dHydCond_dVolLiq,      & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+                           dDiffuse_dVolLiq,      & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+                           dHydCond_dMatric,      & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
+                           dHydCond_dTemp,        & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                           ! output: error control
+                           err,message)             ! intent(out): error control
+     USE soil_utils_module,only:iceImpede           ! compute the ice impedence factor
+     USE soil_utils_module,only:volFracLiq          ! compute volumetric fraction of liquid water as a function of matric head
+     USE soil_utils_module,only:matricHead          ! compute matric head (m)
+     USE soil_utils_module,only:hydCond_psi         ! compute hydraulic conductivity as a function of matric head
+     USE soil_utils_module,only:hydCond_liq         ! compute hydraulic conductivity as a function of volumetric liquid water content
+     USE soil_utils_module,only:hydCondMP_liq       ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
+     USE soil_utils_module,only:dTheta_dPsi         ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
+     USE soil_utils_module,only:dPsi_dTheta         ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+     USE soil_utils_module,only:dPsi_dTheta2        ! compute derivative in dPsi_dTheta (m)
+     USE soil_utils_module,only:dHydCond_dLiq       ! compute derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+     USE soil_utils_module,only:dHydCond_dPsi       ! compute derivative in hydraulic conductivity w.r.t. matric head (s-1)
+     USE soil_utils_module,only:dIceImpede_dTemp    ! compute the derivative in the ice impedance factor w.r.t. temperature (K-1)
+     ! compute hydraulic transmittance and derivatives for all layers
+     implicit none
+     ! input: model control
+     logical(lgt),intent(in)       :: deriv_desired             ! flag indicating if derivatives are desired
+     integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+     ! input: state and diagnostic variables
+     real(rkind),intent(in)           :: scalarTempTrial           ! temperature in each layer (K)
+     real(rkind),intent(in)           :: scalarMatricHeadLiqTrial  ! liquid matric head in each layer (m)
+     real(rkind),intent(in)           :: scalarVolFracLiqTrial     ! volumetric fraction of liquid water in a given layer (-)
+     real(rkind),intent(in)           :: scalarVolFracIceTrial     ! volumetric fraction of ice in a given layer (-)
+     ! input: pre-computed deriavatives
+     real(rkind),intent(in)           :: dTheta_dTk                ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+     real(rkind),intent(in)           :: dPsiLiq_dTemp             ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+     ! input: soil parameters
+     real(rkind),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+     real(rkind),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+     real(rkind),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+     real(rkind),intent(in)           :: mpExp                     ! empirical exponent in macropore flow equation (-)
+     real(rkind),intent(in)           :: theta_sat                 ! soil porosity (-)
+     real(rkind),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+     real(rkind),intent(in)           :: theta_mp                  ! volumetric liquid water content when macropore flow begins (-)
+     real(rkind),intent(in)           :: f_impede                  ! ice impedence factor (-)
+     ! input: saturated hydraulic conductivity
+     real(rkind),intent(in)           :: scalarSatHydCond          ! saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
+     real(rkind),intent(in)           :: scalarSatHydCondMP        ! saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
+     ! output: derivative in the soil water characteristic
+     real(rkind),intent(out)          :: scalardPsi_dTheta         ! derivative in the soil water characteristic
+     real(rkind),intent(out)          :: scalardTheta_dPsi         ! derivative in the soil water characteristic
+     ! output: transmittance
+     real(rkind),intent(out)          :: scalarHydCond             ! hydraulic conductivity at layer mid-points (m s-1)
+     real(rkind),intent(out)          :: scalarDiffuse             ! diffusivity at layer mid-points (m2 s-1)
+     real(rkind),intent(out)          :: iceImpedeFac              ! ice impedence factor in each layer (-)
+     ! output: transmittance derivatives
+     real(rkind),intent(out)          :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+     real(rkind),intent(out)          :: dDiffuse_dVolLiq          ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+     real(rkind),intent(out)          :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t matric head (s-1)
+     real(rkind),intent(out)          :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+     ! output: error control
+     integer(i4b),intent(out)      :: err                       ! error code
+     character(*),intent(out)      :: message                   ! error message
+     ! local variables
+     real(rkind)                      :: localVolFracLiq           ! local volumetric fraction of liquid water
+     real(rkind)                      :: scalarHydCondMP           ! hydraulic conductivity of macropores at layer mid-points (m s-1)
+     real(rkind)                      :: dIceImpede_dT             ! derivative in ice impedance factor w.r.t. temperature (K-1)
+     real(rkind)                      :: dHydCondMacro_dVolLiq     ! derivative in hydraulic conductivity of macropores w.r.t volumetric liquid water content (m s-1)
+     real(rkind)                      :: dHydCondMacro_dMatric     ! derivative in hydraulic conductivity of macropores w.r.t matric head (s-1)
+     real(rkind)                      :: dHydCondMicro_dMatric     ! derivative in hydraulic conductivity of micropores w.r.t matric head (s-1)
+     real(rkind)                      :: dHydCondMicro_dTemp       ! derivative in hydraulic conductivity of micropores w.r.t temperature (m s-1 K-1)
+     real(rkind)                      :: dPsi_dTheta2a             ! derivative in dPsi_dTheta (analytical)
+     real(rkind)                      :: dIceImpede_dLiq           ! derivative in ice impedence factor w.r.t. volumetric liquid water content (-)
+     real(rkind)                      :: hydCond_noIce             ! hydraulic conductivity in the absence of ice (m s-1)
+     real(rkind)                      :: dK_dLiq__noIce            ! derivative in hydraulic conductivity w.r.t volumetric liquid water content, in the absence of ice (m s-1)
+     real(rkind)                      :: dK_dPsi__noIce            ! derivative in hydraulic conductivity w.r.t matric head, in the absence of ice (s-1)
+     real(rkind)                      :: relSatMP                  ! relative saturation of macropores (-)
+     ! local variables to test the derivative
+     logical(lgt),parameter        :: testDeriv=.false.         ! local flag to test the derivative
+     real(rkind)                      :: xConst                    ! LH_fus/(gravity*Tfreeze), used in freezing point depression equation (m K-1)
+     real(rkind)                      :: vTheta                    ! volumetric fraction of total water (-)
+     real(rkind)                      :: volLiq                    ! volumetric fraction of liquid water (-)
+     real(rkind)                      :: volIce                    ! volumetric fraction of ice (-)
+     real(rkind)                      :: volFracLiq1,volFracLiq2   ! different trial values of volumetric liquid water content (-)
+     real(rkind)                      :: effSat                    ! effective saturation (-)
+     real(rkind)                      :: psiLiq                    ! liquid water matric potential (m)
+     real(rkind)                      :: hydCon                    ! hydraulic conductivity (m s-1)
+     real(rkind)                      :: hydIce                    ! hydraulic conductivity after accounting for ice impedance (-)
+     real(rkind),parameter            :: dx = 1.e-8_rkind             ! finite difference increment (m)
+     ! initialize error control
+     err=0; message="diagv_node/"
+    
+     ! *****
+     ! compute the derivative in the soil water characteristic
+     select case(ixRichards)
+      case(moisture)
+       scalardPsi_dTheta = dPsi_dTheta(scalarVolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+       scalardTheta_dPsi = realMissing  ! (deliberately cause problems if this is ever used)
+      case(mixdform)
+       scalardTheta_dPsi = dTheta_dPsi(scalarMatricHeadLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+       scalardPsi_dTheta = dPsi_dTheta(scalarVolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+       if(testDeriv)then
+        volFracLiq1 = volFracLiq(scalarMatricHeadLiqTrial,   vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+        volFracLiq2 = volFracLiq(scalarMatricHeadLiqTrial+dx,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+       end if  ! (testing the derivative)
+      case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+     end select
+    
+     ! *****
+     ! compute hydraulic conductivity and its derivative in each soil layer
+    
+     ! compute the ice impedence factor and its derivative w.r.t. volumetric liquid water content (-)
+     call iceImpede(scalarVolFracIceTrial,f_impede, &  ! input
+                    iceImpedeFac,dIceImpede_dLiq)      ! output
+    
+     select case(ixRichards)
+      ! ***** moisture-based form of Richards' equation
+      case(moisture)
+       ! haven't included macropores yet
+       err=20; message=trim(message)//'still need to include macropores for the moisture-based form of Richards eqn'; return
+       ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
+       hydCond_noIce = hydCond_liq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m)
+       scalarHydCond = hydCond_noIce*iceImpedeFac
+       scalarDiffuse = scalardPsi_dTheta * scalarHydCond
+       ! compute derivative in hydraulic conductivity (m s-1) and hydraulic diffusivity (m2 s-1)
+       if(deriv_desired)then
+        if(scalarVolFracIceTrial > epsilon(iceImpedeFac))then
+         dK_dLiq__noIce   = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)  ! [.true. = analytical]
+         dHydCond_dVolLiq = hydCond_noIce*dIceImpede_dLiq + dK_dLiq__noIce*iceImpedeFac
+        else
+         dHydCond_dVolLiq = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)
+        end if
+        dPsi_dTheta2a    = dPsi_dTheta2(scalarVolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m,.true.)   ! [.true. = analytical] compute derivative in dPsi_dTheta (m)
+        dDiffuse_dVolLiq = dHydCond_dVolLiq*scalardPsi_dTheta + scalarHydCond*dPsi_dTheta2a
+        dHydCond_dMatric = realMissing ! not used, so cause problems
+       end if
+    
+      ! ***** mixed form of Richards' equation -- just compute hydraulic condictivity
+      case(mixdform)
+       ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
+       hydCond_noIce = hydCond_psi(scalarMatricHeadLiqTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
+       scalarDiffuse = realMissing ! not used, so cause problems
+       ! compute the hydraulic conductivity of macropores (m s-1)
+       localVolFracLiq = volFracLiq(scalarMatricHeadLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+       scalarHydCondMP = hydCondMP_liq(localVolFracLiq,theta_sat,theta_mp,mpExp,scalarSatHydCondMP,scalarSatHydCond)
+       scalarHydCond   = hydCond_noIce*iceImpedeFac + scalarHydCondMP
+    
+       ! compute derivative in hydraulic conductivity (m s-1)
+       if(deriv_desired)then
+        ! (compute derivative for macropores)
+        if(localVolFracLiq > theta_mp)then
+         relSatMP              = (localVolFracLiq - theta_mp)/(theta_sat - theta_mp)
+         dHydCondMacro_dVolLiq = ((scalarSatHydCondMP - scalarSatHydCond)/(theta_sat - theta_mp))*mpExp*(relSatMP**(mpExp - 1._rkind))
+         dHydCondMacro_dMatric = scalardTheta_dPsi*dHydCondMacro_dVolLiq
+        else
+         dHydCondMacro_dVolLiq = 0._rkind
+         dHydCondMacro_dMatric = 0._rkind
+        end if
+        ! (compute derivatives for micropores)
+        if(scalarVolFracIceTrial > verySmall)then
+         dK_dPsi__noIce        = dHydCond_dPsi(scalarMatricHeadLiqTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)  ! analytical
+         dHydCondMicro_dTemp   = dPsiLiq_dTemp*dK_dPsi__noIce  ! m s-1 K-1
+         dHydCondMicro_dMatric = hydCond_noIce*dIceImpede_dLiq*scalardTheta_dPsi + dK_dPsi__noIce*iceImpedeFac
+        else
+         dHydCondMicro_dTemp   = 0._rkind
+         dHydCondMicro_dMatric = dHydCond_dPsi(scalarMatricHeadLiqTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)
+        end if
+        ! (combine derivatives)
+        dHydCond_dMatric = dHydCondMicro_dMatric + dHydCondMacro_dMatric
+    
+        ! (compute analytical derivative for change in ice impedance factor w.r.t. temperature)
+        call dIceImpede_dTemp(scalarVolFracIceTrial, & ! intent(in): trial value of volumetric ice content (-)
+                              dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                              f_impede,              & ! intent(in): ice impedance parameter (-)
+                              dIceImpede_dT          ) ! intent(out): derivative in ice impedance factor w.r.t. temperature (K-1)
+        ! (compute derivative in hydraulic conductivity w.r.t. temperature)
+        dHydCond_dTemp = hydCond_noIce*dIceImpede_dT + dHydCondMicro_dTemp*iceImpedeFac
+        ! (test derivative)
+        if(testDeriv)then
+         xConst = LH_fus/(gravity*Tfreeze)                            ! m K-1 (NOTE: J = kg m2 s-2)
+         vTheta = scalarVolFracIceTrial + scalarVolFracLiqTrial
+         volLiq = volFracLiq(xConst*(scalarTempTrial+dx - Tfreeze),vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+         volIce = vTheta - volLiq
+         effSat = (volLiq - theta_res)/(theta_sat - volIce - theta_res)
+         psiLiq = matricHead(effSat,vGn_alpha,0._rkind,1._rkind,vGn_n,vGn_m)  ! use effective saturation, so theta_res=0 and theta_sat=1
+         hydCon = hydCond_psi(psiLiq,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
+         call iceImpede(volIce,f_impede,iceImpedeFac,dIceImpede_dLiq)
+         hydIce = hydCon*iceImpedeFac
+         print*, 'test derivative: ', (psiLiq - scalarMatricHeadLiqTrial)/dx, dPsiLiq_dTemp
+         print*, 'test derivative: ', (hydCon - hydCond_noIce)/dx, dHydCondMicro_dTemp
+         print*, 'test derivative: ', (hydIce - scalarHydCond)/dx, dHydCond_dTemp
+         print*, 'press any key to continue'; read(*,*) ! (alternative to the deprecated 'pause' statement)
+        end if  ! testing the derivative
+        ! (set values that are not used to missing)
+        dHydCond_dVolLiq = realMissing ! not used, so cause problems
+        dDiffuse_dVolLiq = realMissing ! not used, so cause problems
+       end if
+    
+      case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    
+     end select
+    
+     ! if derivatives are not desired, then set values to missing
+     if(.not.deriv_desired)then
+      dHydCond_dVolLiq   = realMissing ! not used, so cause problems
+      dDiffuse_dVolLiq   = realMissing ! not used, so cause problems
+      dHydCond_dMatric   = realMissing ! not used, so cause problems
+     end if
+    
+     end subroutine diagv_node
+    
+    
+     ! ***************************************************************************************************************
+     ! private subroutine surfaceFlx: compute the surface flux and its derivative
+     ! ***************************************************************************************************************
+     subroutine surfaceFlx(&
+                           ! input: model control
+                           doInfiltration,            & ! intent(in): flag indicating if desire to compute infiltration
+                           deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                           bc_upper,                  & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
+                           nRoots,                    & ! intent(in): number of layers that contain roots
+                           ixIce,                     & ! intent(in): index of lowest ice layer
+                           nSoil,                     & ! intent(in): number of soil layers
+                           ! input: state variables
+                           mLayerTemp,                & ! intent(in): temperature (K)
+                           scalarMatricHead,          & ! intent(in): matric head in the upper-most soil layer (m)
+                           mLayerMatricHead,          & ! intent(in): matric head in each soil layer (m)
+                           scalarVolFracLiq,          & ! intent(in): volumetric liquid water content in the upper-most soil layer (-)
+                           mLayerVolFracLiq,          & ! intent(in): volumetric liquid water content in each soil layer (-)
+                           mLayerVolFracIce,          & ! intent(in): volumetric ice content in each soil layer (-)
+                           ! input: pre-computed derivatives
+                           dTheta_dTk,                & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           dTheta_dPsi,               & ! intent(in): derivative in the soil water characteristic w.r.t. psi (m-1)
+                           mLayerdPsi_dTheta,         & ! intent(in): derivative in the soil water characteristic w.r.t. theta (m)
+                           above_soilLiqFluxDeriv,    & ! intent(in): derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+                           above_soildLiq_dTk,        & ! intent(in): derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+                           above_soilFracLiq,         & ! intent(in): fraction of liquid water layer above soil (canopy or snow) (-)
+                           ! input: depth of upper-most soil layer (m)
+                           mLayerDepth,               & ! intent(in): depth of each soil layer (m)
+                           iLayerHeight,              & ! intent(in): height at the interface of each layer (m)
+                           ! input: boundary conditions
+                           upperBoundHead,            & ! intent(in): upper boundary condition (m)
+                           upperBoundTheta,           & ! intent(in): upper boundary condition (-)
+                           ! input: flux at the upper boundary
+                           scalarRainPlusMelt,        & ! intent(in): rain plus melt (m s-1)
+                           ! input: transmittance
+                           surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                           dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                           iceImpedeFac,              & ! intent(in): ice impedence factor in the upper-most soil layer (-)
+                           ! input: soil parameters
+                           vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                           vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
+                           vGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
+                           theta_sat,                 & ! intent(in): soil porosity (-)
+                           theta_res,                 & ! intent(in): soil residual volumetric water content (-)
+                           qSurfScale,                & ! intent(in): scaling factor in the surface runoff parameterization (-)
+                           zScale_TOPMODEL,           & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+                           rootingDepth,              & ! intent(in): rooting depth (m)
+                           wettingFrontSuction,       & ! intent(in): Green-Ampt wetting front suction (m)
+                           soilIceScale,              & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
+                           soilIceCV,                 & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
+                           ! input-output: hydraulic conductivity and diffusivity at the surface
+                           surfaceHydCond,            & ! intent(inout): hydraulic conductivity at the surface (m s-1)
+                           surfaceDiffuse,            & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
+                           ! input-output: fluxes at layer interfaces and surface runoff
+                           xMaxInfilRate,             & ! intent(inout): maximum infiltration rate (m s-1)
+                           scalarInfilArea,           & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                           scalarFrozenArea,          & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                           scalarSurfaceRunoff,       & ! intent(out): surface runoff (m s-1)
+                           scalarSurfaceInfiltration, & ! intent(out): surface infiltration (m s-1)
+                           ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
+                           dq_dHydStateVec,           & ! intent(inout): derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer (m s-1 or s-1)
+                           dq_dNrgStateVec,           & ! intent(inout): derivative in surface infiltration w.r.t. energy state in above soil snow or canopy and every soil layer (m s-1 K-1)
+                           ! output: error control
+                           err,message)                 ! intent(out): error control
+     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 (m s-1)
+     USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
+     USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+     USE soil_utils_module,only:crit_soilT      ! compute critical temperature below which ice exists
+     USE soil_utils_module,only:gammp           ! compute the cumulative probabilty based on the Gamma distribution
+     ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+     implicit none
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! input: model control
+     logical(lgt),intent(in)          :: doInfiltration            ! flag indicating if desire to compute infiltration
+     logical(lgt),intent(in)          :: deriv_desired             ! flag to indicate if derivatives are desired
+     integer(i4b),intent(in)          :: bc_upper                  ! index defining the type of boundary conditions
+     integer(i4b),intent(in)          :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+     integer(i4b),intent(in)          :: nRoots                    ! number of layers that contain roots
+     integer(i4b),intent(in)          :: ixIce                     ! index of lowest ice layer
+     integer(i4b),intent(in)          :: nSoil                     ! number of soil layers
+     ! input: state and diagnostic variables
+     real(rkind),intent(in)           :: mLayerTemp(:)             ! temperature (K)
+     real(rkind),intent(in)           :: scalarMatricHead          ! matric head in the upper-most soil layer (m)
+     real(rkind),intent(in)           :: mLayerMatricHead(:)       ! matric head in each soil layer (m)
+     real(rkind),intent(in)           :: scalarVolFracLiq          ! volumetric liquid water content in the upper-most soil layer (-)
+     real(rkind),intent(in)           :: mLayerVolFracLiq(:)       ! volumetric liquid water content in each soil layer (-)
+     real(rkind),intent(in)           :: mLayerVolFracIce(:)       ! volumetric ice content in each soil layer (-)
+     ! input: pre-computed derivatives, note all of these would need to be recomputed if wanted a numerical derivative
+     real(rkind),intent(in)           :: dTheta_dTk(:)             ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+     real(rkind),intent(in)           :: dTheta_dPsi(:)            ! derivative in the soil water characteristic w.r.t. psi (m-1)
+     real(rkind),intent(in)           :: mLayerdPsi_dTheta(:)      ! derivative in the soil water characteristic w.r.t. theta (m)
+     real(rkind),intent(in)           :: above_soilLiqFluxDeriv    ! derivative in layer above soil (canopy or snow) liquid flux w.r.t. liquid water
+     real(rkind),intent(in)           :: above_soildLiq_dTk        ! derivative of layer above soil (canopy or snow) liquid flux w.r.t. temperature
+     real(rkind),intent(in)           :: above_soilFracLiq         ! fraction of liquid water layer above soil (canopy or snow) (-)
+     ! input: depth of upper-most soil layer (m)
+     real(rkind),intent(in)           :: mLayerDepth(:)            ! depth of upper-most soil layer (m)
+     real(rkind),intent(in)           :: iLayerHeight(0:)          ! height at the interface of each layer (m)
+     ! input: diriclet boundary conditions
+     real(rkind),intent(in)           :: upperBoundHead            ! upper boundary condition for matric head (m)
+     real(rkind),intent(in)           :: upperBoundTheta           ! upper boundary condition for volumetric liquid water content (-)
+     ! input: flux at the upper boundary
+     real(rkind),intent(in)           :: scalarRainPlusMelt        ! rain plus melt, used as input to the soil zone before computing surface runoff (m s-1)
+     ! input: transmittance
+     real(rkind),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
+     real(rkind),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+     real(rkind),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
+     ! input: soil parameters
+     real(rkind),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+     real(rkind),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+     real(rkind),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+     real(rkind),intent(in)           :: theta_sat                 ! soil porosity (-)
+     real(rkind),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+     real(rkind),intent(in)           :: qSurfScale                ! scaling factor in the surface runoff parameterization (-)
+     real(rkind),intent(in)           :: zScale_TOPMODEL           ! scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+     real(rkind),intent(in)           :: rootingDepth              ! rooting depth (m)
+     real(rkind),intent(in)           :: wettingFrontSuction       ! Green-Ampt wetting front suction (m)
+     real(rkind),intent(in)           :: soilIceScale              ! soil ice scaling factor in Gamma distribution used to define frozen area (m)
+     real(rkind),intent(in)           :: soilIceCV                 ! soil ice CV in Gamma distribution used to define frozen area (-)
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! input-output: hydraulic conductivity and diffusivity at the surface
+     ! NOTE: intent(inout) because infiltration may only be computed for the first iteration
+     real(rkind),intent(inout)        :: surfaceHydCond            ! hydraulic conductivity (m s-1)
+     real(rkind),intent(inout)        :: surfaceDiffuse            ! hydraulic diffusivity at the surface (m
+     ! output: surface runoff and infiltration flux (m s-1)
+     real(rkind),intent(inout)        :: xMaxInfilRate             ! maximum infiltration rate (m s-1)
+     real(rkind),intent(inout)        :: scalarInfilArea           ! fraction of unfrozen area where water can infiltrate (-)
+     real(rkind),intent(inout)        :: scalarFrozenArea          ! fraction of area that is considered impermeable due to soil ice (-)
+     real(rkind),intent(out)          :: scalarSurfaceRunoff       ! surface runoff (m s-1)
+     real(rkind),intent(out)          :: scalarSurfaceInfiltration ! surface infiltration (m s-1)
+     ! output: derivatives in surface infiltration w.r.t. states in above soil snow or canopy and every soil layer
+     real(rkind),intent(out)          :: dq_dHydStateVec(0:)       ! derivative in surface infiltration w.r.t. hydrology state in above soil snow or canopy and every soil layer (m s-1 or s-1)
+     real(rkind),intent(out)          :: dq_dNrgStateVec(0:)       ! derivative in surface infiltration w.r.t. energy state in above soil snow or canopy and every soil layer  (m s-1 K-1)
+     ! output: error control
+     integer(i4b),intent(out)         :: err                       ! error code
+     character(*),intent(out)         :: message                   ! error message
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! local variables
+     ! (general)
+     integer(i4b)                     :: iLayer                    ! index of soil layer
+     real(rkind)                      :: Tcrit                     ! temperature where all water is unfrozen (K)
+     real(rkind)                      :: fpart1,fpart2             ! different parts of a function
+     real(rkind)                      :: dpart1(1:nSoil),dpart2(1:nSoil)     ! derivatives for different parts of a function
+     real(rkind)                      :: dfracCap(1:nSoil),dfInfRaw(1:nSoil)  ! derivatives for different parts of a function
+    ! (head boundary condition)
+     real(rkind)                      :: cFlux                     ! capillary flux (m s-1)
+     real(rkind)                      :: dNum                      ! numerical derivative
+     ! (simplified Green-Ampt infiltration)
+     real(rkind)                      :: rootZoneLiq               ! depth of liquid water in the root zone (m)
+     real(rkind)                      :: rootZoneIce               ! depth of ice in the root zone (m)
+     real(rkind)                      :: availCapacity             ! available storage capacity in the root zone (m)
+     real(rkind)                      :: depthWettingFront         ! depth to the wetting front (m)
+     real(rkind)                      :: hydCondWettingFront       ! hydraulic conductivity at the wetting front (m s-1)
+     ! (saturated area associated with variable storage capacity)
+     real(rkind)                      :: fracCap                   ! fraction of pore space filled with liquid water and ice (-)
+     real(rkind)                      :: fInfRaw                   ! infiltrating area before imposing solution constraints (-)
+     real(rkind),parameter            :: maxFracCap=0.995_rkind       ! maximum fraction capacity -- used to avoid numerical problems associated with an enormous derivative
+     real(rkind),parameter            :: scaleFactor=0.000001_rkind   ! scale factor for the smoothing function (-)
+     real(rkind),parameter            :: qSurfScaleMax=1000._rkind    ! maximum surface runoff scaling factor (-)
+     ! (fraction of impermeable area associated with frozen ground)
+     real(rkind)                      :: alpha                     ! shape parameter in the Gamma distribution
+     real(rkind)                      :: xLimg                     ! upper limit of the integral
+     ! (derivatives)
+     real(rkind)                      :: dVolFracLiq_dWat(1:nSoil)  ! derivative in vol fraction of liquid w.r.t. water state variable in root layers
+     real(rkind)                      :: dVolFracIce_dWat(1:nSoil)  ! derivative in vol fraction of ice w.r.t. water state variable in root layers
+     real(rkind)                      :: dVolFracLiq_dTk(1:nSoil)   ! derivative in vol fraction of liquid w.r.t. temperature in root layers
+     real(rkind)                      :: dVolFracIce_dTk(1:nSoil)   ! derivative in vol fraction of ice w.r.t. temperature in root layers
+     real(rkind)                      :: dRootZoneLiq_dWat(1:nSoil)       ! derivative in vol fraction of scalar root zone liquid w.r.t. water state variable in root layers
+     real(rkind)                      :: dRootZoneIce_dWat(1:nSoil)       ! derivative in vol fraction of scalar root zone ice w.r.t. water state variable in root layers
+     real(rkind)                      :: dRootZoneLiq_dTk(1:nSoil)        ! derivative in vol fraction of scalar root zone liquid w.r.t. temperature in root layers
+     real(rkind)                      :: dRootZoneIce_dTk(1:nSoil)        ! derivative in vol fraction of scalar root zone ice w.r.t. temperature in root layers
+     real(rkind)                      :: dDepthWettingFront_dWat(1:nSoil) ! derivative in scalar depth of wetting front w.r.t. water state variable in root layers
+     real(rkind)                      :: dDepthWettingFront_dTk(1:nSoil)  ! derivative in scalar depth of wetting front w.r.t. temperature in root layers
+     real(rkind)                      :: dXMaxInfilRate_dWat(1:nSoil)     ! derivative in scalar max infiltration rate w.r.t. water state variable in root layers
+     real(rkind)                      :: dXMaxInfilRate_dTk(1:nSoil)      ! derivative in scalar max infiltration rate w.r.t. temperature in root layers
+     real(rkind)                      :: dInfilArea_dWat(0:nSoil)         ! derivative in scalar infiltration rate w.r.t. water state variable in canopy or snow and root layers
+     real(rkind)                      :: dInfilArea_dTk(0:nSoil)          ! derivative in scalar infiltration rate w.r.t. temperature in canopy or snow and root layers
+     real(rkind)                      :: dFrozenArea_dWat(0:nSoil)        ! derivative in scalar frozen area w.r.t. water state variable in canopy or snow and root layers
+     real(rkind)                      :: dFrozenArea_dTk(0:nSoil)         ! derivative in scalar frozen area w.r.t. temperature in canopy or snow and root layers
+     real(rkind)                      :: dInfilRate_dWat(0:nSoil)         ! derivative in scalar infiltration rate w.r.t. water state variable in canopy or snow and root layers
+     real(rkind)                      :: dInfilRate_dTk(0:nSoil)          ! derivative in scalar infiltration rate w.r.t. temperature in canopy or snow and root layers
+    
+     ! initialize error control
+     err=0; message="surfaceFlx/"
+    
+     ! initialize derivatives
+     dq_dHydStateVec(:) = 0._rkind
+     dq_dNrgStateVec(:) = 0._rkind
+    
+     ! *****
+     ! compute the surface flux and its derivative
+     select case(bc_upper)
+    
+      ! *****
+      ! head condition
+      case(prescribedHead)
+    
+       ! surface runoff iz zero for the head condition
+       scalarSurfaceRunoff = 0._rkind
+    
+       ! compute transmission and the capillary flux
+       select case(ixRichards)  ! (form of Richards' equation)
+        case(moisture)
+         ! compute the hydraulic conductivity and diffusivity at the boundary
+         surfaceHydCond = hydCond_liq(upperBoundTheta,surfaceSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
+         surfaceDiffuse = dPsi_dTheta(upperBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * surfaceHydCond
+         ! compute the capillary flux
+         cflux = -surfaceDiffuse*(scalarVolFracLiq - upperBoundTheta) / (mLayerDepth(1)*0.5_rkind)
+        case(mixdform)
+         ! compute the hydraulic conductivity and diffusivity at the boundary
+         surfaceHydCond = hydCond_psi(upperBoundHead,surfaceSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
+         surfaceDiffuse = realMissing
+         ! compute the capillary flux
+         cflux = -surfaceHydCond*(scalarMatricHead - upperBoundHead) / (mLayerDepth(1)*0.5_rkind)
+        case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+       end select  ! (form of Richards' eqn)
+       ! compute the total flux
+       scalarSurfaceInfiltration = cflux + surfaceHydCond
+       ! compute the derivative
+       if(deriv_desired)then
+        ! compute the hydrology derivative at the surface
+        select case(ixRichards)  ! (form of Richards' equation)
+         case(moisture); dq_dHydStateVec(1) = -surfaceDiffuse/(mLayerDepth(1)/2._rkind)
+         case(mixdform); dq_dHydStateVec(1) = -surfaceHydCond/(mLayerDepth(1)/2._rkind)
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select
+        ! compute the energy derivative at the surface
+        dq_dNrgStateVec(1) = -(dHydCond_dTemp/2._rkind)*(scalarMatricHead - upperBoundHead)/(mLayerDepth(1)*0.5_rkind) + dHydCond_dTemp/2._rkind
+        ! compute the numerical derivative
+        !cflux = -surfaceHydCond*((scalarMatricHead+dx) - upperBoundHead) / (mLayerDepth(1)*0.5_rkind)
+        !surfaceInfiltration1 = cflux + surfaceHydCond
+        !dNum  = (surfaceInfiltration1 - scalarSurfaceInfiltration)/dx
+       else
+        dNum         = 0._rkind
+       end if
+       !write(*,'(a,1x,10(e30.20,1x))') 'scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum = ', &
+       !                                 scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum
+    
+      ! *****
+      ! flux condition
+      case(liquidFlux)
+    
+       ! force infiltration to be constant over the iterations
+       if(doInfiltration)then
+    
+        ! (process root layers only liquid and ice derivatives)
+        dVolFracLiq_dWat(:) = 0._rkind
+        dVolFracIce_dWat(:) = 0._rkind
+        dVolFracLiq_dTk(:)  = 0._rkind
+        dVolFracIce_dTk(:)  = 0._rkind
+        if(deriv_desired .and. nRoots > 0)then
+         select case(ixRichards)  ! (form of Richards' equation)
+          case(moisture)
+           dVolFracLiq_dWat(:) = 1._rkind
+           dVolFracIce_dWat(:) = mLayerdPsi_dTheta(:) - 1._rkind
+          case(mixdform)
+           do iLayer=1,nRoots
+            Tcrit = crit_soilT( mLayerMatricHead(iLayer) )
+            if(mLayerTemp(iLayer) < Tcrit)then
+             dVolFracLiq_dWat(iLayer) = 0._rkind
+             dVolFracIce_dWat(iLayer) = dTheta_dPsi(iLayer)
+            else
+             dVolFracLiq_dWat(iLayer) = dTheta_dPsi(iLayer)
+             dVolFracIce_dWat(iLayer) = 0._rkind
+            endif
+           enddo
+         end select ! (form of Richards' equation)
+         dVolFracLiq_dTk(:) = dTheta_dTk(:) !already zeroed out if not below critical temperature
+         dVolFracIce_dTk(:) = -dVolFracLiq_dTk(:) !often can and will simplify one of these terms out
+         endif
+    
+        ! define the storage in the root zone (m) and derivatives
+        rootZoneLiq = 0._rkind
+        rootZoneIce = 0._rkind
+        dRootZoneLiq_dWat(:) = 0._rkind
+        dRootZoneIce_dWat(:) = 0._rkind
+        dRootZoneLiq_dTk(:)  = 0._rkind
+        dRootZoneIce_dTk(:)  = 0._rkind
+    
+        ! (process layers where the roots extend to the bottom of the layer)
+        if(nRoots > 1)then
+         do iLayer=1,nRoots-1
+          rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(iLayer)*mLayerDepth(iLayer)
+          rootZoneIce = rootZoneIce + mLayerVolFracIce(iLayer)*mLayerDepth(iLayer)
+          dRootZoneLiq_dWat(iLayer) = dVolFracLiq_dWat(iLayer)*mLayerDepth(iLayer)
+          dRootZoneIce_dWat(iLayer) = dVolFracIce_dWat(iLayer)*mLayerDepth(iLayer)
+          dRootZoneLiq_dTk(iLayer)  = dVolFracLiq_dTk(iLayer) *mLayerDepth(iLayer)
+          dRootZoneIce_dTk(iLayer)  = dVolFracIce_dTk(iLayer) *mLayerDepth(iLayer)
+         end do
+        end if
+        ! (process layers where the roots end in the current layer)
+        rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+        rootZoneIce = rootZoneIce + mLayerVolFracIce(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+        dRootZoneLiq_dWat(nRoots) = dVolFracLiq_dWat(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+        dRootZoneIce_dWat(nRoots) = dVolFracIce_dWat(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+        dRootZoneLiq_dTk(nRoots)  = dVolFracLiq_dTk(nRoots)* (rootingDepth - iLayerHeight(nRoots-1))
+        dRootZoneIce_dTk(nRoots)  = dVolFracIce_dTk(nRoots)* (rootingDepth - iLayerHeight(nRoots-1))
+    
+        ! define available capacity to hold water (m)
+        availCapacity = theta_sat*rootingDepth - rootZoneIce
+        if(rootZoneLiq > availCapacity+verySmall)then
+         message=trim(message)//'liquid water in the root zone exceeds capacity'
+         err=20; return
+        end if
+    
+        ! define the depth to the wetting front (m) and derivatives
+        depthWettingFront = (rootZoneLiq/availCapacity)*rootingDepth
+        dDepthWettingFront_dWat(:)=( dRootZoneLiq_dWat(:)*rootingDepth + dRootZoneIce_dWat(:)*depthWettingFront )/availCapacity
+        dDepthWettingFront_dTk(:) =( dRootZoneLiq_dTk(:)*rootingDepth  + dRootZoneIce_dTk(:)*depthWettingFront  )/availCapacity
+    
+        ! define the hydraulic conductivity at depth=depthWettingFront (m s-1)
+        hydCondWettingFront =  surfaceSatHydCond * ( (1._rkind - depthWettingFront/sum(mLayerDepth))**(zScale_TOPMODEL - 1._rkind) )
+    
+        ! define the maximum infiltration rate (m s-1) and derivatives
+        xMaxInfilRate = hydCondWettingFront*( (wettingFrontSuction + depthWettingFront)/depthWettingFront )  ! maximum infiltration rate (m s-1)
+        !write(*,'(a,1x,f9.3,1x,10(e20.10,1x))') 'depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate = ', depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate
+        fPart1    = hydCondWettingFront
+        fPart2    = (wettingFrontSuction + depthWettingFront)/depthWettingFront
+        dPart1(:) = surfaceSatHydCond*(zScale_TOPMODEL - 1._rkind) * ( (1._rkind - depthWettingFront/sum(mLayerDepth))**(zScale_TOPMODEL - 2._rkind) ) * (-dDepthWettingFront_dWat(:))/sum(mLayerDepth)
+        dPart2(:) = -dDepthWettingFront_dWat(:)*wettingFrontSuction / (depthWettingFront**2._rkind)
+        dXMaxInfilRate_dWat(:) = fPart1*dpart2(:) + fPart2*dPart1(:)
+        dPart1(:) = surfaceSatHydCond*(zScale_TOPMODEL - 1._rkind) * ( (1._rkind - depthWettingFront/sum(mLayerDepth))**(zScale_TOPMODEL - 2._rkind) ) * (-dDepthWettingFront_dTk(:))/sum(mLayerDepth)
+        dPart2(:) = -dDepthWettingFront_dTk(:)*wettingFrontSuction / (depthWettingFront**2._rkind)
+        dXMaxInfilRate_dTk(:)  = fPart1*dpart2(:) + fPart2*dPart1(:)
+    
+        ! define the infiltrating area and derivatives for the non-frozen part of the cell/basin
+        if(qSurfScale < qSurfScaleMax)then
+         fracCap         = rootZoneLiq/(maxFracCap*availCapacity)                              ! fraction of available root zone filled with water
+         fInfRaw         = 1._rkind - exp(-qSurfScale*(1._rkind - fracCap))                          ! infiltrating area -- allowed to violate solution constraints
+         scalarInfilArea = min(0.5_rkind*(fInfRaw + sqrt(fInfRaw**2._rkind + scaleFactor)), 1._rkind)   ! infiltrating area -- constrained
+         if (0.5_rkind*(fInfRaw + sqrt(fInfRaw**2._rkind + scaleFactor))< 1._rkind) then
+          dfracCap(:) = ( dRootZoneLiq_dWat(:)/maxFracCap + dRootZoneIce_dWat(:)*fracCap )/availCapacity
+          dfInfRaw(:) = -qSurfScale*dfracCap(:) * exp(-qSurfScale*(1._rkind - fracCap))
+          dInfilArea_dWat(1:nSoil) = 0.5_rkind*dfInfRaw(:) * (1._rkind + fInfRaw/sqrt(fInfRaw**2._rkind + scaleFactor))
+          dfracCap(:) = ( dRootZoneLiq_dTk(:)/maxFracCap + dRootZoneIce_dTk(:)*fracCap )/availCapacity
+          dfInfRaw(:) = -qSurfScale*dfracCap(:) * exp(-qSurfScale*(1._rkind - fracCap))
+          dInfilArea_dTk(1:nSoil)  = 0.5_rkind*dfInfRaw(:) * (1._rkind + fInfRaw/sqrt(fInfRaw**2._rkind + scaleFactor))
+         else ! scalarInfilArea = 1._rkind
+          dInfilArea_dWat(:) = 0._rkind
+          dInfilArea_dTk(:)  = 0._rkind
+         endif
+        else
+         scalarInfilArea = 1._rkind
+         dInfilArea_dWat(:) = 0._rkind
+         dInfilArea_dTk(:)  = 0._rkind
+        endif
+        dInfilArea_dWat(0) = 0._rkind
+        dInfilArea_dTk(0)  = 0._rkind
+    
+        ! check to ensure we are not infiltrating into a fully saturated column
+        if(ixIce<nRoots)then
+         if(sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) > 0.9999_rkind*theta_sat*sum(mLayerDepth(ixIce+1:nRoots))) scalarInfilArea=0._rkind
+         !print*, 'ixIce, nRoots, scalarInfilArea = ', ixIce, nRoots, scalarInfilArea
+         !print*, 'sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) = ', sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots))
+         !print*, 'theta_sat*sum(mLayerDepth(ixIce+1:nRoots)) = ', theta_sat*sum(mLayerDepth(ixIce+1:nRoots))
+        endif
+    
+        ! define the impermeable area and derivatives due to frozen ground
+        if(rootZoneIce > tiny(rootZoneIce))then  ! (avoid divide by zero)
+         alpha            = 1._rkind/(soilIceCV**2._rkind)        ! shape parameter in the Gamma distribution
+         xLimg            = alpha*soilIceScale/rootZoneIce  ! upper limit of the integral
+         !scalarFrozenArea = 1._rkind - gammp(alpha,xLimg)      ! fraction of frozen area
+         !if we use this, we will have a derivative of scalarFrozenArea w.r.t. water and temperature in each layer (through mLayerVolFracIce)
+         scalarFrozenArea = 0._rkind
+         dFrozenArea_dWat(:) = 0._rkind
+         dFrozenArea_dTk(:)  = 0._rkind
+        else
+         scalarFrozenArea = 0._rkind
+         dFrozenArea_dWat(:) = 0._rkind
+         dFrozenArea_dTk(:)  = 0._rkind
+        end if
+        dFrozenArea_dWat(0) = 0._rkind
+        dFrozenArea_dTk(0)  = 0._rkind
+        !print*, 'scalarFrozenArea, rootZoneIce = ', scalarFrozenArea, rootZoneIce
+    
+       end if ! (if desire to compute infiltration)
+    
+       ! compute infiltration (m s-1)
+       scalarSurfaceInfiltration = (1._rkind - scalarFrozenArea)*scalarInfilArea*min(scalarRainPlusMelt,xMaxInfilRate)
+    
+       ! compute infiltration derivative for layers not at surface
+       if (xMaxInfilRate < scalarRainPlusMelt) then ! = dXMaxInfilRate_d
+        dInfilRate_dWat(1:nSoil) = dXMaxInfilRate_dWat(:)
+        dInfilRate_dTk(1:nSoil)  = dXMaxInfilRate_dTk(:)
+       else ! = dRainPlusMelt_d only dependent on canopy
+        dInfilRate_dWat(:) = 0._rkind !only calculate for layers that are not the surface
+        dInfilRate_dTk(:)  = 0._rkind !only calculate for layers that are not the surface
+        ! dependent on above layer (canopy or snow) water and temp
+        dInfilRate_dWat(0) = above_soilLiqFluxDeriv*above_soilFracLiq
+        dInfilRate_dTk(0) = above_soilLiqFluxDeriv*above_soildLiq_dTk
+       endif
+    
+       ! dq w.r.t. infiltration only, scalarRainPlusMelt accounted for in computeJacDAE_module
+       dq_dHydStateVec(:) = (1._rkind - scalarFrozenArea) * ( dInfilArea_dWat(:)*min(scalarRainPlusMelt,xMaxInfilRate) + scalarInfilArea*dInfilRate_dWat(:) ) +&
+                            (-dFrozenArea_dWat(:))*scalarInfilArea*min(scalarRainPlusMelt,xMaxInfilRate)
+       dq_dNrgStateVec(:) = (1._rkind - scalarFrozenArea) * ( dInfilArea_dTk(:) *min(scalarRainPlusMelt,xMaxInfilRate) + scalarInfilArea*dInfilRate_dTk(:)  ) +&
+                            (-dFrozenArea_dTk(:)) *scalarInfilArea*min(scalarRainPlusMelt,xMaxInfilRate)
+    
+       ! compute surface runoff (m s-1)
+       scalarSurfaceRunoff = scalarRainPlusMelt - scalarSurfaceInfiltration
+       !print*, 'scalarRainPlusMelt, xMaxInfilRate = ', scalarRainPlusMelt, xMaxInfilRate
+       !print*, 'scalarSurfaceInfiltration, scalarSurfaceRunoff = ', scalarSurfaceInfiltration, scalarSurfaceRunoff
+       !print*, '(1._rkind - scalarFrozenArea), (1._rkind - scalarFrozenArea)*scalarInfilArea = ', (1._rkind - scalarFrozenArea), (1._rkind - scalarFrozenArea)*scalarInfilArea
+    
+       ! set surface hydraulic conductivity and diffusivity to missing (not used for flux condition)
+       surfaceHydCond = realMissing
+       surfaceDiffuse = realMissing
+    
+      ! ***** error check
+      case default; err=20; message=trim(message)//'unknown upper boundary condition for soil hydrology'; return
+    
+     end select  ! (type of upper boundary condition)
+    
+     end subroutine surfaceFlx
+    
+    
+     ! ***************************************************************************************************************
+     ! private subroutine iLayerFlux: compute the fluxes and derivatives at layer interfaces
+     ! ***************************************************************************************************************
+     subroutine iLayerFlux(&
+                           ! input: model control
+                           deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                           ! input: state variables (adjacent layers)
+                           nodeMatricHeadLiqTrial,    & ! intent(in): liquid matric head at the soil nodes (m)
+                           nodeVolFracLiqTrial,       & ! intent(in): volumetric liquid water content at the soil nodes (-)
+                           ! input: model coordinate variables (adjacent layers)
+                           nodeHeight,                & ! intent(in): height of the soil nodes (m)
+                           ! input: temperature derivatives
+                           dPsiLiq_dTemp,             & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                           dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                           ! input: transmittance (adjacent layers)
+                           nodeHydCondTrial,          & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
+                           nodeDiffuseTrial,          & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
+                           ! input: transmittance derivatives (adjacent layers)
+                           dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
+                           dDiffuse_dVolLiq,          & ! intent(in): derivative in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
+                           dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in matric head (s-1)
+                           ! output: tranmsmittance at the layer interface (scalars)
+                           iLayerHydCond,             & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
+                           iLayerDiffuse,             & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
+                           ! output: vertical flux at the layer interface (scalars)
+                           iLayerLiqFluxSoil,         & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
+                           ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+                           dq_dHydStateAbove,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+                           dq_dHydStateBelow,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+                           ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+                           dq_dNrgStateAbove,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                           dq_dNrgStateBelow,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                           ! output: error control
+                           err,message)                 ! intent(out): error control
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! input: model control
+     logical(lgt),intent(in)       :: deriv_desired               ! flag indicating if derivatives are desired
+     integer(i4b),intent(in)       :: ixRichards                  ! index defining the option for Richards' equation (moisture or mixdform)
+     ! input: state variables
+     real(rkind),intent(in)           :: nodeMatricHeadLiqTrial(:)   ! liquid matric head at the soil nodes (m)
+     real(rkind),intent(in)           :: nodeVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the soil nodes (-)
+     ! input: model coordinate variables
+     real(rkind),intent(in)           :: nodeHeight(:)               ! height at the mid-point of the lower layer (m)
+     ! input: temperature derivatives
+     real(rkind),intent(in)           :: dPsiLiq_dTemp(:)            ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+     real(rkind),intent(in)           :: dHydCond_dTemp(:)           ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+     ! input: transmittance
+     real(rkind),intent(in)           :: nodeHydCondTrial(:)         ! hydraulic conductivity at layer mid-points (m s-1)
+     real(rkind),intent(in)           :: nodeDiffuseTrial(:)         ! diffusivity at layer mid-points (m2 s-1)
+     ! input: transmittance derivatives
+     real(rkind),intent(in)           :: dHydCond_dVolLiq(:)         ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+     real(rkind),intent(in)           :: dDiffuse_dVolLiq(:)         ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+     real(rkind),intent(in)           :: dHydCond_dMatric(:)         ! derivative in hydraulic conductivity w.r.t matric head (m s-1)
+     ! output: tranmsmittance at the layer interface (scalars)
+     real(rkind),intent(out)          :: iLayerHydCond               ! hydraulic conductivity at the interface between layers (m s-1)
+     real(rkind),intent(out)          :: iLayerDiffuse               ! hydraulic diffusivity at the interface between layers (m2 s-1)
+     ! output: vertical flux at the layer interface (scalars)
+     real(rkind),intent(out)          :: iLayerLiqFluxSoil           ! vertical flux of liquid water at the layer interface (m s-1)
+     ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+     real(rkind),intent(out)          :: dq_dHydStateAbove           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+     real(rkind),intent(out)          :: dq_dHydStateBelow           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+     ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+     real(rkind),intent(out)          :: dq_dNrgStateAbove           ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+     real(rkind),intent(out)          :: dq_dNrgStateBelow           ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+     ! output: error control
+     integer(i4b),intent(out)      :: err                         ! error code
+     character(*),intent(out)      :: message                     ! error message
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! local variables (named variables to provide index of 2-element vectors)
+     integer(i4b),parameter        :: ixUpper=1                   ! index of upper node in the 2-element vectors
+     integer(i4b),parameter        :: ixLower=2                   ! index of lower node in the 2-element vectors
+     logical(lgt),parameter        :: useGeometric=.false.        ! switch between the arithmetic and geometric mean
+     ! local variables (Darcy flux)
+     real(rkind)                      :: dPsi                        ! spatial difference in matric head (m)
+     real(rkind)                      :: dLiq                        ! spatial difference in volumetric liquid water (-)
+     real(rkind)                      :: dz                          ! spatial difference in layer mid-points (m)
+     real(rkind)                      :: cflux                       ! capillary flux (m s-1)
+     ! local variables (derivative in Darcy's flux)
+     real(rkind)                      :: dHydCondIface_dVolLiqAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer above
+     real(rkind)                      :: dHydCondIface_dVolLiqBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer below
+     real(rkind)                      :: dDiffuseIface_dVolLiqAbove  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer above
+     real(rkind)                      :: dDiffuseIface_dVolLiqBelow  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer below
+     real(rkind)                      :: dHydCondIface_dMatricAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer above
+     real(rkind)                      :: dHydCondIface_dMatricBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer below
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! initialize error control
+     err=0; message="iLayerFlux/"
+    
+     ! *****
+     ! compute the vertical flux of liquid water
+     ! compute the hydraulic conductivity at the interface
+     if(useGeometric)then
+      iLayerHydCond   = (nodeHydCondTrial(ixLower)   * nodeHydCondTrial(ixUpper))**0.5_rkind
+     else
+      iLayerHydCond   = (nodeHydCondTrial(ixLower)   + nodeHydCondTrial(ixUpper))*0.5_rkind
+     end if
+     !write(*,'(a,1x,5(e20.10,1x))') 'in iLayerFlux: iLayerHydCond, iLayerHydCondMP = ', iLayerHydCond, iLayerHydCondMP
+     ! compute the height difference between nodes
+     dz = nodeHeight(ixLower) - nodeHeight(ixUpper)
      ! compute the capillary flux
-     cflux = -bottomHydCond*(lowerBoundHead  - nodeMatricHead) / (nodeDepth*0.5_dp)
-    case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-   end select  ! (form of Richards' eqn)
-   scalarDrainage = cflux + bottomHydCond
-
-   ! compute derivatives
-   if(deriv_desired)then
-    ! hydrology derivatives
-    select case(ixRichards)  ! (form of Richards' equation)
-     case(moisture); dq_dHydStateUnsat = bottomDiffuse/(nodeDepth/2._dp)
-     case(mixdform); dq_dHydStateUnsat = bottomHydCond/(nodeDepth/2._dp)
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select
-    ! energy derivatives
-    dq_dNrgStateUnsat = -(dHydCond_dTemp/2._dp)*(lowerBoundHead  - nodeMatricHead)/(nodeDepth*0.5_dp) + dHydCond_dTemp/2._dp
-   else     ! (do not desire derivatives)
-    dq_dHydStateUnsat = realMissing
-    dq_dNrgStateUnsat = realMissing
-   end if
-
-  ! ---------------------------------------------------------------------------------------------
-  ! * function of matric head in the bottom layer
-  ! ---------------------------------------------------------------------------------------------
-  case(funcBottomHead)
-
-   ! compute fluxes
-   select case(ixRichards)
-    case(moisture); nodePsi = matricHead(nodeVolFracLiq,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-    case(mixdform); nodePsi = nodeMatricHead
-   end select
-   zWater = nodeHeight - nodePsi
-   scalarDrainage = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)
-
-   ! compute derivatives
-   if(deriv_desired)then
-    ! hydrology derivatives
-    select case(ixRichards)  ! (form of Richards' equation)
-     case(moisture); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * node__dPsi_dTheta*exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
-     case(mixdform); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select
-    ! energy derivatives
-    err=20; message=trim(message)//"not yet implemented energy derivatives"; return
-   else     ! (do not desire derivatives)
-    dq_dHydStateUnsat = realMissing
-    dq_dNrgStateUnsat = realMissing
-   end if
-
-  ! ---------------------------------------------------------------------------------------------
-  ! * free drainage
-  ! ---------------------------------------------------------------------------------------------
-  case(freeDrainage)
-
-   ! compute flux
-   scalarDrainage = nodeHydCond*kAnisotropic
-
-   ! compute derivatives
-   if(deriv_desired)then
-    ! hydrology derivatives
-    select case(ixRichards)  ! (form of Richards' equation)
-     case(moisture); dq_dHydStateUnsat = dHydCond_dVolLiq*kAnisotropic
-     case(mixdform); dq_dHydStateUnsat = dHydCond_dMatric*kAnisotropic
-     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
-    end select
-    ! energy derivatives
-    dq_dNrgStateUnsat = dHydCond_dTemp*kAnisotropic
-   else     ! (do not desire derivatives)
-    dq_dHydStateUnsat = realMissing
-    dq_dNrgStateUnsat = realMissing
-   end if
-
-
-  ! ---------------------------------------------------------------------------------------------
-  ! * zero flux
-  ! ---------------------------------------------------------------------------------------------
-  case(zeroFlux)
-   scalarDrainage = 0._dp
-   if(deriv_desired)then
-    dq_dHydStateUnsat = 0._dp
-    dq_dNrgStateUnsat = 0._dp
-   else
-    dq_dHydStateUnsat = realMissing
-    dq_dNrgStateUnsat = realMissing
-   end if
-
-  ! ---------------------------------------------------------------------------------------------
-  ! * error check
-  ! ---------------------------------------------------------------------------------------------
-  case default; err=20; message=trim(message)//'unknown lower boundary condition for soil hydrology'; return
-
- end select ! (type of boundary condition)
-
- end subroutine qDrainFlux
-
-
- ! *******************************************************************************************************************************************************************************
- ! *******************************************************************************************************************************************************************************
-
-
-end module soilLiqFlx_module
+     select case(ixRichards)  ! (form of Richards' equation)
+      case(moisture)
+       iLayerDiffuse = (nodeDiffuseTrial(ixLower) * nodeDiffuseTrial(ixUpper))**0.5_rkind
+       dLiq          = nodeVolFracLiqTrial(ixLower) - nodeVolFracLiqTrial(ixUpper)
+       cflux         = -iLayerDiffuse * dLiq/dz
+      case(mixdform)
+       iLayerDiffuse = realMissing
+       dPsi          = nodeMatricHeadLiqTrial(ixLower) - nodeMatricHeadLiqTrial(ixUpper)
+       cflux         = -iLayerHydCond * dPsi/dz
+      case default; err=10; message=trim(message)//"unable to identify option for Richards' equation"; return
+     end select
+     ! compute the total flux (add gravity flux, positive downwards)
+     iLayerLiqFluxSoil = cflux + iLayerHydCond
+     !write(*,'(a,1x,10(e20.10,1x))') 'iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond = ', &
+     !                                 iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond
+    
+     ! ** compute the derivatives
+     if(deriv_desired)then
+      select case(ixRichards)  ! (form of Richards' equation)
+       case(moisture)
+        ! still need to implement arithmetric mean for the moisture-based form
+        if(.not.useGeometric)then
+         message=trim(message)//'only currently implemented for geometric mean -- change local flag'
+         err=20; return
+        end if
+        ! derivatives in hydraulic conductivity at the layer interface (m s-1)
+        dHydCondIface_dVolLiqAbove = dHydCond_dVolLiq(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_rkind/max(iLayerHydCond,verySmall)
+        dHydCondIface_dVolLiqBelow = dHydCond_dVolLiq(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_rkind/max(iLayerHydCond,verySmall)
+        ! derivatives in hydraulic diffusivity at the layer interface (m2 s-1)
+        dDiffuseIface_dVolLiqAbove = dDiffuse_dVolLiq(ixUpper)*nodeDiffuseTrial(ixLower) * 0.5_rkind/max(iLayerDiffuse,verySmall)
+        dDiffuseIface_dVolLiqBelow = dDiffuse_dVolLiq(ixLower)*nodeDiffuseTrial(ixUpper) * 0.5_rkind/max(iLayerDiffuse,verySmall)
+        ! derivatives in the flux w.r.t. volumetric liquid water content
+        dq_dHydStateAbove = -dDiffuseIface_dVolLiqAbove*dLiq/dz + iLayerDiffuse/dz + dHydCondIface_dVolLiqAbove
+        dq_dHydStateBelow = -dDiffuseIface_dVolLiqBelow*dLiq/dz - iLayerDiffuse/dz + dHydCondIface_dVolLiqBelow
+       case(mixdform)
+        ! derivatives in hydraulic conductivity
+        if(useGeometric)then
+         dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_rkind/max(iLayerHydCond,verySmall)
+         dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_rkind/max(iLayerHydCond,verySmall)
+        else
+         dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)/2._rkind
+         dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)/2._rkind
+        end if
+        ! derivatives in the flux w.r.t. matric head
+        dq_dHydStateAbove = -dHydCondIface_dMatricAbove*dPsi/dz + iLayerHydCond/dz + dHydCondIface_dMatricAbove
+        dq_dHydStateBelow = -dHydCondIface_dMatricBelow*dPsi/dz - iLayerHydCond/dz + dHydCondIface_dMatricBelow
+        ! derivative in the flux w.r.t. temperature
+        dq_dNrgStateAbove = -(dHydCond_dTemp(ixUpper)/2._rkind)*dPsi/dz + iLayerHydCond*dPsiLiq_dTemp(ixUpper)/dz + dHydCond_dTemp(ixUpper)/2._rkind
+        dq_dNrgStateBelow = -(dHydCond_dTemp(ixLower)/2._rkind)*dPsi/dz - iLayerHydCond*dPsiLiq_dTemp(ixLower)/dz + dHydCond_dTemp(ixLower)/2._rkind
+       case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+      end select
+     else
+      dq_dHydStateAbove = realMissing
+      dq_dHydStateBelow = realMissing
+     end if
+    
+     end subroutine iLayerFlux
+    
+    
+     ! ***************************************************************************************************************
+     ! private subroutine qDrainFlux: compute the drainage flux from the bottom of the soil profile and its derivative
+     ! ***************************************************************************************************************
+     subroutine qDrainFlux(&
+                           ! input: model control
+                           deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                           bc_lower,                  & ! intent(in): index defining the type of boundary conditions
+                           ! input: state variables
+                           nodeMatricHead,            & ! intent(in): matric head in the lowest unsaturated node (m)
+                           nodeVolFracLiq,            & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
+                           ! input: model coordinate variables
+                           nodeDepth,                 & ! intent(in): depth of the lowest unsaturated soil layer (m)
+                           nodeHeight,                & ! intent(in): height of the lowest unsaturated soil node (m)
+                           ! input: boundary conditions
+                           lowerBoundHead,            & ! intent(in): lower boundary condition (m)
+                           lowerBoundTheta,           & ! intent(in): lower boundary condition (-)
+                           ! input: derivative in soil water characteristix
+                           node_dPsi_dTheta,         & ! intent(in): derivative of the soil moisture characteristic w.r.t. theta (m)
+                           ! input: transmittance
+                           surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                           bottomSatHydCond,          & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+                           nodeHydCond,               & ! intent(in): hydraulic conductivity at the node itself (m s-1)
+                           iceImpedeFac,              & ! intent(in): ice impedence factor in the lower-most soil layer (-)
+                           ! input: transmittance derivatives
+                           dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+                           dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
+                           dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                           ! input: soil parameters
+                           vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                           vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
+                           vGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
+                           theta_sat,                 & ! intent(in): soil porosity (-)
+                           theta_res,                 & ! intent(in): soil residual volumetric water content (-)
+                           kAnisotropic,              & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+                           zScale_TOPMODEL,           & ! intent(in): TOPMODEL scaling factor (m)
+                           ! output: hydraulic conductivity and diffusivity at the surface
+                           bottomHydCond,             & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
+                           bottomDiffuse,             & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+                           ! output: drainage flux from the bottom of the soil profile
+                           scalarDrainage,            & ! intent(out): drainage flux from the bottom of the soil profile (m s-1)
+                           ! output: derivatives in drainage flux
+                           dq_dHydStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in hydrology state variable in lowest unsaturated node (m s-1 or s-1)
+                           dq_dNrgStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
+                           ! output: error control
+                           err,message)                 ! intent(out): error control
+     USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water as a function of matric head (-)
+     USE soil_utils_module,only:matricHead      ! compute matric head as a function of volumetric fraction of liquid water (m)
+     USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head (m s-1)
+     USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
+     USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+     ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+     implicit none
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! input: model control
+     logical(lgt),intent(in)       :: deriv_desired             ! flag to indicate if derivatives are desired
+     integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+     integer(i4b),intent(in)       :: bc_lower                  ! index defining the type of boundary conditions
+     ! input: state and diagnostic variables
+     real(rkind),intent(in)           :: nodeMatricHead            ! matric head in the lowest unsaturated node (m)
+     real(rkind),intent(in)           :: nodeVolFracLiq            ! volumetric liquid water content in the lowest unsaturated node (-)
+     ! input: model coordinate variables
+     real(rkind),intent(in)           :: nodeDepth                 ! depth of the lowest unsaturated soil layer (m)
+     real(rkind),intent(in)           :: nodeHeight                ! height of the lowest unsaturated soil node (m)
+     ! input: diriclet boundary conditions
+     real(rkind),intent(in)           :: lowerBoundHead            ! lower boundary condition for matric head (m)
+     real(rkind),intent(in)           :: lowerBoundTheta           ! lower boundary condition for volumetric liquid water content (-)
+     ! input: derivative in soil water characteristix
+     real(rkind),intent(in)           :: node_dPsi_dTheta         ! derivative of the soil moisture characteristic w.r.t. theta (m)
+     ! input: transmittance
+     real(rkind),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
+     real(rkind),intent(in)           :: bottomSatHydCond          ! saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+     real(rkind),intent(in)           :: nodeHydCond               ! hydraulic conductivity at the node itself (m s-1)
+     real(rkind),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
+     ! input: transmittance derivatives
+     real(rkind),intent(in)           :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+     real(rkind),intent(in)           :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
+     real(rkind),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+     ! input: soil parameters
+     real(rkind),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+     real(rkind),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+     real(rkind),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+     real(rkind),intent(in)           :: theta_sat                 ! soil porosity (-)
+     real(rkind),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+     real(rkind),intent(in)           :: kAnisotropic              ! anisotropy factor for lateral hydraulic conductivity (-)
+     real(rkind),intent(in)           :: zScale_TOPMODEL           ! scale factor for TOPMODEL-ish baseflow parameterization (m)
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! output: hydraulic conductivity at the bottom of the unsaturated zone
+     real(rkind),intent(out)          :: bottomHydCond             ! hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+     real(rkind),intent(out)          :: bottomDiffuse             ! hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+     ! output: drainage flux from the bottom of the soil profile
+     real(rkind),intent(out)          :: scalarDrainage            ! drainage flux from the bottom of the soil profile (m s-1)
+     ! output: derivatives in drainage flux
+     real(rkind),intent(out)          :: dq_dHydStateUnsat         ! change in drainage flux w.r.t. change in state variable in lowest unsaturated node (m s-1 or s-1)
+     real(rkind),intent(out)          :: dq_dNrgStateUnsat         ! change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
+     ! output: error control
+     integer(i4b),intent(out)      :: err                       ! error code
+     character(*),intent(out)      :: message                   ! error message
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! local variables
+     real(rkind)                      :: zWater                    ! effective water table depth (m)
+     real(rkind)                      :: nodePsi                   ! matric head in the lowest unsaturated node (m)
+     real(rkind)                      :: cflux                     ! capillary flux (m s-1)
+     ! -----------------------------------------------------------------------------------------------------------------------------
+     ! initialize error control
+     err=0; message="qDrainFlux/"
+    
+     ! determine lower boundary condition
+     select case(bc_lower)
+    
+      ! ---------------------------------------------------------------------------------------------
+      ! * prescribed head
+      ! ---------------------------------------------------------------------------------------------
+      case(prescribedHead)
+    
+       ! compute fluxes
+       select case(ixRichards)  ! (moisture-based form of Richards' equation)
+        case(moisture)
+         ! compute the hydraulic conductivity and diffusivity at the boundary
+         bottomHydCond = hydCond_liq(lowerBoundTheta,bottomSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
+         bottomDiffuse = dPsi_dTheta(lowerBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * bottomHydCond
+         ! compute the capillary flux
+         cflux = -bottomDiffuse*(lowerBoundTheta - nodeVolFracLiq) / (nodeDepth*0.5_rkind)
+        case(mixdform)
+         ! compute the hydraulic conductivity and diffusivity at the boundary
+         bottomHydCond = hydCond_psi(lowerBoundHead,bottomSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
+         bottomDiffuse = realMissing
+         ! compute the capillary flux
+         cflux = -bottomHydCond*(lowerBoundHead  - nodeMatricHead) / (nodeDepth*0.5_rkind)
+        case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+       end select  ! (form of Richards' eqn)
+       scalarDrainage = cflux + bottomHydCond
+    
+       ! compute derivatives
+       if(deriv_desired)then
+        ! hydrology derivatives
+        select case(ixRichards)  ! (form of Richards' equation)
+         case(moisture); dq_dHydStateUnsat = bottomDiffuse/(nodeDepth/2._rkind)
+         case(mixdform); dq_dHydStateUnsat = bottomHydCond/(nodeDepth/2._rkind)
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select
+        ! energy derivatives
+        dq_dNrgStateUnsat = -(dHydCond_dTemp/2._rkind)*(lowerBoundHead  - nodeMatricHead)/(nodeDepth*0.5_rkind) + dHydCond_dTemp/2._rkind
+       else     ! (do not desire derivatives)
+        dq_dHydStateUnsat = realMissing
+        dq_dNrgStateUnsat = realMissing
+       end if
+    
+      ! ---------------------------------------------------------------------------------------------
+      ! * function of matric head in the bottom layer
+      ! ---------------------------------------------------------------------------------------------
+      case(funcBottomHead)
+    
+       ! compute fluxes
+       select case(ixRichards)
+        case(moisture); nodePsi = matricHead(nodeVolFracLiq,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+        case(mixdform); nodePsi = nodeMatricHead
+       end select
+       zWater = nodeHeight - nodePsi
+       scalarDrainage = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)
+    
+       ! compute derivatives
+       if(deriv_desired)then
+        ! hydrology derivatives
+        select case(ixRichards)  ! (form of Richards' equation)
+         case(moisture); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * node_dPsi_dTheta*exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
+         case(mixdform); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select
+        ! energy derivatives
+        err=20; message=trim(message)//"not yet implemented energy derivatives"; return
+       else     ! (do not desire derivatives)
+        dq_dHydStateUnsat = realMissing
+        dq_dNrgStateUnsat = realMissing
+       end if
+    
+      ! ---------------------------------------------------------------------------------------------
+      ! * free drainage
+      ! ---------------------------------------------------------------------------------------------
+      case(freeDrainage)
+    
+       ! compute flux
+       scalarDrainage = nodeHydCond*kAnisotropic
+    
+       ! compute derivatives
+       if(deriv_desired)then
+        ! hydrology derivatives
+        select case(ixRichards)  ! (form of Richards' equation)
+         case(moisture); dq_dHydStateUnsat = dHydCond_dVolLiq*kAnisotropic
+         case(mixdform); dq_dHydStateUnsat = dHydCond_dMatric*kAnisotropic
+         case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+        end select
+        ! energy derivatives
+        dq_dNrgStateUnsat = dHydCond_dTemp*kAnisotropic
+       else     ! (do not desire derivatives)
+        dq_dHydStateUnsat = realMissing
+        dq_dNrgStateUnsat = realMissing
+       end if
+    
+    
+      ! ---------------------------------------------------------------------------------------------
+      ! * zero flux
+      ! ---------------------------------------------------------------------------------------------
+      case(zeroFlux)
+       scalarDrainage = 0._rkind
+       if(deriv_desired)then
+        dq_dHydStateUnsat = 0._rkind
+        dq_dNrgStateUnsat = 0._rkind
+       else
+        dq_dHydStateUnsat = realMissing
+        dq_dNrgStateUnsat = realMissing
+       end if
+    
+      ! ---------------------------------------------------------------------------------------------
+      ! * error check
+      ! ---------------------------------------------------------------------------------------------
+      case default; err=20; message=trim(message)//'unknown lower boundary condition for soil hydrology'; return
+    
+     end select ! (type of boundary condition)
+    
+     end subroutine qDrainFlux
+    
+    
+     ! *******************************************************************************************************************************************************************************
+     ! *******************************************************************************************************************************************************************************
+    
+    
+    end module soilLiqFlx_module
+    
\ No newline at end of file
diff --git a/build/source/engine/soilLiqFlx_old.f90 b/build/source/engine/soilLiqFlx_old.f90
new file mode 100755
index 0000000..e5c57fe
--- /dev/null
+++ b/build/source/engine/soilLiqFlx_old.f90
@@ -0,0 +1,1759 @@
+! 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 soilLiqFlx_module
+! -----------------------------------------------------------------------------------------------------------
+
+! data types
+USE nrtype
+USE data_types,only:var_d                  ! x%var(:)       (dp)
+USE data_types,only:var_ilength            ! x%var(:)%dat   (i4b)
+USE data_types,only:var_dlength            ! x%var(:)%dat   (dp)
+
+! missing values
+USE globalData,only:integerMissing  ! missing integer
+USE globalData,only:realMissing     ! missing real number
+
+! physical constants
+USE multiconst,only:&
+                    LH_fus,  & ! latent heat of fusion         (J kg-1)
+                    LH_vap,  & ! latent heat of vaporization   (J kg-1)
+                    LH_sub,  & ! latent heat of sublimation    (J kg-1)
+                    gravity, & ! gravitational acceleteration  (m s-2)
+                    Tfreeze, & ! freezing point of pure water  (K)
+                    iden_air,& ! intrinsic density of air      (kg m-3)
+                    iden_ice,& ! intrinsic density of ice      (kg m-3)
+                    iden_water ! intrinsic density of water    (kg m-3)
+
+! named variables
+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
+USE var_lookup,only:iLookINDEX             ! named variables for structure elements
+
+! model decisions
+USE globalData,only:model_decisions        ! model decision structure
+USE var_lookup,only:iLookDECISIONS         ! named variables for elements of the decision structure
+
+! provide access to look-up values for model decisions
+USE mDecisions_module,only:  &
+ ! look-up values for method used to compute derivative
+ numerical,                  & ! numerical solution
+ analytical,                 & ! analytical solution
+ ! look-up values for the form of Richards' equation
+ moisture,                   & ! moisture-based form of Richards' equation
+ mixdform,                   & ! mixed form of Richards' equation
+ ! look-up values for the type of hydraulic conductivity profile
+ constant,                   & ! constant hydraulic conductivity with depth
+ powerLaw_profile,           & ! power-law profile
+ ! look-up values for the choice of groundwater parameterization
+ qbaseTopmodel,              & ! TOPMODEL-ish baseflow parameterization
+ bigBucket,                  & ! a big bucket (lumped aquifer model)
+ noExplicit,                 & ! no explicit groundwater parameterization
+ ! look-up values for the choice of boundary conditions for hydrology
+ prescribedHead,             & ! prescribed head (volumetric liquid water content for mixed form of Richards' eqn)
+ funcBottomHead,             & ! function of matric head in the lower-most layer
+ freeDrainage,               & ! free drainage
+ liquidFlux,                 & ! liquid water flux
+ zeroFlux                      ! zero flux
+
+! -----------------------------------------------------------------------------------------------------------
+implicit none
+private
+public::soilLiqFlx
+! constant parameters
+real(dp),parameter     :: verySmall=1.e-12_dp       ! a very small number (used to avoid divide by zero)
+real(dp),parameter     :: dx=1.e-8_dp               ! finite difference increment
+contains
+
+
+ ! ***************************************************************************************************************
+ ! public subroutine soilLiqFlx: compute liquid water fluxes and their derivatives
+ ! ***************************************************************************************************************
+ subroutine soilLiqFlx(&
+                       ! input: model control
+                       nSoil,                        & ! intent(in): number of soil layers
+                       doInfiltrate,                 & ! intent(in): flag to compute infiltration
+                       scalarSolution,               & ! intent(in):    flag to indicate the scalar solution
+                       deriv_desired,                & ! intent(in): flag indicating if derivatives are desired
+                       ! input: trial state variables
+                       mLayerTempTrial,              & ! intent(in): temperature (K)
+                       mLayerMatricHeadTrial,        & ! intent(in): matric head (m)
+                       mLayerVolFracLiqTrial,        & ! intent(in): volumetric fraction of liquid water (-)
+                       mLayerVolFracIceTrial,        & ! intent(in): volumetric fraction of ice (-)
+                       ! input: pre-computed derivatives
+                       mLayerdTheta_dTk,             & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                       dPsiLiq_dTemp,                & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                       ! input: fluxes
+                       scalarCanopyTranspiration,    & ! intent(in): canopy transpiration (kg m-2 s-1)
+                       scalarGroundEvaporation,      & ! intent(in): ground evaporation (kg m-2 s-1)
+                       scalarRainPlusMelt,           & ! intent(in): rain plus melt (m s-1)
+                       ! input-output: data structures
+                       mpar_data,                    & ! intent(in):    model parameters
+                       indx_data,                    & ! intent(in):    model indices
+                       prog_data,                    & ! intent(in):    model prognostic variables for a local HRU
+                       diag_data,                    & ! intent(inout): model diagnostic variables for a local HRU
+                       flux_data,                    & ! intent(inout): model fluxes for a local HRU
+                       ! output: diagnostic variables for surface runoff
+                       xMaxInfilRate,                & ! intent(inout): maximum infiltration rate (m s-1)
+                       scalarInfilArea,              & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                       scalarFrozenArea,             & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                       scalarSurfaceRunoff,          & ! intent(out): surface runoff (m s-1)
+                       ! output: diagnostic variables for model layers
+                       mLayerdTheta_dPsi,            & ! intent(out): derivative in the soil water characteristic w.r.t. psi (m-1)
+                       mLayerdPsi_dTheta,            & ! intent(out): derivative in the soil water characteristic w.r.t. theta (m)
+                       dHydCond_dMatric,             & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (s-1)
+                       ! output: fluxes
+                       scalarSurfaceInfiltration,    & ! intent(out): surface infiltration rate (m s-1)
+                       iLayerLiqFluxSoil,            & ! intent(out): liquid fluxes at layer interfaces (m s-1)
+                       mLayerTranspire,              & ! intent(out): transpiration loss from each soil layer (m s-1)
+                       mLayerHydCond,                & ! intent(out): hydraulic conductivity in each soil layer (m s-1)
+                       ! output: derivatives in fluxes w.r.t. hydrology state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+                       dq_dHydStateAbove,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer above (m s-1)
+                       dq_dHydStateBelow,            & ! intent(out): derivatives in the flux w.r.t. volumetric liquid water content in the layer below (m s-1)
+                       ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+                       dq_dNrgStateAbove,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                       dq_dNrgStateBelow,            & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                       ! output: error control
+                       err,message)                    ! intent(out): error control
+ ! utility modules
+ USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water
+ USE soil_utils_module,only:matricHead      ! compute matric head (m)
+ USE soil_utils_module,only:dTheta_dPsi     ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
+ USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+ USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head
+ USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content
+ USE soil_utils_module,only:hydCondMP_liq   ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ implicit none
+ ! input: model control
+ integer(i4b),intent(in)          :: nSoil                         ! number of soil layers
+ logical(lgt),intent(in)          :: doInfiltrate                  ! flag to compute infiltration
+ logical(lgt),intent(in)          :: scalarSolution                ! flag to denote if implementing the scalar solution
+ logical(lgt),intent(in)          :: deriv_desired                 ! flag indicating if derivatives are desired
+ ! input: trial model state variables
+ real(dp),intent(in)              :: mLayerTempTrial(:)            ! temperature in each layer at the current iteration (m)
+ real(dp),intent(in)              :: mLayerMatricHeadTrial(:)      ! matric head in each layer at the current iteration (m)
+ real(dp),intent(in)              :: mLayerVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the current iteration (-)
+ real(dp),intent(in)              :: mLayerVolFracIceTrial(:)      ! volumetric fraction of ice at the current iteration (-)
+ ! input: pre-computed derivatves
+ real(dp),intent(in)              :: mLayerdTheta_dTk(:)           ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+ real(dp),intent(in)              :: dPsiLiq_dTemp(:)              ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+ ! input: model fluxes
+ real(dp),intent(in)              :: scalarCanopyTranspiration     ! canopy transpiration (kg m-2 s-1)
+ real(dp),intent(in)              :: scalarGroundEvaporation       ! ground evaporation (kg m-2 s-1)
+ real(dp),intent(in)              :: scalarRainPlusMelt            ! rain plus melt (m s-1)
+ ! input-output: data structures
+ type(var_dlength),intent(in)     :: mpar_data                     ! model parameters
+ type(var_ilength),intent(in)     :: indx_data                     ! state vector geometry
+ type(var_dlength),intent(in)     :: prog_data                     ! prognostic variables for a local HRU
+ type(var_dlength),intent(inout)  :: diag_data                     ! diagnostic variables for a local HRU
+ type(var_dlength),intent(inout)  :: flux_data                     ! model fluxes for a local HRU
+ ! output: diagnostic variables for surface runoff
+ real(dp),intent(inout)           :: xMaxInfilRate                 ! maximum infiltration rate (m s-1)
+ real(dp),intent(inout)           :: scalarInfilArea               ! fraction of unfrozen area where water can infiltrate (-)
+ real(dp),intent(inout)           :: scalarFrozenArea              ! fraction of area that is considered impermeable due to soil ice (-)
+ real(dp),intent(inout)           :: scalarSurfaceRunoff           ! surface runoff (m s-1)
+ ! output: diagnostic variables for each layer
+ real(dp),intent(inout)           :: mLayerdTheta_dPsi(:)          ! derivative in the soil water characteristic w.r.t. psi (m-1)
+ real(dp),intent(inout)           :: mLayerdPsi_dTheta(:)          ! derivative in the soil water characteristic w.r.t. theta (m)
+ real(dp),intent(inout)           :: dHydCond_dMatric(:)           ! derivative in hydraulic conductivity w.r.t matric head (s-1)
+ ! output: liquid fluxes
+ real(dp),intent(inout)           :: scalarSurfaceInfiltration     ! surface infiltration rate (m s-1)
+ real(dp),intent(inout)           :: iLayerLiqFluxSoil(0:)         ! liquid flux at soil layer interfaces (m s-1)
+ real(dp),intent(inout)           :: mLayerTranspire(:)            ! transpiration loss from each soil layer (m s-1)
+ real(dp),intent(inout)           :: mLayerHydCond(:)              ! hydraulic conductivity in each soil layer (m s-1)
+ ! output: derivatives in fluxes w.r.t. state variables in the layer above and layer below (m s-1)
+ real(dp),intent(inout)           :: dq_dHydStateAbove(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer above
+ real(dp),intent(inout)           :: dq_dHydStateBelow(0:)         ! derivative in the flux in layer interfaces w.r.t. state variables in the layer below
+ ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+ real(dp),intent(inout)           :: dq_dNrgStateAbove(0:)         ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+ real(dp),intent(inout)           :: dq_dNrgStateBelow(0:)         ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)         :: err                           ! error code
+ character(*),intent(out)         :: message                       ! error message
+ ! -----------------------------------------------------------------------------------------------------------------------------------------------------
+ ! local variables: general
+ character(LEN=256)               :: cmessage                     ! error message of downwind routine
+ integer(i4b)                     :: ibeg,iend                    ! start and end indices of the soil layers in concatanated snow-soil vector
+ logical(lgt)                     :: desireAnal                   ! flag to identify if analytical derivatives are desired
+ integer(i4b)                     :: iLayer,iSoil                 ! index of soil layer
+ integer(i4b)                     :: ixLayerDesired(1)            ! layer desired (scalar solution)
+ integer(i4b)                     :: ixTop                        ! top layer in subroutine call
+ integer(i4b)                     :: ixBot                        ! bottom layer in subroutine call
+ ! additional variables to compute numerical derivatives
+ integer(i4b)                     :: nFlux                        ! number of flux calculations required (>1 = numerical derivatives with one-sided finite differences)
+ integer(i4b)                     :: itry                         ! index of different flux calculations
+ integer(i4b),parameter           :: unperturbed=0                ! named variable to identify the case of unperturbed state variables
+ integer(i4b),parameter           :: perturbState=1               ! named variable to identify the case where we perturb the state in the current layer
+ integer(i4b),parameter           :: perturbStateAbove=2          ! named variable to identify the case where we perturb the state layer above
+ integer(i4b),parameter           :: perturbStateBelow=3          ! named variable to identify the case where we perturb the state layer below
+ integer(i4b)                     :: ixPerturb                    ! index of element in 2-element vector to perturb
+ integer(i4b)                     :: ixOriginal                   ! index of perturbed element in the original vector
+ real(dp)                         :: scalarVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
+ real(dp)                         :: scalarMatricHeadTrial        ! trial value of matric head (m)
+ real(dp)                         :: scalarHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
+ real(dp)                         :: scalarHydCondMicro           ! trial value of hydraulic conductivity of micropores (m s-1)
+ real(dp)                         :: scalarHydCondMacro           ! trial value of hydraulic conductivity of macropores (m s-1)
+ real(dp)                         :: scalarFlux                   ! vertical flux (m s-1)
+ real(dp)                         :: scalarFlux_dStateAbove       ! vertical flux with perturbation to the state above (m s-1)
+ real(dp)                         :: scalarFlux_dStateBelow       ! vertical flux with perturbation to the state below (m s-1)
+ ! transpiration sink term
+ real(dp),dimension(nSoil)        :: mLayerTranspireFrac          ! fraction of transpiration allocated to each soil layer (-)
+ ! diagnostic variables
+ real(dp),dimension(nSoil)        :: iceImpedeFac                 ! ice impedence factor at layer mid-points (-)
+ real(dp),dimension(nSoil)        :: mLayerDiffuse                ! diffusivity at layer mid-point (m2 s-1)
+ real(dp),dimension(nSoil)        :: dHydCond_dVolLiq             ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+ real(dp),dimension(nSoil)        :: dDiffuse_dVolLiq             ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+ real(dp),dimension(nSoil)        :: dHydCond_dTemp               ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+ real(dp),dimension(0:nSoil)      :: iLayerHydCond                ! hydraulic conductivity at layer interface (m s-1)
+ real(dp),dimension(0:nSoil)      :: iLayerDiffuse                ! diffusivity at layer interface (m2 s-1)
+ ! compute surface flux
+ integer(i4b)                     :: nRoots                       ! number of soil layers with roots
+ integer(i4b)                     :: ixIce                        ! index of the lowest soil layer that contains ice
+ real(dp),dimension(0:nSoil)      :: iLayerHeight                 ! height of the layer interfaces (m)
+ ! compute fluxes and derivatives at layer interfaces
+ real(dp),dimension(2)            :: vectorVolFracLiqTrial        ! trial value of volumetric liquid water content (-)
+ real(dp),dimension(2)            :: vectorMatricHeadTrial        ! trial value of matric head (m)
+ real(dp),dimension(2)            :: vectorHydCondTrial           ! trial value of hydraulic conductivity (m s-1)
+ real(dp),dimension(2)            :: vectorDiffuseTrial           ! trial value of hydraulic diffusivity (m2 s-1)
+ real(dp)                         :: scalardPsi_dTheta            ! derivative in soil water characteristix, used for perturbations when computing numerical derivatives
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! initialize error control
+ err=0; message='soilLiqFlx/'
+
+ ! get indices for the data structures
+ ibeg = indx_data%var(iLookINDEX%nSnow)%dat(1) + 1
+ iend = indx_data%var(iLookINDEX%nSnow)%dat(1) + indx_data%var(iLookINDEX%nSoil)%dat(1)
+
+ ! get a copy of iLayerHeight
+ ! NOTE: performance hit, though cannot define the shape (0:) with the associate construct
+ iLayerHeight(0:nSoil) = prog_data%var(iLookPROG%iLayerHeight)%dat(ibeg-1:iend)  ! height of the layer interfaces (m)
+
+ ! make association between local variables and the information in the data structures
+ associate(&
+  ! input: model control
+  ixDerivMethod          => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision,   & ! intent(in): index of the method used to calculate flux derivatives
+  ixRichards             => model_decisions(iLookDECISIONS%f_Richards)%iDecision,   & ! intent(in): index of the form of Richards' equation
+  ixBcUpperSoilHydrology => model_decisions(iLookDECISIONS%bcUpprSoiH)%iDecision,   & ! intent(in): index of the upper boundary conditions for soil hydrology
+  ixBcLowerSoilHydrology => model_decisions(iLookDECISIONS%bcLowrSoiH)%iDecision,   & ! intent(in): index of the lower boundary conditions for soil hydrology
+  ! input: model indices
+  ixMatricHead           => indx_data%var(iLookINDEX%ixMatricHead)%dat,             & ! intent(in): indices of soil layers where matric head is the state variable
+  ixSoilOnlyHyd          => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat,            & ! intent(in): index in the state subset for hydrology state variables in the soil domain
+  ! input: model coordinate variables -- NOTE: use of ibeg and iend
+  mLayerDepth            => prog_data%var(iLookPROG%mLayerDepth)%dat(ibeg:iend),    & ! intent(in): depth of the layer (m)
+  mLayerHeight           => prog_data%var(iLookPROG%mLayerHeight)%dat(ibeg:iend),   & ! intent(in): height of the layer mid-point (m)
+  ! input: upper boundary conditions
+  upperBoundHead         => mpar_data%var(iLookPARAM%upperBoundHead)%dat(1),        & ! intent(in): upper boundary condition for matric head (m)
+  upperBoundTheta        => mpar_data%var(iLookPARAM%upperBoundTheta)%dat(1),       & ! intent(in): upper boundary condition for volumetric liquid water content (-)
+  ! input: lower boundary conditions
+  lowerBoundHead         => mpar_data%var(iLookPARAM%lowerBoundHead)%dat(1),        & ! intent(in): lower boundary condition for matric head (m)
+  lowerBoundTheta        => mpar_data%var(iLookPARAM%lowerBoundTheta)%dat(1),       & ! intent(in): lower boundary condition for volumetric liquid water content (-)
+  ! input: vertically variable soil parameters
+  vGn_m                  => diag_data%var(iLookDIAG%scalarVGn_m)%dat,               & ! intent(in): van Genutchen "m" parameter (-)
+  vGn_n                  => mpar_data%var(iLookPARAM%vGn_n)%dat,                    & ! intent(in): van Genutchen "n" parameter (-)
+  vGn_alpha              => mpar_data%var(iLookPARAM%vGn_alpha)%dat,                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+  theta_sat              => mpar_data%var(iLookPARAM%theta_sat)%dat,                & ! intent(in): soil porosity (-)
+  theta_res              => mpar_data%var(iLookPARAM%theta_res)%dat,                & ! intent(in): soil residual volumetric water content (-)
+  ! input: vertically constant soil parameters
+  wettingFrontSuction    => mpar_data%var(iLookPARAM%wettingFrontSuction)%dat(1),   & ! intent(in): Green-Ampt wetting front suction (m)
+  rootingDepth           => mpar_data%var(iLookPARAM%rootingDepth)%dat(1),          & ! intent(in): rooting depth (m)
+  kAnisotropic           => mpar_data%var(iLookPARAM%kAnisotropic)%dat(1),          & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+  zScale_TOPMODEL        => mpar_data%var(iLookPARAM%zScale_TOPMODEL)%dat(1),       & ! intent(in): TOPMODEL scaling factor (m)
+  qSurfScale             => mpar_data%var(iLookPARAM%qSurfScale)%dat(1),            & ! intent(in): scaling factor in the surface runoff parameterization (-)
+  f_impede               => mpar_data%var(iLookPARAM%f_impede)%dat(1),              & ! intent(in): ice impedence factor (-)
+  soilIceScale           => mpar_data%var(iLookPARAM%soilIceScale)%dat(1),          & ! intent(in): scaling factor for depth of soil ice, used to get frozen fraction (m)
+  soilIceCV              => mpar_data%var(iLookPARAM%soilIceCV)%dat(1),             & ! intent(in): CV of depth of soil ice, used to get frozen fraction (-)
+  theta_mp               => mpar_data%var(iLookPARAM%theta_mp)%dat(1),              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+  mpExp                  => mpar_data%var(iLookPARAM%mpExp)%dat(1),                 & ! intent(in): empirical exponent in macropore flow equation (-)
+  ! input: saturated hydraulic conductivity
+  mLayerSatHydCondMP     => flux_data%var(iLookFLUX%mLayerSatHydCondMP)%dat,        & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
+  mLayerSatHydCond       => flux_data%var(iLookFLUX%mLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
+  iLayerSatHydCond       => flux_data%var(iLookFLUX%iLayerSatHydCond)%dat,          & ! intent(in): saturated hydraulic conductivity at the interface of each layer (m s-1)
+  ! input: factors limiting transpiration (from vegFlux routine)
+  mLayerRootDensity      => diag_data%var(iLookDIAG%mLayerRootDensity)%dat,         & ! intent(in): root density in each layer (-)
+  scalarTranspireLim     => diag_data%var(iLookDIAG%scalarTranspireLim)%dat(1),     & ! intent(in): weighted average of the transpiration limiting factor (-)
+  mLayerTranspireLim     => diag_data%var(iLookDIAG%mLayerTranspireLim)%dat         & ! intent(in): transpiration limiting factor in each layer (-)
+ )  ! associating local variables with the information in the data structures
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! preliminaries
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ ! define the pethod to compute derivatives
+ !print*, 'numerical derivatives = ', (ixDerivMethod==numerical)
+
+ ! numerical derivatives are not implemented yet
+ if(ixDerivMethod==numerical)then
+  message=trim(message)//'numerical derivates do not account for the cross derivatives between hydrology and thermodynamics'
+  err=20; return
+ end if
+
+ ! check the need to compute analytical derivatives
+ if(deriv_desired .and. ixDerivMethod==analytical)then
+  desireAnal = .true.
+ else
+  desireAnal = .false.
+ end if
+
+ ! check the need to compute numerical derivatives
+ if(deriv_desired .and. ixDerivMethod==numerical)then
+  nFlux=3  ! compute the derivatives using one-sided finite differences
+ else
+  nFlux=0  ! compute analytical derivatives
+ end if
+
+ ! get the indices for the soil layers
+ if(scalarSolution)then
+  ixLayerDesired = pack(ixMatricHead, ixSoilOnlyHyd/=integerMissing)
+  ixTop = ixLayerDesired(1)
+  ixBot = ixLayerDesired(1)
+ else
+  ixTop = 1
+  ixBot = nSoil
+ endif
+
+ ! identify the number of layers that contain roots
+ nRoots = count(iLayerHeight(0:nSoil-1) < rootingDepth-verySmall)
+ if(nRoots==0)then
+  message=trim(message)//'no layers with roots'
+  err=20; return
+ endif
+
+ ! identify lowest soil layer with ice
+ ! NOTE: cannot use count because there may be an unfrozen wedge
+ ixIce = 0  ! initialize the index of the ice layer (0 means no ice in the soil profile)
+ do iLayer=1,nSoil ! (loop through soil layers)
+  if(mLayerVolFracIceTrial(iLayer) > verySmall) ixIce = iLayer
+ end do
+ !if(ixIce==nSoil)then; err=20; message=trim(message)//'ice extends to the bottom of the soil profile'; return; end if
+
+ ! *************************************************************************************************************************************************
+ ! *************************************************************************************************************************************************
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! compute the transpiration sink term
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ ! check the need to compute transpiration (NOTE: intent=inout)
+ if( .not. (scalarSolution .and. ixTop>1) )then
+
+  ! compute the fraction of transpiration loss from each soil layer
+  if(scalarTranspireLim > tiny(scalarTranspireLim))then ! (transpiration may be non-zero even if the soil moisture limiting factor is zero)
+   mLayerTranspireFrac(:) = mLayerRootDensity(:)*mLayerTranspireLim(:)/scalarTranspireLim
+  else ! (possible for there to be non-zero conductance and therefore transpiration in this case)
+   mLayerTranspireFrac(:) = mLayerRootDensity(:) / sum(mLayerRootDensity)
+  end if
+
+  ! check fractions sum to one
+  if(abs(sum(mLayerTranspireFrac) - 1._dp) > verySmall)then
+   message=trim(message)//'fraction transpiration in soil layers does not sum to one'
+   err=20; return
+  endif
+
+  ! compute transpiration loss from each soil layer (kg m-2 s-1 --> m s-1)
+  mLayerTranspire = mLayerTranspireFrac(:)*scalarCanopyTranspiration/iden_water
+
+  ! special case of prescribed head -- no transpiration
+  if(ixBcUpperSoilHydrology==prescribedHead) mLayerTranspire(:) = 0._dp
+
+ endif  ! if need to compute transpiration
+
+ ! *************************************************************************************************************************************************
+ ! *************************************************************************************************************************************************
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! compute diagnostic variables at the nodes throughout the soil profile
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ do iSoil=ixTop,min(ixBot+1,nSoil) ! (loop through soil layers)
+
+  call diagv_node(&
+                  ! input: model control
+                  desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
+                  ixRichards,                      & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
+                  ! input: state variables
+                  mLayerTempTrial(iSoil),          & ! intent(in): temperature (K)
+                  mLayerMatricHeadTrial(iSoil),    & ! intent(in): matric head in each layer (m)
+                  mLayerVolFracLiqTrial(iSoil),    & ! intent(in): volumetric liquid water content in each soil layer (-)
+                  mLayerVolFracIceTrial(iSoil),    & ! intent(in): volumetric ice content in each soil layer (-)
+                  ! input: pre-computed deriavatives
+                  mLayerdTheta_dTk(iSoil),         & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                  dPsiLiq_dTemp(iSoil),            & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                  ! input: soil parameters
+                  vGn_alpha(iSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                  vGn_n(iSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
+                  VGn_m(iSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
+                  mpExp,                           & ! intent(in): empirical exponent in macropore flow equation (-)
+                  theta_sat(iSoil),                & ! intent(in): soil porosity (-)
+                  theta_res(iSoil),                & ! intent(in): soil residual volumetric water content (-)
+                  theta_mp,                        & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+                  f_impede,                        & ! intent(in): ice impedence factor (-)
+                  ! input: saturated hydraulic conductivity
+                  mLayerSatHydCond(iSoil),         & ! intent(in): saturated hydraulic conductivity at the mid-point of each layer (m s-1)
+                  mLayerSatHydCondMP(iSoil),       & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of each layer (m s-1)
+                  ! output: derivative in the soil water characteristic
+                  mLayerdPsi_dTheta(iSoil),        & ! intent(out): derivative in the soil water characteristic
+                  mLayerdTheta_dPsi(iSoil),        & ! intent(out): derivative in the soil water characteristic
+                  ! output: transmittance
+                  mLayerHydCond(iSoil),            & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
+                  mLayerDiffuse(iSoil),            & ! intent(out): diffusivity at layer mid-points (m2 s-1)
+                  iceImpedeFac(iSoil),             & ! intent(out): ice impedence factor in each layer (-)
+                  ! output: transmittance derivatives
+                  dHydCond_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+                  dDiffuse_dVolLiq(iSoil),         & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+                  dHydCond_dMatric(iSoil),         & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
+                  dHydCond_dTemp(iSoil),           & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                  ! output: error control
+                  err,cmessage)                      ! intent(out): error control
+  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+
+ end do  ! (looping through soil layers)
+
+ ! *************************************************************************************************************************************************
+ ! *************************************************************************************************************************************************
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ ! set derivative w.r.t. state above to zero (does not exist)
+ dq_dHydStateAbove(0) = 0._dp
+ dq_dNrgStateAbove(0) = 0._dp
+
+ ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+ do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+
+  ! =====
+  ! get input state variables...
+  ! ============================
+  ! identify the type of perturbation
+  select case(itry)
+
+   ! skip undesired perturbations
+   case(perturbStateAbove); cycle  ! cannot perturb state above (does not exist) -- so keep cycling
+   case(perturbState); cycle       ! perturbing the layer below the flux at the top interface
+
+   ! un-perturbed case
+   case(unperturbed)
+    scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
+    scalarMatricHeadTrial = mLayerMatricHeadTrial(1)
+
+   ! perturb soil state (one-sided finite differences)
+   case(perturbStateBelow)
+    ! (perturbation depends on the form of Richards' equation)
+    select case(ixRichards)
+     case(moisture)
+      scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1) + dx
+      scalarMatricHeadTrial = mLayerMatricHeadTrial(1)
+     case(mixdform)
+      scalarVolFracLiqTrial = mLayerVolFracLiqTrial(1)
+      scalarMatricHeadTrial = mLayerMatricHeadTrial(1) + dx
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select ! (form of Richards' equation
+   ! check for an unknown perturbation
+   case default; err=10; message=trim(message)//"unknown perturbation"; return
+
+  end select ! (type of perturbation)
+
+  ! =====
+  ! compute surface flux and its derivative...
+  ! ==========================================
+
+  call surfaceFlx(&
+                  ! input: model control
+                  doInfiltrate,                       & ! intent(in): flag indicating if desire to compute infiltration
+                  desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
+                  ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                  ixBcUpperSoilHydrology,             & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
+                  nRoots,                             & ! intent(in): number of layers that contain roots
+                  ixIce,                              & ! intent(in): index of lowest ice layer
+                  ! input: state variables
+                  scalarMatricHeadTrial,              & ! intent(in): matric head in the upper-most soil layer (m)
+                  scalarVolFracLiqTrial,              & ! intent(in): volumetric liquid water content the upper-most soil layer (-)
+                  mLayerVolFracLiqTrial,              & ! intent(in): volumetric liquid water content in each soil layer (-)
+                  mLayerVolFracIceTrial,              & ! intent(in): volumetric ice content in each soil layer (-)
+                  ! input: depth of upper-most soil layer (m)
+                  mLayerDepth,                        & ! intent(in): depth of each soil layer (m)
+                  iLayerHeight,                       & ! intent(in): height at the interface of each layer (m)
+                  ! input: boundary conditions
+                  upperBoundHead,                     & ! intent(in): upper boundary condition (m)
+                  upperBoundTheta,                    & ! intent(in): upper boundary condition (-)
+                  ! input: flux at the upper boundary
+                  scalarRainPlusMelt,                 & ! intent(in): rain plus melt (m s-1)
+                  ! input: transmittance
+                  iLayerSatHydCond(0),                & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                  dHydCond_dTemp(1),                  & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                  iceImpedeFac(1),                    & ! intent(in): ice impedence factor in the upper-most soil layer (-)
+                  ! input: soil parameters
+                  vGn_alpha(1),                       & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                  vGn_n(1),                           & ! intent(in): van Genutchen "n" parameter (-)
+                  VGn_m(1),                           & ! intent(in): van Genutchen "m" parameter (-)
+                  theta_sat(1),                       & ! intent(in): soil porosity (-)
+                  theta_res(1),                       & ! intent(in): soil residual volumetric water content (-)
+                  qSurfScale,                         & ! intent(in): scaling factor in the surface runoff parameterization (-)
+                  zScale_TOPMODEL,                    & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+                  rootingDepth,                       & ! intent(in): rooting depth (m)
+                  wettingFrontSuction,                & ! intent(in): Green-Ampt wetting front suction (m)
+                  soilIceScale,                       & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
+                  soilIceCV,                          & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
+                  ! input-output: hydraulic conductivity and diffusivity at the surface
+                  iLayerHydCond(0),                   & ! intent(inout): hydraulic conductivity at the surface (m s-1)
+                  iLayerDiffuse(0),                   & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
+                  ! input-output: fluxes at layer interfaces and surface runoff
+                  xMaxInfilRate,                      & ! intent(inout): maximum infiltration rate (m s-1)
+                  scalarInfilArea,                    & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                  scalarFrozenArea,                   & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                  scalarSurfaceRunoff,                & ! intent(out): surface runoff (m s-1)
+                  scalarSurfaceInfiltration,          & ! intent(out): surface infiltration (m s-1)
+                  ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
+                  dq_dHydStateBelow(0),               & ! intent(inout): derivative in surface infiltration w.r.t. hydrology state variable in the upper-most soil layer (m s-1 or s-1)
+                  dq_dNrgStateBelow(0),               & ! intent(out):   derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
+                  ! output: error control
+                  err,cmessage)                         ! intent(out): error control
+  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+  ! print*, "scalarGroundEvaporation =", scalarGroundEvaporation
+  ! include base soil evaporation as the upper boundary flux
+  iLayerLiqFluxSoil(0) = scalarGroundEvaporation/iden_water + scalarSurfaceInfiltration
+
+  ! get copies of surface flux to compute numerical derivatives
+  if(deriv_desired .and. ixDerivMethod==numerical)then
+   select case(itry)
+    case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(0)
+    case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(0)
+    case default; err=10; message=trim(message)//"unknown perturbation"; return
+   end select
+  end if
+
+  ! write(*,'(a,1x,10(f30.15))') 'scalarRainPlusMelt, scalarSurfaceInfiltration = ', scalarRainPlusMelt, scalarSurfaceInfiltration
+
+ end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+
+ ! compute numerical derivatives
+ if(deriv_desired .and. ixDerivMethod==numerical)then
+  dq_dHydStateBelow(0) = (scalarFlux_dStateBelow - scalarFlux)/dx ! change in surface flux w.r.t. change in the soil moisture in the top soil layer (m s-1)
+ end if
+!  print*, 'scalarSurfaceInfiltration, iLayerLiqFluxSoil(0) = ', scalarSurfaceInfiltration, iLayerLiqFluxSoil(0)
+ !print*, '(ixDerivMethod==numerical), dq_dHydStateBelow(0) = ', (ixDerivMethod==numerical), dq_dHydStateBelow(0)
+ !pause
+
+ ! *************************************************************************************************************************************************
+ ! *************************************************************************************************************************************************
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! * compute fluxes and derivatives at layer interfaces...
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ ! NOTE: computing flux at the bottom of the layer
+
+ ! loop through soil layers
+ do iLayer=ixTop,min(ixBot,nSoil-1)
+
+  ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+  do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+
+   ! =====
+   ! determine layer to perturb
+   ! ============================
+   select case(itry)
+    ! skip undesired perturbations
+    case(perturbState); cycle       ! perturbing the layers above and below the flux at the interface
+    ! identify the index for the perturbation
+    case(unperturbed);       ixPerturb = 0
+    case(perturbStateAbove); ixPerturb = 1
+    case(perturbStateBelow); ixPerturb = 2
+    case default; err=10; message=trim(message)//"unknown perturbation"; return
+   end select ! (identifying layer to of perturbation)
+   ! determine the index in the original vector
+   ixOriginal = iLayer + (ixPerturb-1)
+
+   ! =====
+   ! get input state variables...
+   ! ============================
+   ! start with the un-perturbed case
+   vectorVolFracLiqTrial(1:2) = mLayerVolFracLiqTrial(iLayer:iLayer+1)
+   vectorMatricHeadTrial(1:2) = mLayerMatricHeadTrial(iLayer:iLayer+1)
+   ! make appropriate perturbations
+   if(ixPerturb > 0)then
+    select case(ixRichards)
+     case(moisture); vectorVolFracLiqTrial(ixPerturb) = vectorVolFracLiqTrial(ixPerturb) + dx
+     case(mixdform); vectorMatricHeadTrial(ixPerturb) = vectorMatricHeadTrial(ixPerturb) + dx
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select ! (form of Richards' equation)
+   end if
+
+   ! =====
+   ! get hydraulic conductivty...
+   ! ============================
+   ! start with the un-perturbed case
+   vectorHydCondTrial(1:2) = mLayerHydCond(iLayer:iLayer+1)
+   vectorDiffuseTrial(1:2) = mLayerDiffuse(iLayer:iLayer+1)
+   ! make appropriate perturbations
+   if(ixPerturb > 0)then
+    select case(ixRichards)
+     case(moisture)
+      scalardPsi_dTheta             = dPsi_dTheta(vectorVolFracLiqTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
+      vectorHydCondTrial(ixPerturb) = hydCond_liq(vectorVolFracLiqTrial(ixPerturb),mLayerSatHydCond(ixOriginal),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
+      vectorDiffuseTrial(ixPerturb) = scalardPsi_dTheta * vectorHydCondTrial(ixPerturb)
+     case(mixdform)
+      scalarVolFracLiqTrial = volFracLiq(vectorMatricHeadTrial(ixPerturb),vGn_alpha(ixPerturb),theta_res(ixPerturb),theta_sat(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb))
+      scalarHydCondMicro    = hydCond_psi(vectorMatricHeadTrial(ixPerturb),mLayerSatHydCond(ixOriginal),vGn_alpha(ixPerturb),vGn_n(ixPerturb),vGn_m(ixPerturb)) * iceImpedeFac(ixOriginal)
+      scalarHydCondMacro    = hydCondMP_liq(scalarVolFracLiqTrial,theta_sat(ixPerturb),theta_mp,mpExp,mLayerSatHydCondMP(ixOriginal),mLayerSatHydCond(ixOriginal))
+      vectorHydCondTrial(ixPerturb) = scalarHydCondMicro + scalarHydCondMacro
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select ! (form of Richards' equation)
+   end if
+
+   ! =====
+   ! compute vertical flux at layer interface and its derivative w.r.t. the state above and the state below...
+   ! =========================================================================================================
+
+   ! NOTE: computing flux at the bottom of the layer
+
+   call iLayerFlux(&
+                   ! input: model control
+                   desireAnal,                         & ! intent(in): flag indicating if derivatives are desired
+                   ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                   ! input: state variables (adjacent layers)
+                   vectorMatricHeadTrial,              & ! intent(in): matric head at the soil nodes (m)
+                   vectorVolFracLiqTrial,              & ! intent(in): volumetric liquid water content at the soil nodes (-)
+                   ! input: model coordinate variables (adjacent layers)
+                   mLayerHeight(iLayer:iLayer+1),      & ! intent(in): height of the soil nodes (m)
+                   ! input: temperature derivatives
+                   dPsiLiq_dTemp(iLayer:iLayer+1),     & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                   dHydCond_dTemp(iLayer:iLayer+1),    & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                   ! input: transmittance (adjacent layers)
+                   vectorHydCondTrial,                 & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
+                   vectorDiffuseTrial,                 & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
+                   ! input: transmittance derivatives (adjacent layers)
+                   dHydCond_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
+                   dDiffuse_dVolLiq(iLayer:iLayer+1),  & ! intent(in): change in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
+                   dHydCond_dMatric(iLayer:iLayer+1),  & ! intent(in): change in hydraulic conductivity w.r.t. change in matric head (s-1)
+                   ! output: tranmsmittance at the layer interface (scalars)
+                   iLayerHydCond(iLayer),              & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
+                   iLayerDiffuse(iLayer),              & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
+                   ! output: vertical flux at the layer interface (scalars)
+                   iLayerLiqFluxSoil(iLayer),          & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
+                   ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+                   dq_dHydStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+                   dq_dHydStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+                   ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+                   dq_dNrgStateAbove(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                   dq_dNrgStateBelow(iLayer),          & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                   ! output: error control
+                   err,cmessage)                         ! intent(out): error control
+   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+
+   ! compute total vertical flux, to compute derivatives
+   if(deriv_desired .and. ixDerivMethod==numerical)then
+    select case(itry)
+     case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(iLayer)
+     case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(iLayer)
+     case(perturbStateBelow); scalarFlux_dStateBelow = iLayerLiqFluxSoil(iLayer)
+     case default; err=10; message=trim(message)//"unknown perturbation"; return
+    end select
+   end if
+
+  end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+
+  ! compute numerical derivatives
+  if(deriv_desired .and. ixDerivMethod==numerical)then
+   dq_dHydStateAbove(iLayer) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
+   dq_dHydStateBelow(iLayer) = (scalarFlux_dStateBelow - scalarFlux)/dx    ! change in drainage flux w.r.t. change in the state in the layer below (m s-1 or s-1)
+  end if
+
+  ! check
+  !if(iLayer==6) write(*,'(a,i4,1x,10(e25.15,1x))') 'iLayer, vectorMatricHeadTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer) = ',&
+  !                                                  iLayer, vectorMatricHeadTrial, iLayerHydCond(iLayer), iLayerLiqFluxSoil(iLayer)
+  !if(iLayer==1) write(*,'(a,i4,1x,L1,1x,2(e15.5,1x))') 'iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer) = ', &
+  !                                                      iLayer, (ixDerivMethod==numerical), dq_dHydStateBelow(iLayer-1), dq_dHydStateAbove(iLayer)
+  !pause
+
+ end do  ! (looping through soil layers)
+
+ ! add infiltration to the upper-most unfrozen layer
+ ! NOTE: this is done here rather than in surface runoff
+ !iLayerLiqFluxSoil(ixIce) = iLayerLiqFluxSoil(ixIce) + scalarSurfaceInfiltration
+
+ ! *************************************************************************************************************************************************
+ ! *************************************************************************************************************************************************
+
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+ ! * compute drainage flux from the bottom of the soil profile, and its derivative
+ ! -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ ! define the need to compute drainage
+ if( .not. (scalarSolution .and. ixTop<nSoil) )then
+
+  ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+  do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+
+   ! =====
+   ! get input state variables...
+   ! ============================
+   ! identify the type of perturbation
+   select case(itry)
+
+    ! skip undesired perturbations
+    case(perturbStateBelow); cycle   ! only perturb soil state at this time (perhaps perturb aquifer state later)
+    case(perturbState); cycle        ! here pertubing the state above the flux at the interface
+
+    ! un-perturbed case
+    case(unperturbed)
+     scalarVolFracLiqTrial   = mLayerVolFracLiqTrial(nSoil)
+     scalarMatricHeadTrial   = mLayerMatricHeadTrial(nSoil)
+
+    ! perturb soil state (one-sided finite differences)
+    case(perturbStateAbove)
+     select case(ixRichards)  ! (perturbation depends on the form of Richards' equation)
+      case(moisture)
+       scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil) + dx
+       scalarMatricHeadTrial = mLayerMatricHeadTrial(nSoil)
+      case(mixdform)
+       scalarVolFracLiqTrial = mLayerVolFracLiqTrial(nSoil)
+       scalarMatricHeadTrial = mLayerMatricHeadTrial(nSoil) + dx
+      case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+     end select ! (form of Richards' equation)
+
+   end select ! (type of perturbation)
+
+   ! =====
+   ! get hydraulic conductivty...
+   ! ============================
+   select case(itry)
+
+    ! compute perturbed value of hydraulic conductivity
+    case(perturbStateAbove)
+     select case(ixRichards)
+      case(moisture); scalarHydCondTrial = hydCond_liq(scalarVolFracLiqTrial,mLayerSatHydCond(nSoil),theta_res(nSoil),theta_sat(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
+      case(mixdform); scalarHydCondTrial = hydCond_psi(scalarMatricHeadTrial,mLayerSatHydCond(nSoil),vGn_alpha(nSoil),vGn_n(nSoil),vGn_m(nSoil)) * iceImpedeFac(nSoil)
+     end select
+
+    ! (use un-perturbed value)
+    case default
+     scalarHydCondTrial = mLayerHydCond(nSoil)        ! hydraulic conductivity at the mid-point of the lowest unsaturated soil layer (m s-1)
+
+   end select ! (re-computing hydraulic conductivity)
+
+   ! =====
+   ! compute drainage flux and its derivative...
+   ! ===========================================
+
+   call qDrainFlux(&
+                   ! input: model control
+                   desireAnal,                      & ! intent(in): flag indicating if derivatives are desired
+                   ixRichards,                      & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                   ixBcLowerSoilHydrology,          & ! intent(in): index defining the type of boundary conditions
+                   ! input: state variables
+                   scalarMatricHeadTrial,           & ! intent(in): matric head in the lowest unsaturated node (m)
+                   scalarVolFracLiqTrial,           & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
+                   ! input: model coordinate variables
+                   mLayerDepth(nSoil),              & ! intent(in): depth of the lowest unsaturated soil layer (m)
+                   mLayerHeight(nSoil),             & ! intent(in): height of the lowest unsaturated soil node (m)
+                   ! input: boundary conditions
+                   lowerBoundHead,                  & ! intent(in): lower boundary condition (m)
+                   lowerBoundTheta,                 & ! intent(in): lower boundary condition (-)
+                   ! input: derivative in the soil water characteristic
+                   mLayerdPsi_dTheta(nSoil),        & ! intent(in): derivative in the soil water characteristic
+                   ! input: transmittance
+                   iLayerSatHydCond(0),             & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                   iLayerSatHydCond(nSoil),         & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+                   scalarHydCondTrial,              & ! intent(in): hydraulic conductivity at the node itself (m s-1)
+                   iceImpedeFac(nSoil),             & ! intent(in): ice impedence factor in the lower-most soil layer (-)
+                   ! input: transmittance derivatives
+                   dHydCond_dVolLiq(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+                   dHydCond_dMatric(nSoil),         & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
+                   dHydCond_dTemp(nSoil),           & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                   ! input: soil parameters
+                   vGn_alpha(nSoil),                & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                   vGn_n(nSoil),                    & ! intent(in): van Genutchen "n" parameter (-)
+                   VGn_m(nSoil),                    & ! intent(in): van Genutchen "m" parameter (-)
+                   theta_sat(nSoil),                & ! intent(in): soil porosity (-)
+                   theta_res(nSoil),                & ! intent(in): soil residual volumetric water content (-)
+                   kAnisotropic,                    & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+                   zScale_TOPMODEL,                 & ! intent(in): TOPMODEL scaling factor (m)
+                   ! output: hydraulic conductivity and diffusivity at the surface
+                   iLayerHydCond(nSoil),            & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
+                   iLayerDiffuse(nSoil),            & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+                   ! output: drainage flux
+                   iLayerLiqFluxSoil(nSoil),        & ! intent(out): drainage flux (m s-1)
+                   ! output: derivatives in drainage flux
+                   dq_dHydStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in hydrology state in lowest unsaturated node (m s-1 or s-1)
+                   dq_dNrgStateAbove(nSoil),        & ! intent(out): change in drainage flux w.r.t. change in energy state in lowest unsaturated node (m s-1 or s-1)
+                   ! output: error control
+                   err,cmessage)                ! intent(out): error control
+   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+
+   ! get copies of drainage flux to compute derivatives
+   if(deriv_desired .and. ixDerivMethod==numerical)then
+    select case(itry)
+     case(unperturbed);       scalarFlux             = iLayerLiqFluxSoil(nSoil)
+     case(perturbStateAbove); scalarFlux_dStateAbove = iLayerLiqFluxSoil(nSoil)
+     case(perturbStateBelow); err=20; message=trim(message)//'lower state should never be perturbed when computing drainage do not expect to get here'; return
+     case default; err=10; message=trim(message)//"unknown perturbation"; return
+    end select
+   end if
+
+  end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+
+  ! compute numerical derivatives
+  ! NOTE: drainage derivatives w.r.t. state below are *actually* w.r.t. water table depth, so need to be corrected for aquifer storage
+  !       (note also negative sign to account for inverse relationship between water table depth and aquifer storage)
+  if(deriv_desired .and. ixDerivMethod==numerical)then
+   dq_dHydStateAbove(nSoil) = (scalarFlux_dStateAbove - scalarFlux)/dx    ! change in drainage flux w.r.t. change in state in lowest unsaturated node (m s-1 or s-1)
+  end if
+
+  ! no dependence on the aquifer for drainage
+  dq_dHydStateBelow(nSoil) = 0._dp  ! keep this here in case we want to couple some day....
+  dq_dNrgStateBelow(nSoil) = 0._dp  ! keep this here in case we want to couple some day....
+
+  ! print drainage
+  !print*, 'iLayerLiqFluxSoil(nSoil) = ', iLayerLiqFluxSoil(nSoil)
+
+ endif  ! if computing drainage
+ ! end of drainage section
+
+ ! *****************************************************************************************************************************************************************
+ ! *****************************************************************************************************************************************************************
+
+ ! end association between local variables and the information in the data structures
+ end associate
+
+ end subroutine soilLiqFlx
+
+ ! ***************************************************************************************************************
+ ! private subroutine diagv_node: compute transmittance and derivatives for model nodes
+ ! ***************************************************************************************************************
+ subroutine diagv_node(&
+                       ! input: model control
+                       deriv_desired,         & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,            & ! intent(in): index defining the option for Richards' equation (moisture or mixdform)
+                       ! input: state variables
+                       scalarTempTrial,       & ! intent(in): temperature (K)
+                       scalarMatricHeadTrial, & ! intent(in): matric head in a given layer (m)
+                       scalarVolFracLiqTrial, & ! intent(in): volumetric liquid water content in a given soil layer (-)
+                       scalarVolFracIceTrial, & ! intent(in): volumetric ice content in a given soil layer (-)
+                       ! input: pre-computed deriavatives
+                       dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                       dPsiLiq_dTemp,         & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                       ! input: soil parameters
+                       vGn_alpha,             & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                       vGn_n,                 & ! intent(in): van Genutchen "n" parameter (-)
+                       VGn_m,                 & ! intent(in): van Genutchen "m" parameter (-)
+                       mpExp,                 & ! intent(in): empirical exponent in macropore flow equation (-)
+                       theta_sat,             & ! intent(in): soil porosity (-)
+                       theta_res,             & ! intent(in): soil residual volumetric water content (-)
+                       theta_mp,              & ! intent(in): volumetric liquid water content when macropore flow begins (-)
+                       f_impede,              & ! intent(in): ice impedence factor (-)
+                       ! input: saturated hydraulic conductivity
+                       scalarSatHydCond,      & ! intent(in): saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
+                       scalarSatHydCondMP,    & ! intent(in): saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
+                       ! output: derivative in the soil water characteristic
+                       scalardPsi_dTheta,     & ! derivative in the soil water characteristic
+                       scalardTheta_dPsi,     & ! derivative in the soil water characteristic
+                       ! output: transmittance
+                       scalarHydCond,         & ! intent(out): hydraulic conductivity at layer mid-points (m s-1)
+                       scalarDiffuse,         & ! intent(out): diffusivity at layer mid-points (m2 s-1)
+                       iceImpedeFac,          & ! intent(out): ice impedence factor in each layer (-)
+                       ! output: transmittance derivatives
+                       dHydCond_dVolLiq,      & ! intent(out): derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+                       dDiffuse_dVolLiq,      & ! intent(out): derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+                       dHydCond_dMatric,      & ! intent(out): derivative in hydraulic conductivity w.r.t matric head (m s-1)
+                       dHydCond_dTemp,        & ! intent(out): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       ! output: error control
+                       err,message)             ! intent(out): error control
+ USE soil_utils_module,only:iceImpede           ! compute the ice impedence factor
+ USE soil_utils_module,only:volFracLiq          ! compute volumetric fraction of liquid water as a function of matric head
+ USE soil_utils_module,only:matricHead          ! compute matric head (m)
+ USE soil_utils_module,only:hydCond_psi         ! compute hydraulic conductivity as a function of matric head
+ USE soil_utils_module,only:hydCond_liq         ! compute hydraulic conductivity as a function of volumetric liquid water content
+ USE soil_utils_module,only:hydCondMP_liq       ! compute hydraulic conductivity of macropores as a function of volumetric liquid water content
+ USE soil_utils_module,only:dTheta_dPsi         ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
+ USE soil_utils_module,only:dPsi_dTheta         ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+ USE soil_utils_module,only:dPsi_dTheta2        ! compute derivative in dPsi_dTheta (m)
+ USE soil_utils_module,only:dHydCond_dLiq       ! compute derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+ USE soil_utils_module,only:dHydCond_dPsi       ! compute derivative in hydraulic conductivity w.r.t. matric head (s-1)
+ USE soil_utils_module,only:dIceImpede_dTemp    ! compute the derivative in the ice impedance factor w.r.t. temperature (K-1)
+ ! compute hydraulic transmittance and derivatives for all layers
+ implicit none
+ ! input: model control
+ logical(lgt),intent(in)       :: deriv_desired             ! flag indicating if derivatives are desired
+ integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+ ! input: state and diagnostic variables
+ real(dp),intent(in)           :: scalarTempTrial           ! temperature in each layer (K)
+ real(dp),intent(in)           :: scalarMatricHeadTrial     ! matric head in each layer (m)
+ real(dp),intent(in)           :: scalarVolFracLiqTrial     ! volumetric fraction of liquid water in a given layer (-)
+ real(dp),intent(in)           :: scalarVolFracIceTrial     ! volumetric fraction of ice in a given layer (-)
+ ! input: pre-computed deriavatives
+ real(dp),intent(in)           :: dTheta_dTk                ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+ real(dp),intent(in)           :: dPsiLiq_dTemp             ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+ ! input: soil parameters
+ real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+ real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+ real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+ real(dp),intent(in)           :: mpExp                     ! empirical exponent in macropore flow equation (-)
+ real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
+ real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+ real(dp),intent(in)           :: theta_mp                  ! volumetric liquid water content when macropore flow begins (-)
+ real(dp),intent(in)           :: f_impede                  ! ice impedence factor (-)
+ ! input: saturated hydraulic conductivity
+ real(dp),intent(in)           :: scalarSatHydCond          ! saturated hydraulic conductivity at the mid-point of a given layer (m s-1)
+ real(dp),intent(in)           :: scalarSatHydCondMP        ! saturated hydraulic conductivity of macropores at the mid-point of a given layer (m s-1)
+ ! output: derivative in the soil water characteristic
+ real(dp),intent(out)          :: scalardPsi_dTheta         ! derivative in the soil water characteristic
+ real(dp),intent(out)          :: scalardTheta_dPsi         ! derivative in the soil water characteristic
+ ! output: transmittance
+ real(dp),intent(out)          :: scalarHydCond             ! hydraulic conductivity at layer mid-points (m s-1)
+ real(dp),intent(out)          :: scalarDiffuse             ! diffusivity at layer mid-points (m2 s-1)
+ real(dp),intent(out)          :: iceImpedeFac              ! ice impedence factor in each layer (-)
+ ! output: transmittance derivatives
+ real(dp),intent(out)          :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+ real(dp),intent(out)          :: dDiffuse_dVolLiq          ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+ real(dp),intent(out)          :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t matric head (s-1)
+ real(dp),intent(out)          :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)      :: err                       ! error code
+ character(*),intent(out)      :: message                   ! error message
+ ! local variables
+ real(dp)                      :: localVolFracLiq           ! local volumetric fraction of liquid water
+ real(dp)                      :: scalarHydCondMP           ! hydraulic conductivity of macropores at layer mid-points (m s-1)
+ real(dp)                      :: dIceImpede_dT             ! derivative in ice impedance factor w.r.t. temperature (K-1)
+ real(dp)                      :: dHydCondMacro_dVolLiq     ! derivative in hydraulic conductivity of macropores w.r.t volumetric liquid water content (m s-1)
+ real(dp)                      :: dHydCondMacro_dMatric     ! derivative in hydraulic conductivity of macropores w.r.t matric head (s-1)
+ real(dp)                      :: dHydCondMicro_dMatric     ! derivative in hydraulic conductivity of micropores w.r.t matric head (s-1)
+ real(dp)                      :: dHydCondMicro_dTemp       ! derivative in hydraulic conductivity of micropores w.r.t temperature (m s-1 K-1)
+ real(dp)                      :: dPsi_dTheta2a             ! derivative in dPsi_dTheta (analytical)
+ real(dp)                      :: dIceImpede_dLiq           ! derivative in ice impedence factor w.r.t. volumetric liquid water content (-)
+ real(dp)                      :: hydCond_noIce             ! hydraulic conductivity in the absence of ice (m s-1)
+ real(dp)                      :: dK_dLiq__noIce            ! derivative in hydraulic conductivity w.r.t volumetric liquid water content, in the absence of ice (m s-1)
+ real(dp)                      :: dK_dPsi__noIce            ! derivative in hydraulic conductivity w.r.t matric head, in the absence of ice (s-1)
+ real(dp)                      :: relSatMP                  ! relative saturation of macropores (-)
+ ! local variables to test the derivative
+ logical(lgt),parameter        :: testDeriv=.false.         ! local flag to test the derivative
+ real(dp)                      :: xConst                    ! LH_fus/(gravity*Tfreeze), used in freezing point depression equation (m K-1)
+ real(dp)                      :: vTheta                    ! volumetric fraction of total water (-)
+ real(dp)                      :: volLiq                    ! volumetric fraction of liquid water (-)
+ real(dp)                      :: volIce                    ! volumetric fraction of ice (-)
+ real(dp)                      :: volFracLiq1,volFracLiq2   ! different trial values of volumetric liquid water content (-)
+ real(dp)                      :: effSat                    ! effective saturation (-)
+ real(dp)                      :: psiLiq                    ! liquid water matric potential (m)
+ real(dp)                      :: hydCon                    ! hydraulic conductivity (m s-1)
+ real(dp)                      :: hydIce                    ! hydraulic conductivity after accounting for ice impedance (-)
+ real(dp),parameter            :: dx = 1.e-8_dp             ! finite difference increment (m)
+ ! initialize error control
+ err=0; message="diagv_node/"
+
+ ! *****
+ ! compute the derivative in the soil water characteristic
+ select case(ixRichards)
+  case(moisture)
+   scalardPsi_dTheta = dPsi_dTheta(scalarvolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+   scalardTheta_dPsi = realMissing  ! (deliberately cause problems if this is ever used)
+  case(mixdform)
+   scalardTheta_dPsi = dTheta_dPsi(scalarMatricHeadTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+   scalardPsi_dTheta = dPsi_dTheta(scalarvolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+   if(testDeriv)then
+    volFracLiq1 = volFracLiq(scalarMatricHeadTrial,   vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+    volFracLiq2 = volFracLiq(scalarMatricHeadTrial+dx,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+   end if  ! (testing the derivative)
+  case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+ end select
+
+ ! *****
+ ! compute hydraulic conductivity and its derivative in each soil layer
+
+ ! compute the ice impedence factor and its derivative w.r.t. volumetric liquid water content (-)
+ call iceImpede(scalarVolFracIceTrial,f_impede, &  ! input
+                iceImpedeFac,dIceImpede_dLiq)      ! output
+
+ select case(ixRichards)
+  ! ***** moisture-based form of Richards' equation
+  case(moisture)
+   ! haven't included macropores yet
+   err=20; message=trim(message)//'still need to include macropores for the moisture-based form of Richards eqn'; return
+   ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
+   hydCond_noIce = hydCond_liq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m)
+   scalarHydCond = hydCond_noIce*iceImpedeFac
+   scalarDiffuse = scalardPsi_dTheta * scalarHydCond
+   ! compute derivative in hydraulic conductivity (m s-1) and hydraulic diffusivity (m2 s-1)
+   if(deriv_desired)then
+    if(scalarVolFracIceTrial > epsilon(iceImpedeFac))then
+     dK_dLiq__noIce   = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)  ! [.true. = analytical]
+     dHydCond_dVolLiq = hydCond_noIce*dIceImpede_dLiq + dK_dLiq__noIce*iceImpedeFac
+    else
+     dHydCond_dVolLiq = dHydCond_dLiq(scalarVolFracLiqTrial,scalarSatHydCond,theta_res,theta_sat,vGn_m,.true.)
+    end if
+    dPsi_dTheta2a    = dPsi_dTheta2(scalarVolFracLiqTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m,.true.)   ! [.true. = analytical] compute derivative in dPsi_dTheta (m)
+    dDiffuse_dVolLiq = dHydCond_dVolLiq*scalardPsi_dTheta + scalarHydCond*dPsi_dTheta2a
+    dHydCond_dMatric = realMissing ! not used, so cause problems
+   end if
+
+  ! ***** mixed form of Richards' equation -- just compute hydraulic condictivity
+  case(mixdform)
+   ! compute the hydraulic conductivity (m s-1) and diffusivity (m2 s-1) for a given layer
+   hydCond_noIce = hydCond_psi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
+   scalarDiffuse = realMissing ! not used, so cause problems
+   ! compute the hydraulic conductivity of macropores (m s-1)
+   localVolFracLiq = volFracLiq(scalarMatricHeadTrial,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+   scalarHydCondMP = hydCondMP_liq(localVolFracLiq,theta_sat,theta_mp,mpExp,scalarSatHydCondMP,scalarSatHydCond)
+   scalarHydCond   = hydCond_noIce*iceImpedeFac + scalarHydCondMP
+
+   ! compute derivative in hydraulic conductivity (m s-1)
+   if(deriv_desired)then
+    ! (compute derivative for macropores)
+    if(localVolFracLiq > theta_mp)then
+     relSatMP              = (localVolFracLiq - theta_mp)/(theta_sat - theta_mp)
+     dHydCondMacro_dVolLiq = ((scalarSatHydCondMP - scalarSatHydCond)/(theta_sat - theta_mp))*mpExp*(relSatMP**(mpExp - 1._dp))
+     dHydCondMacro_dMatric = scalardTheta_dPsi*dHydCondMacro_dVolLiq
+    else
+     dHydCondMacro_dVolLiq = 0._dp
+     dHydCondMacro_dMatric = 0._dp
+    end if
+    ! (compute derivatives for micropores)
+    if(scalarVolFracIceTrial > verySmall)then
+     dK_dPsi__noIce        = dHydCond_dPsi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)  ! analytical
+     dHydCondMicro_dTemp   = dPsiLiq_dTemp*dK_dPsi__noIce  ! m s-1 K-1
+     dHydCondMicro_dMatric = hydCond_noIce*dIceImpede_dLiq*scalardTheta_dPsi + dK_dPsi__noIce*iceImpedeFac
+    else
+     dHydCondMicro_dTemp   = 0._dp
+     dHydCondMicro_dMatric = dHydCond_dPsi(scalarMatricHeadTrial,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m,.true.)
+    end if
+    ! (combine derivatives)
+    dHydCond_dMatric = dHydCondMicro_dMatric + dHydCondMacro_dMatric
+
+    ! (compute analytical derivative for change in ice impedance factor w.r.t. temperature)
+    call dIceImpede_dTemp(scalarVolFracIceTrial, & ! intent(in): trial value of volumetric ice content (-)
+                          dTheta_dTk,            & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                          f_impede,              & ! intent(in): ice impedance parameter (-)
+                          dIceImpede_dT          ) ! intent(out): derivative in ice impedance factor w.r.t. temperature (K-1)
+    ! (compute derivative in hydraulic conductivity w.r.t. temperature)
+    dHydCond_dTemp = hydCond_noIce*dIceImpede_dT + dHydCondMicro_dTemp*iceImpedeFac
+    ! (test derivative)
+    if(testDeriv)then
+     xConst = LH_fus/(gravity*Tfreeze)                            ! m K-1 (NOTE: J = kg m2 s-2)
+     vTheta = scalarVolFracIceTrial + scalarVolFracLiqTrial
+     volLiq = volFracLiq(xConst*(scalarTempTrial+dx - Tfreeze),vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+     volIce = vTheta - volLiq
+     effSat = (volLiq - theta_res)/(theta_sat - volIce - theta_res)
+     psiLiq = matricHead(effSat,vGn_alpha,0._dp,1._dp,vGn_n,vGn_m)  ! use effective saturation, so theta_res=0 and theta_sat=1
+     hydCon = hydCond_psi(psiLiq,scalarSatHydCond,vGn_alpha,vGn_n,vGn_m)
+     call iceImpede(volIce,f_impede,iceImpedeFac,dIceImpede_dLiq)
+     hydIce = hydCon*iceImpedeFac
+     print*, 'test derivative: ', (psiLiq - scalarMatricHeadTrial)/dx, dPsiLiq_dTemp
+     print*, 'test derivative: ', (hydCon - hydCond_noIce)/dx, dHydCondMicro_dTemp
+     print*, 'test derivative: ', (hydIce - scalarHydCond)/dx, dHydCond_dTemp
+     print*, 'press any key to continue'; read(*,*) ! (alternative to the deprecated 'pause' statement)
+    end if  ! testing the derivative
+    ! (set values that are not used to missing)
+    dHydCond_dVolLiq = realMissing ! not used, so cause problems
+    dDiffuse_dVolLiq = realMissing ! not used, so cause problems
+   end if
+
+  case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+
+ end select
+
+ ! if derivatives are not desired, then set values to missing
+ if(.not.deriv_desired)then
+  dHydCond_dVolLiq   = realMissing ! not used, so cause problems
+  dDiffuse_dVolLiq   = realMissing ! not used, so cause problems
+  dHydCond_dMatric   = realMissing ! not used, so cause problems
+ end if
+
+ end subroutine diagv_node
+
+
+ ! ***************************************************************************************************************
+ ! private subroutine surfaceFlx: compute the surface flux and its derivative
+ ! ***************************************************************************************************************
+ subroutine surfaceFlx(&
+                       ! input: model control
+                       doInfiltration,            & ! intent(in): flag indicating if desire to compute infiltration
+                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                       bc_upper,                  & ! intent(in): index defining the type of boundary conditions (neumann or diriclet)
+                       nRoots,                    & ! intent(in): number of layers that contain roots
+                       ixIce,                     & ! intent(in): index of lowest ice layer
+                       ! input: state variables
+                       scalarMatricHead,          & ! intent(in): matric head in the upper-most soil layer (m)
+                       scalarVolFracLiq,          & ! intent(in): volumetric liquid water content in the upper-most soil layer (-)
+                       mLayerVolFracLiq,          & ! intent(in): volumetric liquid water content in each soil layer (-)
+                       mLayerVolFracIce,          & ! intent(in): volumetric ice content in each soil layer (-)
+                       ! input: depth of upper-most soil layer (m)
+                       mLayerDepth,               & ! intent(in): depth of each soil layer (m)
+                       iLayerHeight,              & ! intent(in): height at the interface of each layer (m)
+                       ! input: boundary conditions
+                       upperBoundHead,            & ! intent(in): upper boundary condition (m)
+                       upperBoundTheta,           & ! intent(in): upper boundary condition (-)
+                       ! input: flux at the upper boundary
+                       scalarRainPlusMelt,        & ! intent(in): rain plus melt (m s-1)
+                       ! input: transmittance
+                       surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       iceImpedeFac,              & ! intent(in): ice impedence factor in the upper-most soil layer (-)
+                       ! input: soil parameters
+                       vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                       vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
+                       VGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
+                       theta_sat,                 & ! intent(in): soil porosity (-)
+                       theta_res,                 & ! intent(in): soil residual volumetric water content (-)
+                       qSurfScale,                & ! intent(in): scaling factor in the surface runoff parameterization (-)
+                       zScale_TOPMODEL,           & ! intent(in): scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+                       rootingDepth,              & ! intent(in): rooting depth (m)
+                       wettingFrontSuction,       & ! intent(in): Green-Ampt wetting front suction (m)
+                       soilIceScale,              & ! intent(in): soil ice scaling factor in Gamma distribution used to define frozen area (m)
+                       soilIceCV,                 & ! intent(in): soil ice CV in Gamma distribution used to define frozen area (-)
+                       ! input-output: hydraulic conductivity and diffusivity at the surface
+                       surfaceHydCond,            & ! intent(inout): hydraulic conductivity at the surface (m s-1)
+                       surfaceDiffuse,            & ! intent(inout): hydraulic diffusivity at the surface (m2 s-1)
+                       ! input-output: fluxes at layer interfaces and surface runoff
+                       xMaxInfilRate,             & ! intent(inout): maximum infiltration rate (m s-1)
+                       scalarInfilArea,           & ! intent(inout): fraction of unfrozen area where water can infiltrate (-)
+                       scalarFrozenArea,          & ! intent(inout): fraction of area that is considered impermeable due to soil ice (-)
+                       scalarSurfaceRunoff,       & ! intent(out): surface runoff (m s-1)
+                       scalarSurfaceInfiltration, & ! intent(out): surface infiltration (m s-1)
+                       ! input-output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
+                       dq_dHydState,              & ! intent(inout): derivative in surface infiltration w.r.t. state variable in the upper-most soil layer (m s-1 or s-1)
+                       dq_dNrgState,              & ! intent(out):   derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
+                       ! output: error control
+                       err,message)                 ! intent(out): error control
+ 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 (m s-1)
+ USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
+ USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+ USE soil_utils_module,only:gammp           ! compute the cumulative probabilty based on the Gamma distribution
+ ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+ implicit none
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! input: model control
+ logical(lgt),intent(in)       :: doInfiltration            ! flag indicating if desire to compute infiltration
+ logical(lgt),intent(in)       :: deriv_desired             ! flag to indicate if derivatives are desired
+ integer(i4b),intent(in)       :: bc_upper                  ! index defining the type of boundary conditions
+ integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+ integer(i4b),intent(in)       :: nRoots                    ! number of layers that contain roots
+ integer(i4b),intent(in)       :: ixIce                     ! index of lowest ice layer
+ ! input: state and diagnostic variables
+ real(dp),intent(in)           :: scalarMatricHead          ! matric head in the upper-most soil layer (m)
+ real(dp),intent(in)           :: scalarVolFracLiq          ! volumetric liquid water content in the upper-most soil layer (-)
+ real(dp),intent(in)           :: mLayerVolFracLiq(:)       ! volumetric liquid water content in each soil layer (-)
+ real(dp),intent(in)           :: mLayerVolFracIce(:)       ! volumetric ice content in each soil layer (-)
+ ! input: depth of upper-most soil layer (m)
+ real(dp),intent(in)           :: mLayerDepth(:)            ! depth of upper-most soil layer (m)
+ real(dp),intent(in)           :: iLayerHeight(0:)          ! height at the interface of each layer (m)
+ ! input: diriclet boundary conditions
+ real(dp),intent(in)           :: upperBoundHead            ! upper boundary condition for matric head (m)
+ real(dp),intent(in)           :: upperBoundTheta           ! upper boundary condition for volumetric liquid water content (-)
+ ! input: flux at the upper boundary
+ real(dp),intent(in)           :: scalarRainPlusMelt        ! rain plus melt, used as input to the soil zone before computing surface runoff (m s-1)
+ ! input: transmittance
+ real(dp),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
+ real(dp),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+ real(dp),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
+ ! input: soil parameters
+ real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+ real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+ real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+ real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
+ real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+ real(dp),intent(in)           :: qSurfScale                ! scaling factor in the surface runoff parameterization (-)
+ real(dp),intent(in)           :: zScale_TOPMODEL           ! scaling factor used to describe decrease in hydraulic conductivity with depth (m)
+ real(dp),intent(in)           :: rootingDepth              ! rooting depth (m)
+ real(dp),intent(in)           :: wettingFrontSuction       ! Green-Ampt wetting front suction (m)
+ real(dp),intent(in)           :: soilIceScale              ! soil ice scaling factor in Gamma distribution used to define frozen area (m)
+ real(dp),intent(in)           :: soilIceCV                 ! soil ice CV in Gamma distribution used to define frozen area (-)
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! input-output: hydraulic conductivity and diffusivity at the surface
+ ! NOTE: intent(inout) because infiltration may only be computed for the first iteration
+ real(dp),intent(inout)        :: surfaceHydCond            ! hydraulic conductivity (m s-1)
+ real(dp),intent(inout)        :: surfaceDiffuse            ! hydraulic diffusivity at the surface (m
+ ! output: surface runoff and infiltration flux (m s-1)
+ real(dp),intent(inout)        :: xMaxInfilRate             ! maximum infiltration rate (m s-1)
+ real(dp),intent(inout)        :: scalarInfilArea           ! fraction of unfrozen area where water can infiltrate (-)
+ real(dp),intent(inout)        :: scalarFrozenArea          ! fraction of area that is considered impermeable due to soil ice (-)
+ real(dp),intent(out)          :: scalarSurfaceRunoff       ! surface runoff (m s-1)
+ real(dp),intent(out)          :: scalarSurfaceInfiltration ! surface infiltration (m s-1)
+ ! output: deriavtives in surface infiltration w.r.t. volumetric liquid water (m s-1) and matric head (s-1) in the upper-most soil layer
+ real(dp),intent(out)          :: dq_dHydState              ! derivative in surface infiltration w.r.t. state variable in the upper-most soil layer (m s-1 or s-1)
+ real(dp),intent(out)          :: dq_dNrgState              ! derivative in surface infiltration w.r.t. energy state variable in the upper-most soil layer (m s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)      :: err                       ! error code
+ character(*),intent(out)      :: message                   ! error message
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! local variables
+ ! (general)
+ integer(i4b)                  :: iLayer                    ! index of soil layer
+ ! (head boundary condition)
+ real(dp)                      :: cFlux                     ! capillary flux (m s-1)
+ real(dp)                      :: dNum                      ! numerical derivative
+ ! (simplified Green-Ampt infiltration)
+ real(dp)                      :: rootZoneLiq               ! depth of liquid water in the root zone (m)
+ real(dp)                      :: rootZoneIce               ! depth of ice in the root zone (m)
+ real(dp)                      :: availCapacity             ! available storage capacity in the root zone (m)
+ real(dp)                      :: depthWettingFront         ! depth to the wetting front (m)
+ real(dp)                      :: hydCondWettingFront       ! hydraulic conductivity at the wetting front (m s-1)
+ ! (saturated area associated with variable storage capacity)
+ real(dp)                      :: fracCap                   ! fraction of pore space filled with liquid water and ice (-)
+ real(dp)                      :: fInfRaw                   ! infiltrating area before imposing solution constraints (-)
+ real(dp),parameter            :: maxFracCap=0.995_dp       ! maximum fraction capacity -- used to avoid numerical problems associated with an enormous derivative
+ real(dp),parameter            :: scaleFactor=0.000001_dp   ! scale factor for the smoothing function (-)
+ real(dp),parameter            :: qSurfScaleMax=1000._dp    ! maximum surface runoff scaling factor (-)
+ ! (fraction of impermeable area associated with frozen ground)
+ real(dp)                      :: alpha                     ! shape parameter in the Gamma distribution
+ real(dp)                      :: xLimg                     ! upper limit of the integral
+ ! initialize error control
+ err=0; message="surfaceFlx/"
+
+ ! compute derivative in the energy state
+ ! NOTE: revisit the need to do this
+ dq_dNrgState = 0._dp
+
+ ! *****
+ ! compute the surface flux and its derivative
+ select case(bc_upper)
+
+  ! *****
+  ! head condition
+  case(prescribedHead)
+
+   ! surface runoff iz zero for the head condition
+   scalarSurfaceRunoff = 0._dp
+
+   ! compute transmission and the capillary flux
+   select case(ixRichards)  ! (form of Richards' equation)
+    case(moisture)
+     ! compute the hydraulic conductivity and diffusivity at the boundary
+     surfaceHydCond = hydCond_liq(upperBoundTheta,surfaceSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
+     surfaceDiffuse = dPsi_dTheta(upperBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * surfaceHydCond
+     ! compute the capillary flux
+     cflux = -surfaceDiffuse*(scalarVolFracLiq - upperBoundTheta) / (mLayerDepth(1)*0.5_dp)
+    case(mixdform)
+     ! compute the hydraulic conductivity and diffusivity at the boundary
+     surfaceHydCond = hydCond_psi(upperBoundHead,surfaceSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
+     surfaceDiffuse = realMissing
+     ! compute the capillary flux
+     cflux = -surfaceHydCond*(scalarMatricHead - upperBoundHead) / (mLayerDepth(1)*0.5_dp)
+    case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+   end select  ! (form of Richards' eqn)
+   ! compute the total flux
+   scalarSurfaceInfiltration = cflux + surfaceHydCond
+   ! compute the derivative
+   if(deriv_desired)then
+    ! compute the hydrology derivative
+    select case(ixRichards)  ! (form of Richards' equation)
+     case(moisture); dq_dHydState = -surfaceDiffuse/(mLayerDepth(1)/2._dp)
+     case(mixdform); dq_dHydState = -surfaceHydCond/(mLayerDepth(1)/2._dp)
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select
+    ! compute the energy derivative
+    dq_dNrgState = -(dHydCond_dTemp/2._dp)*(scalarMatricHead - upperBoundHead)/(mLayerDepth(1)*0.5_dp) + dHydCond_dTemp/2._dp
+    ! compute the numerical derivative
+    !cflux = -surfaceHydCond*((scalarMatricHead+dx) - upperBoundHead) / (mLayerDepth(1)*0.5_dp)
+    !surfaceInfiltration1 = cflux + surfaceHydCond
+    !dNum  = (surfaceInfiltration1 - scalarSurfaceInfiltration)/dx
+   else
+    dq_dHydState = 0._dp
+    dNum         = 0._dp
+   end if
+   !write(*,'(a,1x,10(e30.20,1x))') 'scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum = ', &
+   !                                 scalarMatricHead, scalarSurfaceInfiltration, dq_dHydState, dNum
+
+  ! *****
+  ! flux condition
+  case(liquidFlux)
+
+   ! force infiltration to be constant over the iterations
+   if(doInfiltration)then
+
+    ! define the storage in the root zone (m)
+    rootZoneLiq = 0._dp
+    rootZoneIce = 0._dp
+    ! (process layers where the roots extend to the bottom of the layer)
+    if(nRoots > 1)then
+     do iLayer=1,nRoots-1
+      rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(iLayer)*mLayerDepth(iLayer)
+      rootZoneIce = rootZoneIce + mLayerVolFracIce(iLayer)*mLayerDepth(iLayer)
+     end do
+    end if
+    ! (process layers where the roots end in the current layer)
+    rootZoneLiq = rootZoneLiq + mLayerVolFracLiq(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+    rootZoneIce = rootZoneIce + mLayerVolFracIce(nRoots)*(rootingDepth - iLayerHeight(nRoots-1))
+
+    ! define available capacity to hold water (m)
+    availCapacity = theta_sat*rootingDepth - rootZoneIce
+    if(rootZoneLiq > availCapacity+verySmall)then
+     message=trim(message)//'liquid water in the root zone exceeds capacity'
+     err=20; return
+    end if
+
+    ! define the depth to the wetting front (m)
+    depthWettingFront = (rootZoneLiq/availCapacity)*rootingDepth
+
+    ! define the hydraulic conductivity at depth=depthWettingFront (m s-1)
+    hydCondWettingFront =  surfaceSatHydCond * ( (1._dp - depthWettingFront/sum(mLayerDepth))**(zScale_TOPMODEL - 1._dp) )
+
+    ! define the maximum infiltration rate (m s-1)
+    xMaxInfilRate = hydCondWettingFront*( (wettingFrontSuction + depthWettingFront)/depthWettingFront )  ! maximum infiltration rate (m s-1)
+    !write(*,'(a,1x,f9.3,1x,10(e20.10,1x))') 'depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate = ', depthWettingFront, surfaceSatHydCond, hydCondWettingFront, xMaxInfilRate
+
+    ! define the infiltrating area for the non-frozen part of the cell/basin
+    if(qSurfScale < qSurfScaleMax)then
+     fracCap         = rootZoneLiq/(maxFracCap*availCapacity)                              ! fraction of available root zone filled with water
+     fInfRaw         = 1._dp - exp(-qSurfScale*(1._dp - fracCap))                          ! infiltrating area -- allowed to violate solution constraints
+     scalarInfilArea = min(0.5_dp*(fInfRaw + sqrt(fInfRaw**2._dp + scaleFactor)), 1._dp)   ! infiltrating area -- constrained
+    else
+     scalarInfilArea = 1._dp
+    endif
+
+    ! check to ensure we are not infiltrating into a fully saturated column
+    if(ixIce<nRoots)then
+     if(sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) > 0.9999_dp*theta_sat*sum(mLayerDepth(ixIce+1:nRoots))) scalarInfilArea=0._dp
+     !print*, 'ixIce, nRoots, scalarInfilArea = ', ixIce, nRoots, scalarInfilArea
+     !print*, 'sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots)) = ', sum(mLayerVolFracLiq(ixIce+1:nRoots)*mLayerDepth(ixIce+1:nRoots))
+     !print*, 'theta_sat*sum(mLayerDepth(ixIce+1:nRoots)) = ', theta_sat*sum(mLayerDepth(ixIce+1:nRoots))
+    endif
+
+    ! define the impermeable area due to frozen ground
+    if(rootZoneIce > tiny(rootZoneIce))then  ! (avoid divide by zero)
+     alpha            = 1._dp/(soilIceCV**2._dp)        ! shape parameter in the Gamma distribution
+     xLimg            = alpha*soilIceScale/rootZoneIce  ! upper limit of the integral
+     !scalarFrozenArea = 1._dp - gammp(alpha,xLimg)      ! fraction of frozen area
+     scalarFrozenArea = 0._dp
+    else
+     scalarFrozenArea = 0._dp
+    end if
+    !print*, 'scalarFrozenArea, rootZoneIce = ', scalarFrozenArea, rootZoneIce
+
+   end if ! (if desire to compute infiltration)
+
+   ! compute infiltration (m s-1)
+   scalarSurfaceInfiltration = (1._dp - scalarFrozenArea)*scalarInfilArea*min(scalarRainPlusMelt,xMaxInfilRate)
+
+   ! compute surface runoff (m s-1)
+   scalarSurfaceRunoff = scalarRainPlusMelt - scalarSurfaceInfiltration
+   !print*, 'scalarRainPlusMelt, xMaxInfilRate = ', scalarRainPlusMelt, xMaxInfilRate
+   !print*, 'scalarSurfaceInfiltration, scalarSurfaceRunoff = ', scalarSurfaceInfiltration, scalarSurfaceRunoff
+   !print*, '(1._dp - scalarFrozenArea), (1._dp - scalarFrozenArea)*scalarInfilArea = ', (1._dp - scalarFrozenArea), (1._dp - scalarFrozenArea)*scalarInfilArea
+
+   ! set surface hydraulic conductivity and diffusivity to missing (not used for flux condition)
+   surfaceHydCond = realMissing
+   surfaceDiffuse = realMissing
+
+   ! set numerical derivative to zero
+   ! NOTE 1: Depends on multiple soil layers and does not jive with the current tridiagonal matrix
+   ! NOTE 2: Need to define the derivative at every call, because intent(out)
+   dq_dHydState = 0._dp
+   dq_dNrgState = 0._dp
+
+  ! ***** error check
+  case default; err=20; message=trim(message)//'unknown upper boundary condition for soil hydrology'; return
+
+ end select  ! (type of upper boundary condition)
+
+ end subroutine surfaceFlx
+
+
+ ! ***************************************************************************************************************
+ ! private subroutine iLayerFlux: compute the fluxes and derivatives at layer interfaces
+ ! ***************************************************************************************************************
+ subroutine iLayerFlux(&
+                       ! input: model control
+                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                       ! input: state variables (adjacent layers)
+                       nodeMatricHeadTrial,       & ! intent(in): matric head at the soil nodes (m)
+                       nodeVolFracLiqTrial,       & ! intent(in): volumetric liquid water content at the soil nodes (-)
+                       ! input: model coordinate variables (adjacent layers)
+                       nodeHeight,                & ! intent(in): height of the soil nodes (m)
+                       ! input: temperature derivatives
+                       dPsiLiq_dTemp,             & ! intent(in): derivative in liquid water matric potential w.r.t. temperature (m K-1)
+                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       ! input: transmittance (adjacent layers)
+                       nodeHydCondTrial,          & ! intent(in): hydraulic conductivity at the soil nodes (m s-1)
+                       nodeDiffuseTrial,          & ! intent(in): hydraulic diffusivity at the soil nodes (m2 s-1)
+                       ! input: transmittance derivatives (adjacent layers)
+                       dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in volumetric liquid water content (m s-1)
+                       dDiffuse_dVolLiq,          & ! intent(in): derivative in hydraulic diffusivity w.r.t. change in volumetric liquid water content (m2 s-1)
+                       dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. change in matric head (s-1)
+                       ! output: tranmsmittance at the layer interface (scalars)
+                       iLayerHydCond,             & ! intent(out): hydraulic conductivity at the interface between layers (m s-1)
+                       iLayerDiffuse,             & ! intent(out): hydraulic diffusivity at the interface between layers (m2 s-1)
+                       ! output: vertical flux at the layer interface (scalars)
+                       iLayerLiqFluxSoil,         & ! intent(out): vertical flux of liquid water at the layer interface (m s-1)
+                       ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+                       dq_dHydStateAbove,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+                       dq_dHydStateBelow,         & ! intent(out): derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+                       ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+                       dq_dNrgStateAbove,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+                       dq_dNrgStateBelow,         & ! intent(out): derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+                       ! output: error control
+                       err,message)                 ! intent(out): error control
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! input: model control
+ logical(lgt),intent(in)       :: deriv_desired               ! flag indicating if derivatives are desired
+ integer(i4b),intent(in)       :: ixRichards                  ! index defining the option for Richards' equation (moisture or mixdform)
+ ! input: state variables
+ real(dp),intent(in)           :: nodeMatricHeadTrial(:)      ! matric head at the soil nodes (m)
+ real(dp),intent(in)           :: nodeVolFracLiqTrial(:)      ! volumetric fraction of liquid water at the soil nodes (-)
+ ! input: model coordinate variables
+ real(dp),intent(in)           :: nodeHeight(:)               ! height at the mid-point of the lower layer (m)
+ ! input: temperature derivatives
+ real(dp),intent(in)           :: dPsiLiq_dTemp(:)            ! derivative in liquid water matric potential w.r.t. temperature (m K-1)
+ real(dp),intent(in)           :: dHydCond_dTemp(:)           ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+ ! input: transmittance
+ real(dp),intent(in)           :: nodeHydCondTrial(:)         ! hydraulic conductivity at layer mid-points (m s-1)
+ real(dp),intent(in)           :: nodeDiffuseTrial(:)         ! diffusivity at layer mid-points (m2 s-1)
+ ! input: transmittance derivatives
+ real(dp),intent(in)           :: dHydCond_dVolLiq(:)         ! derivative in hydraulic conductivity w.r.t volumetric liquid water content (m s-1)
+ real(dp),intent(in)           :: dDiffuse_dVolLiq(:)         ! derivative in hydraulic diffusivity w.r.t volumetric liquid water content (m2 s-1)
+ real(dp),intent(in)           :: dHydCond_dMatric(:)         ! derivative in hydraulic conductivity w.r.t matric head (m s-1)
+ ! output: tranmsmittance at the layer interface (scalars)
+ real(dp),intent(out)          :: iLayerHydCond               ! hydraulic conductivity at the interface between layers (m s-1)
+ real(dp),intent(out)          :: iLayerDiffuse               ! hydraulic diffusivity at the interface between layers (m2 s-1)
+ ! output: vertical flux at the layer interface (scalars)
+ real(dp),intent(out)          :: iLayerLiqFluxSoil           ! vertical flux of liquid water at the layer interface (m s-1)
+ ! output: derivatives in fluxes w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below (m s-1 or s-1)
+ real(dp),intent(out)          :: dq_dHydStateAbove           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer above (m s-1 or s-1)
+ real(dp),intent(out)          :: dq_dHydStateBelow           ! derivatives in the flux w.r.t. matric head or volumetric lquid water in the layer below (m s-1 or s-1)
+ ! output: derivatives in fluxes w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (m s-1 K-1)
+ real(dp),intent(out)          :: dq_dNrgStateAbove           ! derivatives in the flux w.r.t. temperature in the layer above (m s-1 K-1)
+ real(dp),intent(out)          :: dq_dNrgStateBelow           ! derivatives in the flux w.r.t. temperature in the layer below (m s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)      :: err                         ! error code
+ character(*),intent(out)      :: message                     ! error message
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! local variables (named variables to provide index of 2-element vectors)
+ integer(i4b),parameter        :: ixUpper=1                   ! index of upper node in the 2-element vectors
+ integer(i4b),parameter        :: ixLower=2                   ! index of lower node in the 2-element vectors
+ logical(lgt),parameter        :: useGeometric=.false.        ! switch between the arithmetic and geometric mean
+ ! local variables (Darcy flux)
+ real(dp)                      :: dPsi                        ! spatial difference in matric head (m)
+ real(dp)                      :: dLiq                        ! spatial difference in volumetric liquid water (-)
+ real(dp)                      :: dz                          ! spatial difference in layer mid-points (m)
+ real(dp)                      :: cflux                       ! capillary flux (m s-1)
+ ! local variables (derivative in Darcy's flux)
+ real(dp)                      :: dHydCondIface_dVolLiqAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer above
+ real(dp)                      :: dHydCondIface_dVolLiqBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. volumetric liquid water content in layer below
+ real(dp)                      :: dDiffuseIface_dVolLiqAbove  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer above
+ real(dp)                      :: dDiffuseIface_dVolLiqBelow  ! derivative in hydraulic diffusivity at layer interface w.r.t. volumetric liquid water content in layer below
+ real(dp)                      :: dHydCondIface_dMatricAbove  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer above
+ real(dp)                      :: dHydCondIface_dMatricBelow  ! derivative in hydraulic conductivity at layer interface w.r.t. matric head in layer below
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! initialize error control
+ err=0; message="iLayerFlux/"
+
+ ! *****
+ ! compute the vertical flux of liquid water
+ ! compute the hydraulic conductivity at the interface
+ if(useGeometric)then
+  iLayerHydCond   = (nodeHydCondTrial(ixLower)   * nodeHydCondTrial(ixUpper))**0.5_dp
+ else
+  iLayerHydCond   = (nodeHydCondTrial(ixLower)   + nodeHydCondTrial(ixUpper))*0.5_dp
+ end if
+ !write(*,'(a,1x,5(e20.10,1x))') 'in iLayerFlux: iLayerHydCond, iLayerHydCondMP = ', iLayerHydCond, iLayerHydCondMP
+ ! compute the height difference between nodes
+ dz = nodeHeight(ixLower) - nodeHeight(ixUpper)
+ ! compute the capillary flux
+ select case(ixRichards)  ! (form of Richards' equation)
+  case(moisture)
+   iLayerDiffuse = (nodeDiffuseTrial(ixLower) * nodeDiffuseTrial(ixUpper))**0.5_dp
+   dLiq          = nodeVolFracLiqTrial(ixLower) - nodeVolFracLiqTrial(ixUpper)
+   cflux         = -iLayerDiffuse * dLiq/dz
+  case(mixdform)
+   iLayerDiffuse = realMissing
+   dPsi          = nodeMatricHeadTrial(ixLower) - nodeMatricHeadTrial(ixUpper)
+   cflux         = -iLayerHydCond * dPsi/dz
+  case default; err=10; message=trim(message)//"unable to identify option for Richards' equation"; return
+ end select
+ ! compute the total flux (add gravity flux, positive downwards)
+ iLayerLiqFluxSoil = cflux + iLayerHydCond
+ !write(*,'(a,1x,10(e20.10,1x))') 'iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond = ', &
+ !                                 iLayerLiqFluxSoil, dPsi, dz, cflux, iLayerHydCond
+
+ ! ** compute the derivatives
+ if(deriv_desired)then
+  select case(ixRichards)  ! (form of Richards' equation)
+   case(moisture)
+    ! still need to implement arithmetric mean for the moisture-based form
+    if(.not.useGeometric)then
+     message=trim(message)//'only currently implemented for geometric mean -- change local flag'
+     err=20; return
+    end if
+    ! derivatives in hydraulic conductivity at the layer interface (m s-1)
+    dHydCondIface_dVolLiqAbove = dHydCond_dVolLiq(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_dp/max(iLayerHydCond,verySmall)
+    dHydCondIface_dVolLiqBelow = dHydCond_dVolLiq(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_dp/max(iLayerHydCond,verySmall)
+    ! derivatives in hydraulic diffusivity at the layer interface (m2 s-1)
+    dDiffuseIface_dVolLiqAbove = dDiffuse_dVolLiq(ixUpper)*nodeDiffuseTrial(ixLower) * 0.5_dp/max(iLayerDiffuse,verySmall)
+    dDiffuseIface_dVolLiqBelow = dDiffuse_dVolLiq(ixLower)*nodeDiffuseTrial(ixUpper) * 0.5_dp/max(iLayerDiffuse,verySmall)
+    ! derivatives in the flux w.r.t. volumetric liquid water content
+    dq_dHydStateAbove = -dDiffuseIface_dVolLiqAbove*dLiq/dz + iLayerDiffuse/dz + dHydCondIface_dVolLiqAbove
+    dq_dHydStateBelow = -dDiffuseIface_dVolLiqBelow*dLiq/dz - iLayerDiffuse/dz + dHydCondIface_dVolLiqBelow
+   case(mixdform)
+    ! derivatives in hydraulic conductivity
+    if(useGeometric)then
+     dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)*nodeHydCondTrial(ixLower) * 0.5_dp/max(iLayerHydCond,verySmall)
+     dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)*nodeHydCondTrial(ixUpper) * 0.5_dp/max(iLayerHydCond,verySmall)
+    else
+     dHydCondIface_dMatricAbove = dHydCond_dMatric(ixUpper)/2._dp
+     dHydCondIface_dMatricBelow = dHydCond_dMatric(ixLower)/2._dp
+    end if
+    ! derivatives in the flux w.r.t. matric head
+    dq_dHydStateAbove = -dHydCondIface_dMatricAbove*dPsi/dz + iLayerHydCond/dz + dHydCondIface_dMatricAbove
+    dq_dHydStateBelow = -dHydCondIface_dMatricBelow*dPsi/dz - iLayerHydCond/dz + dHydCondIface_dMatricBelow
+    ! derivative in the flux w.r.t. temperature
+    dq_dNrgStateAbove = -(dHydCond_dTemp(ixUpper)/2._dp)*dPsi/dz + iLayerHydCond*dPsiLiq_dTemp(ixUpper)/dz + dHydCond_dTemp(ixUpper)/2._dp
+    dq_dNrgStateBelow = -(dHydCond_dTemp(ixLower)/2._dp)*dPsi/dz - iLayerHydCond*dPsiLiq_dTemp(ixLower)/dz + dHydCond_dTemp(ixLower)/2._dp
+   case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+  end select
+ else
+  dq_dHydStateAbove = realMissing
+  dq_dHydStateBelow = realMissing
+ end if
+
+ end subroutine iLayerFlux
+
+
+ ! ***************************************************************************************************************
+ ! private subroutine qDrainFlux: compute the drainage flux from the bottom of the soil profile and its derivative
+ ! ***************************************************************************************************************
+ subroutine qDrainFlux(&
+                       ! input: model control
+                       deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                       ixRichards,                & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                       bc_lower,                  & ! intent(in): index defining the type of boundary conditions
+                       ! input: state variables
+                       nodeMatricHead,            & ! intent(in): matric head in the lowest unsaturated node (m)
+                       nodeVolFracLiq,            & ! intent(in): volumetric liquid water content the lowest unsaturated node (-)
+                       ! input: model coordinate variables
+                       nodeDepth,                 & ! intent(in): depth of the lowest unsaturated soil layer (m)
+                       nodeHeight,                & ! intent(in): height of the lowest unsaturated soil node (m)
+                       ! input: boundary conditions
+                       lowerBoundHead,            & ! intent(in): lower boundary condition (m)
+                       lowerBoundTheta,           & ! intent(in): lower boundary condition (-)
+                       ! input: derivative in soil water characteristix
+                       node__dPsi_dTheta,         & ! intent(in): derivative of the soil moisture characteristic w.r.t. theta (m)
+                       ! input: transmittance
+                       surfaceSatHydCond,         & ! intent(in): saturated hydraulic conductivity at the surface (m s-1)
+                       bottomSatHydCond,          & ! intent(in): saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+                       nodeHydCond,               & ! intent(in): hydraulic conductivity at the node itself (m s-1)
+                       iceImpedeFac,              & ! intent(in): ice impedence factor in the lower-most soil layer (-)
+                       ! input: transmittance derivatives
+                       dHydCond_dVolLiq,          & ! intent(in): derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+                       dHydCond_dMatric,          & ! intent(in): derivative in hydraulic conductivity w.r.t. matric head (s-1)
+                       dHydCond_dTemp,            & ! intent(in): derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+                       ! input: soil parameters
+                       vGn_alpha,                 & ! intent(in): van Genutchen "alpha" parameter (m-1)
+                       vGn_n,                     & ! intent(in): van Genutchen "n" parameter (-)
+                       VGn_m,                     & ! intent(in): van Genutchen "m" parameter (-)
+                       theta_sat,                 & ! intent(in): soil porosity (-)
+                       theta_res,                 & ! intent(in): soil residual volumetric water content (-)
+                       kAnisotropic,              & ! intent(in): anisotropy factor for lateral hydraulic conductivity (-)
+                       zScale_TOPMODEL,           & ! intent(in): TOPMODEL scaling factor (m)
+                       ! output: hydraulic conductivity and diffusivity at the surface
+                       bottomHydCond,             & ! intent(out): hydraulic conductivity at the bottom of the unsatuarted zone (m s-1)
+                       bottomDiffuse,             & ! intent(out): hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+                       ! output: drainage flux from the bottom of the soil profile
+                       scalarDrainage,            & ! intent(out): drainage flux from the bottom of the soil profile (m s-1)
+                       ! output: derivatives in drainage flux
+                       dq_dHydStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in hydrology state variable in lowest unsaturated node (m s-1 or s-1)
+                       dq_dNrgStateUnsat,         & ! intent(out): change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
+                       ! output: error control
+                       err,message)                 ! intent(out): error control
+ USE soil_utils_module,only:volFracLiq      ! compute volumetric fraction of liquid water as a function of matric head (-)
+ USE soil_utils_module,only:matricHead      ! compute matric head as a function of volumetric fraction of liquid water (m)
+ USE soil_utils_module,only:hydCond_psi     ! compute hydraulic conductivity as a function of matric head (m s-1)
+ USE soil_utils_module,only:hydCond_liq     ! compute hydraulic conductivity as a function of volumetric liquid water content (m s-1)
+ USE soil_utils_module,only:dPsi_dTheta     ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+ ! compute infiltraton at the surface and its derivative w.r.t. mass in the upper soil layer
+ implicit none
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! input: model control
+ logical(lgt),intent(in)       :: deriv_desired             ! flag to indicate if derivatives are desired
+ integer(i4b),intent(in)       :: ixRichards                ! index defining the option for Richards' equation (moisture or mixdform)
+ integer(i4b),intent(in)       :: bc_lower                  ! index defining the type of boundary conditions
+ ! input: state and diagnostic variables
+ real(dp),intent(in)           :: nodeMatricHead            ! matric head in the lowest unsaturated node (m)
+ real(dp),intent(in)           :: nodeVolFracLiq            ! volumetric liquid water content in the lowest unsaturated node (-)
+ ! input: model coordinate variables
+ real(dp),intent(in)           :: nodeDepth                 ! depth of the lowest unsaturated soil layer (m)
+ real(dp),intent(in)           :: nodeHeight                ! height of the lowest unsaturated soil node (m)
+ ! input: diriclet boundary conditions
+ real(dp),intent(in)           :: lowerBoundHead            ! lower boundary condition for matric head (m)
+ real(dp),intent(in)           :: lowerBoundTheta           ! lower boundary condition for volumetric liquid water content (-)
+ ! input: derivative in soil water characteristix
+ real(dp),intent(in)           :: node__dPsi_dTheta         ! derivative of the soil moisture characteristic w.r.t. theta (m)
+ ! input: transmittance
+ real(dp),intent(in)           :: surfaceSatHydCond         ! saturated hydraulic conductivity at the surface (m s-1)
+ real(dp),intent(in)           :: bottomSatHydCond          ! saturated hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+ real(dp),intent(in)           :: nodeHydCond               ! hydraulic conductivity at the node itself (m s-1)
+ real(dp),intent(in)           :: iceImpedeFac              ! ice impedence factor in the upper-most soil layer (-)
+ ! input: transmittance derivatives
+ real(dp),intent(in)           :: dHydCond_dVolLiq          ! derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+ real(dp),intent(in)           :: dHydCond_dMatric          ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
+ real(dp),intent(in)           :: dHydCond_dTemp            ! derivative in hydraulic conductivity w.r.t temperature (m s-1 K-1)
+ ! input: soil parameters
+ real(dp),intent(in)           :: vGn_alpha                 ! van Genutchen "alpha" parameter (m-1)
+ real(dp),intent(in)           :: vGn_n                     ! van Genutchen "n" parameter (-)
+ real(dp),intent(in)           :: vGn_m                     ! van Genutchen "m" parameter (-)
+ real(dp),intent(in)           :: theta_sat                 ! soil porosity (-)
+ real(dp),intent(in)           :: theta_res                 ! soil residual volumetric water content (-)
+ real(dp),intent(in)           :: kAnisotropic              ! anisotropy factor for lateral hydraulic conductivity (-)
+ real(dp),intent(in)           :: zScale_TOPMODEL           ! scale factor for TOPMODEL-ish baseflow parameterization (m)
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! output: hydraulic conductivity at the bottom of the unsaturated zone
+ real(dp),intent(out)          :: bottomHydCond             ! hydraulic conductivity at the bottom of the unsaturated zone (m s-1)
+ real(dp),intent(out)          :: bottomDiffuse             ! hydraulic diffusivity at the bottom of the unsatuarted zone (m2 s-1)
+ ! output: drainage flux from the bottom of the soil profile
+ real(dp),intent(out)          :: scalarDrainage            ! drainage flux from the bottom of the soil profile (m s-1)
+ ! output: derivatives in drainage flux
+ real(dp),intent(out)          :: dq_dHydStateUnsat         ! change in drainage flux w.r.t. change in state variable in lowest unsaturated node (m s-1 or s-1)
+ real(dp),intent(out)          :: dq_dNrgStateUnsat         ! change in drainage flux w.r.t. change in energy state variable in lowest unsaturated node (m s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)      :: err                       ! error code
+ character(*),intent(out)      :: message                   ! error message
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! local variables
+ real(dp)                      :: zWater                    ! effective water table depth (m)
+ real(dp)                      :: nodePsi                   ! matric head in the lowest unsaturated node (m)
+ real(dp)                      :: cflux                     ! capillary flux (m s-1)
+ ! -----------------------------------------------------------------------------------------------------------------------------
+ ! initialize error control
+ err=0; message="qDrainFlux/"
+
+ ! determine lower boundary condition
+ select case(bc_lower)
+
+  ! ---------------------------------------------------------------------------------------------
+  ! * prescribed head
+  ! ---------------------------------------------------------------------------------------------
+  case(prescribedHead)
+
+   ! compute fluxes
+   select case(ixRichards)  ! (moisture-based form of Richards' equation)
+    case(moisture)
+     ! compute the hydraulic conductivity and diffusivity at the boundary
+     bottomHydCond = hydCond_liq(lowerBoundTheta,bottomSatHydCond,theta_res,theta_sat,vGn_m) * iceImpedeFac
+     bottomDiffuse = dPsi_dTheta(lowerBoundTheta,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m) * bottomHydCond
+     ! compute the capillary flux
+     cflux = -bottomDiffuse*(lowerBoundTheta - nodeVolFracLiq) / (nodeDepth*0.5_dp)
+    case(mixdform)
+     ! compute the hydraulic conductivity and diffusivity at the boundary
+     bottomHydCond = hydCond_psi(lowerBoundHead,bottomSatHydCond,vGn_alpha,vGn_n,vGn_m) * iceImpedeFac
+     bottomDiffuse = realMissing
+     ! compute the capillary flux
+     cflux = -bottomHydCond*(lowerBoundHead  - nodeMatricHead) / (nodeDepth*0.5_dp)
+    case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+   end select  ! (form of Richards' eqn)
+   scalarDrainage = cflux + bottomHydCond
+
+   ! compute derivatives
+   if(deriv_desired)then
+    ! hydrology derivatives
+    select case(ixRichards)  ! (form of Richards' equation)
+     case(moisture); dq_dHydStateUnsat = bottomDiffuse/(nodeDepth/2._dp)
+     case(mixdform); dq_dHydStateUnsat = bottomHydCond/(nodeDepth/2._dp)
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select
+    ! energy derivatives
+    dq_dNrgStateUnsat = -(dHydCond_dTemp/2._dp)*(lowerBoundHead  - nodeMatricHead)/(nodeDepth*0.5_dp) + dHydCond_dTemp/2._dp
+   else     ! (do not desire derivatives)
+    dq_dHydStateUnsat = realMissing
+    dq_dNrgStateUnsat = realMissing
+   end if
+
+  ! ---------------------------------------------------------------------------------------------
+  ! * function of matric head in the bottom layer
+  ! ---------------------------------------------------------------------------------------------
+  case(funcBottomHead)
+
+   ! compute fluxes
+   select case(ixRichards)
+    case(moisture); nodePsi = matricHead(nodeVolFracLiq,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+    case(mixdform); nodePsi = nodeMatricHead
+   end select
+   zWater = nodeHeight - nodePsi
+   scalarDrainage = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)
+
+   ! compute derivatives
+   if(deriv_desired)then
+    ! hydrology derivatives
+    select case(ixRichards)  ! (form of Richards' equation)
+     case(moisture); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * node__dPsi_dTheta*exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
+     case(mixdform); dq_dHydStateUnsat = kAnisotropic*surfaceSatHydCond * exp(-zWater/zScale_TOPMODEL)/zScale_TOPMODEL
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select
+    ! energy derivatives
+    err=20; message=trim(message)//"not yet implemented energy derivatives"; return
+   else     ! (do not desire derivatives)
+    dq_dHydStateUnsat = realMissing
+    dq_dNrgStateUnsat = realMissing
+   end if
+
+  ! ---------------------------------------------------------------------------------------------
+  ! * free drainage
+  ! ---------------------------------------------------------------------------------------------
+  case(freeDrainage)
+
+   ! compute flux
+   scalarDrainage = nodeHydCond*kAnisotropic
+
+   ! compute derivatives
+   if(deriv_desired)then
+    ! hydrology derivatives
+    select case(ixRichards)  ! (form of Richards' equation)
+     case(moisture); dq_dHydStateUnsat = dHydCond_dVolLiq*kAnisotropic
+     case(mixdform); dq_dHydStateUnsat = dHydCond_dMatric*kAnisotropic
+     case default; err=10; message=trim(message)//"unknown form of Richards' equation"; return
+    end select
+    ! energy derivatives
+    dq_dNrgStateUnsat = dHydCond_dTemp*kAnisotropic
+   else     ! (do not desire derivatives)
+    dq_dHydStateUnsat = realMissing
+    dq_dNrgStateUnsat = realMissing
+   end if
+
+
+  ! ---------------------------------------------------------------------------------------------
+  ! * zero flux
+  ! ---------------------------------------------------------------------------------------------
+  case(zeroFlux)
+   scalarDrainage = 0._dp
+   if(deriv_desired)then
+    dq_dHydStateUnsat = 0._dp
+    dq_dNrgStateUnsat = 0._dp
+   else
+    dq_dHydStateUnsat = realMissing
+    dq_dNrgStateUnsat = realMissing
+   end if
+
+  ! ---------------------------------------------------------------------------------------------
+  ! * error check
+  ! ---------------------------------------------------------------------------------------------
+  case default; err=20; message=trim(message)//'unknown lower boundary condition for soil hydrology'; return
+
+ end select ! (type of boundary condition)
+
+ end subroutine qDrainFlux
+
+
+ ! *******************************************************************************************************************************************************************************
+ ! *******************************************************************************************************************************************************************************
+
+
+end module soilLiqFlx_module
diff --git a/build/source/engine/ssdNrgFlux.f90 b/build/source/engine/ssdNrgFlux.f90
old mode 100755
new mode 100644
index 25fc68e..b9c7918
--- a/build/source/engine/ssdNrgFlux.f90
+++ b/build/source/engine/ssdNrgFlux.f90
@@ -20,288 +20,965 @@
 
 module ssdNrgFlux_module
 
-! data types
-USE nrtype
-
-! data types
-USE data_types,only:var_d           ! x%var(:)       (dp)
-USE data_types,only:var_dlength     ! x%var(:)%dat   (dp)
-USE data_types,only:var_ilength     ! x%var(:)%dat   (i4b)
-
-! physical constants
-USE multiconst,only:&
-                    sb,          & ! Stefan Boltzman constant      (W m-2 K-4)
-                    Em_Sno,      & ! emissivity of snow            (-)
-                    Cp_air,      & ! specific heat of air          (J kg-1 K-1)
-                    Cp_water,    & ! specifric heat of water       (J kg-1 K-1)
-                    LH_fus,      & ! latent heat of fusion         (J kg-1)
-                    LH_vap,      & ! latent heat of vaporization   (J kg-1)
-                    LH_sub,      & ! latent heat of sublimation    (J kg-1)
-                    gravity,     & ! gravitational acceleteration  (m s-2)
-                    Tfreeze,     & ! freezing point of pure water  (K)
-                    iden_air,    & ! intrinsic density of air      (kg m-3)
-                    iden_ice,    & ! intrinsic density of ice      (kg m-3)
-                    iden_water     ! intrinsic density of water    (kg m-3)
-
-! missing values
-USE globalData,only:integerMissing  ! missing integer
-USE globalData,only:realMissing     ! missing real number
-
-! named variables for snow and soil
-USE globalData,only:iname_snow     ! named variables for snow
-USE globalData,only:iname_soil     ! named variables for soil
-
-! named variables
-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
-USE var_lookup,only:iLookINDEX      ! named variables for structure elements
-
-! model decisions
-USE globalData,only:model_decisions                         ! model decision structure
-USE var_lookup,only:iLookDECISIONS                          ! named variables for elements of the decision structure
-
-! provide access to look-up values for model decisions
-USE mDecisions_module,only:      &
- ! look-up values for the numerical method
- iterative,                      & ! iterative
- nonIterative,                   & ! non-iterative
- iterSurfEnergyBal,              & ! iterate only on the surface energy balance
- ! look-up values for method used to compute derivative
- numerical,                      & ! numerical solution
- analytical,                     & ! analytical solution
- ! look-up values for choice of boundary conditions for thermodynamics
- prescribedTemp,                 & ! prescribed temperature
- energyFlux,                     & ! energy flux
- zeroFlux,                       & ! zero flux
- ! look-up values for choice of boundary conditions for soil hydrology
- prescribedHead                    ! prescribed head
-
-! -------------------------------------------------------------------------------------------------
-implicit none
-private
-public::ssdNrgFlux
-! global parameters
-real(dp),parameter            :: dx=1.e-10_dp             ! finite difference increment (K)
-real(dp),parameter            :: valueMissing=-9999._dp   ! missing value parameter
-contains
-
- ! ************************************************************************************************
- ! public subroutine ssdNrgFlux: compute energy fluxes and derivatives at layer interfaces
- ! ************************************************************************************************
- subroutine ssdNrgFlux(&
-                       ! input: model control
-                       scalarSolution,                     & ! intent(in):    flag to indicate the scalar solution
-                       ! input: fluxes and derivatives at the upper boundary
-                       groundNetFlux,                      & ! intent(in):    total flux at the ground surface (W m-2)
-                       dGroundNetFlux_dGroundTemp,         & ! intent(in):    derivative in total ground surface flux w.r.t. ground temperature (W m-2 K-1)
-                       ! input: liquid water fluxes
-                       iLayerLiqFluxSnow,                  & ! intent(in):    liquid flux at the interface of each snow layer (m s-1)
-                       iLayerLiqFluxSoil,                  & ! intent(in):    liquid flux at the interface of each soil layer (m s-1)
-                       ! input: trial value of model state variabes
-                       mLayerTempTrial,                    & ! intent(in):    trial temperature at the current iteration (K)
-                       mLayerMatricHeadTrial,              & ! intent(in):    trial matric head at the current iteration(m)
-                       mLayerVolFracLiqTrial,              & ! intent(in):    trial volumetric fraction of liquid water at the current iteration(-)
-                       mLayerVolFracIceTrial,              & ! intent(in):    trial volumetric fraction of ice water at the current iteration(-)
-                       ! input-output: data structures
-                       mpar_data,                          & ! intent(in):    model parameters
-                       indx_data,                          & ! intent(in):    model indices
-                       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: fluxes and derivatives at all layer interfaces
-                       iLayerNrgFlux,                      & ! intent(out):   energy flux at the layer interfaces (W m-2)
-                       dFlux_dTempAbove,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer above (W m-2 K-1)
-                       dFlux_dTempBelow,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer below (W m-2 K-1)
-                       ! output: error control
-                       err,message)                          ! intent(out): error control
- implicit none
- ! input: model control
- logical(lgt),intent(in)         :: scalarSolution             ! flag to denote if implementing the scalar solution
- ! input: fluxes and derivatives at the upper boundary
- real(dp),intent(in)             :: groundNetFlux              ! net energy flux for the ground surface (W m-2)
- real(dp),intent(in)             :: dGroundNetFlux_dGroundTemp ! derivative in net ground flux w.r.t. ground temperature (W m-2 K-1)
- ! input: liquid water fluxes
- real(dp),intent(in)             :: iLayerLiqFluxSnow(0:)      ! intent(in): liquid flux at the interface of each snow layer (m s-1)
- real(dp),intent(in)             :: iLayerLiqFluxSoil(0:)      ! intent(in): liquid flux at the interface of each soil layer (m s-1)
- ! input: trial value of model state variables
- real(dp),intent(in)             :: mLayerTempTrial(:)         ! trial temperature of each snow/soil layer at the current iteration (K)
- real(dp),intent(in)             :: mLayerMatricHeadTrial(:)   ! matric head in each layer at the current iteration (m)
- real(dp),intent(in)             :: mLayerVolFracLiqTrial(:)   ! volumetric fraction of liquid at the current iteration (-)
- real(dp),intent(in)             :: mLayerVolFracIceTrial(:)   ! volumetric fraction of ice at the current iteration (-)
- ! input-output: data structures
- type(var_dlength),intent(in)    :: mpar_data                  ! model parameters
- type(var_ilength),intent(in)    :: indx_data                  ! state vector geometry
- 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: fluxes and derivatives at all layer interfaces
- real(dp),intent(out)            :: iLayerNrgFlux(0:)          ! energy flux at the layer interfaces (W m-2)
- real(dp),intent(out)            :: dFlux_dTempAbove(0:)       ! derivatives in the flux w.r.t. temperature in the layer above (J m-2 s-1 K-1)
- real(dp),intent(out)            :: dFlux_dTempBelow(0:)       ! derivatives in the flux w.r.t. temperature in the layer below (J m-2 s-1 K-1)
- ! output: error control
- integer(i4b),intent(out)        :: err                        ! error code
- character(*),intent(out)        :: message                    ! error message
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------
- ! local variables
- integer(i4b)                    :: iLayer                     ! index of model layers
- integer(i4b)                    :: ixLayerDesired(1)          ! layer desired (scalar solution)
- integer(i4b)                    :: ixTop                      ! top layer in subroutine call
- integer(i4b)                    :: ixBot                      ! bottom layer in subroutine call
- real(dp)                        :: qFlux                      ! liquid flux at layer interfaces (m s-1)
- real(dp)                        :: dz                         ! height difference (m)
- real(dp)                        :: flux0,flux1,flux2          ! fluxes used to calculate derivatives (W m-2)
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------
- ! make association of local variables with information in the data structures
- associate(&
-  ix_fDerivMeth        => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision, & ! intent(in): method used to calculate flux derivatives
-  ix_bcLowrTdyn        => model_decisions(iLookDECISIONS%bcLowrTdyn)%iDecision, & ! intent(in): method used to calculate the lower boundary condition for thermodynamics
-  ! input: model coordinates
-  nSnow                => indx_data%var(iLookINDEX%nSnow)%dat(1),               & ! intent(in): number of snow layers
-  nLayers              => indx_data%var(iLookINDEX%nLayers)%dat(1),             & ! intent(in): total number of layers
-  layerType            => indx_data%var(iLookINDEX%layerType)%dat,              & ! intent(in): layer type (iname_soil or iname_snow)
-  ixLayerState         => indx_data%var(iLookINDEX%ixLayerState)%dat,           & ! intent(in): list of indices for all model layers
-  ixSnowSoilNrg        => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat,          & ! intent(in): index in the state subset for energy state variables in the snow+soil domain
-  ! input: thermal properties
-  mLayerDepth          => prog_data%var(iLookPROG%mLayerDepth)%dat,             & ! intent(in): depth of each layer (m)
-  mLayerHeight         => prog_data%var(iLookPROG%mLayerHeight)%dat,            & ! intent(in): height at the mid-point of each layer (m)
-  iLayerThermalC       => diag_data%var(iLookDIAG%iLayerThermalC)%dat,          & ! intent(in): thermal conductivity at the interface of each layer (W m-1 K-1)
-  lowerBoundTemp       => mpar_data%var(iLookPARAM%lowerBoundTemp)%dat(1),      & ! intent(in): temperature of the lower boundary (K)
-  ! output: diagnostic fluxes
-  iLayerConductiveFlux => flux_data%var(iLookFLUX%iLayerConductiveFlux)%dat,    & ! intent(out): conductive energy flux at layer interfaces at end of time step (W m-2)
-  iLayerAdvectiveFlux  => flux_data%var(iLookFLUX%iLayerAdvectiveFlux)%dat      & ! intent(out): advective energy flux at layer interfaces at end of time step (W m-2)
- )  ! association of local variables with information in the data structures
- ! ------------------------------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='ssdNrgFlux/'
-
- ! set conductive and advective fluxes to missing in the upper boundary
- ! NOTE: advective flux at the upper boundary is included in the ground heat flux
- iLayerConductiveFlux(0) = valueMissing
- iLayerAdvectiveFlux(0)  = valueMissing
-
- ! get the indices for the snow+soil layers
- if(scalarSolution)then
-  ixLayerDesired = pack(ixLayerState, ixSnowSoilNrg/=integerMissing)
-  ixTop = ixLayerDesired(1)
-  ixBot = ixLayerDesired(1)
- else
-  ixTop = 1
-  ixBot = nLayers
- endif
-
- ! -------------------------------------------------------------------------------------------------------------------------
- ! ***** compute the conductive fluxes at layer interfaces *****
- ! -------------------------------------------------------------------------------------------------------------------------
- do iLayer=ixTop,ixBot ! (loop through model layers)
-
-  ! compute fluxes at the lower boundary -- positive downwards
-  if(iLayer==nLayers)then
-   ! flux depends on the type of lower boundary condition
-   select case(ix_bcLowrTdyn) ! (identify the lower boundary condition for thermodynamics
-    case(prescribedTemp); iLayerConductiveFlux(nLayers) = -iLayerThermalC(iLayer)*(lowerBoundTemp - mLayerTempTrial(iLayer))/(mLayerDepth(iLayer)*0.5_dp)
-    case(zeroFlux);       iLayerConductiveFlux(nLayers) = 0._dp
-    case default;         err=20; message=trim(message)//'unable to identify lower boundary condition for thermodynamics'; return
-   end select  ! (identifying the lower boundary condition for thermodynamics)
-
-  ! compute fluxes within the domain -- positive downwards
-  else
-    iLayerConductiveFlux(iLayer)  = -iLayerThermalC(iLayer)*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer)) / &
-                                    (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
-
-    !write(*,'(a,i4,1x,2(f9.3,1x))') 'iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer) = ', iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer)
-  end if ! (the type of layer)
- end do
-
- ! -------------------------------------------------------------------------------------------------------------------------
- ! ***** compute the advective fluxes at layer interfaces *****
- ! -------------------------------------------------------------------------------------------------------------------------
- do iLayer=ixTop,ixBot
-  ! get the liquid flux at layer interfaces
-  select case(layerType(iLayer))
-   case(iname_snow); qFlux = iLayerLiqFluxSnow(iLayer)
-   case(iname_soil); qFlux = iLayerLiqFluxSoil(iLayer-nSnow)
-   case default; err=20; message=trim(message)//'unable to identify layer type'; return
-  end select
-  ! compute fluxes at the lower boundary -- positive downwards
-  if(iLayer==nLayers)then
-   iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(lowerBoundTemp - mLayerTempTrial(iLayer))
-  ! compute fluxes within the domain -- positive downwards
-  else
-   iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer))
-  end if
- end do  ! looping through layers
-
- ! -------------------------------------------------------------------------------------------------------------------------
- ! ***** compute the total fluxes at layer interfaces *****
- ! -------------------------------------------------------------------------------------------------------------------------
- ! NOTE: ignore advective fluxes for now
- iLayerNrgFlux(0)           = groundNetFlux
- iLayerNrgFlux(ixTop:ixBot) = iLayerConductiveFlux(ixTop:ixBot)
- !print*, 'iLayerNrgFlux(0:4) = ', iLayerNrgFlux(0:4)
-
- ! -------------------------------------------------------------------------------------------------------------------------
- ! ***** compute the derivative in fluxes at layer interfaces w.r.t temperature in the layer above and the layer below *****
- ! -------------------------------------------------------------------------------------------------------------------------
-
- ! initialize un-used elements
- dFlux_dTempBelow(nLayers) = -huge(lowerBoundTemp)  ! don't expect this to be used, so deliberately set to a ridiculous value to cause problems
-
- ! ***** the upper boundary
- dFlux_dTempBelow(0) = dGroundNetFlux_dGroundTemp
-
- ! loop through INTERFACES...
- do iLayer=ixTop,ixBot
-
-  ! ***** the lower boundary
-  if(iLayer==nLayers)then  ! (lower boundary)
-
-   ! identify the lower boundary condition
-   select case(ix_bcLowrTdyn)
-
-    ! * prescribed temperature at the lower boundary
-    case(prescribedTemp)
-
-     dz = mLayerDepth(iLayer)*0.5_dp
-     if(ix_fDerivMeth==analytical)then    ! ** analytical derivatives
-      dFlux_dTempAbove(iLayer) = iLayerThermalC(iLayer)/dz
-     else                              ! ** numerical derivatives
-      flux0 = -iLayerThermalC(iLayer)*(lowerBoundTemp - (mLayerTempTrial(iLayer)   ))/dz
-      flux1 = -iLayerThermalC(iLayer)*(lowerBoundTemp - (mLayerTempTrial(iLayer)+dx))/dz
-      dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
+    ! data types
+    USE nrtype
+    
+    ! data types
+    USE data_types,only:var_d           ! x%var(:)       (rkind)
+    USE data_types,only:var_dlength     ! x%var(:)%dat   (rkind)
+    USE data_types,only:var_ilength     ! x%var(:)%dat   (i4b)
+    
+    ! physical constants
+    USE multiconst,only:&
+                        sb,          & ! Stefan Boltzman constant      (W m-2 K-4)
+                        Em_Sno,      & ! emissivity of snow            (-)
+                        LH_fus,      & ! latent heat of fusion         (J kg-1)
+                        LH_vap,      & ! latent heat of vaporization   (J kg-1)
+                        LH_sub,      & ! latent heat of sublimation    (J kg-1)
+                        gravity,     & ! gravitational acceleteration  (m s-2)
+                        Tfreeze,     & ! freezing point of pure water  (K)
+                        iden_air,    & ! intrinsic density of air      (kg m-3)
+                        iden_ice,    & ! intrinsic density of ice      (kg m-3)
+                        iden_water,  &  ! intrinsic density of water    (kg m-3)
+                        ! specific heat
+                        Cp_air,      & ! specific heat of air          (J kg-1 K-1)
+                        Cp_water,    & ! specific heat of liquid water (J kg-1 K-1)
+                        ! thermal conductivity
+                        lambda_air,  & ! thermal conductivity of air   (J s-1 m-1)
+                        lambda_ice,  & ! thermal conductivity of ice   (J s-1 m-1)
+                        lambda_water   ! thermal conductivity of water (J s-1 m-1)
+    
+    
+    ! missing values
+    USE globalData,only:integerMissing  ! missing integer
+    USE globalData,only:realMissing     ! missing real number
+    
+    ! named variables for snow and soil
+    USE globalData,only:iname_snow     ! named variables for snow
+    USE globalData,only:iname_soil     ! named variables for soil
+    
+    ! named variables
+    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
+    USE var_lookup,only:iLookINDEX      ! named variables for structure elements
+    
+    ! model decisions
+    USE globalData,only:model_decisions                         ! model decision structure
+    USE var_lookup,only:iLookDECISIONS                          ! named variables for elements of the decision structure
+    
+    ! provide access to look-up values for model decisions
+    USE mDecisions_module,only:      &
+     ! look-up values for method used to compute derivative
+     numerical,                      & ! numerical solution
+     analytical,                     & ! analytical solution
+     ! look-up values for choice of boundary conditions for thermodynamics
+     prescribedTemp,                 & ! prescribed temperature
+     energyFlux,                     & ! energy flux
+     zeroFlux,                       & ! zero flux
+     ! look-up values for choice of boundary conditions for soil hydrology
+     prescribedHead,                 & ! prescribed head
+     ! look-up values for choice of thermal conductivity representation for snow
+     Yen1965,                        & ! Yen (1965)
+     Mellor1977,                     & ! Mellor (1977)
+     Jordan1991,                     & ! Jordan (1991)
+     Smirnova2000,                   & ! Smirnova et al. (2000)
+     ! look-up values for choice of thermal conductivity representation for soil
+     funcSoilWet,                    & ! function of soil wetness
+     mixConstit,                     & ! mixture of constituents
+     hanssonVZJ,                     & ! test case for the mizoguchi lab experiment, Hansson et al. VZJ 2004
+     ! look-up values for the form of Richards' equation
+     moisture,                       & ! moisture-based form of Richards' equation
+     mixdform                          ! mixed form of Richards' equation
+    
+    ! -------------------------------------------------------------------------------------------------
+    implicit none
+    private
+    public::ssdNrgFlux
+    ! global parameters
+    real(rkind),parameter            :: dx=1.e-10_rkind             ! finite difference increment (K)
+    contains
+    
+    
+     ! **********************************************************************************************************
+     ! public subroutine ssdNrgFlux: compute energy fluxes and derivatives at layer interfaces
+     ! **********************************************************************************************************
+     subroutine ssdNrgFlux(&
+                           ! input: model control
+                           scalarSolution,                     & ! intent(in):    flag to indicate the scalar solution
+                           deriv_desired,                & ! intent(in): flag indicating if derivatives are desired
+                           ! input: fluxes and derivatives at the upper boundary
+                           groundNetFlux,                      & ! intent(in):    total flux at the ground surface (W m-2)
+                           dGroundNetFlux_dGroundTemp,         & ! intent(in):    derivative in total ground surface flux w.r.t. ground temperature (W m-2 K-1)
+                           ! input: liquid water fluxes
+                           iLayerLiqFluxSnow,                  & ! intent(in):    liquid flux at the interface of each snow layer (m s-1)
+                           iLayerLiqFluxSoil,                  & ! intent(in):    liquid flux at the interface of each soil layer (m s-1)
+                           ! input: trial value of model state variables
+                           mLayerTempTrial,                    & ! intent(in):    trial temperature at the current iteration (K)
+                           mLayerMatricHeadTrial,              & ! intent(in):    trial matric head at the current iteration(m)
+                           mLayerVolFracLiqTrial,              & ! intent(in):    trial volumetric fraction of liquid water at the current iteration(-)
+                           mLayerVolFracIceTrial,              & ! intent(in):    trial volumetric fraction of ice water at the current iteration(-)
+                           ! input: pre-computed derivatives
+                           mLayerdTheta_dTk,                   & ! intent(in):    derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           mLayerFracLiqSnow,                  & ! intent(in):    fraction of liquid water (-)
+                           ! input-output: data structures
+                           mpar_data,                          & ! intent(in):    model parameters
+                           indx_data,                          & ! intent(in):    model indices
+                           prog_data,                          & ! intent(in):    model prognostic variables for a local HRU
+                           diag_data,                          & ! intent(inout):    model diagnostic variables for a local HRU
+                           flux_data,                          & ! intent(inout): model fluxes for a local HRU
+                           ! output: fluxes and derivatives at all layer interfaces
+                           iLayerNrgFlux,                      & ! intent(out):   energy flux at the layer interfaces (W m-2)
+                           dFlux_dTempAbove,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer above (W m-2 K-1)
+                           dFlux_dTempBelow,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer below (W m-2 K-1)
+                           dFlux_dWatAbove,                    & ! intent(out):   derivatives in the flux w.r.t. water state in the layer above (W m-2 K-1)
+                           dFlux_dWatBelow,                    & ! intent(out):   derivatives in the flux w.r.t. water state in the layer below (W m-2 K-1)
+                          ! output: error control
+                           err,message)                          ! intent(out): error control
+     ! utility modules
+     USE soil_utils_module,only:volFracLiq     ! compute volumetric fraction of liquid water
+     USE soil_utils_module,only:matricHead     ! compute the matric head based on volumetric water content
+     USE soil_utils_module,only:crit_soilT     ! compute critical temperature below which ice exists
+     USE snow_utils_module,only:fracliquid     ! compute fraction of liquid water at a given temperature
+     USE soil_utils_module,only:dTheta_dPsi    ! compute derivative of the soil moisture characteristic w.r.t. psi (m-1)
+     USE soil_utils_module,only:dPsi_dTheta    ! compute derivative of the soil moisture characteristic w.r.t. theta (m)
+    
+     ! constants
+     USE multiconst, only: gravity, &                          ! gravitational acceleration (m s-1)
+                          Tfreeze, &                          ! freezing point of water (K)
+                          iden_water,iden_ice,&      ! intrinsic density of water and ice (kg m-3)
+                          LH_fus                              ! latent heat of fusion (J kg-1)
+     ! -------------------------------------------------------------------------------------------------------------------------------------------------
+     implicit none
+     ! input: model control
+     logical(lgt),intent(in)            :: scalarSolution              ! flag to denote if implementing the scalar solution
+     logical(lgt),intent(in)            :: deriv_desired               ! flag indicating if derivatives are desired
+     ! input: fluxes and derivatives at the upper boundary
+     real(rkind),intent(in)             :: groundNetFlux               ! net energy flux for the ground surface (W m-2)
+     real(rkind),intent(inout)          :: dGroundNetFlux_dGroundTemp  ! derivative in net ground flux w.r.t. ground temperature (W m-2 K-1)
+     ! input: liquid water fluxes
+     real(rkind),intent(in)             :: iLayerLiqFluxSnow(0:)       ! liquid flux at the interface of each snow layer (m s-1)
+     real(rkind),intent(in)             :: iLayerLiqFluxSoil(0:)       ! liquid flux at the interface of each soil layer (m s-1)
+     ! input: trial model state variables
+     real(rkind),intent(in)              :: mLayerTempTrial(:)         ! temperature in each layer at the current iteration (m)
+     real(rkind),intent(in)              :: mLayerMatricHeadTrial(:)   ! matric head in each layer at the current iteration (m)
+     real(rkind),intent(in)              :: mLayerVolFracLiqTrial(:)   ! volumetric fraction of liquid at the current iteration (-)
+     real(rkind),intent(in)              :: mLayerVolFracIceTrial(:)   ! volumetric fraction of ice at the current iteration (-)
+    ! input: pre-computed derivatives
+     real(rkind),intent(in)              :: mLayerdTheta_dTk(:)        ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+     real(rkind),intent(in)              :: mLayerFracLiqSnow(:)       ! fraction of liquid water (-)
+     ! input-output: data structures
+     type(var_dlength),intent(in)        :: mpar_data                  ! model parameters
+     type(var_ilength),intent(in)        :: indx_data                  ! state vector geometry
+     type(var_dlength),intent(in)        :: prog_data                  ! prognostic variables for a local HRU
+     type(var_dlength),intent(inout)        :: diag_data                  ! diagnostic variables for a local HRU
+     type(var_dlength),intent(inout)     :: flux_data                  ! model fluxes for a local HRU
+     ! output: fluxes and derivatives at all layer interfaces
+     real(rkind),intent(out)             :: iLayerNrgFlux(0:)          ! energy flux at the layer interfaces (W m-2)
+     real(rkind),intent(out)             :: dFlux_dTempAbove(0:)       ! derivatives in the flux w.r.t. temperature in the layer above (J m-2 s-1 K-1)
+     real(rkind),intent(out)             :: dFlux_dTempBelow(0:)       ! derivatives in the flux w.r.t. temperature in the layer below (J m-2 s-1 K-1)
+     real(rkind),intent(out)             :: dFlux_dWatAbove(0:)        ! derivatives in the flux w.r.t. water state in the layer above (J m-2 s-1 K-1)
+     real(rkind),intent(out)             :: dFlux_dWatBelow(0:)        ! derivatives in the flux w.r.t. water state in the layer below (J m-2 s-1 K-1)
+     ! output: error control
+     integer(i4b),intent(out)            :: err                        ! error code
+     character(*),intent(out)            :: message                    ! error message
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! local variables
+     character(LEN=256)               :: cmessage                     ! error message of downwind routine
+     integer(i4b)                     :: i,j,iLayer                   ! index of model layers
+     integer(i4b)                     :: ixLayerDesired(1)            ! layer desired (scalar solution)
+     integer(i4b)                     :: ixTop                        ! top layer in subroutine call
+     integer(i4b)                     :: ixBot                        ! bottom layer in subroutine call
+     real(rkind)                      :: qFlux                        ! liquid flux at layer interfaces (m s-1)
+     real(rkind)                      :: dz                           ! height difference (m)
+     ! additional variables to compute numerical derivatives
+     integer(i4b)                     :: nFlux                        ! number of flux calculations required (>1 = numerical derivatives with one-sided finite differences)
+     integer(i4b)                     :: itry                         ! index of different flux calculations
+     integer(i4b),parameter           :: unperturbed=0                ! named variable to identify the case of unperturbed state variables
+     integer(i4b),parameter           :: perturbState=1               ! named variable to identify the case where we perturb the state in the current layer
+     integer(i4b),parameter           :: perturbStateTempAbove=2      ! named variable to identify the case where we perturb the state layer above
+     integer(i4b),parameter           :: perturbStateTempBelow=3      ! named variable to identify the case where we perturb the state layer below
+     integer(i4b),parameter           :: perturbStateWatAbove=4       ! named variable to identify the case where we perturb the state layer above
+     integer(i4b),parameter           :: perturbStateWatBelow=5       ! named variable to identify the case where we perturb the state layer below
+     integer(i4b)                     :: ixPerturb                    ! index of element in 2-element vector to perturb
+     integer(i4b)                     :: ixOriginal                   ! index of perturbed element in the original vector
+     real(rkind)                      :: scalarThermCFlux               ! thermal conductivity (W m-1 K-1)
+     real(rkind)                      :: scalarThermCFlux_dTempAbove    ! thermal conductivity with perturbation to the temperature state above (W m-1 K-1)
+     real(rkind)                      :: scalarThermCFlux_dTempBelow    ! thermal conductivity with perturbation to the temperature state below (W m-1 K-1)
+     real(rkind)                      :: scalarThermCFlux_dWatAbove     ! thermal conductivity with perturbation to the water state above
+     real(rkind)                      :: scalarThermCFlux_dWatBelow     ! thermal conductivity with perturbation to the water state below
+     real(rkind)                      :: flux0,flux1,flux2            ! fluxes used to calculate derivatives (W m-2)
+     ! compute fluxes and derivatives at layer interfaces
+     integer(i4b),dimension(2)        :: mLayer_ind                   ! indices of above and below layers
+     integer(i4b),dimension(2)        :: iLayer_ind                   ! indices of above and below interfaces
+     real(rkind)                      :: matricFHead                  ! matric head for frozen soil
+     real(rkind)                      :: Tcrit                        ! temperature where all water is unfrozen (K)
+     real(rkind)                      :: fLiq                         ! fraction of liquid water (-)
+     real(rkind),dimension(2)         :: vectorMatricHeadTrial        ! trial value of matric head (m)
+     real(rkind),dimension(2)         :: vectorVolFracLiqTrial        ! trial value of volumetric liquid content (-)
+     real(rkind),dimension(2)         :: vectorVolFracIceTrial        ! trial value of volumetric ice content (-)
+     real(rkind),dimension(2)         :: vectorTempTrial              ! trial value of temperature (K)
+     real(rkind),dimension(2)         :: vectordTheta_dPsi            ! derivative in the soil water characteristic w.r.t. psi (m-1)
+     real(rkind),dimension(2)         :: vectordPsi_dTheta            ! derivative in the soil water characteristic w.r.t. theta (m)
+     real(rkind),dimension(2)         :: vectorFracLiqSnow            ! fraction of liquid water (-)
+     real(rkind),dimension(2)         :: vectortheta_sat              ! layer above and below soil porosity (-)
+     real(rkind),dimension(2)         :: vectoriden_soil              ! layer above and below density of soil (kg m-3)
+     real(rkind),dimension(2)         :: vectorthCond_soil            ! layer above and below thermal conductivity of soil (W m-1 K-1)
+     real(rkind),dimension(2)         :: vectorfrac_sand              ! layer above and below fraction of sand (-)
+     real(rkind),dimension(2)         :: vectorfrac_clay              ! layer above and below fraction of clay (-)
+     ! recompute the perturbed version of iLayerThermalC, this could be the only version and remove the omputThermConduct_module
+     real(rkind)                      :: dThermalC_dHydStateAbove     ! derivative in the thermal conductivity w.r.t. water state in the layer above
+     real(rkind)                      :: dThermalC_dHydStateBelow     ! derivative in the thermal conductivity w.r.t. water state in the layer above
+     real(rkind)                      :: dThermalC_dNrgStateAbove     ! derivative in the thermal conductivity w.r.t. energy state in the layer above
+     real(rkind)                      :: dThermalC_dNrgStateBelow     ! derivative in the thermal conductivity w.r.t. energy state in the layer above
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! make association of local variables with information in the data structures
+     associate(&
+      ixDerivMethod           => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision,      & ! intent(in): method used to calculate flux derivatives
+      ix_bcUpprTdyn           => model_decisions(iLookDECISIONS%bcUpprTdyn)%iDecision,      & ! intent(in): method used to calculate the upper boundary condition for thermodynamics
+      ix_bcLowrTdyn           => model_decisions(iLookDECISIONS%bcLowrTdyn)%iDecision,      & ! intent(in): method used to calculate the lower boundary condition for thermodynamics
+      ixRichards                 => model_decisions(iLookDECISIONS%f_Richards)%iDecision,   & ! intent(in): index of the form of Richards' equation
+      ixThCondSnow            => model_decisions(iLookDECISIONS%thCondSnow)%iDecision,      & ! intent(in): choice of method for thermal conductivity of snow
+      ixThCondSoil            => model_decisions(iLookDECISIONS%thCondSoil)%iDecision,      & ! intent(in): choice of method for thermal conductivity of soil
+      ! input: model coordinates
+      nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1),               & ! intent(in): number of snow layers
+      nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1),             & ! intent(in): total number of layers
+      layerType               => indx_data%var(iLookINDEX%layerType)%dat,              & ! intent(in): layer type (iname_soil or iname_snow)
+      ixLayerState            => indx_data%var(iLookINDEX%ixLayerState)%dat,           & ! intent(in): list of indices for all model layers
+      ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat,          & ! intent(in): index in the state subset for energy state variables in the snow+soil domain
+      ! input: thermal properties
+      mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat,             & ! intent(in): depth of each layer (m)
+      mLayerHeight            => prog_data%var(iLookPROG%mLayerHeight)%dat,            & ! intent(in): height at the mid-point of each layer (m)
+      upperBoundTemp          => mpar_data%var(iLookPARAM%upperBoundTemp)%dat(1),      & ! intent(in): temperature of the upper boundary (K)
+      lowerBoundTemp          => mpar_data%var(iLookPARAM%lowerBoundTemp)%dat(1),      & ! intent(in): temperature of the lower boundary (K)
+      iLayerHeight            => prog_data%var(iLookPROG%iLayerHeight)%dat,            & ! intent(in): height at the interface of each layer (m)
+      fixedThermalCond_snow   => mpar_data%var(iLookPARAM%fixedThermalCond_snow)%dat(1),    & ! intent(in): temporally constant thermal conductivity of snow (W m-1 K-1)
+      iLayerThermalC          => diag_data%var(iLookDIAG%iLayerThermalC)%dat,          & ! intent(inout): thermal conductivity at the interface of each layer (W m-1 K-1)
+      ! input: depth varying soil parameters
+      iden_soil               => mpar_data%var(iLookPARAM%soil_dens_intr)%dat,              & ! intent(in): intrinsic density of soil (kg m-3)
+      thCond_soil             => mpar_data%var(iLookPARAM%thCond_soil)%dat,                 & ! intent(in): thermal conductivity of soil (W m-1 K-1)
+      theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat,                   & ! intent(in): soil porosity (-)
+      frac_sand               => mpar_data%var(iLookPARAM%frac_sand)%dat,                   & ! intent(in): fraction of sand (-)
+      frac_clay               => mpar_data%var(iLookPARAM%frac_clay)%dat,                   & ! intent(in): fraction of clay (-)
+      vGn_m                   => diag_data%var(iLookDIAG%scalarVGn_m)%dat,                  & ! intent(in):  [dp(:)] van Genutchen "m" parameter (-)
+      vGn_n                   => mpar_data%var(iLookPARAM%vGn_n)%dat,                       & ! intent(in):  [dp(:)] van Genutchen "n" parameter (-)
+      vGn_alpha               => mpar_data%var(iLookPARAM%vGn_alpha)%dat,                   & ! intent(in):  [dp(:)] van Genutchen "alpha" parameter (m-1)
+      theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat,                   & ! intent(in):  [dp(:)] soil residual volumetric water content (-)
+      ! input: snow parameters
+      snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1),            & ! intent(in):  [dp] scaling parameter for the snow freezing curve (K-1)
+      ! output: diagnostic fluxes
+      iLayerConductiveFlux => flux_data%var(iLookFLUX%iLayerConductiveFlux)%dat,    & ! intent(out): conductive energy flux at layer interfaces at end of time step (W m-2)
+      iLayerAdvectiveFlux  => flux_data%var(iLookFLUX%iLayerAdvectiveFlux)%dat      & ! intent(out): advective energy flux at layer interfaces at end of time step (W m-2)
+     )  ! association of local variables with information in the data structures
+     ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+     ! initialize error control
+     err=0; message='ssdNrgFlux/'
+    
+     ! set conductive and advective fluxes to missing in the upper boundary
+     ! NOTE: advective flux at the upper boundary is included in the ground heat flux
+     iLayerConductiveFlux(0) = realMissing
+     iLayerAdvectiveFlux(0)  = realMissing
+    
+     ! check the need to compute numerical derivatives
+     if(ixDerivMethod==numerical)then
+      nFlux=5  ! compute the derivatives and cross derivates using one-sided finite differences
+     else
+      nFlux=0  ! compute analytical derivatives
      end if
-
-     ! * zero flux at the lower boundary
-     case(zeroFlux)
-      dFlux_dTempAbove(iLayer) = 0._dp
-
-     case default; err=20; message=trim(message)//'unable to identify lower boundary condition for thermodynamics'; return
-
-   end select  ! (identifying the lower boundary condition for thermodynamics)
-
-  ! ***** internal layers
-  else
-   dz = (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
-   if(ix_fDerivMeth==analytical)then    ! ** analytical derivatives
-    dFlux_dTempAbove(iLayer) =  iLayerThermalC(iLayer)/dz
-    dFlux_dTempBelow(iLayer) = -iLayerThermalC(iLayer)/dz
-   else                              ! ** numerical derivatives
-    flux0 = -iLayerThermalC(iLayer)*( mLayerTempTrial(iLayer+1)     -  mLayerTempTrial(iLayer)    ) / dz
-    flux1 = -iLayerThermalC(iLayer)*( mLayerTempTrial(iLayer+1)     - (mLayerTempTrial(iLayer)+dx)) / dz
-    flux2 = -iLayerThermalC(iLayer)*((mLayerTempTrial(iLayer+1)+dx) -  mLayerTempTrial(iLayer)    ) / dz
-    dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
-    dFlux_dTempBelow(iLayer) = (flux2 - flux0)/dx
-   end if
-
-  end if  ! type of layer (upper, internal, or lower)
-
- end do  ! (looping through layers)
-
- ! end association of local variables with information in the data structures
- end associate
-
- end subroutine ssdNrgFlux
-
-end module ssdNrgFlux_module
-
+    
+     ! get the indices for the snow+soil layers
+     if(scalarSolution)then
+      ixLayerDesired = pack(ixLayerState, ixSnowSoilNrg/=integerMissing)
+      ixTop = ixLayerDesired(1)
+      ixBot = ixLayerDesired(1)
+     else
+      ixTop = 0 !include layer 0 in layer interface derivatives
+      ixBot = nLayers
+     endif
+    
+     ! -------------------------------------------------------------------------------------------------------------------
+     ! ***** compute the derivative in fluxes at layer interfaces w.r.t state in the layer above and the layer below *****
+     ! -------------------------------------------------------------------------------------------------------------------
+    
+     ! initialize un-used elements
+     ! ***** the upper boundary
+     dFlux_dTempAbove(0) = 0._rkind ! this will be in canopy
+     dFlux_dWatAbove(0) = 0._rkind ! this will be in canopy
+    
+     ! ***** the lower boundary
+     dFlux_dTempBelow(nLayers) = -huge(lowerBoundTemp)  ! don't expect this to be used, so deliberately set to a ridiculous value to cause problems
+     dFlux_dWatBelow(nLayers) = -huge(lowerBoundTemp)  ! don't expect this to be used, so deliberately set to a ridiculous value to cause problems
+    
+     ! loop through INTERFACES...
+     do iLayer=ixTop,ixBot
+    
+      ! either one or multiple flux calls, depending on if using analytical or numerical derivatives
+      do itry=nFlux,0,-1  ! (work backwards to ensure all computed fluxes come from the un-perturbed case)
+    
+       ! =====
+       ! determine layer to perturb
+       ! ==========================
+       select case(itry)
+        ! skip undesired perturbations
+        case(perturbState); cycle       ! perturbing the layers above and below the flux at the interface
+        ! identify the index for the perturbation
+        case(unperturbed);       ixPerturb = 0
+        case(perturbStateTempAbove)
+         if(iLayer==0) cycle ! cannot perturb state above (does not exist) -- so keep cycling
+         ixPerturb = 1
+        case(perturbStateTempBelow)
+         if(iLayer==nLayers) cycle  ! cannot perturb state below (does not exist) -- so keep cycling
+         ixPerturb = 2
+        case(perturbStateWatAbove)
+         if(iLayer==0) cycle ! cannot perturb state above (does not exist) -- so keep cycling
+         ixPerturb = 3
+        case(perturbStateWatBelow)
+         if(iLayer==nLayers) cycle  ! cannot perturb state below (does not exist) -- so keep cycling
+         ixPerturb = 4
+        case default; err=10; message=trim(message)//"unknown perturbation"; return
+       end select ! (identifying layer to of perturbation)
+       ! determine the index in the original vector
+       ixOriginal = iLayer + (ixPerturb-1)
+    
+       ! =====
+       ! set indices and parameters needed for layer perturbation
+       ! ========================================================
+       mLayer_ind(1) = iLayer
+       mLayer_ind(2) = iLayer+1
+       if (iLayer==0 ) mLayer_ind(1) = 1
+       if (iLayer==nLayers ) mLayer_ind(2) = nLayers
+       ! indices of interface are different at top layer since interface 0 exists
+       iLayer_ind = mLayer_ind
+       if (iLayer==0 ) iLayer_ind(1) = 0
+    
+       ! =====
+       ! get input state variables...
+       ! ============================
+       ! start with the un-perturbed case
+       vectorVolFracLiqTrial(1:2) = mLayerVolFracLiqTrial(mLayer_ind)
+       vectorMatricHeadTrial(1:2) = mLayerMatricHeadTrial(mLayer_ind-nSnow)
+       vectorTempTrial(1:2) = mLayerTempTrial(mLayer_ind)
+       vectorVolFracIceTrial(1:2) = mLayerVolFracIceTrial(mLayer_ind)
+       ! make appropriate perturbations,
+       if(ixPerturb > 2)then
+        vectorMatricHeadTrial(ixPerturb-2) = vectorMatricHeadTrial(ixPerturb-2) + dx
+        vectorVolFracLiqTrial(ixPerturb-2) = vectorVolFracLiqTrial(ixPerturb-2) + dx
+       else if(ixPerturb > 0)then
+        vectorTempTrial(ixPerturb) = vectorTempTrial(ixPerturb) + dx
+       endif
+    
+       ! *****
+       ! * compute the volumetric fraction of liquid, ice, and air in each layer in response to perturbation ...
+       ! *******************************************************************************************************
+    
+       do i = 1,2 !(layer above and below)
+        select case(layerType(mLayer_ind(i))) !(snow or soil)
+    
+         case(iname_soil)
+          j = mLayer_ind(i)-nSnow !soil layer
+          if(ixPerturb > 0)then ! only recompute these if perturbed
+           select case(ixRichards)  ! (form of Richards' equation)
+            case(moisture) !
+             vectorMatricHeadTrial(i) = matricHead(vectorVolFracLiqTrial(i),vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+             Tcrit = crit_soilT(vectorMatricHeadTrial(i))
+             !if change temp and below critical, it changes the state variable, seems like a problem FIX
+             if(vectorTempTrial(i) < Tcrit) then !if do not perturb temperature, this should not change
+              matricFHead = (LH_fus/gravity)*(vectorTempTrial(i) - Tfreeze)/Tfreeze
+              vectorVolFracLiqTrial(i) = volFracLiq(matricFHead,vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+             endif
+            case(mixdform)
+             Tcrit = crit_soilT(vectorMatricHeadTrial(i))
+             if(vectorTempTrial(i) < Tcrit) then !if do not perturb temperature, this should not change, but matricHeadTrial will have changed
+              matricFHead = (LH_fus/gravity)*(vectorTempTrial(i) - Tfreeze)/Tfreeze
+              vectorVolFracLiqTrial(i) = volFracLiq(matricFHead,vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+             else
+              vectorVolFracLiqTrial(i) = volFracLiq(vectorMatricHeadTrial(i),vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+             endif
+           end select ! (form of Richards' equation)
+           vectorVolFracIceTrial(i) = volFracLiq(vectorMatricHeadTrial(i),vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j)) - vectorVolFracLiqTrial(i)
+          endif ! (recompute if perturbed)
+          ! derivatives, these need to be computed because they are computed only in soilLiqFlx which is called after this
+          vectordPsi_dTheta(i) = dPsi_dTheta(vectorVolFracLiqTrial(i),vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+          vectordTheta_dPsi(i) = dTheta_dPsi(vectorMatricHeadTrial(i),vGn_alpha(j),theta_res(j),theta_sat(j),vGn_n(j),vGn_m(j))
+          vectorFracLiqSnow(i) = realMissing
+          ! soil parameters
+          vectortheta_sat(i) = theta_sat(j)
+          vectoriden_soil(i) = iden_soil(j)
+          vectorthCond_soil(i) = thCond_soil(j)
+          vectorfrac_sand(i) = frac_sand(j)
+          vectorfrac_clay(i) = frac_clay(j)
+    
+         case(iname_snow)
+          fLiq = fracliquid(vectorTempTrial(i),snowfrz_scale) ! fraction of liquid water
+          if(ixPerturb > 0) vectorVolFracIceTrial(i) = ( vectorVolFracLiqTrial(i) / fLiq - vectorVolFracLiqTrial(i) )*(iden_water/iden_ice) ! use perturbed nodeVolTotWatTrial
+          ! derivatives
+          vectordPsi_dTheta(i) = realMissing
+          vectordTheta_dPsi(i) = realMissing
+          vectorFracLiqSnow(i) = mLayerFracLiqSnow(mLayer_ind(i))
+          ! soil parameters do not exist
+          vectortheta_sat(i) = realMissing
+          vectoriden_soil(i) = realMissing
+          vectorthCond_soil(i) = realMissing
+          vectorfrac_sand(i) = realMissing
+          vectorfrac_clay(i) = realMissing
+    
+         case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute volumetric fraction of air'; return
+    
+        end select !(snow or soil)
+       enddo !(layer above and below)
+    
+       ! =====
+       ! get thermal conductivity at layer interface and its derivative w.r.t. the state above and the state below...
+       ! ============================================================================================================
+       call iLayerThermalConduct(&
+                           ! input: model control
+                           deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,                         & ! intent(in): index defining the form of Richards' equation (moisture or mixdform)
+                           ixThCondSnow,                        & ! intent(in): choice of method for thermal conductivity of snow
+                           ixThCondSoil,                        & ! intent(in): choice of method for thermal conductivity of soil
+                           ! input: coordinate variables
+                           nLayers,                             & ! intent(in): number of layers
+                           iLayer,                              & ! intent(in): layer index for output
+                           layerType(mLayer_ind),               & ! intent(in): layer type (iname_soil or iname_snow)
+                           ! input: state variables (adjacent layers)
+                           vectorMatricHeadTrial,               & ! intent(in): matric head at the nodes (m)
+                           vectorVolFracLiqTrial,               & ! intent(in): volumetric liquid water at the nodes (m)
+                           vectorVolFracIceTrial,               & ! intent(in): volumetric ice at the nodes (m)
+                           vectorTempTrial,                     & ! intent(in): temperature at the nodes (m)
+                           ! input: pre-computed derivatives
+                           mLayerdTheta_dTk(mLayer_ind),        & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           vectorFracLiqSnow,                   & ! intent(in): fraction of liquid water (-)
+                           vectordTheta_dPsi,                   & ! intent(in): derivative in the soil water characteristic w.r.t. psi (m-1)
+                           vectordPsi_dTheta,                   & ! intent(in): derivative in the soil water characteristic w.r.t. theta (m)
+                           ! input: model coordinate variables (adjacent layers)
+                           mLayerHeight(mLayer_ind),            & ! intent(in): height at the mid-point of the node (m)
+                           iLayerHeight(iLayer_ind),            & ! intent(in): height at the interface of the nodes (m)
+                           ! input: soil parameters
+                           vectortheta_sat,                     & ! intent(in): soil porosity (-)
+                           vectoriden_soil,                     & ! intent(in): intrinsic density of soil (kg m-3)
+                           vectorthCond_soil,                   & ! intent(in): thermal conductivity of soil (W m-1 K-1)
+                           vectorfrac_sand,                     & ! intent(in): fraction of sand (-)
+                           vectorfrac_clay,                     & ! intent(in): fraction of clay (-)
+                           ! input: snow parameters
+                           fixedThermalCond_snow,               & ! intent(in): temporally constant thermal conductivity of snow (W m-1 K-1)
+                           ! output: conductivity at the layer interface (scalars)
+                           iLayerThermalC(iLayer),       & ! intent(inout): thermal conductivity at the interface of each layer (W m-1 K-1)
+                           ! output: derivatives in thermal conductivity w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below
+                           dThermalC_dHydStateAbove,    & ! intent(out): derivative in the thermal conductivity w.r.t. water state in the layer above
+                           dThermalC_dHydStateBelow,    & ! intent(out): derivative in the thermal conductivity w.r.t. water state in the layer above
+                           ! output: derivatives in thermal conductivity w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (W m-1 K-2)
+                           dThermalC_dNrgStateAbove,    & ! intent(out): derivative in the thermal conductivity w.r.t. energy state in the layer above
+                           dThermalC_dNrgStateBelow,    & ! intent(out): derivative in the thermal conductivity w.r.t. energy state in the layer above
+                           ! output: error control
+                           err,cmessage)               ! intent(out): error control
+    
+       if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+       ! compute total vertical flux, to compute derivatives
+       if(deriv_desired .and. ixDerivMethod==numerical)then
+        select case(itry)
+         case(unperturbed);           scalarThermCFlux            = iLayerThermalC(iLayer)
+         case(perturbStateTempAbove); scalarThermCFlux_dTempAbove = iLayerThermalC(iLayer)
+         case(perturbStateTempBelow); scalarThermCFlux_dTempBelow = iLayerThermalC(iLayer)
+         case(perturbStateWatAbove);  scalarThermCFlux_dWatAbove  = iLayerThermalC(iLayer)
+         case(perturbStateWatBelow);  scalarThermCFlux_dWatBelow  = iLayerThermalC(iLayer)
+         case default; err=10; message=trim(message)//"unknown perturbation"; return
+        end select
+       end if
+    
+      end do  ! (looping through different flux calculations -- one or multiple calls depending if desire for numerical or analytical derivatives)
+    
+    
+      ! ***** the upper boundary
+      if(iLayer==0)then  ! (upper boundary)
+    
+       ! identify the upper boundary condition
+       select case(ix_bcUpprTdyn)
+    
+        ! * prescribed temperature at the upper boundary
+        case(prescribedTemp)
+         dz = (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+         if(ixDerivMethod==analytical)then    ! ** analytical derivatives
+          dFlux_dWatBelow(iLayer)  = -dThermalC_dHydStateBelow * ( mLayerTempTrial(iLayer+1) - upperBoundTemp )/dz
+          dFlux_dTempBelow(iLayer) = -dThermalC_dNrgStateBelow * ( mLayerTempTrial(iLayer+1) - upperBoundTemp )/dz - iLayerThermalC(iLayer)/dz
+         else                              ! ** numerical derivatives
+          flux0 = -scalarThermCFlux          *( mLayerTempTrial(iLayer+1) - upperBoundTemp ) / dz
+          flux2 = -scalarThermCFlux_dWatBelow*( mLayerTempTrial(iLayer+1) - upperBoundTemp ) / dz
+          dFlux_dWatBelow(iLayer) = (flux2 - flux0)/dx
+          flux0 = -scalarThermCFlux           *( mLayerTempTrial(iLayer+1)     - upperBoundTemp ) / dz
+          flux2 = -scalarThermCFlux_dTempBelow*((mLayerTempTrial(iLayer+1)+dx) - upperBoundTemp ) / dz
+          dFlux_dTempBelow(iLayer) = (flux2 - flux0)/dx
+         end if
+    
+         ! * zero flux at the upper boundary
+        case(zeroFlux)
+         dFlux_dWatBelow(iLayer) = 0._rkind
+         dFlux_dTempBelow(iLayer) = 0._rkind
+    
+         ! * compute flux inside vegetation energy flux routine, use here
+        case(energyFlux)
+         dFlux_dWatBelow(iLayer) = 0._rkind !dGroundNetFlux_dGroundWat, does not exist in vegNrgFlux
+         dFlux_dTempBelow(iLayer) = dGroundNetFlux_dGroundTemp
+    
+        case default; err=20; message=trim(message)//'unable to identify upper boundary condition for thermodynamics'; return
+    
+       end select  ! (identifying the upper boundary condition for thermodynamics)
+       !dGroundNetFlux_dGroundWat  = dFlux_dWatBelow(iLayer) ! this is true, but since not used in vegNrgFlux do not define
+       dGroundNetFlux_dGroundTemp = dFlux_dTempBelow(iLayer) ! need this in vegNrgFlux
+    
+      ! ***** the lower boundary
+      else if(iLayer==nLayers)then  ! (lower boundary)
+    
+       ! identify the lower boundary condition
+       select case(ix_bcLowrTdyn)
+    
+        ! * prescribed temperature at the lower boundary
+        case(prescribedTemp)
+         dz = mLayerDepth(iLayer)*0.5_rkind
+         if(ixDerivMethod==analytical)then    ! ** analytical derivatives
+          dFlux_dWatAbove(iLayer)  = -dThermalC_dHydStateAbove * ( lowerBoundTemp - mLayerTempTrial(iLayer) )/dz
+          dFlux_dTempAbove(iLayer) = -dThermalC_dNrgStateAbove * ( lowerBoundTemp - mLayerTempTrial(iLayer) )/dz + iLayerThermalC(iLayer)/dz
+         else                              ! ** numerical derivatives
+          flux0 = -scalarThermCFlux           * ( lowerBoundTemp - mLayerTempTrial(iLayer) )/dz
+          flux1 = -scalarThermCFlux_dWatAbove * ( lowerBoundTemp - mLayerTempTrial(iLayer) )/dz
+          dFlux_dWatAbove(iLayer) = (flux1 - flux0)/dx
+          flux0 = -scalarThermCFlux            * ( lowerBoundTemp -  mLayerTempTrial(iLayer)     )/dz
+          flux1 = -scalarThermCFlux_dTempAbove * ( lowerBoundTemp - (mLayerTempTrial(iLayer)+dx) )/dz
+          dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
+         end if
+    
+         ! * zero flux at the lower boundary
+        case(zeroFlux)
+         dFlux_dWatAbove(iLayer) = 0._rkind
+         dFlux_dTempAbove(iLayer) = 0._rkind
+    
+        case default; err=20; message=trim(message)//'unable to identify lower boundary condition for thermodynamics'; return
+    
+       end select  ! (identifying the lower boundary condition for thermodynamics)
+    
+       ! ***** internal layers
+    
+      else
+       dz = (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+       if(ixDerivMethod==analytical)then    ! ** analytical derivatives
+        dFlux_dWatAbove(iLayer)  = -dThermalC_dHydStateAbove * ( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) )/dz
+        dFlux_dWatBelow(iLayer)  = -dThermalC_dHydStateBelow * ( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) )/dz
+        dFlux_dTempAbove(iLayer) = -dThermalC_dNrgStateAbove * ( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) )/dz + iLayerThermalC(iLayer)/dz
+        dFlux_dTempBelow(iLayer) = -dThermalC_dNrgStateBelow * ( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) )/dz - iLayerThermalC(iLayer)/dz
+       else                              ! ** numerical derivatives
+        flux0 = -scalarThermCFlux          *( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) ) / dz
+        flux1 = -scalarThermCFlux_dWatAbove*( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) ) / dz
+        flux2 = -scalarThermCFlux_dWatBelow*( mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer) ) / dz
+        dFlux_dWatAbove(iLayer) = (flux1 - flux0)/dx
+        dFlux_dWatBelow(iLayer) = (flux2 - flux0)/dx
+        flux0 = -scalarThermCFlux           *( mLayerTempTrial(iLayer+1)     -  mLayerTempTrial(iLayer)    ) / dz
+        flux1 = -scalarThermCFlux_dTempAbove*( mLayerTempTrial(iLayer+1)     - (mLayerTempTrial(iLayer)+dx)) / dz
+        flux2 = -scalarThermCFlux_dTempBelow*((mLayerTempTrial(iLayer+1)+dx) -  mLayerTempTrial(iLayer)    ) / dz
+        dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
+        dFlux_dTempBelow(iLayer) = (flux2 - flux0)/dx
+       end if
+    
+      end if  ! type of layer (upper, internal, or lower)
+    
+     end do  ! (looping through layers)
+    
+     ! -------------------------------------------------------------------------------------------------------------------------
+     ! ***** compute the conductive fluxes at layer interfaces *****
+     ! Compute flux after the derivatives, because need iLayerThermal as calculated above
+     ! -------------------------------------------------------------------------------------------------------------------------
+     do iLayer=ixTop,ixBot ! (loop through model layers)
+    
+      if(iLayer==0)then  ! (upper boundary fluxes -- positive downwards)
+      ! flux depends on the type of upper boundary condition
+       select case(ix_bcUpprTdyn) ! (identify the upper boundary condition for thermodynamics
+        case(prescribedTemp); iLayerConductiveFlux(iLayer) = -iLayerThermalC(iLayer)*( mLayerTempTrial(iLayer+1) - upperBoundTemp )/ &
+                                        (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+        case(zeroFlux);       iLayerConductiveFlux(iLayer) = 0._rkind
+        case(energyFlux);     iLayerConductiveFlux(iLayer) = groundNetFlux !from vegNrgFlux module
+       end select  ! (identifying the lower boundary condition for thermodynamics)
+    
+      else if(iLayer==nLayers)then ! (lower boundary fluxes -- positive downwards)
+       ! flux depends on the type of lower boundary condition
+       select case(ix_bcLowrTdyn) ! (identify the lower boundary condition for thermodynamics
+        case(prescribedTemp); iLayerConductiveFlux(iLayer) = -iLayerThermalC(iLayer)*(lowerBoundTemp - mLayerTempTrial(iLayer))/(mLayerDepth(iLayer)*0.5_rkind)
+        case(zeroFlux);       iLayerConductiveFlux(iLayer) = 0._rkind
+       end select  ! (identifying the lower boundary condition for thermodynamics)
+    
+      else ! (domain boundary fluxes -- positive downwards)
+        iLayerConductiveFlux(iLayer)  = -iLayerThermalC(iLayer)*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer)) / &
+                                        (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+    
+        !write(*,'(a,i4,1x,2(f9.3,1x))') 'iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer) = ', iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer)
+      end if ! (the type of layer)
+     end do  ! looping through layers
+    
+     ! -------------------------------------------------------------------------------------------------------------------------
+     ! ***** compute the advective fluxes at layer interfaces *****
+     ! -------------------------------------------------------------------------------------------------------------------------
+     do iLayer=ixTop,ixBot  !(loop through model layers)
+    
+      if (iLayer==0) then
+       iLayerAdvectiveFlux(iLayer) = realMissing !advective flux at the upper boundary is included in the ground heat flux
+      else ! get the liquid flux at layer interfaces
+       select case(layerType(iLayer))
+        case(iname_snow); qFlux = iLayerLiqFluxSnow(iLayer)
+        case(iname_soil); qFlux = iLayerLiqFluxSoil(iLayer-nSnow)
+        case default; err=20; message=trim(message)//'unable to identify layer type'; return
+       end select
+       ! compute fluxes at the lower boundary -- positive downwards
+       if(iLayer==nLayers)then
+        iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(lowerBoundTemp - mLayerTempTrial(iLayer))
+       ! compute fluxes within the domain -- positive downwards
+       else
+        iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer))
+       end if
+      end if ! (all layers except surface)
+     end do  ! looping through layers
+    
+     ! -------------------------------------------------------------------------------------------------------------------------
+     ! ***** compute the total fluxes at layer interfaces *****
+     ! -------------------------------------------------------------------------------------------------------------------------
+     ! NOTE: ignore advective fluxes for now
+     iLayerNrgFlux(ixTop:ixBot) = iLayerConductiveFlux(ixTop:ixBot)
+     !print*, 'iLayerNrgFlux(0:4) = ', iLayerNrgFlux(0:4)
+    
+     ! end association of local variables with information in the data structures
+     end associate
+    
+     end subroutine ssdNrgFlux
+    
+    
+     ! *************************************************************************************************************************************
+     ! private subroutine iLayerThermalConduct: compute diagnostic energy variables (thermal conductivity and heat capacity) and derivatives
+     ! *************************************************************************************************************************************
+     subroutine iLayerThermalConduct(&
+                           ! input: model control
+                           deriv_desired,             & ! intent(in): flag indicating if derivatives are desired
+                           ixRichards,                & ! intent(in):    choice of option for Richards' equation
+                           ixThCondSnow,              & ! intent(in): choice of method for thermal conductivity of snow
+                           ixThCondSoil,              & ! intent(in): choice of method for thermal conductivity of soil
+                           ! input: coordinate variables
+                           nLayers,                   & ! intent(in): number of layers
+                           ixLayerDesired,            & ! intent(in): layer index for output
+                           layerType,                 & ! intent(in): layer type (iname_soil or iname_snow)
+                           ! input: state variables (adjacent layers)
+                           nodeMatricHead,            & ! intent(in): matric head at the nodes (m)
+                           nodeVolFracLiq,            & ! intent(in): volumetric liquid water content at the nodes (m)
+                           nodeVolFracIce,            & ! intent(in): volumetric ice at the nodes (m)
+                           nodeTemp,                  & ! intent(in): temperature at the nodes (m)
+                           ! input: pre-computed derivatives
+                           dTheta_dTk,                & ! intent(in): derivative in volumetric liquid water content w.r.t. temperature (K-1)
+                           fracLiqSnow,               & ! intent(in)  : fraction of liquid water (-)
+                           dTheta_dPsi,               & ! intent(in): derivative in the soil water characteristic w.r.t. psi (m-1)
+                           dPsi_dTheta,               & ! intent(in): derivative in the soil water characteristic w.r.t. theta (m)
+                           ! input: model coordinate variables (adjacent layers)
+                           nodeHeight,                & ! intent(in): height at the mid-point of the node (m)
+                           node_iHeight,              & ! intent(in): height at the interface of the nodes (m)
+                           ! input: soil parameters at nodes
+                           theta_sat,                 & ! intent(in): soil porosity (-)
+                           iden_soil,                 & !intrinsic density of soil (kg m-3)
+                           thCond_soil,               & ! thermal conductivity of soil (W m-1 K-1)
+                           frac_sand,                 & ! intent(in): fraction of sand (-)
+                           frac_clay,                 & ! fraction of clay (-)
+                           ! input: snow parameters
+                           fixedThermalCond_snow,     & ! intent(in): temporally constant thermal conductivity of snow (W m-1 K-1)
+                           ! output: conductivity at the layer interface (scalars)
+                           iLayerThermalC,            & ! intent(inout) thermal conductivity at the interface of each layer (W m-1 K-1)
+                            ! output: derivatives in thermal conductivity w.r.t. state variables -- matric head or volumetric lquid water -- in the layer above and layer below
+                           dThermalC_dHydStateAbove,  & ! intent(out): derivative in the thermal conductivity w.r.t. water state in the layer above
+                           dThermalC_dHydStateBelow,  & ! intent(out): derivative in the thermal conductivity w.r.t. water state in the layer above
+                          ! output: derivatives in thermal conductivity w.r.t. energy state variables -- now just temperature -- in the layer above and layer below (W m-1 K-2)
+                           dThermalC_dNrgStateAbove,  & ! intent(out): derivative in the thermal conductivity w.r.t. energy state in the layer above
+                           dThermalC_dNrgStateBelow,  & ! intent(out): derivative in the thermal conductivity w.r.t. energy state in the layer above
+                           ! output: error control
+                           err,message)                 ! intent(out): error control
+    
+     USE snow_utils_module,only:tcond_snow     ! compute thermal conductivity of snow
+     USE soil_utils_module,only:crit_soilT     ! compute critical temperature below which ice exists
+     ! constants
+     USE multiconst, only: gravity, &                          ! gravitational acceleration (m s-1)
+                           Tfreeze, &                          ! freezing point of water (K)
+                           iden_water,iden_ice,&               ! intrinsic density of water and ice (kg m-3)
+                           LH_fus                              ! latent heat of fusion (J kg-1)
+    
+     implicit none
+     ! --------------------------------------------------------------------------------------------------------------------------------------
+     ! input: model control
+     logical(lgt),intent(in)          :: deriv_desired             ! flag to indicate if derivatives are desired
+     integer(i4b),intent(in)          :: ixRichards                ! choice of option for Richards' equation
+     integer(i4b),intent(in)          :: ixThCondSnow              ! choice of method for thermal conductivity of snow
+     integer(i4b),intent(in)          :: ixThCondSoil              ! choice of method for thermal conductivity of soil
+     ! input: coordinate variables
+     integer(i4b),intent(in)          :: nLayers                   ! number of layers
+     integer(i4b),intent(in)          :: ixLayerDesired            ! layer index for output
+     integer(i4b),intent(in)          :: layerType(:)              ! layer type (iname_soil or iname_snow)
+     ! input: state variables
+     real(rkind),intent(in)           :: nodeMatricHead(:)         ! trial vector of total water matric potential (m)
+     real(rkind),intent(in)           :: nodeVolFracLiq(:)         ! trial vector of volumetric liquid water content, recomputed with perturbed water state(-)
+     real(rkind),intent(in)           :: nodeVolFracIce(:)         ! trial vector of ice content, recomputed with perturbed water state(-)
+     real(rkind),intent(in)           :: nodeTemp(:)               ! trial vector of temperature (K)
+     ! input: pre-computed derivatives
+     real(rkind),intent(in)           :: dTheta_dTk(:)             ! derivative in volumetric liquid water content w.r.t. temperature (K-1)
+     real(rkind),intent(in)           :: fracLiqSnow(:)            ! fraction of liquid water (-)
+     real(rkind),intent(in)           :: dTheta_dPsi(:)            ! derivative in the soil water characteristic w.r.t. psi (m-1)
+     real(rkind),intent(in)           :: dPsi_dTheta(:)            ! derivative in the soil water characteristic w.r.t. theta (m)
+     ! input: model coordinate variables
+     real(rkind),intent(in)           :: nodeHeight(:)             ! height at the mid-point of the lower node (m)
+     real(rkind),intent(in)           :: node_iHeight(:)           ! height at the interface of each node (m)
+     ! input: soil parameters
+     real(rkind),intent(in)           :: theta_sat(:)              ! soil porosity (-)
+     real(rkind),intent(in)           :: iden_soil(:)              ! intrinsic density of soil (kg m-3)
+     real(rkind),intent(in)           :: thCond_soil(:)            ! thermal conductivity of soil (W m-1 K-1)
+     real(rkind),intent(in)           :: frac_sand(:)              ! intent(in): fraction of sand (-)
+     real(rkind),intent(in)           :: frac_clay(:)              ! fraction of clay (-)
+     ! input: snow parameters
+     real(rkind),intent(in)           :: fixedThermalCond_snow     ! intent(in): temporally constant thermal conductivity of snow (W m-1 K-1)
+     ! output: thermal conductivity at layer interfaces
+     real(rkind),intent(inout)        :: iLayerThermalC            ! thermal conductivity at the interface of each layer (W m-1 K-1)
+     ! output: thermal conductivity derivatives at all layer interfaces
+     real(rkind),intent(out)          :: dThermalC_dHydStateAbove  ! derivatives in the thermal conductivity w.r.t. matric head or volumetric liquid water in the layer above
+     real(rkind),intent(out)          :: dThermalC_dHydStateBelow  ! derivatives in the thermal conductivity w.r.t. matric head or volumetric liquid water in the layer below
+     real(rkind),intent(out)          :: dThermalC_dNrgStateAbove  ! derivatives in the thermal conductivity w.r.t. temperature in the layer above (W m-1 K-2)
+     real(rkind),intent(out)          :: dThermalC_dNrgStateBelow  ! derivatives in the thermal conductivity w.r.t. temperature in the layer below (W m-1 K-2)
+     ! output: error control
+     integer(i4b),intent(out)         :: err                       ! error code
+     character(*),intent(out)         :: message                   ! error message
+     ! --------------------------------------------------------------------------------------------------------------------------------
+     ! local variables (named variables to provide index of 2-element vectors)
+     integer(i4b),parameter           :: ixUpper=1                 ! index of upper node in the 2-element vectors
+     integer(i4b),parameter           :: ixLower=2                 ! index of lower node in the 2-element vectors
+     character(LEN=256)               :: cmessage                  ! error message of downwind routine
+     integer(i4b)                     :: iLayer                    ! index of model layer
+     real(rkind)                      :: TCn                       ! thermal conductivity below the layer interface (W m-1 K-1)
+     real(rkind)                      :: TCp                       ! thermal conductivity above the layer interface (W m-1 K-1)
+     real(rkind)                      :: zdn                       ! height difference between interface and lower value (m)
+     real(rkind)                      :: zdp                       ! height difference between interface and upper value (m)
+     real(rkind)                      :: bulkden_soil              ! bulk density of soil (kg m-3)
+     real(rkind)                      :: lambda_drysoil            ! thermal conductivity of dry soil (W m-1)
+     real(rkind)                      :: lambda_wetsoil            ! thermal conductivity of wet soil (W m-1)
+     real(rkind)                      :: lambda_wet                ! thermal conductivity of the wet material
+     real(rkind)                      :: relativeSat               ! relative saturation (-)
+     real(rkind)                      :: kerstenNum                ! the Kersten number (-), defining weight applied to conductivity of the wet medium
+     real(rkind)                      :: den                       ! denominator in the thermal conductivity calculations
+     real(rkind)                      :: dThermalC_dWat(2)   ! derivative in thermal conductivity w.r.t. matric head or volumetric liquid water
+     real(rkind)                      :: dThermalC_dNrg(2)   ! derivative in thermal conductivity w.r.t. temperature
+     real(rkind)                      :: Tcrit                     ! temperature where all water is unfrozen (K)
+     real(rkind)                      :: dlambda_wet_dWat          ! derivative in thermal conductivity of wet material w.r.t.soil water state variable
+     real(rkind)                      :: dlambda_wet_dTk           ! derivative in thermal conductivity of wet material w.r.t. temperature
+     real(rkind)                      :: dkerstenNum_dWat          ! derivative in Kersten number w.r.t. soil water state variable
+     real(rkind)                      :: mLayerThermalC(2)         ! thermal conductivity of each layer (W m-1 K-1)
+     real(rkind)                      :: dVolFracLiq_dWat    ! derivative in vol fraction of liquid w.r.t. water state variable
+     real(rkind)                      :: dVolFracIce_dWat    ! derivative in vol fraction of ice w.r.t. water state variable
+     real(rkind)                      :: dVolFracLiq_dTk     ! derivative in vol fraction of liquid w.r.t. temperature
+     real(rkind)                      :: dVolFracIce_dTk     ! derivative in vol fraction of ice w.r.t. temperature
+    ! local variables to reproduce the thermal conductivity of Hansson et al. VZJ 2005
+     real(rkind),parameter            :: c1=0.55_rkind             ! optimized parameter from Hansson et al. VZJ 2005 (W m-1 K-1)
+     real(rkind),parameter            :: c2=0.8_rkind              ! optimized parameter from Hansson et al. VZJ 2005 (W m-1 K-1)
+     real(rkind),parameter            :: c3=3.07_rkind             ! optimized parameter from Hansson et al. VZJ 2005 (-)
+     real(rkind),parameter            :: c4=0.13_rkind             ! optimized parameter from Hansson et al. VZJ 2005 (W m-1 K-1)
+     real(rkind),parameter            :: c5=4._rkind               ! optimized parameter from Hansson et al. VZJ 2005 (-)
+     real(rkind),parameter            :: f1=13.05_rkind            ! optimized parameter from Hansson et al. VZJ 2005 (-)
+     real(rkind),parameter            :: f2=1.06_rkind             ! optimized parameter from Hansson et al. VZJ 2005 (-)
+     real(rkind)                      :: fArg,xArg                 ! temporary variables (see Hansson et al. VZJ 2005 for details)
+     real(rkind)                      :: dxArg_dWat,dxArg_dTk      ! derivates of the temporary variables with respect to soil water state variable and temperature
+    
+     ! --------------------------------------------------------------------------------------------------------------------------------
+     ! initialize error control
+     err=0; message="iLayerThermalConduct/"
+    
+     ! loop through layers
+     do iLayer=ixUpper,ixLower
+    
+      ! compute the thermal conductivity of dry and wet soils (W m-1)
+      ! NOTE: this is actually constant over the simulation, and included here for clarity
+      if(ixThCondSoil==funcSoilWet .and. layerType(iLayer)==iname_soil)then
+       bulkden_soil   = iden_soil(iLayer)*( 1._rkind - theta_sat(iLayer) )
+       lambda_drysoil = (0.135_rkind*bulkden_soil + 64.7_rkind) / (iden_soil(iLayer) - 0.947_rkind*bulkden_soil)
+       lambda_wetsoil = (8.80_rkind*frac_sand(iLayer) + 2.92_rkind*frac_clay(iLayer)) / (frac_sand(iLayer) + frac_clay(iLayer))
+      end if
+    
+      ! *****
+      ! * compute the thermal conductivity of snow and soil and derivates at the mid-point of each layer...
+      ! ***************************************************************************************************
+      dThermalC_dWat(iLayer) = 0._rkind
+      dThermalC_dNrg(iLayer) = 0._rkind
+    
+      select case(layerType(iLayer))
+    
+       ! ***** soil
+       case(iname_soil)
+    
+        ! (process derivatives)
+        dVolFracLiq_dWat = 0._rkind
+        dVolFracIce_dWat = 0._rkind
+        dVolFracLiq_dTk  = 0._rkind
+        dVolFracIce_dTk  = 0._rkind
+        if(deriv_desired)then
+         select case(ixRichards)  ! (form of Richards' equation)
+          case(moisture)
+           dVolFracLiq_dWat = 1._rkind
+           dVolFracIce_dWat = dPsi_dTheta(iLayer) - 1._rkind
+          case(mixdform)
+           Tcrit = crit_soilT(nodeMatricHead(iLayer) )
+           if(nodeTemp(iLayer) < Tcrit) then
+            dVolFracLiq_dWat = 0._rkind
+            dVolFracIce_dWat = dTheta_dPsi(iLayer)
+           else
+            dVolFracLiq_dWat = dTheta_dPsi(iLayer)
+            dVolFracIce_dWat = 0._rkind
+           endif
+         end select
+         dVolFracLiq_dTk = dTheta_dTk(iLayer) !already zeroed out if not below critical temperature
+         dVolFracIce_dTk = -dVolFracLiq_dTk !often can and will simplify one of these terms out
+        endif
+    
+        ! select option for thermal conductivity of soil
+        select case(ixThCondSoil)
+    
+         ! ** function of soil wetness
+         case(funcSoilWet)
+    
+          ! compute the thermal conductivity of the wet material (W m-1)
+          lambda_wet  = lambda_wetsoil**( 1._rkind - theta_sat(iLayer) ) * lambda_water**theta_sat(iLayer) * lambda_ice**(theta_sat(iLayer) - nodeVolFracLiq(iLayer))
+          dlambda_wet_dWat = -lambda_wet * log(lambda_ice) * dVolFracLiq_dWat
+          dlambda_wet_dTk  = -lambda_wet * log(lambda_ice) * dVolFracLiq_dTk
+    
+          relativeSat = (nodeVolFracIce(iLayer) + nodeVolFracLiq(iLayer))/theta_sat(iLayer)  ! relative saturation
+          ! drelativeSat_dWat = dPsi0_dWat/theta_sat(iLayer), and drelativeSat_dTk = 0 (so dkerstenNum_dTk = 0)
+          ! compute the Kersten number (-)
+          if(relativeSat > 0.1_rkind)then ! log10(0.1) = -1
+           kerstenNum = log10(relativeSat) + 1._rkind
+           dkerstenNum_dWat = (dVolFracIce_dWat + dVolFracLiq_dWat) / ( theta_sat(iLayer) * relativeSat * log(10._rkind) )
+          else
+           kerstenNum = 0._rkind  ! dry thermal conductivity
+           dkerstenNum_dWat = 0._rkind
+          endif
+          ! ...and, compute the thermal conductivity
+          mLayerThermalC(iLayer) = kerstenNum*lambda_wet + (1._rkind - kerstenNum)*lambda_drysoil
+    
+          ! compute derivatives
+          dThermalC_dWat(iLayer) = dkerstenNum_dWat * ( lambda_wet - lambda_drysoil ) + kerstenNum*dlambda_wet_dWat
+          dThermalC_dNrg(iLayer) = kerstenNum*dlambda_wet_dTk
+    
+         ! ** mixture of constituents
+         case(mixConstit)
+          mLayerThermalC(iLayer) = thCond_soil(iLayer) * ( 1._rkind - theta_sat(iLayer) ) + & ! soil component
+                                   lambda_ice         * nodeVolFracIce(iLayer)     + & ! ice component
+                                   lambda_water       * nodeVolFracLiq(iLayer)     + & ! liquid water component
+                                   lambda_air         * ( theta_sat(iLayer) - (nodeVolFracIce(iLayer) + nodeVolFracLiq(iLayer)) ) ! air component
+          ! compute derivatives
+          dThermalC_dWat(iLayer) = lambda_ice*dVolFracIce_dWat + lambda_water*dVolFracLiq_dWat + lambda_air*(-dVolFracIce_dWat - dVolFracLiq_dWat)
+          dThermalC_dNrg(iLayer) = (lambda_ice - lambda_water) * dVolFracIce_dTk
+    
+         ! ** test case for the mizoguchi lab experiment, Hansson et al. VZJ 2004
+         case(hanssonVZJ)
+          fArg  = 1._rkind + f1*nodeVolFracIce(iLayer)**f2
+          xArg  = nodeVolFracLiq(iLayer) + fArg*nodeVolFracIce(iLayer)
+          dxArg_dWat = dVolFracLiq_dWat + dVolFracIce_dWat * (1._rkind + f1*(f2+1)*nodeVolFracIce(iLayer)**f2)
+          dxArg_dTk  = dVolFracIce_dTk * f1*(f2+1)*nodeVolFracIce(iLayer)**f2
+          ! ...and, compute the thermal conductivity
+          mLayerThermalC(iLayer) = c1 + c2*xArg + (c1 - c4)*exp(-(c3*xArg)**c5)
+    
+          ! compute derivatives
+          dThermalC_dWat(iLayer) = ( c2 - c5*c3*(c3*xArg)**(c5-1)*(c1 - c4)*exp(-(c3*xArg)**c5) ) * dxArg_dWat
+          dThermalC_dNrg(iLayer) = ( c2 - c5*c3*(c3*xArg)**(c5-1)*(c1 - c4)*exp(-(c3*xArg)**c5) ) * dxArg_dTk
+    
+         ! ** check
+         case default; err=20; message=trim(message)//'unable to identify option for thermal conductivity of soil'; return
+    
+        end select  ! option for the thermal conductivity of soil
+    
+       ! ***** snow
+       case(iname_snow)
+        dVolFracIce_dWat = ( 1._rkind - fracLiqSnow(iLayer) )*(iden_water/iden_ice)
+        dVolFracIce_dTk = -dTheta_dTk(iLayer)*(iden_water/iden_ice)
+    
+        ! temporally constant thermal conductivity
+        if(ixThCondSnow==Smirnova2000)then
+         mLayerThermalC(iLayer) = fixedThermalCond_snow
+         dThermalC_dWat(iLayer) = 0._rkind
+         dThermalC_dNrg(iLayer) = 0._rkind
+        ! thermal conductivity as a function of snow density
+        else
+         call tcond_snow(nodeVolFracIce(iLayer)*iden_ice,  & ! input: snow density (kg m-3)
+                         mLayerThermalC(iLayer),             & ! output: thermal conductivity (W m-1 K-1)
+                         err,cmessage)                         ! output: error control
+         if(err/=0)then; message=trim(message)//trim(cmessage); return; end if
+    
+         select case(ixThCondSnow)
+          case(Yen1965)
+           dThermalC_dWat(iLayer) = 2._rkind * 3.217d-6 * nodeVolFracIce(iLayer) * iden_ice**2._rkind * dVolFracIce_dWat
+           dThermalC_dNrg(iLayer) = 2._rkind * 3.217d-6 * nodeVolFracIce(iLayer) * iden_ice**2._rkind * dVolFracIce_dTk
+          case(Mellor1977)
+           dThermalC_dWat(iLayer) = 2._rkind * 2.576d-6 * nodeVolFracIce(iLayer) * iden_ice**2._rkind * dVolFracIce_dWat
+           dThermalC_dNrg(iLayer) = 2._rkind * 2.576d-6 * nodeVolFracIce(iLayer) * iden_ice**2._rkind * dVolFracIce_dTk
+          case(Jordan1991)
+           dThermalC_dWat(iLayer) = ( 7.75d-5 + 2._rkind * 1.105d-6 * nodeVolFracIce(iLayer) * iden_ice ) * (lambda_ice-lambda_air) * iden_ice * dVolFracIce_dWat
+           dThermalC_dNrg(iLayer) = ( 7.75d-5 + 2._rkind * 1.105d-6 * nodeVolFracIce(iLayer) * iden_ice ) * (lambda_ice-lambda_air) * iden_ice * dVolFracIce_dTk
+         end select  ! option for the thermal conductivity of snow
+        end if
+    
+       ! * error check
+       case default; err=20; message=trim(message)//'unable to identify type of layer (snow or soil) to compute thermal conductivity'; return
+    
+      end select
+      !print*, 'iLayer, mLayerThermalC(iLayer) = ', iLayer, mLayerThermalC(iLayer)
+    
+     end do  ! looping through layers
+     !pause
+    
+     ! *****
+     ! * compute the thermal conductivity of snow at the interface of each layer...
+     ! ****************************************************************************
+     if (ixLayerDesired==0) then
+      ! special case of hansson
+      if(ixThCondSoil==hanssonVZJ)then
+       iLayerThermalC = 28._rkind*(0.5_rkind*(node_iHeight(ixLower) - node_iHeight(ixUpper))) ! these are indices 1,0 since was passed with 0:1
+       dThermalC_dHydStateBelow = 0._rkind
+       dThermalC_dNrgStateBelow = 0._rkind
+      else
+       iLayerThermalC = mLayerThermalC(ixUpper) ! index was passed with 1:1
+       dThermalC_dHydStateBelow = dThermalC_dWat(ixUpper)
+       dThermalC_dNrgStateBelow = dThermalC_dNrg(ixUpper)
+      end if
+      dThermalC_dHydStateAbove = realMissing
+      dThermalC_dNrgStateAbove = realMissing
+     else if (ixLayerDesired==nLayers ) then
+      ! assume the thermal conductivity at the domain boundaries is equal to the thermal conductivity of the layer
+      iLayerThermalC = mLayerThermalC(ixLower) ! index was passed with iLayers:iLayers
+      dThermalC_dHydStateAbove = dThermalC_dWat(ixLower)
+      dThermalC_dNrgStateAbove = dThermalC_dNrg(ixLower)
+      dThermalC_dHydStateBelow = realMissing
+      dThermalC_dNrgStateBelow = realMissing
+     else
+      ! get temporary variables
+      TCn = mLayerThermalC(ixUpper)    ! thermal conductivity below the layer interface (W m-1 K-1)
+      TCp = mLayerThermalC(ixLower)  ! thermal conductivity above the layer interface (W m-1 K-1)
+      zdn = node_iHeight(ixUpper)   - nodeHeight(ixUpper) ! height difference between interface and lower value (m)
+      zdp = nodeHeight(ixLower) - node_iHeight(ixUpper) ! height difference between interface and upper value (m)
+      den = TCn*zdp + TCp*zdn  ! denominator
+      ! compute thermal conductivity
+      if(TCn+TCp > epsilon(TCn))then
+       iLayerThermalC = (TCn*TCp*(zdn + zdp)) / den
+       dThermalC_dHydStateBelow = ( TCn*(zdn + zdp) - iLayerThermalC*zdn ) / den * dThermalC_dWat(ixLower)
+       dThermalC_dHydStateAbove = ( TCp*(zdn + zdp) - iLayerThermalC*zdp ) / den * dThermalC_dWat(ixUpper)
+       dThermalC_dNrgStateBelow = ( TCn*(zdn + zdp) - iLayerThermalC*zdn ) / den * dThermalC_dNrg(ixLower)
+       dThermalC_dNrgStateAbove = ( TCp*(zdn + zdp) - iLayerThermalC*zdp ) / den * dThermalC_dNrg(ixUpper)
+      else
+       iLayerThermalC = (TCn*zdn +  TCp*zdp) / (zdn + zdp)
+       dThermalC_dHydStateBelow = zdp / (zdn + zdp) * dThermalC_dWat(ixLower)
+       dThermalC_dHydStateAbove = zdn / (zdn + zdp) * dThermalC_dWat(ixUpper)
+       dThermalC_dNrgStateBelow = zdp / (zdn + zdp) * dThermalC_dNrg(ixLower)
+       dThermalC_dNrgStateAbove = zdn / (zdn + zdp) * dThermalC_dNrg(ixUpper)
+      end if
+      !write(*,'(a,1x,i4,1x,10(f9.3,1x))') 'iLayer, TCn, TCp, zdn, zdp, iLayerThermalC(iLayer) = ', iLayer, TCn, TCp, zdn, zdp, iLayerThermalC(iLayer)
+     endif
+    
+     end subroutine iLayerThermalConduct
+    
+    
+    
+    end module ssdNrgFlux_module
+    
+    
\ No newline at end of file
diff --git a/build/source/engine/ssdNrgFlux_old.f90 b/build/source/engine/ssdNrgFlux_old.f90
new file mode 100755
index 0000000..25fc68e
--- /dev/null
+++ b/build/source/engine/ssdNrgFlux_old.f90
@@ -0,0 +1,307 @@
+! 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 ssdNrgFlux_module
+
+! data types
+USE nrtype
+
+! data types
+USE data_types,only:var_d           ! x%var(:)       (dp)
+USE data_types,only:var_dlength     ! x%var(:)%dat   (dp)
+USE data_types,only:var_ilength     ! x%var(:)%dat   (i4b)
+
+! physical constants
+USE multiconst,only:&
+                    sb,          & ! Stefan Boltzman constant      (W m-2 K-4)
+                    Em_Sno,      & ! emissivity of snow            (-)
+                    Cp_air,      & ! specific heat of air          (J kg-1 K-1)
+                    Cp_water,    & ! specifric heat of water       (J kg-1 K-1)
+                    LH_fus,      & ! latent heat of fusion         (J kg-1)
+                    LH_vap,      & ! latent heat of vaporization   (J kg-1)
+                    LH_sub,      & ! latent heat of sublimation    (J kg-1)
+                    gravity,     & ! gravitational acceleteration  (m s-2)
+                    Tfreeze,     & ! freezing point of pure water  (K)
+                    iden_air,    & ! intrinsic density of air      (kg m-3)
+                    iden_ice,    & ! intrinsic density of ice      (kg m-3)
+                    iden_water     ! intrinsic density of water    (kg m-3)
+
+! missing values
+USE globalData,only:integerMissing  ! missing integer
+USE globalData,only:realMissing     ! missing real number
+
+! named variables for snow and soil
+USE globalData,only:iname_snow     ! named variables for snow
+USE globalData,only:iname_soil     ! named variables for soil
+
+! named variables
+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
+USE var_lookup,only:iLookINDEX      ! named variables for structure elements
+
+! model decisions
+USE globalData,only:model_decisions                         ! model decision structure
+USE var_lookup,only:iLookDECISIONS                          ! named variables for elements of the decision structure
+
+! provide access to look-up values for model decisions
+USE mDecisions_module,only:      &
+ ! look-up values for the numerical method
+ iterative,                      & ! iterative
+ nonIterative,                   & ! non-iterative
+ iterSurfEnergyBal,              & ! iterate only on the surface energy balance
+ ! look-up values for method used to compute derivative
+ numerical,                      & ! numerical solution
+ analytical,                     & ! analytical solution
+ ! look-up values for choice of boundary conditions for thermodynamics
+ prescribedTemp,                 & ! prescribed temperature
+ energyFlux,                     & ! energy flux
+ zeroFlux,                       & ! zero flux
+ ! look-up values for choice of boundary conditions for soil hydrology
+ prescribedHead                    ! prescribed head
+
+! -------------------------------------------------------------------------------------------------
+implicit none
+private
+public::ssdNrgFlux
+! global parameters
+real(dp),parameter            :: dx=1.e-10_dp             ! finite difference increment (K)
+real(dp),parameter            :: valueMissing=-9999._dp   ! missing value parameter
+contains
+
+ ! ************************************************************************************************
+ ! public subroutine ssdNrgFlux: compute energy fluxes and derivatives at layer interfaces
+ ! ************************************************************************************************
+ subroutine ssdNrgFlux(&
+                       ! input: model control
+                       scalarSolution,                     & ! intent(in):    flag to indicate the scalar solution
+                       ! input: fluxes and derivatives at the upper boundary
+                       groundNetFlux,                      & ! intent(in):    total flux at the ground surface (W m-2)
+                       dGroundNetFlux_dGroundTemp,         & ! intent(in):    derivative in total ground surface flux w.r.t. ground temperature (W m-2 K-1)
+                       ! input: liquid water fluxes
+                       iLayerLiqFluxSnow,                  & ! intent(in):    liquid flux at the interface of each snow layer (m s-1)
+                       iLayerLiqFluxSoil,                  & ! intent(in):    liquid flux at the interface of each soil layer (m s-1)
+                       ! input: trial value of model state variabes
+                       mLayerTempTrial,                    & ! intent(in):    trial temperature at the current iteration (K)
+                       mLayerMatricHeadTrial,              & ! intent(in):    trial matric head at the current iteration(m)
+                       mLayerVolFracLiqTrial,              & ! intent(in):    trial volumetric fraction of liquid water at the current iteration(-)
+                       mLayerVolFracIceTrial,              & ! intent(in):    trial volumetric fraction of ice water at the current iteration(-)
+                       ! input-output: data structures
+                       mpar_data,                          & ! intent(in):    model parameters
+                       indx_data,                          & ! intent(in):    model indices
+                       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: fluxes and derivatives at all layer interfaces
+                       iLayerNrgFlux,                      & ! intent(out):   energy flux at the layer interfaces (W m-2)
+                       dFlux_dTempAbove,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer above (W m-2 K-1)
+                       dFlux_dTempBelow,                   & ! intent(out):   derivatives in the flux w.r.t. temperature in the layer below (W m-2 K-1)
+                       ! output: error control
+                       err,message)                          ! intent(out): error control
+ implicit none
+ ! input: model control
+ logical(lgt),intent(in)         :: scalarSolution             ! flag to denote if implementing the scalar solution
+ ! input: fluxes and derivatives at the upper boundary
+ real(dp),intent(in)             :: groundNetFlux              ! net energy flux for the ground surface (W m-2)
+ real(dp),intent(in)             :: dGroundNetFlux_dGroundTemp ! derivative in net ground flux w.r.t. ground temperature (W m-2 K-1)
+ ! input: liquid water fluxes
+ real(dp),intent(in)             :: iLayerLiqFluxSnow(0:)      ! intent(in): liquid flux at the interface of each snow layer (m s-1)
+ real(dp),intent(in)             :: iLayerLiqFluxSoil(0:)      ! intent(in): liquid flux at the interface of each soil layer (m s-1)
+ ! input: trial value of model state variables
+ real(dp),intent(in)             :: mLayerTempTrial(:)         ! trial temperature of each snow/soil layer at the current iteration (K)
+ real(dp),intent(in)             :: mLayerMatricHeadTrial(:)   ! matric head in each layer at the current iteration (m)
+ real(dp),intent(in)             :: mLayerVolFracLiqTrial(:)   ! volumetric fraction of liquid at the current iteration (-)
+ real(dp),intent(in)             :: mLayerVolFracIceTrial(:)   ! volumetric fraction of ice at the current iteration (-)
+ ! input-output: data structures
+ type(var_dlength),intent(in)    :: mpar_data                  ! model parameters
+ type(var_ilength),intent(in)    :: indx_data                  ! state vector geometry
+ 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: fluxes and derivatives at all layer interfaces
+ real(dp),intent(out)            :: iLayerNrgFlux(0:)          ! energy flux at the layer interfaces (W m-2)
+ real(dp),intent(out)            :: dFlux_dTempAbove(0:)       ! derivatives in the flux w.r.t. temperature in the layer above (J m-2 s-1 K-1)
+ real(dp),intent(out)            :: dFlux_dTempBelow(0:)       ! derivatives in the flux w.r.t. temperature in the layer below (J m-2 s-1 K-1)
+ ! output: error control
+ integer(i4b),intent(out)        :: err                        ! error code
+ character(*),intent(out)        :: message                    ! error message
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! local variables
+ integer(i4b)                    :: iLayer                     ! index of model layers
+ integer(i4b)                    :: ixLayerDesired(1)          ! layer desired (scalar solution)
+ integer(i4b)                    :: ixTop                      ! top layer in subroutine call
+ integer(i4b)                    :: ixBot                      ! bottom layer in subroutine call
+ real(dp)                        :: qFlux                      ! liquid flux at layer interfaces (m s-1)
+ real(dp)                        :: dz                         ! height difference (m)
+ real(dp)                        :: flux0,flux1,flux2          ! fluxes used to calculate derivatives (W m-2)
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! make association of local variables with information in the data structures
+ associate(&
+  ix_fDerivMeth        => model_decisions(iLookDECISIONS%fDerivMeth)%iDecision, & ! intent(in): method used to calculate flux derivatives
+  ix_bcLowrTdyn        => model_decisions(iLookDECISIONS%bcLowrTdyn)%iDecision, & ! intent(in): method used to calculate the lower boundary condition for thermodynamics
+  ! input: model coordinates
+  nSnow                => indx_data%var(iLookINDEX%nSnow)%dat(1),               & ! intent(in): number of snow layers
+  nLayers              => indx_data%var(iLookINDEX%nLayers)%dat(1),             & ! intent(in): total number of layers
+  layerType            => indx_data%var(iLookINDEX%layerType)%dat,              & ! intent(in): layer type (iname_soil or iname_snow)
+  ixLayerState         => indx_data%var(iLookINDEX%ixLayerState)%dat,           & ! intent(in): list of indices for all model layers
+  ixSnowSoilNrg        => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat,          & ! intent(in): index in the state subset for energy state variables in the snow+soil domain
+  ! input: thermal properties
+  mLayerDepth          => prog_data%var(iLookPROG%mLayerDepth)%dat,             & ! intent(in): depth of each layer (m)
+  mLayerHeight         => prog_data%var(iLookPROG%mLayerHeight)%dat,            & ! intent(in): height at the mid-point of each layer (m)
+  iLayerThermalC       => diag_data%var(iLookDIAG%iLayerThermalC)%dat,          & ! intent(in): thermal conductivity at the interface of each layer (W m-1 K-1)
+  lowerBoundTemp       => mpar_data%var(iLookPARAM%lowerBoundTemp)%dat(1),      & ! intent(in): temperature of the lower boundary (K)
+  ! output: diagnostic fluxes
+  iLayerConductiveFlux => flux_data%var(iLookFLUX%iLayerConductiveFlux)%dat,    & ! intent(out): conductive energy flux at layer interfaces at end of time step (W m-2)
+  iLayerAdvectiveFlux  => flux_data%var(iLookFLUX%iLayerAdvectiveFlux)%dat      & ! intent(out): advective energy flux at layer interfaces at end of time step (W m-2)
+ )  ! association of local variables with information in the data structures
+ ! ------------------------------------------------------------------------------------------------------------------------------------------------------
+ ! initialize error control
+ err=0; message='ssdNrgFlux/'
+
+ ! set conductive and advective fluxes to missing in the upper boundary
+ ! NOTE: advective flux at the upper boundary is included in the ground heat flux
+ iLayerConductiveFlux(0) = valueMissing
+ iLayerAdvectiveFlux(0)  = valueMissing
+
+ ! get the indices for the snow+soil layers
+ if(scalarSolution)then
+  ixLayerDesired = pack(ixLayerState, ixSnowSoilNrg/=integerMissing)
+  ixTop = ixLayerDesired(1)
+  ixBot = ixLayerDesired(1)
+ else
+  ixTop = 1
+  ixBot = nLayers
+ endif
+
+ ! -------------------------------------------------------------------------------------------------------------------------
+ ! ***** compute the conductive fluxes at layer interfaces *****
+ ! -------------------------------------------------------------------------------------------------------------------------
+ do iLayer=ixTop,ixBot ! (loop through model layers)
+
+  ! compute fluxes at the lower boundary -- positive downwards
+  if(iLayer==nLayers)then
+   ! flux depends on the type of lower boundary condition
+   select case(ix_bcLowrTdyn) ! (identify the lower boundary condition for thermodynamics
+    case(prescribedTemp); iLayerConductiveFlux(nLayers) = -iLayerThermalC(iLayer)*(lowerBoundTemp - mLayerTempTrial(iLayer))/(mLayerDepth(iLayer)*0.5_dp)
+    case(zeroFlux);       iLayerConductiveFlux(nLayers) = 0._dp
+    case default;         err=20; message=trim(message)//'unable to identify lower boundary condition for thermodynamics'; return
+   end select  ! (identifying the lower boundary condition for thermodynamics)
+
+  ! compute fluxes within the domain -- positive downwards
+  else
+    iLayerConductiveFlux(iLayer)  = -iLayerThermalC(iLayer)*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer)) / &
+                                    (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+
+    !write(*,'(a,i4,1x,2(f9.3,1x))') 'iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer) = ', iLayer, iLayerConductiveFlux(iLayer), iLayerThermalC(iLayer)
+  end if ! (the type of layer)
+ end do
+
+ ! -------------------------------------------------------------------------------------------------------------------------
+ ! ***** compute the advective fluxes at layer interfaces *****
+ ! -------------------------------------------------------------------------------------------------------------------------
+ do iLayer=ixTop,ixBot
+  ! get the liquid flux at layer interfaces
+  select case(layerType(iLayer))
+   case(iname_snow); qFlux = iLayerLiqFluxSnow(iLayer)
+   case(iname_soil); qFlux = iLayerLiqFluxSoil(iLayer-nSnow)
+   case default; err=20; message=trim(message)//'unable to identify layer type'; return
+  end select
+  ! compute fluxes at the lower boundary -- positive downwards
+  if(iLayer==nLayers)then
+   iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(lowerBoundTemp - mLayerTempTrial(iLayer))
+  ! compute fluxes within the domain -- positive downwards
+  else
+   iLayerAdvectiveFlux(iLayer) = -Cp_water*iden_water*qFlux*(mLayerTempTrial(iLayer+1) - mLayerTempTrial(iLayer))
+  end if
+ end do  ! looping through layers
+
+ ! -------------------------------------------------------------------------------------------------------------------------
+ ! ***** compute the total fluxes at layer interfaces *****
+ ! -------------------------------------------------------------------------------------------------------------------------
+ ! NOTE: ignore advective fluxes for now
+ iLayerNrgFlux(0)           = groundNetFlux
+ iLayerNrgFlux(ixTop:ixBot) = iLayerConductiveFlux(ixTop:ixBot)
+ !print*, 'iLayerNrgFlux(0:4) = ', iLayerNrgFlux(0:4)
+
+ ! -------------------------------------------------------------------------------------------------------------------------
+ ! ***** compute the derivative in fluxes at layer interfaces w.r.t temperature in the layer above and the layer below *****
+ ! -------------------------------------------------------------------------------------------------------------------------
+
+ ! initialize un-used elements
+ dFlux_dTempBelow(nLayers) = -huge(lowerBoundTemp)  ! don't expect this to be used, so deliberately set to a ridiculous value to cause problems
+
+ ! ***** the upper boundary
+ dFlux_dTempBelow(0) = dGroundNetFlux_dGroundTemp
+
+ ! loop through INTERFACES...
+ do iLayer=ixTop,ixBot
+
+  ! ***** the lower boundary
+  if(iLayer==nLayers)then  ! (lower boundary)
+
+   ! identify the lower boundary condition
+   select case(ix_bcLowrTdyn)
+
+    ! * prescribed temperature at the lower boundary
+    case(prescribedTemp)
+
+     dz = mLayerDepth(iLayer)*0.5_dp
+     if(ix_fDerivMeth==analytical)then    ! ** analytical derivatives
+      dFlux_dTempAbove(iLayer) = iLayerThermalC(iLayer)/dz
+     else                              ! ** numerical derivatives
+      flux0 = -iLayerThermalC(iLayer)*(lowerBoundTemp - (mLayerTempTrial(iLayer)   ))/dz
+      flux1 = -iLayerThermalC(iLayer)*(lowerBoundTemp - (mLayerTempTrial(iLayer)+dx))/dz
+      dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
+     end if
+
+     ! * zero flux at the lower boundary
+     case(zeroFlux)
+      dFlux_dTempAbove(iLayer) = 0._dp
+
+     case default; err=20; message=trim(message)//'unable to identify lower boundary condition for thermodynamics'; return
+
+   end select  ! (identifying the lower boundary condition for thermodynamics)
+
+  ! ***** internal layers
+  else
+   dz = (mLayerHeight(iLayer+1) - mLayerHeight(iLayer))
+   if(ix_fDerivMeth==analytical)then    ! ** analytical derivatives
+    dFlux_dTempAbove(iLayer) =  iLayerThermalC(iLayer)/dz
+    dFlux_dTempBelow(iLayer) = -iLayerThermalC(iLayer)/dz
+   else                              ! ** numerical derivatives
+    flux0 = -iLayerThermalC(iLayer)*( mLayerTempTrial(iLayer+1)     -  mLayerTempTrial(iLayer)    ) / dz
+    flux1 = -iLayerThermalC(iLayer)*( mLayerTempTrial(iLayer+1)     - (mLayerTempTrial(iLayer)+dx)) / dz
+    flux2 = -iLayerThermalC(iLayer)*((mLayerTempTrial(iLayer+1)+dx) -  mLayerTempTrial(iLayer)    ) / dz
+    dFlux_dTempAbove(iLayer) = (flux1 - flux0)/dx
+    dFlux_dTempBelow(iLayer) = (flux2 - flux0)/dx
+   end if
+
+  end if  ! type of layer (upper, internal, or lower)
+
+ end do  ! (looping through layers)
+
+ ! end association of local variables with information in the data structures
+ end associate
+
+ end subroutine ssdNrgFlux
+
+end module ssdNrgFlux_module
+
diff --git a/build/source/engine/sundials/computEnthalpy.f90 b/build/source/engine/sundials/computEnthalpy.f90
index d76bbaa..41aedaa 100644
--- a/build/source/engine/sundials/computEnthalpy.f90
+++ b/build/source/engine/sundials/computEnthalpy.f90
@@ -137,7 +137,7 @@ contains
  )
  
  if(computeVegFlux)then
-	scalarCanopyEnthalpyPrime = heatCapVeg * scalarCanopyTempPrime - LH_fus*scalarCanopyIcePrime/canopyDepth
+    scalarCanopyEnthalpyPrime = heatCapVeg * scalarCanopyTempPrime - LH_fus*scalarCanopyIcePrime/canopyDepth
  end if
   ! (loop through non-missing energy state variables in the snow+soil domain)
   do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   
diff --git a/build/source/engine/sundials/computHeatCap.f90 b/build/source/engine/sundials/computHeatCap.f90
index 5e880c5..1c8440c 100644
--- a/build/source/engine/sundials/computHeatCap.f90
+++ b/build/source/engine/sundials/computHeatCap.f90
@@ -34,15 +34,15 @@ USE var_lookup,only:iLookPARAM,iLookDIAG,iLookINDEX  ! named variables for struc
 
 ! physical constants
 USE multiconst,only:&
-					Tfreeze, 	 & ! freezing point of water (K)
-                    iden_air,    & ! intrinsic density of air      (kg m-3)
-                    iden_ice,    & ! intrinsic density of ice      (kg m-3)
-                    iden_water,  & ! intrinsic density of water    (kg m-3)
-                    ! specific heat
-                    Cp_air,      & ! specific heat of air          (J kg-1 K-1)
-                    Cp_ice,      & ! specific heat of ice          (J kg-1 K-1)
-                    Cp_soil,     & ! specific heat of soil         (J kg-1 K-1)
-                    Cp_water       ! specific heat of liquid water (J kg-1 K-1)
+                     Tfreeze,     & ! freezing point of water (K)
+                     iden_air,    & ! intrinsic density of air      (kg m-3)
+                     iden_ice,    & ! intrinsic density of ice      (kg m-3)
+                     iden_water,  & ! intrinsic density of water    (kg m-3)
+                     ! specific heat
+                     Cp_air,      & ! specific heat of air          (J kg-1 K-1)
+                     Cp_ice,      & ! specific heat of ice          (J kg-1 K-1)
+                     Cp_soil,     & ! specific heat of soil         (J kg-1 K-1)
+                     Cp_water       ! specific heat of liquid water (J kg-1 K-1)
 ! named variables to describe the state variable type
 USE globalData,only:iname_nrgCanair  ! named variable defining the energy of the canopy air space
 USE globalData,only:iname_nrgCanopy  ! named variable defining the energy of the vegetation canopy
@@ -405,7 +405,7 @@ contains
                        computeVegFlux,          & ! intent(in): flag to denote if computing the vegetation flux
                        ! input: state variables
                        scalarCanopyTemp,        & ! intent(in)
-                       mLayerTemp,       		& ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
+                       mLayerTemp,              & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
                        mLayerMatricHead,        & ! intent(in)
                        ! input data structures
                        mpar_data,               & ! intent(in):    model parameters
@@ -484,9 +484,9 @@ snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)   & !
     g2 = mLayerTemp(iLayer) - Tfreeze
     Tcrit = crit_soilT( mLayerMatricHead(iSoil) )
     if( mLayerTemp(iLayer) < Tcrit)then
-    	mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air) * g2
+      mLayerCm(iLayer) = (iden_ice * Cp_ice - iden_air * Cp_air) * g2
     else
-    	mLayerCm(iLayer) = (iden_water * Cp_water - iden_air * Cp_air) * g2
+      mLayerCm(iLayer) = (iden_water * Cp_water - iden_air * Cp_air) * g2
     end if
     
    case(iname_snow)
diff --git a/build/source/engine/sundials/soil_utilsSundials.f90 b/build/source/engine/sundials/soil_utilsSundials.f90
index 9c02f31..0d06b2c 100644
--- a/build/source/engine/sundials/soil_utilsSundials.f90
+++ b/build/source/engine/sundials/soil_utilsSundials.f90
@@ -59,7 +59,6 @@ contains
                        vGn_alpha,vGn_n,theta_sat,theta_res,vGn_m,& ! intent(in)    : soil parameters
                        dVolTot_dPsi0                            ,& ! intent(in)    : derivative in the soil water characteristic (m-1)
                        dTheta_dT                                ,& ! intent(in)    : derivative in volumetric total water w.r.t. temperature (K-1)
-                       tempPrime                                ,& ! intent(in)
                        volFracLiqPrime                          ,& ! intent(in)
                        volFracIcePrime                          ,& ! intent(in)
                        ! output
@@ -78,7 +77,6 @@ contains
  real(rkind),intent(in)            :: vGn_alpha,vGn_n,theta_sat,theta_res,vGn_m ! soil parameters
  real(rkind),intent(in)  ,optional :: dVolTot_dPsi0                             ! derivative in the soil water characteristic (m-1)
  real(rkind),intent(in)  ,optional :: dTheta_dT                                 ! derivative in volumetric total water w.r.t. temperature (K-1)
- real(rkind),intent(in)            :: TempPrime
  real(rkind),intent(in)            :: volFracLiqPrime
  real(rkind),intent(in)            :: volFracIcePrime
  ! output
@@ -163,10 +161,7 @@ contains
    ! (compute the derivative in the liquid water matric potential w.r.t. temperature)
    dEffSat_dTemp = -dTheta_dT*xNum/(xDen**2._rkind) + dTheta_dT/xDen
    dPsiLiq_dTemp = dPsiLiq_dEffSat*dEffSat_dTemp
-  ! matricHeadLiqPrime = dPsiLiq_dTemp * tempPrime
-
-
-
+   
   endif  ! if dPsiLiq_dTemp is desired
 
  ! ** unfrozen soil
diff --git a/build/source/engine/sundials/updatStateSundials.f90 b/build/source/engine/sundials/updatStateSundials.f90
index 51a3ead..c02a1b0 100644
--- a/build/source/engine/sundials/updatStateSundials.f90
+++ b/build/source/engine/sundials/updatStateSundials.f90
@@ -232,7 +232,6 @@ contains
  ! *************************************************************************************************************
  subroutine updateSoilSundials2(&
                        ! input
-                       dt_cur                ,& ! intent(in): time step
                        mLayerTemp            ,& ! intent(in): temperature vector (K)
                        mLayerMatricHead      ,& ! intent(in): total water matric potential (m)
                        mLayerTempPrime       ,& ! intent(in): temperature time derivative (K/s)
@@ -256,7 +255,6 @@ contains
  USE soil_utils_module,only:dTheta_dPsi
  implicit none
  ! input variables
- real(rkind),intent(in)           :: dt_cur
  real(rkind),intent(in)           :: mLayerTemp           ! estimate of temperature (K)
  real(rkind),intent(in)           :: mLayerMatricHead     ! matric head (m)
  real(rkind),intent(in)           :: mLayerTempPrime      ! temperature time derivative (K/s)
diff --git a/build/source/engine/sundials/updateVars4JacDAE.f90 b/build/source/engine/sundials/updateVars4JacDAE.f90
index 734483c..6ff6bc7 100644
--- a/build/source/engine/sundials/updateVars4JacDAE.f90
+++ b/build/source/engine/sundials/updateVars4JacDAE.f90
@@ -572,7 +572,6 @@ contains
 
       ! compute volumetric fraction of liquid water and ice
       call updateSoilSundials2(&
-                      dt,                                                & ! intent(in) : time step
                       xTemp,                                             & ! intent(in) : temperature (K)
                       mLayerMatricHeadTrial(ixControlIndex),             & ! intent(in) : total water matric potential (m)
                       mLayerTempPrime(iLayer),                           & ! intent(in) : temperature time derivative (K/s)
@@ -756,7 +755,6 @@ contains
                     vGn_alpha(ixControlIndex),vGn_n(ixControlIndex),theta_sat(ixControlIndex),theta_res(ixControlIndex),vGn_m(ixControlIndex), & ! intent(in) : soil parameters
                     dVolTot_dPsi0(ixControlIndex)                                                                                             ,& ! intent(in) : derivative in the soil water characteristic (m-1)
                     mLayerdTheta_dTk(iLayer)                                                                                                  ,& ! intent(in) : derivative in volumetric total water w.r.t. temperature (K-1)
-                    mLayerTempPrime(ixControlIndex) ,&
                     mLayerVolFracLiqPrime(iLayer)                                                                                             ,&
                     mLayerVolFracIcePrime(iLayer)                                                                                              ,&
                     ! output
diff --git a/build/source/engine/sundials/updateVarsSundials.f90 b/build/source/engine/sundials/updateVarsSundials.f90
index 35a7d4c..bd79753 100644
--- a/build/source/engine/sundials/updateVarsSundials.f90
+++ b/build/source/engine/sundials/updateVarsSundials.f90
@@ -625,7 +625,6 @@ contains
                     vGn_alpha(ixControlIndex),vGn_n(ixControlIndex),theta_sat(ixControlIndex),theta_res(ixControlIndex),vGn_m(ixControlIndex), & ! intent(in) : soil parameters
                     dVolTot_dPsi0(ixControlIndex)                                                                                             ,& ! intent(in) : derivative in the soil water characteristic (m-1)
                     mLayerdTheta_dTk(iLayer)                                                                                                  ,& ! intent(in) : derivative in volumetric total water w.r.t. temperature (K-1)
-                    mLayerTempPrime(ixControlIndex)                                                                                           ,&
                     mLayerVolFracLiqPrime(iLayer)                                                                                             ,&
                     mLayerVolFracIcePrime(iLayer)                                                                                             ,&
                     ! output
diff --git a/build/source/engine/sundials/varExtrSundials.f90 b/build/source/engine/sundials/varExtrSundials.f90
index 0760b51..35ba1f7 100644
--- a/build/source/engine/sundials/varExtrSundials.f90
+++ b/build/source/engine/sundials/varExtrSundials.f90
@@ -349,8 +349,6 @@ contains
  subroutine residDiscontinuity(&
                        ! input
                        stateVec,                                  & ! intent(in):    model state vector (mixed units)
-                       diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
-                       prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
                        indx_data,                                 & ! intent(in):    indices defining model states and layers
                        ! output
                        resid,                                     & ! intent(out)
@@ -360,8 +358,6 @@ contains
  implicit none
  ! input
  real(rkind),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
- type(var_dlength),intent(in)    :: diag_data                       ! diagnostic variables for a local HRU
- type(var_dlength),intent(in)    :: prog_data                       ! prognostic variables for a local HRU
  type(var_ilength),intent(in)    :: indx_data                       ! indices defining model states and layers
  real(qp),intent(out)            :: resid(:)
  ! output: error control
@@ -436,9 +432,6 @@ contains
  ! **********************************************************************************************************
  subroutine countDiscontinuity(&
                        ! input
-                       stateVec,                                  & ! intent(in):    model state vector (mixed units)
-                       diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
-                       prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
                        indx_data,                                 & ! intent(in):    indices defining model states and layers
                        ! output
                        countD,                                     & ! intent(out)
@@ -447,9 +440,6 @@ contains
  ! --------------------------------------------------------------------------------------------------------------------------------
  implicit none
  ! input
- real(rkind),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
- type(var_dlength),intent(in)    :: diag_data                       ! diagnostic variables for a local HRU
- type(var_dlength),intent(in)    :: prog_data                       ! prognostic variables for a local HRU
  type(var_ilength),intent(in)    :: indx_data                       ! indices defining model states and layers
  integer(i4b),intent(out)        :: countD
  ! output: error control
-- 
GitLab