diff --git a/build/source/dshare/globalData.f90 b/build/source/dshare/globalData.f90
index 1e1cbf74b546f14a96753ee129038803b75079e6..205788e200250c50aa5686176dc792977edccae1 100755
--- a/build/source/dshare/globalData.f90
+++ b/build/source/dshare/globalData.f90
@@ -315,7 +315,7 @@ MODULE globalData
 
   ! define fixed dimensions
   integer(i4b),parameter,public                   :: nBand=2          ! number of spectral bands
-  integer(i4b),parameter,public                   :: nTimeDelay=3000  ! number of hours in the time delay histogram (default: ~1 season = 24*365/4)
+  integer(i4b),parameter,public                   :: nTimeDelay=2000  ! number of hours in the time delay histogram (default: ~1 season = 24*365/4)
 
 
   character(len=1024),public,save                 :: fname                         ! temporary filename
diff --git a/build/source/engine/coupled_em.f90 b/build/source/engine/coupled_em.f90
index f11a0a8e9f09561a0d97388ee3915d19946b9621..62bb6d28dd9cbe913fe6c019b7741c514b50e2b1 100755
--- a/build/source/engine/coupled_em.f90
+++ b/build/source/engine/coupled_em.f90
@@ -65,9 +65,8 @@ USE globalData,only:globalPrintFlag        ! the global print flag
 
 ! look-up values for the numerical method
 USE mDecisions_module,only:         &
- iterative,                         &      ! iterative
- nonIterative,                      &      ! non-iterative
- iterSurfEnergyBal                         ! iterate only on the surface energy balance
+ bEuler,                            &      ! home-grown backward Euler solution with long time steps
+ sundials                                  ! SUNDIALS/IDA solution
 
 ! look-up values for the maximum interception capacity
 USE mDecisions_module,only:         &
@@ -143,14 +142,6 @@ subroutine coupled_em(&
   USE var_derive_module,only:calcHeight      ! module to calculate height at layer interfaces and layer mid-point
   USE computSnowDepth_module,only:computSnowDepth
   ! look-up values for the numerical method
-  USE mDecisions_module,only:         &
-    iterative,                         &      ! iterative
-    nonIterative,                      &      ! non-iterative
-    iterSurfEnergyBal                         ! iterate only on the surface energy balance
-  ! look-up values for the maximum interception capacity
-  USE mDecisions_module,only:          &
-                        stickySnow,    &      ! maximum interception capacity an increasing function of temerature
-                        lightSnow             ! maximum interception capacity an inverse function of new snow density
   implicit none
   ! model control
   integer(4),intent(in)                :: indxHRU                ! hruId
@@ -253,14 +244,6 @@ subroutine coupled_em(&
   ! initialize error control
   err=0; message="coupled_em/"
 
-  ! print*, "scalarCanopyWat"
-  ! print*, "mLayerVolFracWat"
-  ! print*, "mLayerMatricHead"
-  ! print*, ""
-  ! print*, ""
-  ! print*, ""
-  ! print*, ""
-
   ! check that the decision is supported
   if(model_decisions(iLookDECISIONS%groundwatr)%iDecision==bigBucket .and. &
       model_decisions(iLookDECISIONS%spatial_gw)%iDecision/=localColumn)then
@@ -1177,7 +1160,9 @@ subroutine coupled_em(&
 
     ! adjust length of the sub-step (make sure that we don't exceed the step)
     ! TODO: This is different in Ashley's code
-    dt_sub = min(data_step - dt_solv, dt_sub)
+    ! dt_sub = min(data_step - dt_solv, dt_sub)
+    dt_sub = data_step - dt_solv !min(data_step - dt_solv, dt_sub)
+
     !print*, 'dt_sub = ', dt_sub
 
   end do  substeps ! (sub-step loop)
diff --git a/build/source/engine/mDecisions.f90 b/build/source/engine/mDecisions.f90
index 72258c04f57a72805cd4a04a246e06aa84957352..4ead60cf0ca3f420381fb6078b9d9cd7feaa26c3 100755
--- a/build/source/engine/mDecisions.f90
+++ b/build/source/engine/mDecisions.f90
@@ -156,7 +156,7 @@ contains
 ! ************************************************************************************************
 ! public subroutine mDecisions: save model decisions as named integers
 ! ************************************************************************************************
-subroutine mDecisions(err,message)
+subroutine mDecisions(num_steps,err,message)
   ! model time structures
   USE multiconst,only:secprday               ! number of seconds in a day
   USE var_lookup,only:iLookTIME              ! named variables that identify indices in the time structures
@@ -181,10 +181,11 @@ subroutine mDecisions(err,message)
   USE time_utils_module,only:extractTime     ! extract time info from units string
   USE time_utils_module,only:compjulday      ! compute the julian day
   USE time_utils_module,only:fracDay         ! compute fractional day
-  USE summaFileManager,only: SIM_START_TM, SIM_END_TM   ! time info from control file module
+  USE summaActors_FileManager,only: SIM_START_TM, SIM_END_TM   ! time info from control file module
 
   implicit none
   ! define output
+  integer(i4b),intent(out)             :: num_steps
   integer(i4b),intent(out)             :: err            ! error code
   character(*),intent(out)             :: message        ! error message
   ! define local variables
@@ -287,8 +288,8 @@ subroutine mDecisions(err,message)
   oldTime%var(:) = startTime%var(:)
 
   ! compute the number of time steps
-  numtim = nint( (dJulianFinsh - dJulianStart)*secprday/data_step ) + 1
-  write(*,'(a,1x,i10)') 'number of time steps = ', numtim
+  num_steps = nint( (dJulianFinsh - dJulianStart)*secprday/data_step ) + 1
+  numTim = num_steps
 
 
   ! set Noah-MP options
@@ -675,8 +676,8 @@ subroutine readoption(err,message)
   USE ascii_util_module,only:file_open       ! open file
   USE ascii_util_module,only:linewidth       ! max character number for one line
   USE ascii_util_module,only:get_vlines      ! get a vector of non-comment lines
-  USE summaFileManager,only:SETTINGS_PATH    ! path for metadata files
-  USE summaFileManager,only:M_DECISIONS      ! definition of modeling options
+  USE summaActors_FileManager,only:SETTINGS_PATH    ! path for metadata files
+  USE summaActors_FileManager,only:M_DECISIONS      ! definition of modeling options
   USE get_ixname_module,only:get_ixdecisions ! identify index of named variable
   USE globalData,only:model_decisions        ! model decision structure
   implicit none
diff --git a/build/source/engine/nrtype.mod b/build/source/engine/nrtype.mod
deleted file mode 100644
index cb753b75bed2441f7d23ae5b89340b7015376d91..0000000000000000000000000000000000000000
Binary files a/build/source/engine/nrtype.mod and /dev/null differ
diff --git a/build/source/engine/opSplittin.f90 b/build/source/engine/opSplittin.f90
index ba0cbcab421a055fe8818ff4d830909bfc019b6f..5fcc36469e0d41eaeca1d43406e584dee0448635 100755
--- a/build/source/engine/opSplittin.f90
+++ b/build/source/engine/opSplittin.f90
@@ -20,1094 +20,1093 @@
 
 module opSplittin_module
 
-  ! data types
-  USE nrtype
-  
-  ! access the global print flag
-  USE globalData,only:globalPrintFlag
-  
-  ! access missing values
-  USE globalData,only:integerMissing   ! missing integer
-  USE globalData,only:realMissing      ! missing double precision number
-  USE globalData,only:quadMissing      ! missing quadruple precision number
-  
-  ! access matrix information
-  USE globalData,only: nBands          ! length of the leading dimension of the band diagonal matrix
-  USE globalData,only: ixFullMatrix    ! named variable for the full Jacobian matrix
-  USE globalData,only: ixBandMatrix    ! named variable for the band diagonal matrix
-  USE globalData,only: iJac1           ! first layer of the Jacobian to print
-  USE globalData,only: iJac2           ! last layer of the Jacobian to print
-  
-  ! domain types
-  USE globalData,only:iname_cas        ! named variables for the canopy air space
-  USE globalData,only:iname_veg        ! named variables for vegetation
-  USE globalData,only:iname_snow       ! named variables for snow
-  USE globalData,only:iname_soil       ! named variables for soil
-  
-  ! 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
-  USE globalData,only:iname_watCanopy  ! named variable defining the mass of total water on the vegetation canopy
-  USE globalData,only:iname_liqCanopy  ! named variable defining the mass of liquid water on the vegetation canopy
-  USE globalData,only:iname_nrgLayer   ! named variable defining the energy state variable for snow+soil layers
-  USE globalData,only:iname_watLayer   ! named variable defining the total water state variable for snow+soil layers
-  USE globalData,only:iname_liqLayer   ! named variable defining the liquid  water state variable for snow+soil layers
-  USE globalData,only:iname_matLayer   ! named variable defining the matric head state variable for soil layers
-  USE globalData,only:iname_lmpLayer   ! named variable defining the liquid matric potential state variable for soil layers
-  USE globalData,only:iname_watAquifer ! named variable defining the water storage in the aquifer
-  
-  ! global metadata
-  USE globalData,only:flux_meta                        ! metadata on the model fluxes
-  USE globalData,only:diag_meta                        ! metadata on the model diagnostic variables
-  USE globalData,only:prog_meta                        ! metadata on the model prognostic variables
-  USE globalData,only:deriv_meta                       ! metadata on the model derivatives
-  USE globalData,only:flux2state_orig                  ! metadata on flux-to-state mapping (original state variables)
-  USE globalData,only:flux2state_liq                   ! metadata on flux-to-state mapping (liquid water state variables)
-  
-  ! constants
-  USE multiconst,only:&
-                      gravity,       & ! acceleration of gravity              (m s-2)
-                      Tfreeze,       & ! temperature at freezing              (K)
-                      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)
-                      Cp_air,        & ! specific heat of air                 (J kg-1 K-1)
-                      iden_air,      & ! intrinsic density of air             (kg m-3)
-                      iden_ice,      & ! intrinsic density of ice             (kg m-3)
-                      iden_water       ! intrinsic density of liquid water    (kg m-3)
-  
-  ! provide access to indices that define elements of the data structures
-  USE var_lookup,only:iLookATTR        ! named variables for structure elements
-  USE var_lookup,only:iLookTYPE        ! named variables for structure elements
-  USE var_lookup,only:iLookPROG        ! named variables for structure elements
-  USE var_lookup,only:iLookDIAG        ! named variables for structure elements
-  USE var_lookup,only:iLookFLUX        ! named variables for structure elements
-  USE var_lookup,only:iLookFORCE       ! 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
-  USE var_lookup,only:iLookDECISIONS   ! named variables for elements of the decision structure
-  
-  ! look up structure for variable types
-  USE var_lookup,only:iLookVarType
-  
-  ! provide access to the number of flux variables
-  USE var_lookup,only:nFlux=>maxvarFlux ! number of model flux variables
-  
-  ! provide access to the derived types to define the data structures
-  USE data_types,only:&
-                      var_i,        & ! data vector (i4b)
-                      var_d,        & ! data vector (rkind)
-                      var_flagVec,  & ! data vector with variable length dimension (i4b)
-                      var_ilength,  & ! data vector with variable length dimension (i4b)
-                      var_dlength,  & ! data vector with variable length dimension (rkind)
-                      zLookup,      & ! data vector with variable length dimension (rkind)
-                      model_options   ! defines the model decisions
-  
-  ! look-up values for the choice of groundwater representation (local-column, or single-basin)
-  USE mDecisions_module,only:       &
-   localColumn,                     & ! separate groundwater representation in each local soil column
-   singleBasin                        ! single groundwater store over the entire basin
-  
-  ! look-up values for the choice of groundwater parameterization
-  USE mDecisions_module,only:      &
-   qbaseTopmodel,                  & ! TOPMODEL-ish baseflow parameterization
-   bigBucket,                      & ! a big bucket (lumped aquifer model)
-   noExplicit,                     & ! no explicit groundwater parameterization
-   sundials,                       & ! SUNDIALS/IDA solution
-   bEuler                            ! home-grown backward Euler solution with long time step
-  
-  ! safety: set private unless specified otherwise
+! data types
+USE nrtype
+
+! access the global print flag
+USE globalData,only:globalPrintFlag
+
+! access missing values
+USE globalData,only:integerMissing   ! missing integer
+USE globalData,only:realMissing      ! missing double precision number
+USE globalData,only:quadMissing      ! missing quadruple precision number
+
+! access matrix information
+USE globalData,only: nBands          ! length of the leading dimension of the band diagonal matrix
+USE globalData,only: ixFullMatrix    ! named variable for the full Jacobian matrix
+USE globalData,only: ixBandMatrix    ! named variable for the band diagonal matrix
+USE globalData,only: iJac1           ! first layer of the Jacobian to print
+USE globalData,only: iJac2           ! last layer of the Jacobian to print
+
+! domain types
+USE globalData,only:iname_cas        ! named variables for the canopy air space
+USE globalData,only:iname_veg        ! named variables for vegetation
+USE globalData,only:iname_snow       ! named variables for snow
+USE globalData,only:iname_soil       ! named variables for soil
+
+! 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
+USE globalData,only:iname_watCanopy  ! named variable defining the mass of total water on the vegetation canopy
+USE globalData,only:iname_liqCanopy  ! named variable defining the mass of liquid water on the vegetation canopy
+USE globalData,only:iname_nrgLayer   ! named variable defining the energy state variable for snow+soil layers
+USE globalData,only:iname_watLayer   ! named variable defining the total water state variable for snow+soil layers
+USE globalData,only:iname_liqLayer   ! named variable defining the liquid  water state variable for snow+soil layers
+USE globalData,only:iname_matLayer   ! named variable defining the matric head state variable for soil layers
+USE globalData,only:iname_lmpLayer   ! named variable defining the liquid matric potential state variable for soil layers
+USE globalData,only:iname_watAquifer ! named variable defining the water storage in the aquifer
+
+! global metadata
+USE globalData,only:flux_meta                        ! metadata on the model fluxes
+USE globalData,only:diag_meta                        ! metadata on the model diagnostic variables
+USE globalData,only:prog_meta                        ! metadata on the model prognostic variables
+USE globalData,only:deriv_meta                       ! metadata on the model derivatives
+USE globalData,only:flux2state_orig                  ! metadata on flux-to-state mapping (original state variables)
+USE globalData,only:flux2state_liq                   ! metadata on flux-to-state mapping (liquid water state variables)
+
+! constants
+USE multiconst,only:&
+                    gravity,       & ! acceleration of gravity              (m s-2)
+                    Tfreeze,       & ! temperature at freezing              (K)
+                    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)
+                    Cp_air,        & ! specific heat of air                 (J kg-1 K-1)
+                    iden_air,      & ! intrinsic density of air             (kg m-3)
+                    iden_ice,      & ! intrinsic density of ice             (kg m-3)
+                    iden_water       ! intrinsic density of liquid water    (kg m-3)
+
+! provide access to indices that define elements of the data structures
+USE var_lookup,only:iLookATTR        ! named variables for structure elements
+USE var_lookup,only:iLookTYPE        ! named variables for structure elements
+USE var_lookup,only:iLookPROG        ! named variables for structure elements
+USE var_lookup,only:iLookDIAG        ! named variables for structure elements
+USE var_lookup,only:iLookFLUX        ! named variables for structure elements
+USE var_lookup,only:iLookFORCE       ! 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
+USE var_lookup,only:iLookDECISIONS   ! named variables for elements of the decision structure
+
+! look up structure for variable types
+USE var_lookup,only:iLookVarType
+
+! provide access to the number of flux variables
+USE var_lookup,only:nFlux=>maxvarFlux ! number of model flux variables
+
+! provide access to the derived types to define the data structures
+USE data_types,only:&
+                    var_i,        & ! data vector (i4b)
+                    var_d,        & ! data vector (rkind)
+                    var_flagVec,  & ! data vector with variable length dimension (i4b)
+                    var_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength,  & ! data vector with variable length dimension (rkind)
+                    zLookup,      & ! data vector with variable length dimension (rkind)
+                    model_options   ! defines the model decisions
+
+! look-up values for the choice of groundwater representation (local-column, or single-basin)
+USE mDecisions_module,only:       &
+  localColumn,                     & ! separate groundwater representation in each local soil column
+  singleBasin                        ! single groundwater store over the entire basin
+
+! look-up values for the choice of groundwater parameterization
+USE mDecisions_module,only:      &
+  qbaseTopmodel,                  & ! TOPMODEL-ish baseflow parameterization
+  bigBucket,                      & ! a big bucket (lumped aquifer model)
+  noExplicit,                     & ! no explicit groundwater parameterization
+  sundials,                       & ! SUNDIALS/IDA solution
+  bEuler                            ! home-grown backward Euler solution with long time step
+
+! safety: set private unless specified otherwise
+implicit none
+private
+public::opSplittin
+
+! named variables for the coupling method
+integer(i4b),parameter  :: fullyCoupled=1             ! 1st try: fully coupled solution
+integer(i4b),parameter  :: stateTypeSplit=2           ! 2nd try: separate solutions for each state type
+
+! named variables for the state variable split
+integer(i4b),parameter  :: nrgSplit=1                 ! order in sequence for the energy operation
+integer(i4b),parameter  :: massSplit=2                ! order in sequence for the mass operation
+
+! named variables for the domain type split
+integer(i4b),parameter  :: vegSplit=1                 ! order in sequence for the vegetation split
+integer(i4b),parameter  :: snowSplit=2                ! order in sequence for the snow split
+integer(i4b),parameter  :: soilSplit=3                ! order in sequence for the soil split
+integer(i4b),parameter  :: aquiferSplit=4             ! order in sequence for the aquifer split
+
+! named variables for the solution method
+integer(i4b),parameter  :: vector=1                   ! vector solution method
+integer(i4b),parameter  :: scalar=2                   ! scalar solution method
+integer(i4b),parameter  :: nSolutions=2               ! number of solution methods
+
+! named variables for the switch between states and domains
+integer(i4b),parameter  :: fullDomain=1               ! full domain (veg+snow+soil)
+integer(i4b),parameter  :: subDomain=2                ! sub domain (veg, snow, and soil separately)
+
+! maximum number of possible splits
+integer(i4b),parameter  :: nStateTypes=2              ! number of state types (energy, water)
+integer(i4b),parameter  :: nDomains=4                 ! number of domains (vegetation, snow, soil, and aquifer)
+
+! control parameters
+real(rkind),parameter   :: valueMissing=-9999._rkind     ! missing value
+real(rkind),parameter   :: verySmall=1.e-12_rkind        ! a very small number (used to check consistency)
+real(rkind),parameter   :: veryBig=1.e+20_rkind          ! a very big number
+real(rkind),parameter   :: dx = 1.e-8_rkind              ! finite difference increment
+
+contains
+
+
+! **********************************************************************************************************
+! public subroutine opSplittin: run the coupled energy-mass model for one timestep
+!
+! The logic of the solver is as follows:
+! (1) Attempt different solutions in the following order: (a) fully coupled; (b) split by state type and by
+!      domain type for a given energy and mass split (vegetation, snow, and soil); and (c) scalar solution
+!      for a given state type and domain subset.
+! (2) For a given split, compute a variable number of substeps (in varSubstepSundials).
+! **********************************************************************************************************
+subroutine opSplittin(&
+                      ! input: model control
+                      nSnow,          & ! intent(in):    number of snow layers
+                      nSoil,          & ! intent(in):    number of soil layers
+                      nLayers,        & ! intent(in):    total number of layers
+                      nState,         & ! intent(in):    total number of state variables
+                      dt,             & ! intent(inout): time step (s)
+                      firstSubStep,   & ! intent(in):    flag to denote first sub-step
+                      computeVegFlux, & ! intent(in):    flag to denote if computing energy flux over vegetation
+                      ! input/output: data structures
+                      type_data,      & ! intent(in):    type of vegetation and soil
+                      attr_data,      & ! intent(in):    spatial attributes
+                      forc_data,      & ! intent(in):    model forcing data
+                      mpar_data,      & ! intent(in):    model parameters
+                      indx_data,      & ! intent(inout): index data
+                      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
+                      bvar_data,      & ! intent(in):    model variables for the local basin
+                      lookup_data,    & ! intent(in):    lookup tables
+                      model_decisions,& ! intent(in):    model decisions
+                      ! output: model control
+                      dtMultiplier,   & ! intent(out):   substep multiplier (-)
+                      tooMuchMelt,    & ! intent(out):   flag to denote that ice is insufficient to support melt
+                      stepFailure,    & ! intent(out):   flag to denote step failure
+                      ixCoupling,     & ! intent(out):   coupling method used in this iteration
+                      err,message)      ! intent(out):   error code and error message
+  ! ---------------------------------------------------------------------------------------
+  ! structure allocations
+  USE allocspace_module,only:allocLocal                ! allocate local data structures
+  ! simulation of fluxes and residuals given a trial state vector
+  USE soil_utils_module,only:matricHead                ! compute the matric head based on volumetric water content
+  USE soil_utils_module,only:liquidHead                ! compute the liquid water matric potential
+  ! population/extraction of state vectors
+  USE indexState_module,only:indexSplit                ! get state indices
+  USE varSubstep_module,only:varSubstep                ! complete substeps for a given split
+  USE varSubstepSundials_module,only:varSubstepSundials                ! complete substeps for a given split
+  ! identify name of variable type (for error message)
+  USE get_ixName_module,only:get_varTypeName           ! to access type strings for error messages
   implicit none
-  private
-  public::opSplittin
-  
-  ! named variables for the coupling method
-  integer(i4b),parameter  :: fullyCoupled=1             ! 1st try: fully coupled solution
-  integer(i4b),parameter  :: stateTypeSplit=2           ! 2nd try: separate solutions for each state type
-  
-  ! named variables for the state variable split
-  integer(i4b),parameter  :: nrgSplit=1                 ! order in sequence for the energy operation
-  integer(i4b),parameter  :: massSplit=2                ! order in sequence for the mass operation
-  
-  ! named variables for the domain type split
-  integer(i4b),parameter  :: vegSplit=1                 ! order in sequence for the vegetation split
-  integer(i4b),parameter  :: snowSplit=2                ! order in sequence for the snow split
-  integer(i4b),parameter  :: soilSplit=3                ! order in sequence for the soil split
-  integer(i4b),parameter  :: aquiferSplit=4             ! order in sequence for the aquifer split
-  
-  ! named variables for the solution method
-  integer(i4b),parameter  :: vector=1                   ! vector solution method
-  integer(i4b),parameter  :: scalar=2                   ! scalar solution method
-  integer(i4b),parameter  :: nSolutions=2               ! number of solution methods
-  
-  ! named variables for the switch between states and domains
-  integer(i4b),parameter  :: fullDomain=1               ! full domain (veg+snow+soil)
-  integer(i4b),parameter  :: subDomain=2                ! sub domain (veg, snow, and soil separately)
-  
-  ! maximum number of possible splits
-  integer(i4b),parameter  :: nStateTypes=2              ! number of state types (energy, water)
-  integer(i4b),parameter  :: nDomains=4                 ! number of domains (vegetation, snow, soil, and aquifer)
-  
-  ! control parameters
-  real(rkind),parameter   :: valueMissing=-9999._rkind     ! missing value
-  real(rkind),parameter   :: verySmall=1.e-12_rkind        ! a very small number (used to check consistency)
-  real(rkind),parameter   :: veryBig=1.e+20_rkind          ! a very big number
-  real(rkind),parameter   :: dx = 1.e-8_rkind              ! finite difference increment
-  
-  contains
-  
-  
-  ! **********************************************************************************************************
-  ! public subroutine opSplittin: run the coupled energy-mass model for one timestep
-  !
-  ! The logic of the solver is as follows:
-  ! (1) Attempt different solutions in the following order: (a) fully coupled; (b) split by state type and by
-  !      domain type for a given energy and mass split (vegetation, snow, and soil); and (c) scalar solution
-  !      for a given state type and domain subset.
-  ! (2) For a given split, compute a variable number of substeps (in varSubstepSundials).
-  ! **********************************************************************************************************
-  subroutine opSplittin(&
-                        ! input: model control
-                        nSnow,          & ! intent(in):    number of snow layers
-                        nSoil,          & ! intent(in):    number of soil layers
-                        nLayers,        & ! intent(in):    total number of layers
-                        nState,         & ! intent(in):    total number of state variables
-                        dt,             & ! intent(inout): time step (s)
-                        firstSubStep,   & ! intent(in):    flag to denote first sub-step
-                        computeVegFlux, & ! intent(in):    flag to denote if computing energy flux over vegetation
-                        ! input/output: data structures
-                        type_data,      & ! intent(in):    type of vegetation and soil
-                        attr_data,      & ! intent(in):    spatial attributes
-                        forc_data,      & ! intent(in):    model forcing data
-                        mpar_data,      & ! intent(in):    model parameters
-                        indx_data,      & ! intent(inout): index data
-                        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
-                        bvar_data,      & ! intent(in):    model variables for the local basin
-                        lookup_data,    & ! intent(in):    lookup tables
-                        model_decisions,& ! intent(in):    model decisions
-                        ! output: model control
-                        dtMultiplier,   & ! intent(out):   substep multiplier (-)
-                        tooMuchMelt,    & ! intent(out):   flag to denote that ice is insufficient to support melt
-                        stepFailure,    & ! intent(out):   flag to denote step failure
-                        ixCoupling,     & ! intent(out):   coupling method used in this iteration
-                        err,message)      ! intent(out):   error code and error message
-    ! ---------------------------------------------------------------------------------------
-    ! structure allocations
-    USE allocspace_module,only:allocLocal                ! allocate local data structures
-    ! simulation of fluxes and residuals given a trial state vector
-    USE soil_utils_module,only:matricHead                ! compute the matric head based on volumetric water content
-    USE soil_utils_module,only:liquidHead                ! compute the liquid water matric potential
-    ! population/extraction of state vectors
-    USE indexState_module,only:indexSplit                ! get state indices
-    USE varSubstep_module,only:varSubstep                ! complete substeps for a given split
-    USE varSubstepSundials_module,only:varSubstepSundials                ! complete substeps for a given split
-    ! identify name of variable type (for error message)
-    USE get_ixName_module,only:get_varTypeName           ! to access type strings for error messages
-    implicit none
-    ! ---------------------------------------------------------------------------------------
-    ! * dummy variables
-    ! ---------------------------------------------------------------------------------------
-    ! input: model control
-    integer(i4b),intent(in)         :: nSnow                          ! number of snow layers
-    integer(i4b),intent(in)         :: nSoil                          ! number of soil layers
-    integer(i4b),intent(in)         :: nLayers                        ! total number of layers
-    integer(i4b),intent(in)         :: nState                         ! total number of state variables
-    real(rkind),intent(inout)       :: dt                             ! time step (seconds)
-    logical(lgt),intent(in)         :: firstSubStep                   ! flag to indicate if we are processing the first sub-step
-    logical(lgt),intent(in)         :: computeVegFlux                 ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
-    ! input/output: data structures
-    type(var_i),intent(in)          :: type_data                      ! type of vegetation and soil
-    type(var_d),intent(in)          :: attr_data                      ! spatial attributes
-    type(var_d),intent(in)          :: forc_data                      ! model forcing data
-    type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
-    type(var_ilength),intent(inout) :: indx_data                      ! indices for a local HRU
-    type(var_dlength),intent(inout) :: 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
-    type(var_dlength),intent(in)    :: bvar_data                      ! model variables for the local basin
-    type(zLookup),    intent(in)    :: lookup_data                    ! lookup tables
-    type(model_options),intent(in)  :: model_decisions(:)             ! model decisions
-    ! output: model control
-    real(rkind),intent(out)         :: dtMultiplier                   ! substep multiplier (-)
-    logical(lgt),intent(out)        :: tooMuchMelt                    ! flag to denote that ice is insufficient to support melt
-    logical(lgt),intent(out)        :: stepFailure                    ! flag to denote step failure
-    integer(i4b),intent(out)        :: err                            ! error code
-    character(*),intent(out)        :: message                        ! error message
-    ! ---------------------------------------------------------------------------------------
-    ! * general local variables
-    ! ---------------------------------------------------------------------------------------
-    character(LEN=256)              :: cmessage                       ! error message of downwind routine
-    integer(i4b)                    :: minLayer                       ! the minimum layer used in assigning flags for flux aggregations
-    integer(i4b)                    :: iOffset                        ! offset to account for different indices in the soil domain
-    integer(i4b)                    :: iMin(1),iMax(1)                ! bounds of a given vector
-    integer(i4b)                    :: iLayer,jLayer                  ! index of model layer
-    integer(i4b)                    :: iSoil                          ! index of soil layer
-    integer(i4b)                    :: iVar                           ! index of variables in data structures
-    logical(lgt)                    :: firstSuccess                   ! flag to define the first success
-    logical(lgt)                    :: firstFluxCall                  ! flag to define the first flux call
-    logical(lgt)                    :: reduceCoupledStep              ! flag to define the need to reduce the length of the coupled step
-    type(var_dlength)               :: prog_temp                      ! temporary model prognostic variables
-    type(var_dlength)               :: diag_temp                      ! temporary model diagnostic variables
-    type(var_dlength)               :: flux_temp                      ! temporary model fluxes
-    type(var_dlength)               :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
-    real(rkind),dimension(nLayers)  :: mLayerVolFracIceInit           ! initial vector for volumetric fraction of ice (-)
-    ! ------------------------------------------------------------------------------------------------------
-    ! * operator splitting
-    ! ------------------------------------------------------------------------------------------------------
-    ! minimum timestep
-    real(rkind),parameter           :: dtmin_coupled=1800._rkind         ! minimum time step for the fully coupled solution (seconds)
-    real(rkind),parameter           :: dtmin_split=60._rkind             ! minimum time step for the fully split solution (seconds)
-    real(rkind),parameter           :: dtmin_scalar=10._rkind            ! minimum time step for the scalar solution (seconds)
-    real(rkind)                     :: dt_min                         ! minimum time step (seconds)
-    real(rkind)                     :: dtInit                         ! initial time step (seconds)
-    ! explicit error tolerance (depends on state type split, so defined here)
-    real(rkind),parameter           :: errorTolLiqFlux=0.01_rkind        ! error tolerance in the explicit solution (liquid flux)
-    real(rkind),parameter           :: errorTolNrgFlux=10._rkind         ! error tolerance in the explicit solution (energy flux)
-    ! number of substeps taken for a given split
-    integer(i4b)                    :: nSubsteps                      ! number of substeps taken for a given split
-    ! named variables defining the coupling and solution method
-    integer(i4b)                    :: ixCoupling                     ! index of coupling method (1,2)
-    integer(i4b)                    :: ixSolution                     ! index of solution method (1,2)
-    integer(i4b)                    :: ixStateThenDomain              ! switch between the state and domain (1,2)
-    integer(i4b)                    :: tryDomainSplit                 ! (0,1) - flag to try the domain split
-    ! actual number of splits
-    integer(i4b)                    :: nStateTypeSplit                ! number of splits for the state type
-    integer(i4b)                    :: nDomainSplit                   ! number of splits for the domain
-    integer(i4b)                    :: nStateSplit                    ! number of splits for the states within a given domain
-    ! indices for the state type and the domain split
-    integer(i4b)                    :: iStateTypeSplit                ! index of the state type split
-    integer(i4b)                    :: iDomainSplit                   ! index of the domain split
-    integer(i4b)                    :: iStateSplit                    ! index of the state split
-    ! flux masks
-    logical(lgt)                    :: neededFlux(nFlux)              ! .true. if flux is needed at all
-    logical(lgt)                    :: desiredFlux                    ! .true. if flux is desired for a given split
-    type(var_ilength)               :: fluxCount                      ! number of times each flux is updated (should equal nSubsteps)
-    type(var_flagVec)               :: fluxMask                       ! mask defining model fluxes
-    ! state masks
-    integer(i4b),dimension(nState)  :: stateCheck                     ! number of times each state variable is updated (should equal 1)
-    logical(lgt),dimension(nState)  :: stateMask                      ! mask defining desired state variables
-    integer(i4b)                    :: nSubset                        ! number of selected state variables for a given split
-    ! flags
-    logical(lgt)                    :: failure                        ! flag to denote failure of substepping
-    logical(lgt)                    :: doAdjustTemp                   ! flag to adjust temperature after the mass split
-    logical(lgt)                    :: failedMinimumStep              ! flag to denote failure of substepping for a given split
-    integer(i4b)                    :: ixSaturation                   ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
-    integer(i4b)                    :: nCoupling
-    real(qp)						 :: dt_out                         !
-    ! ---------------------------------------------------------------------------------------
-    ! point to variables in the data structures
+  ! ---------------------------------------------------------------------------------------
+  ! * dummy variables
+  ! ---------------------------------------------------------------------------------------
+  ! input: model control
+  integer(i4b),intent(in)         :: nSnow                          ! number of snow layers
+  integer(i4b),intent(in)         :: nSoil                          ! number of soil layers
+  integer(i4b),intent(in)         :: nLayers                        ! total number of layers
+  integer(i4b),intent(in)         :: nState                         ! total number of state variables
+  real(rkind),intent(inout)       :: dt                             ! time step (seconds)
+  logical(lgt),intent(in)         :: firstSubStep                   ! flag to indicate if we are processing the first sub-step
+  logical(lgt),intent(in)         :: computeVegFlux                 ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
+  ! input/output: data structures
+  type(var_i),intent(in)          :: type_data                      ! type of vegetation and soil
+  type(var_d),intent(in)          :: attr_data                      ! spatial attributes
+  type(var_d),intent(in)          :: forc_data                      ! model forcing data
+  type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
+  type(var_ilength),intent(inout) :: indx_data                      ! indices for a local HRU
+  type(var_dlength),intent(inout) :: 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
+  type(var_dlength),intent(in)    :: bvar_data                      ! model variables for the local basin
+  type(zLookup),    intent(in)    :: lookup_data                    ! lookup tables
+  type(model_options),intent(in)  :: model_decisions(:)             ! model decisions
+  ! output: model control
+  real(rkind),intent(out)         :: dtMultiplier                   ! substep multiplier (-)
+  logical(lgt),intent(out)        :: tooMuchMelt                    ! flag to denote that ice is insufficient to support melt
+  logical(lgt),intent(out)        :: stepFailure                    ! flag to denote step failure
+  integer(i4b),intent(out)        :: err                            ! error code
+  character(*),intent(out)        :: message                        ! error message
+  ! ---------------------------------------------------------------------------------------
+  ! * general local variables
+  ! ---------------------------------------------------------------------------------------
+  character(LEN=256)              :: cmessage                       ! error message of downwind routine
+  integer(i4b)                    :: minLayer                       ! the minimum layer used in assigning flags for flux aggregations
+  integer(i4b)                    :: iOffset                        ! offset to account for different indices in the soil domain
+  integer(i4b)                    :: iMin(1),iMax(1)                ! bounds of a given vector
+  integer(i4b)                    :: iLayer,jLayer                  ! index of model layer
+  integer(i4b)                    :: iSoil                          ! index of soil layer
+  integer(i4b)                    :: iVar                           ! index of variables in data structures
+  logical(lgt)                    :: firstSuccess                   ! flag to define the first success
+  logical(lgt)                    :: firstFluxCall                  ! flag to define the first flux call
+  logical(lgt)                    :: reduceCoupledStep              ! flag to define the need to reduce the length of the coupled step
+  type(var_dlength)               :: prog_temp                      ! temporary model prognostic variables
+  type(var_dlength)               :: diag_temp                      ! temporary model diagnostic variables
+  type(var_dlength)               :: flux_temp                      ! temporary model fluxes
+  type(var_dlength)               :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
+  real(rkind),dimension(nLayers)  :: mLayerVolFracIceInit           ! initial vector for volumetric fraction of ice (-)
+  ! ------------------------------------------------------------------------------------------------------
+  ! * operator splitting
+  ! ------------------------------------------------------------------------------------------------------
+  ! minimum timestep
+  real(rkind),parameter           :: dtmin_coupled=1800._rkind         ! minimum time step for the fully coupled solution (seconds)
+  real(rkind),parameter           :: dtmin_split=60._rkind             ! minimum time step for the fully split solution (seconds)
+  real(rkind),parameter           :: dtmin_scalar=10._rkind            ! minimum time step for the scalar solution (seconds)
+  real(rkind)                     :: dt_min                         ! minimum time step (seconds)
+  real(rkind)                     :: dtInit                         ! initial time step (seconds)
+  ! explicit error tolerance (depends on state type split, so defined here)
+  real(rkind),parameter           :: errorTolLiqFlux=0.01_rkind        ! error tolerance in the explicit solution (liquid flux)
+  real(rkind),parameter           :: errorTolNrgFlux=10._rkind         ! error tolerance in the explicit solution (energy flux)
+  ! number of substeps taken for a given split
+  integer(i4b)                    :: nSubsteps                      ! number of substeps taken for a given split
+  ! named variables defining the coupling and solution method
+  integer(i4b)                    :: ixCoupling                     ! index of coupling method (1,2)
+  integer(i4b)                    :: ixSolution                     ! index of solution method (1,2)
+  integer(i4b)                    :: ixStateThenDomain              ! switch between the state and domain (1,2)
+  integer(i4b)                    :: tryDomainSplit                 ! (0,1) - flag to try the domain split
+  ! actual number of splits
+  integer(i4b)                    :: nStateTypeSplit                ! number of splits for the state type
+  integer(i4b)                    :: nDomainSplit                   ! number of splits for the domain
+  integer(i4b)                    :: nStateSplit                    ! number of splits for the states within a given domain
+  ! indices for the state type and the domain split
+  integer(i4b)                    :: iStateTypeSplit                ! index of the state type split
+  integer(i4b)                    :: iDomainSplit                   ! index of the domain split
+  integer(i4b)                    :: iStateSplit                    ! index of the state split
+  ! flux masks
+  logical(lgt)                    :: neededFlux(nFlux)              ! .true. if flux is needed at all
+  logical(lgt)                    :: desiredFlux                    ! .true. if flux is desired for a given split
+  type(var_ilength)               :: fluxCount                      ! number of times each flux is updated (should equal nSubsteps)
+  type(var_flagVec)               :: fluxMask                       ! mask defining model fluxes
+  ! state masks
+  integer(i4b),dimension(nState)  :: stateCheck                     ! number of times each state variable is updated (should equal 1)
+  logical(lgt),dimension(nState)  :: stateMask                      ! mask defining desired state variables
+  integer(i4b)                    :: nSubset                        ! number of selected state variables for a given split
+  ! flags
+  logical(lgt)                    :: failure                        ! flag to denote failure of substepping
+  logical(lgt)                    :: doAdjustTemp                   ! flag to adjust temperature after the mass split
+  logical(lgt)                    :: failedMinimumStep              ! flag to denote failure of substepping for a given split
+  integer(i4b)                    :: ixSaturation                   ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
+  integer(i4b)                    :: nCoupling
+  real(qp)						 :: dt_out                         !
+  ! ---------------------------------------------------------------------------------------
+  ! point to variables in the data structures
+  ! ---------------------------------------------------------------------------------------
+
+  globalVars: associate(&
+    ! model decisions
+    ixGroundwater           => model_decisions(iLookDECISIONS%groundwatr)%iDecision   ,& ! intent(in):    [i4b]    groundwater parameterization
+    ixSpatialGroundwater    => model_decisions(iLookDECISIONS%spatial_gw)%iDecision   ,& ! intent(in):    [i4b]    spatial representation of groundwater (local-column or single-basin)
+    ixNumericalMethod       => model_decisions(iLookDECISIONS%num_method)%iDecision   ,& ! intent(in): [i4b] choice of numerical method, backward Euler or SUNDIALS/IDA
+    ! domain boundary conditions
+    airtemp                 => forc_data%var(iLookFORCE%airtemp)                      ,& ! intent(in):    [dp]     temperature of the upper boundary of the snow and soil domains (K)
+    ! vector of energy and hydrology indices for the snow and soil domains
+    ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):    [i4b(:)] index in the state subset for energy state variables in the snow+soil domain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):    [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain
+    nSnowSoilNrg            => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1)         ,& ! intent(in):    [i4b]    number of energy state variables in the snow+soil domain
+    nSnowSoilHyd            => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology state variables in the snow+soil domain
+    ! indices of model state variables
+    ixMapSubset2Full        => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat         ,& ! intent(in):    [i4b(:)] list of indices in the state subset (missing for values not in the subset)
+    ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,& ! intent(in):    [i4b(:)] indices defining the type of the state (ixNrgState...)
+    ixNrgCanair             => indx_data%var(iLookINDEX%ixNrgCanair)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in canopy air space domain
+    ixNrgCanopy             => indx_data%var(iLookINDEX%ixNrgCanopy)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in the canopy domain
+    ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the canopy domain
+    ixNrgLayer              => indx_data%var(iLookINDEX%ixNrgLayer)%dat               ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in the snow+soil domain
+    ixHydLayer              => indx_data%var(iLookINDEX%ixHydLayer)%dat               ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the snow+soil domain
+    ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy air space energy state variable
+    ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy energy state variable
+    ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy hydrology state variable (mass)
+    ! numerix tracking
+    numberStateSplit        => indx_data%var(iLookINDEX%numberStateSplit     )%dat(1) ,& ! intent(inout): [i4b]    number of state splitting solutions             (-)
+    numberDomainSplitNrg    => indx_data%var(iLookINDEX%numberDomainSplitNrg )%dat(1) ,& ! intent(inout): [i4b]    number of domain splitting solutions for energy (-)
+    numberDomainSplitMass   => indx_data%var(iLookINDEX%numberDomainSplitMass)%dat(1) ,& ! intent(inout): [i4b]    number of domain splitting solutions for mass   (-)
+    numberScalarSolutions   => indx_data%var(iLookINDEX%numberScalarSolutions)%dat(1) ,& ! intent(inout): [i4b]    number of scalar solutions                      (-)
+    ! domain configuration
+    canopyDepth             => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1)      ,& ! intent(in):    [dp]     canopy depth (m)
+    mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
+    ! snow parameters
+    snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,& ! intent(in):    [dp]     scaling parameter for the snow freezing curve (K-1)
+    ! depth-varying soil parameters
+    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_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,& ! intent(in):    [dp(:)]  soil porosity (-)
+    theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,& ! intent(in):    [dp(:)]  soil residual volumetric water content (-)
+    ! soil parameters
+    specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,& ! intent(in):    [dp]     specific storage coefficient (m-1)
+    ! model diagnostic variables (fraction of liquid water)
+    scalarFracLiqVeg        => diag_data%var(iLookDIAG%scalarFracLiqVeg)%dat(1)       ,& ! intent(out):   [dp]     fraction of liquid water on vegetation (-)
+    mLayerFracLiqSnow       => diag_data%var(iLookDIAG%mLayerFracLiqSnow)%dat         ,& ! intent(out):   [dp(:)]  fraction of liquid water in each snow layer (-)
+    mLayerMeltFreeze        => diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat          ,& ! intent(out):   [dp(:)]  melt-freeze in each snow and soil layer (kg m-3)
+    ! model state variables (vegetation canopy)
+    scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(out):   [dp]     temperature of the canopy air space (K)
+    scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(out):   [dp]     temperature of the vegetation canopy (K)
+    scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(out):   [dp]     mass of ice on the vegetation canopy (kg m-2)
+    scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(out):   [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+    scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(out):   [dp]     mass of total water on the vegetation canopy (kg m-2)
+    ! model state variables (snow and soil domains)
+    mLayerTemp              => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(out):   [dp(:)]  temperature of each snow/soil layer (K)
+    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of ice (-)
+    mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of liquid water (-)
+    mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of total water (-)
+    mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(out):   [dp(:)]  matric head (m)
+    mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(out):   [dp(:)]  matric potential of liquid water (m)
+    )
     ! ---------------------------------------------------------------------------------------
-  
-    globalVars: associate(&
-      ! model decisions
-      ixGroundwater           => model_decisions(iLookDECISIONS%groundwatr)%iDecision   ,& ! intent(in):    [i4b]    groundwater parameterization
-      ixSpatialGroundwater    => model_decisions(iLookDECISIONS%spatial_gw)%iDecision   ,& ! intent(in):    [i4b]    spatial representation of groundwater (local-column or single-basin)
-      ixNumericalMethod       => model_decisions(iLookDECISIONS%num_method)%iDecision   ,& ! intent(in): [i4b] choice of numerical method, backward Euler or SUNDIALS/IDA
-      ! domain boundary conditions
-      airtemp                 => forc_data%var(iLookFORCE%airtemp)                      ,& ! intent(in):    [dp]     temperature of the upper boundary of the snow and soil domains (K)
-      ! vector of energy and hydrology indices for the snow and soil domains
-      ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):    [i4b(:)] index in the state subset for energy state variables in the snow+soil domain
-      ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):    [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain
-      nSnowSoilNrg            => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1)         ,& ! intent(in):    [i4b]    number of energy state variables in the snow+soil domain
-      nSnowSoilHyd            => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology state variables in the snow+soil domain
-      ! indices of model state variables
-      ixMapSubset2Full        => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat         ,& ! intent(in):    [i4b(:)] list of indices in the state subset (missing for values not in the subset)
-      ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,& ! intent(in):    [i4b(:)] indices defining the type of the state (ixNrgState...)
-      ixNrgCanair             => indx_data%var(iLookINDEX%ixNrgCanair)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in canopy air space domain
-      ixNrgCanopy             => indx_data%var(iLookINDEX%ixNrgCanopy)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in the canopy domain
-      ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the canopy domain
-      ixNrgLayer              => indx_data%var(iLookINDEX%ixNrgLayer)%dat               ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for energy states in the snow+soil domain
-      ixHydLayer              => indx_data%var(iLookINDEX%ixHydLayer)%dat               ,& ! intent(in):    [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the snow+soil domain
-      ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy air space energy state variable
-      ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy energy state variable
-      ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy hydrology state variable (mass)
-      ! numerix tracking
-      numberStateSplit        => indx_data%var(iLookINDEX%numberStateSplit     )%dat(1) ,& ! intent(inout): [i4b]    number of state splitting solutions             (-)
-      numberDomainSplitNrg    => indx_data%var(iLookINDEX%numberDomainSplitNrg )%dat(1) ,& ! intent(inout): [i4b]    number of domain splitting solutions for energy (-)
-      numberDomainSplitMass   => indx_data%var(iLookINDEX%numberDomainSplitMass)%dat(1) ,& ! intent(inout): [i4b]    number of domain splitting solutions for mass   (-)
-      numberScalarSolutions   => indx_data%var(iLookINDEX%numberScalarSolutions)%dat(1) ,& ! intent(inout): [i4b]    number of scalar solutions                      (-)
-      ! domain configuration
-      canopyDepth             => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1)      ,& ! intent(in):    [dp]     canopy depth (m)
-      mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
-      ! snow parameters
-      snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,& ! intent(in):    [dp]     scaling parameter for the snow freezing curve (K-1)
-      ! depth-varying soil parameters
-      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_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,& ! intent(in):    [dp(:)]  soil porosity (-)
-      theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,& ! intent(in):    [dp(:)]  soil residual volumetric water content (-)
-      ! soil parameters
-      specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,& ! intent(in):    [dp]     specific storage coefficient (m-1)
-      ! model diagnostic variables (fraction of liquid water)
-      scalarFracLiqVeg        => diag_data%var(iLookDIAG%scalarFracLiqVeg)%dat(1)       ,& ! intent(out):   [dp]     fraction of liquid water on vegetation (-)
-      mLayerFracLiqSnow       => diag_data%var(iLookDIAG%mLayerFracLiqSnow)%dat         ,& ! intent(out):   [dp(:)]  fraction of liquid water in each snow layer (-)
-      mLayerMeltFreeze        => diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat          ,& ! intent(out):   [dp(:)]  melt-freeze in each snow and soil layer (kg m-3)
-      ! model state variables (vegetation canopy)
-      scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(out):   [dp]     temperature of the canopy air space (K)
-      scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(out):   [dp]     temperature of the vegetation canopy (K)
-      scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(out):   [dp]     mass of ice on the vegetation canopy (kg m-2)
-      scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(out):   [dp]     mass of liquid water on the vegetation canopy (kg m-2)
-      scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(out):   [dp]     mass of total water on the vegetation canopy (kg m-2)
-      ! model state variables (snow and soil domains)
-      mLayerTemp              => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(out):   [dp(:)]  temperature of each snow/soil layer (K)
-      mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of ice (-)
-      mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of liquid water (-)
-      mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(out):   [dp(:)]  volumetric fraction of total water (-)
-      mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(out):   [dp(:)]  matric head (m)
-      mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(out):   [dp(:)]  matric potential of liquid water (m)
-      )
-      ! ---------------------------------------------------------------------------------------
-      ! initialize error control
-      err=0; message="opSplittin/"
-  
-      ! we just solve the fully coupled problem by with Sundials for now
-      select case(ixNumericalMethod)
-        case(sundials); nCoupling = 1
-        case(bEuler); nCoupling = 2
-        case default; err=20; message=trim(message)//'expect num_method to be sundials or bEuler (or itertive, which is bEuler)'; return
-      end select
-  
-      ! -----
-      ! * initialize...
-      ! ---------------
-  
-      ! set the global print flag
-      globalPrintFlag=.false.
-  
-      if(globalPrintFlag)&
-      print*, trim(message), dt
-  
-      ! initialize the first success call
-      firstSuccess=.false.
-  
-      ! initialize the flags
-      tooMuchMelt=.false.  ! too much melt (merge snow layers)
-      stepFailure=.false.  ! step failure
-  
-      ! initialize flag for the success of the substepping
-      failure=.false.
-  
-      ! initialize the flux check
-      neededFlux(:) = .false.
-  
-      ! initialize the state check
-      stateCheck(:) = 0
-  
-      ! compute the total water content in the vegetation canopy
-      scalarCanopyWat = scalarCanopyLiq + scalarCanopyIce  ! kg m-2
-  
-      ! save volumetric ice content at the start of the step
-      ! NOTE: used for volumetric loss due to melt-freeze
-      mLayerVolFracIceInit(:) = mLayerVolFracIce(:)
-  
-      ! compute the total water content in snow and soil
-      ! NOTE: no ice expansion allowed for soil
-      if(nSnow>0)&
-      mLayerVolFracWat(      1:nSnow  ) = mLayerVolFracLiq(      1:nSnow  ) + mLayerVolFracIce(      1:nSnow  )*(iden_ice/iden_water)
-      mLayerVolFracWat(nSnow+1:nLayers) = mLayerVolFracLiq(nSnow+1:nLayers) + mLayerVolFracIce(nSnow+1:nLayers)
-  
-      ! compute the liquid water matric potential (m)
-      ! NOTE: include ice content as part of the solid porosity - major effect of ice is to reduce the pore size; ensure that effSat=1 at saturation
-      ! (from Zhao et al., J. Hydrol., 1997: Numerical analysis of simultaneous heat and mass transfer...)
-      do iSoil=1,nSoil
-        call liquidHead(mLayerMatricHead(iSoil),mLayerVolFracLiq(nSnow+iSoil),mLayerVolFracIce(nSnow+iSoil),  & ! input:  state variables
-                        vGn_alpha(iSoil),vGn_n(iSoil),theta_sat(iSoil),theta_res(iSoil),vGn_m(iSoil),         & ! input:  parameters
-                        matricHeadLiq=mLayerMatricHeadLiq(iSoil),                                             & ! output: liquid water matric potential (m)
-                        err=err,message=cmessage)                                                               ! output: error control
-        if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-      end do  ! looping through soil layers (computing liquid water matric potential)
-  
-      ! allocate space for the flux mask (used to define when fluxes are updated)
-      call allocLocal(flux_meta(:),fluxMask,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-      ! allocate space for the flux count (used to check that fluxes are only updated once)
-      call allocLocal(flux_meta(:),fluxCount,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-      ! allocate space for the temporary prognostic variable structure
-      call allocLocal(prog_meta(:),prog_temp,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-      ! allocate space for the temporary diagnostic variable structure
-      call allocLocal(diag_meta(:),diag_temp,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-      ! allocate space for the temporary flux variable structure
-      call allocLocal(flux_meta(:),flux_temp,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-      ! allocate space for the derivative structure
-      call allocLocal(deriv_meta(:),deriv_data,nSnow,nSoil,err,cmessage)
-      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; end if
-  
-      ! intialize the flux conter
-      do iVar=1,size(flux_meta)  ! loop through fluxes
-        fluxCount%var(iVar)%dat(:) = 0
-      end do
-  
-      ! initialize the model fluxes
-      do iVar=1,size(flux_meta)  ! loop through fluxes
-        if(flux2state_orig(iVar)%state1==integerMissing .and. flux2state_orig(iVar)%state2==integerMissing) cycle ! flux does not depend on state (e.g., input)
-        if(flux2state_orig(iVar)%state1==iname_watCanopy .and. .not.computeVegFlux) cycle ! use input fluxes in cases where there is no canopy
-        flux_data%var(iVar)%dat(:) = 0._rkind
-      end do
-  
-      ! initialize derivatives
-      do iVar=1,size(deriv_meta)
-        deriv_data%var(iVar)%dat(:) = 0._rkind
-      end do
-  
-      ! ==========================================================================================================================================
-      ! ==========================================================================================================================================
-      ! ==========================================================================================================================================
-      ! ==========================================================================================================================================
-  
-      ! loop through different coupling strategies
-      coupling: do ixCoupling=1,nCoupling
-  
-        ! initialize the time step
-        dtInit = min( merge(dt,            dtmin_coupled, ixCoupling==fullyCoupled), dt) ! initial time step
-        dt_min = min( merge(dtmin_coupled, dtmin_split,   ixCoupling==fullyCoupled), dt) ! minimum time step
-  
-        ! keep track of the number of state splits
-        if(ixCoupling/=fullyCoupled) numberStateSplit = numberStateSplit + 1
-  
-        ! define the number of operator splits for the state type
-        select case(ixCoupling)
-        case(fullyCoupled);   nStateTypeSplit=1
-        case(stateTypeSplit); nStateTypeSplit=nStateTypes
-        case default; err=20; message=trim(message)//'coupling case not found'; return
-        end select  ! operator splitting option
-  
-        ! define if we wish to try the domain split
-        select case(ixCoupling)
-        case(fullyCoupled);   tryDomainSplit=0
-        case(stateTypeSplit); tryDomainSplit=1
-        case default; err=20; message=trim(message)//'coupling case not found'; return
-        end select  ! operator splitting option
-  
-        ! state splitting loop
-        stateTypeSplit: do iStateTypeSplit=1,nStateTypeSplit
-  
-          ! -----
-          ! * identify state-specific variables for a given state split...
-          ! --------------------------------------------------------------
-  
-          ! flag to adjust the temperature
-          doAdjustTemp = (ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)
-  
-          ! modify the state type names associated with the state vector
-          if(ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)then
-            if(computeVegFlux)then
-              where(ixStateType(ixHydCanopy)==iname_watCanopy) ixStateType(ixHydCanopy)=iname_liqCanopy
-            endif
-            where(ixStateType(ixHydLayer) ==iname_watLayer)  ixStateType(ixHydLayer) =iname_liqLayer
-            where(ixStateType(ixHydLayer) ==iname_matLayer)  ixStateType(ixHydLayer) =iname_lmpLayer
-          endif  ! if modifying state variables for the mass split
-  
-          ! first try the state type split, then try the domain split within a given state type
-          stateThenDomain: do ixStateThenDomain=1,1+tryDomainSplit ! 1=state type split; 2=domain split within a given state type
-  
-            ! keep track of the number of domain splits
-            if(iStateTypeSplit==nrgSplit  .and. ixStateThenDomain==subDomain) numberDomainSplitNrg  = numberDomainSplitNrg  + 1
-            if(iStateTypeSplit==massSplit .and. ixStateThenDomain==subDomain) numberDomainSplitMass = numberDomainSplitMass + 1
-  
-            ! define the number of domain splits for the state type
-            select case(ixStateThenDomain)
-              case(fullDomain); nDomainSplit=1
-              case(subDomain);  nDomainSplit=nDomains
-              case default; err=20; message=trim(message)//'coupling case not found'; return
-            end select
-  
-            ! check that we haven't split the domain when we are fully coupled
-            if(ixCoupling==fullyCoupled .and. nDomainSplit==nDomains)then
-              message=trim(message)//'cannot split domains when fully coupled'
-              err=20; return
-            endif
-  
-            ! domain splitting loop
-            domainSplit: do iDomainSplit=1,nDomainSplit
-  
-              ! trial with the vector then scalar solution
-              solution: do ixSolution=1,nSolutions
-  
-                ! initialize error control
-                err=0; message="opSplittin/"
-  
-                ! refine the time step
-                if(ixSolution==scalar)then
-                  dtInit = min(dtmin_split, dt)    ! initial time step
-                  dt_min = min(dtmin_scalar, dt)   ! minimum time step
-                endif
-  
-                ! initialize the first flux call
-                firstFluxCall=.true.
-  
-                ! get the number of split layers
-                select case(ixSolution)
-                  case(vector); nStateSplit=1
-                  case(scalar); nStateSplit=count(stateMask)
-                  case default; err=20; message=trim(message)//'unknown solution method'; return
-                end select
-  
-  
-                ! loop through layers (NOTE: nStateSplit=1 for the vector solution, hence no looping)
-                stateSplit: do iStateSplit=1,nStateSplit
-  
-                  ! -----
-                  ! * define state subsets for a given split...
-                  ! -------------------------------------------
-  
-                  ! get the mask for the state subset
-                  call stateFilter(ixCoupling,ixSolution,ixStateThenDomain,iStateTypeSplit,iDomainSplit,iStateSplit,&
-                                    indx_data,stateMask,nSubset,err,cmessage)
-                  if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-  
-                  ! check that state variables exist
-                  if(nSubset==0) cycle domainSplit
-  
-                  ! avoid redundant case where vector solution is of length 1
-                  if(ixSolution==vector .and. count(stateMask)==1) cycle solution
-  
-  
-  
-                  ! -----
-                  ! * assemble vectors for a given split...
-                  ! ---------------------------------------
-                  ! get indices for a given split
-                  call indexSplit(stateMask,                   & ! intent(in)    : logical vector (.true. if state is in the subset)
-                                  nSnow,nSoil,nLayers,nSubset, & ! intent(in)    : number of snow and soil layers, and total number of layers
-                                  indx_data,                   & ! intent(inout) : index data structure
-                                  err,cmessage)                  ! intent(out)   : error control
-                  if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-  
-                  ! -----
-                  ! * define the mask of the fluxes used...
-                  ! ---------------------------------------
-  
-                  ! identify the type of state for the states in the subset
-                  stateSubset: associate(ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat ,& ! intent(in): [i4b(:)] indices of state types
-                                          ixMapFull2Subset    => indx_data%var(iLookINDEX%ixMapFull2Subset)%dat   ,& ! intent(in): [i4b(:)] mapping of full state vector to the state subset
-                                          ixControlVolume     => indx_data%var(iLookINDEX%ixControlVolume)%dat    ,& ! intent(in): [i4b(:)] index of control volume for different domains (veg, snow, soil)
-                                          ixLayerActive       => indx_data%var(iLookINDEX%ixLayerActive)%dat      ,& ! intent(in): [i4b(:)] list of indices for all active layers (inactive=integerM
-                                          ixDomainType        => indx_data%var(iLookINDEX%ixDomainType)%dat       )  ! intent(in): [i4b(:)] indices defining the type of the domain (iname_veg, iname_snow, iname_soil)
-  
-                    ! loop through flux variables
-                    do iVar=1,size(flux_meta)
-  
-                      ! * identify flux mask for the fully coupled solution
-                      if(ixCoupling==fullyCoupled)then
-                        desiredFlux            = any(ixStateType_subset==flux2state_orig(iVar)%state1) .or. any(ixStateType_subset==flux2state_orig(iVar)%state2)
+    ! initialize error control
+    err=0; message="opSplittin/"
+
+    ! we just solve the fully coupled problem by with Sundials for now
+    select case(ixNumericalMethod)
+      case(sundials); nCoupling = 1
+      case(bEuler); nCoupling = 2
+      case default; err=20; message=trim(message)//'expect num_method to be sundials or bEuler (or itertive, which is bEuler)'; return
+    end select
+
+    ! -----
+    ! * initialize...
+    ! ---------------
+
+    ! set the global print flag
+    globalPrintFlag=.false.
+
+    ! if(globalPrintFlag)&
+    print*, trim(message), dt
+
+    ! initialize the first success call
+    firstSuccess=.false.
+
+    ! initialize the flags
+    tooMuchMelt=.false.  ! too much melt (merge snow layers)
+    stepFailure=.false.  ! step failure
+
+    ! initialize flag for the success of the substepping
+    failure=.false.
+
+    ! initialize the flux check
+    neededFlux(:) = .false.
+
+    ! initialize the state check
+    stateCheck(:) = 0
+
+    ! compute the total water content in the vegetation canopy
+    scalarCanopyWat = scalarCanopyLiq + scalarCanopyIce  ! kg m-2
+
+    ! save volumetric ice content at the start of the step
+    ! NOTE: used for volumetric loss due to melt-freeze
+    mLayerVolFracIceInit(:) = mLayerVolFracIce(:)
+
+    ! compute the total water content in snow and soil
+    ! NOTE: no ice expansion allowed for soil
+    if(nSnow>0)&
+    mLayerVolFracWat(      1:nSnow  ) = mLayerVolFracLiq(      1:nSnow  ) + mLayerVolFracIce(      1:nSnow  )*(iden_ice/iden_water)
+    mLayerVolFracWat(nSnow+1:nLayers) = mLayerVolFracLiq(nSnow+1:nLayers) + mLayerVolFracIce(nSnow+1:nLayers)
+
+    ! compute the liquid water matric potential (m)
+    ! NOTE: include ice content as part of the solid porosity - major effect of ice is to reduce the pore size; ensure that effSat=1 at saturation
+    ! (from Zhao et al., J. Hydrol., 1997: Numerical analysis of simultaneous heat and mass transfer...)
+    do iSoil=1,nSoil
+      call liquidHead(mLayerMatricHead(iSoil),mLayerVolFracLiq(nSnow+iSoil),mLayerVolFracIce(nSnow+iSoil),  & ! input:  state variables
+                      vGn_alpha(iSoil),vGn_n(iSoil),theta_sat(iSoil),theta_res(iSoil),vGn_m(iSoil),         & ! input:  parameters
+                      matricHeadLiq=mLayerMatricHeadLiq(iSoil),                                             & ! output: liquid water matric potential (m)
+                      err=err,message=cmessage)                                                               ! output: error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+    end do  ! looping through soil layers (computing liquid water matric potential)
+
+    ! allocate space for the flux mask (used to define when fluxes are updated)
+    call allocLocal(flux_meta(:),fluxMask,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the flux count (used to check that fluxes are only updated once)
+    call allocLocal(flux_meta(:),fluxCount,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the temporary prognostic variable structure
+    call allocLocal(prog_meta(:),prog_temp,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the temporary diagnostic variable structure
+    call allocLocal(diag_meta(:),diag_temp,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the temporary flux variable structure
+    call allocLocal(flux_meta(:),flux_temp,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the derivative structure
+    call allocLocal(deriv_meta(:),deriv_data,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; end if
+
+    ! intialize the flux conter
+    do iVar=1,size(flux_meta)  ! loop through fluxes
+      fluxCount%var(iVar)%dat(:) = 0
+    end do
+
+    ! initialize the model fluxes
+    do iVar=1,size(flux_meta)  ! loop through fluxes
+      if(flux2state_orig(iVar)%state1==integerMissing .and. flux2state_orig(iVar)%state2==integerMissing) cycle ! flux does not depend on state (e.g., input)
+      if(flux2state_orig(iVar)%state1==iname_watCanopy .and. .not.computeVegFlux) cycle ! use input fluxes in cases where there is no canopy
+      flux_data%var(iVar)%dat(:) = 0._rkind
+    end do
+
+    ! initialize derivatives
+    do iVar=1,size(deriv_meta)
+      deriv_data%var(iVar)%dat(:) = 0._rkind
+    end do
+
+    ! ==========================================================================================================================================
+    ! ==========================================================================================================================================
+    ! ==========================================================================================================================================
+    ! ==========================================================================================================================================
+
+    ! loop through different coupling strategies
+    coupling: do ixCoupling=1,nCoupling
+
+      ! initialize the time step
+      dtInit = min( merge(dt,            dtmin_coupled, ixCoupling==fullyCoupled), dt) ! initial time step
+      dt_min = min( merge(dtmin_coupled, dtmin_split,   ixCoupling==fullyCoupled), dt) ! minimum time step
+
+      ! keep track of the number of state splits
+      if(ixCoupling/=fullyCoupled) numberStateSplit = numberStateSplit + 1
+
+      ! define the number of operator splits for the state type
+      select case(ixCoupling)
+      case(fullyCoupled);   nStateTypeSplit=1
+      case(stateTypeSplit); nStateTypeSplit=nStateTypes
+      case default; err=20; message=trim(message)//'coupling case not found'; return
+      end select  ! operator splitting option
+
+      ! define if we wish to try the domain split
+      select case(ixCoupling)
+      case(fullyCoupled);   tryDomainSplit=0
+      case(stateTypeSplit); tryDomainSplit=1
+      case default; err=20; message=trim(message)//'coupling case not found'; return
+      end select  ! operator splitting option
+
+      ! state splitting loop
+      stateTypeSplit: do iStateTypeSplit=1,nStateTypeSplit
+
+        ! -----
+        ! * identify state-specific variables for a given state split...
+        ! --------------------------------------------------------------
+
+        ! flag to adjust the temperature
+        doAdjustTemp = (ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)
+
+        ! modify the state type names associated with the state vector
+        if(ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)then
+          if(computeVegFlux)then
+            where(ixStateType(ixHydCanopy)==iname_watCanopy) ixStateType(ixHydCanopy)=iname_liqCanopy
+          endif
+          where(ixStateType(ixHydLayer) ==iname_watLayer)  ixStateType(ixHydLayer) =iname_liqLayer
+          where(ixStateType(ixHydLayer) ==iname_matLayer)  ixStateType(ixHydLayer) =iname_lmpLayer
+        endif  ! if modifying state variables for the mass split
+
+        ! first try the state type split, then try the domain split within a given state type
+        stateThenDomain: do ixStateThenDomain=1,1+tryDomainSplit ! 1=state type split; 2=domain split within a given state type
+
+          ! keep track of the number of domain splits
+          if(iStateTypeSplit==nrgSplit  .and. ixStateThenDomain==subDomain) numberDomainSplitNrg  = numberDomainSplitNrg  + 1
+          if(iStateTypeSplit==massSplit .and. ixStateThenDomain==subDomain) numberDomainSplitMass = numberDomainSplitMass + 1
+
+          ! define the number of domain splits for the state type
+          select case(ixStateThenDomain)
+            case(fullDomain); nDomainSplit=1
+            case(subDomain);  nDomainSplit=nDomains
+            case default; err=20; message=trim(message)//'coupling case not found'; return
+          end select
+
+          ! check that we haven't split the domain when we are fully coupled
+          if(ixCoupling==fullyCoupled .and. nDomainSplit==nDomains)then
+            message=trim(message)//'cannot split domains when fully coupled'
+            err=20; return
+          endif
+
+          ! domain splitting loop
+          domainSplit: do iDomainSplit=1,nDomainSplit
+
+            ! trial with the vector then scalar solution
+            solution: do ixSolution=1,nSolutions
+
+              ! initialize error control
+              err=0; message="opSplittin/"
+
+              ! refine the time step
+              if(ixSolution==scalar)then
+                dtInit = min(dtmin_split, dt)    ! initial time step
+                dt_min = min(dtmin_scalar, dt)   ! minimum time step
+              endif
+
+              ! initialize the first flux call
+              firstFluxCall=.true.
+
+              ! get the number of split layers
+              select case(ixSolution)
+                case(vector); nStateSplit=1
+                case(scalar); nStateSplit=count(stateMask)
+                case default; err=20; message=trim(message)//'unknown solution method'; return
+              end select
+
+
+              ! loop through layers (NOTE: nStateSplit=1 for the vector solution, hence no looping)
+              stateSplit: do iStateSplit=1,nStateSplit
+
+                ! -----
+                ! * define state subsets for a given split...
+                ! -------------------------------------------
+
+                ! get the mask for the state subset
+                call stateFilter(ixCoupling,ixSolution,ixStateThenDomain,iStateTypeSplit,iDomainSplit,iStateSplit,&
+                                  indx_data,stateMask,nSubset,err,cmessage)
+                if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+
+                ! check that state variables exist
+                if(nSubset==0) cycle domainSplit
+
+                ! avoid redundant case where vector solution is of length 1
+                if(ixSolution==vector .and. count(stateMask)==1) cycle solution
+
+
+
+                ! -----
+                ! * assemble vectors for a given split...
+                ! ---------------------------------------
+                ! get indices for a given split
+                call indexSplit(stateMask,                   & ! intent(in)    : logical vector (.true. if state is in the subset)
+                                nSnow,nSoil,nLayers,nSubset, & ! intent(in)    : number of snow and soil layers, and total number of layers
+                                indx_data,                   & ! intent(inout) : index data structure
+                                err,cmessage)                  ! intent(out)   : error control
+                if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+
+                ! -----
+                ! * define the mask of the fluxes used...
+                ! ---------------------------------------
+
+                ! identify the type of state for the states in the subset
+                stateSubset: associate(ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat ,& ! intent(in): [i4b(:)] indices of state types
+                                        ixMapFull2Subset    => indx_data%var(iLookINDEX%ixMapFull2Subset)%dat   ,& ! intent(in): [i4b(:)] mapping of full state vector to the state subset
+                                        ixControlVolume     => indx_data%var(iLookINDEX%ixControlVolume)%dat    ,& ! intent(in): [i4b(:)] index of control volume for different domains (veg, snow, soil)
+                                        ixLayerActive       => indx_data%var(iLookINDEX%ixLayerActive)%dat      ,& ! intent(in): [i4b(:)] list of indices for all active layers (inactive=integerM
+                                        ixDomainType        => indx_data%var(iLookINDEX%ixDomainType)%dat       )  ! intent(in): [i4b(:)] indices defining the type of the domain (iname_veg, iname_snow, iname_soil)
+
+                  ! loop through flux variables
+                  do iVar=1,size(flux_meta)
+
+                    ! * identify flux mask for the fully coupled solution
+                    if(ixCoupling==fullyCoupled)then
+                      desiredFlux            = any(ixStateType_subset==flux2state_orig(iVar)%state1) .or. any(ixStateType_subset==flux2state_orig(iVar)%state2)
+                      fluxMask%var(iVar)%dat = desiredFlux
+
+                    ! * identify flux mask for the split solution
+                    else
+
+                      ! identify the flux mask for a given state split
+                      select case(iStateTypeSplit)
+                        case(nrgSplit);  desiredFlux = any(ixStateType_subset==flux2state_orig(iVar)%state1) .or. any(ixStateType_subset==flux2state_orig(iVar)%state2)
+                        case(massSplit); desiredFlux = any(ixStateType_subset==flux2state_liq(iVar)%state1)  .or. any(ixStateType_subset==flux2state_liq(iVar)%state2)
+                        case default; err=20; message=trim(message)//'unable to identify split based on state type'; return
+                      end select
+
+                      ! no domain splitting
+                      if(nDomains==1)then
                         fluxMask%var(iVar)%dat = desiredFlux
-  
-                      ! * identify flux mask for the split solution
+
+                      ! domain splitting
                       else
-  
-                        ! identify the flux mask for a given state split
-                        select case(iStateTypeSplit)
-                          case(nrgSplit);  desiredFlux = any(ixStateType_subset==flux2state_orig(iVar)%state1) .or. any(ixStateType_subset==flux2state_orig(iVar)%state2)
-                          case(massSplit); desiredFlux = any(ixStateType_subset==flux2state_liq(iVar)%state1)  .or. any(ixStateType_subset==flux2state_liq(iVar)%state2)
-                          case default; err=20; message=trim(message)//'unable to identify split based on state type'; return
-                        end select
-  
-                        ! no domain splitting
-                        if(nDomains==1)then
-                          fluxMask%var(iVar)%dat = desiredFlux
-  
-                        ! domain splitting
-                        else
-                          print*,"split domain"
-  
-                          ! initialize to .false.
-                          fluxMask%var(iVar)%dat = .false.
-  
-                          ! only need to proceed if the flux is desired
-                          if(desiredFlux)then
-  
-                            ! different domain splitting operations
-                            select case(iDomainSplit)
-  
-                              ! canopy fluxes -- (:1) gets the upper boundary(0) if it exists
-                              case(vegSplit)
-  
-                                ! vector solution (should only be present for energy)
-                                if(ixSolution==vector)then
-                                  fluxMask%var(iVar)%dat(:1) = desiredFlux
-                                  if(ixStateThenDomain>1 .and. iStateTypeSplit/=nrgSplit)then
-                                    message=trim(message)//'only expect a vector solution for the vegetation domain for energy'
-                                    err=20; return
-                                  endif
-  
-                                ! scalar solution
-                                else
-                                  fluxMask%var(iVar)%dat(:1) = desiredFlux
+                        print*,"split domain"
+
+                        ! initialize to .false.
+                        fluxMask%var(iVar)%dat = .false.
+
+                        ! only need to proceed if the flux is desired
+                        if(desiredFlux)then
+
+                          ! different domain splitting operations
+                          select case(iDomainSplit)
+
+                            ! canopy fluxes -- (:1) gets the upper boundary(0) if it exists
+                            case(vegSplit)
+
+                              ! vector solution (should only be present for energy)
+                              if(ixSolution==vector)then
+                                fluxMask%var(iVar)%dat(:1) = desiredFlux
+                                if(ixStateThenDomain>1 .and. iStateTypeSplit/=nrgSplit)then
+                                  message=trim(message)//'only expect a vector solution for the vegetation domain for energy'
+                                  err=20; return
                                 endif
-  
-                              ! fluxes through snow and soil
-                              case(snowSplit,soilSplit)
-  
-                                ! loop through layers
-                                do iLayer=1,nLayers
-                                  if(ixlayerActive(iLayer)/=integerMissing)then
-  
-                                    ! get the offset (ixLayerActive=1,2,3,...nLayers, and soil vectors nSnow+1, nSnow+2, ..., nLayers)
-                                    iOffset = merge(nSnow, 0, flux_meta(iVar)%vartype==iLookVarType%midSoil .or. flux_meta(iVar)%vartype==iLookVarType%ifcSoil)
-                                    jLayer  = iLayer-iOffset
-  
-                                    ! identify the minimum layer
-                                    select case(flux_meta(iVar)%vartype)
-                                      case(iLookVarType%ifcToto, iLookVarType%ifcSnow, iLookVarType%ifcSoil); minLayer=merge(jLayer-1, jLayer, jLayer==1)
-                                      case(iLookVarType%midToto, iLookVarType%midSnow, iLookVarType%midSoil); minLayer=jLayer
-                                      case default; minLayer=integerMissing
-                                    end select
-  
-                                    ! set desired layers
-                                    select case(flux_meta(iVar)%vartype)
-                                      case(iLookVarType%midToto,iLookVarType%ifcToto);                   fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
-                                      case(iLookVarType%midSnow,iLookVarType%ifcSnow); if(iLayer<=nSnow) fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
-                                      case(iLookVarType%midSoil,iLookVarType%ifcSoil); if(iLayer> nSnow) fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
+
+                              ! scalar solution
+                              else
+                                fluxMask%var(iVar)%dat(:1) = desiredFlux
+                              endif
+
+                            ! fluxes through snow and soil
+                            case(snowSplit,soilSplit)
+
+                              ! loop through layers
+                              do iLayer=1,nLayers
+                                if(ixlayerActive(iLayer)/=integerMissing)then
+
+                                  ! get the offset (ixLayerActive=1,2,3,...nLayers, and soil vectors nSnow+1, nSnow+2, ..., nLayers)
+                                  iOffset = merge(nSnow, 0, flux_meta(iVar)%vartype==iLookVarType%midSoil .or. flux_meta(iVar)%vartype==iLookVarType%ifcSoil)
+                                  jLayer  = iLayer-iOffset
+
+                                  ! identify the minimum layer
+                                  select case(flux_meta(iVar)%vartype)
+                                    case(iLookVarType%ifcToto, iLookVarType%ifcSnow, iLookVarType%ifcSoil); minLayer=merge(jLayer-1, jLayer, jLayer==1)
+                                    case(iLookVarType%midToto, iLookVarType%midSnow, iLookVarType%midSoil); minLayer=jLayer
+                                    case default; minLayer=integerMissing
+                                  end select
+
+                                  ! set desired layers
+                                  select case(flux_meta(iVar)%vartype)
+                                    case(iLookVarType%midToto,iLookVarType%ifcToto);                   fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
+                                    case(iLookVarType%midSnow,iLookVarType%ifcSnow); if(iLayer<=nSnow) fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
+                                    case(iLookVarType%midSoil,iLookVarType%ifcSoil); if(iLayer> nSnow) fluxMask%var(iVar)%dat(minLayer:jLayer) = desiredFlux
+                                  end select
+
+                                  ! add hydrology states for scalar variables
+                                  if(iStateTypeSplit==massSplit .and. flux_meta(iVar)%vartype==iLookVarType%scalarv)then
+                                    select case(iDomainSplit)
+                                    case(snowSplit); if(iLayer==nSnow)   fluxMask%var(iVar)%dat = desiredFlux
+                                    case(soilSplit); if(iLayer==nSnow+1) fluxMask%var(iVar)%dat = desiredFlux
                                     end select
-  
-                                    ! add hydrology states for scalar variables
-                                    if(iStateTypeSplit==massSplit .and. flux_meta(iVar)%vartype==iLookVarType%scalarv)then
-                                      select case(iDomainSplit)
-                                      case(snowSplit); if(iLayer==nSnow)   fluxMask%var(iVar)%dat = desiredFlux
-                                      case(soilSplit); if(iLayer==nSnow+1) fluxMask%var(iVar)%dat = desiredFlux
-                                      end select
-                                    endif  ! if hydrology split and scalar
-  
-                                  endif    ! if the layer is active
-                                end do   ! looping through layers
-  
-                              ! check
-                              case default; err=20; message=trim(message)//'unable to identify split based on domain type'; return
-                            end select  ! domain split
-  
-                          endif  ! if flux is desired
-  
-                        endif  ! domain splitting
-                      endif  ! not fully coupled
-  
-                      ! define if the flux is desired
-                      if(desiredFlux) neededFlux(iVar)=.true.
-                      !if(desiredFlux) print*, flux_meta(iVar)%varname, fluxMask%var(iVar)%dat
-  
-                      ! * check
-                      if( globalPrintFlag .and. count(fluxMask%var(iVar)%dat)>0 )&
-                      print*, trim(flux_meta(iVar)%varname)
-  
-                    end do  ! (loop through fluxes)
-  
-                  end associate stateSubset
-  
-                  ! *******************************************************************************************************************************
-                  ! *******************************************************************************************************************************
-                  ! *******************************************************************************************************************************
-                  ! ***** trial with a given solution method...
-  
-                  ! check that we do not attempt the scalar solution for the fully coupled case
-                  if(ixCoupling==fullyCoupled .and. ixSolution==scalar)then
-                    message=trim(message)//'only apply the scalar solution to the fully split coupling strategy'
-                    err=20; return
-                  endif
-  
-                  ! reset the flag for the first flux call
-                  if(.not.firstSuccess) firstFluxCall=.true.
-  
-                  ! save/recover copies of prognostic variables
-                  do iVar=1,size(prog_data%var)
-                    select case(failure)
-                      case(.false.); prog_temp%var(iVar)%dat(:) = prog_data%var(iVar)%dat(:)
-                      case(.true.);  prog_data%var(iVar)%dat(:) = prog_temp%var(iVar)%dat(:)
-                    end select
-                  end do  ! looping through variables
-  
-                  ! save/recover copies of diagnostic variables
-                  do iVar=1,size(diag_data%var)
-                    select case(failure)
-                      case(.false.); diag_temp%var(iVar)%dat(:) = diag_data%var(iVar)%dat(:)
-                      case(.true.);  diag_data%var(iVar)%dat(:) = diag_temp%var(iVar)%dat(:)
-                    end select
-                  end do  ! looping through variables
-  
-                  ! save/recover copies of model fluxes
-                  do iVar=1,size(flux_data%var)
-                    select case(failure)
-                      case(.false.); flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
-                      case(.true.);  flux_data%var(iVar)%dat(:) = flux_temp%var(iVar)%dat(:)
-                    end select
-                  end do  ! looping through variables
-  
-                  ! -----
-                  ! * solve variable subset for one time step...
-                  ! --------------------------------------------
-  
-                  ! keep track of the number of scalar solutions
-                  if(ixSolution==scalar) numberScalarSolutions = numberScalarSolutions + 1
-  
-                  ! solve variable subset for one full time step
-                  select case(ixNumericalMethod)
-                    case(sundials)
-                      call varSubstepSundials(&
-                                  ! input: model control
-                                  dt,                         & ! intent(in)    : time step (s)
-                                  dtInit,                     & ! intent(in)    : initial time step (seconds)
-                                  dt_min,                     & ! intent(in)    : minimum time step (seconds)
-                                  nSubset,                    & ! intent(in)    : total number of variables in the state subset
-                                  doAdjustTemp,               & ! intent(in)    : flag to indicate if we adjust the temperature
-                                  firstSubStep,               & ! intent(in)    : flag to denote first sub-step
-                                  firstFluxCall,              & ! intent(inout) : flag to indicate if we are processing the first flux call
-                                  computeVegFlux,             & ! intent(in)    : flag to denote if computing energy flux over vegetation
-                                  (ixSolution==scalar),       & ! intent(in)    : flag to denote computing the scalar solution
-                                  iStateSplit,                & ! intent(in)    : index of the layer in the splitting operation
-                                  fluxMask,                   & ! intent(in)    : mask for the fluxes used in this given state subset
-                                  fluxCount,                  & ! intent(inout) : number of times fluxes are updated (should equal nsubstep)
-                                  ! input/output: data structures
-                                  model_decisions,            & ! intent(in)    : model decisions
-                                  lookup_data,                & ! intent(in)    : lookup tables
-                                  type_data,                  & ! intent(in)    : type of vegetation and soil
-                                  attr_data,                  & ! intent(in)    : spatial attributes
-                                  forc_data,                  & ! intent(in)    : model forcing data
-                                  mpar_data,                  & ! intent(in)    : model parameters
-                                  indx_data,                  & ! intent(inout) : index data
-                                  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
-                                  deriv_data,                 & ! intent(inout) : derivatives in model fluxes w.r.t. relevant state variables
-                                  bvar_data,                  & ! intent(in)    : model variables for the local basin
-                                  ! output: control
-                                  ixSaturation,               & ! intent(inout) : index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                                  dtMultiplier,               & ! intent(out)   : substep multiplier (-)
-                                  nSubsteps,                  & ! intent(out)   : number of substeps taken for a given split
-                                  failedMinimumStep,          & ! intent(out)   : flag for failed substeps
-                                  reduceCoupledStep,          & ! intent(out)   : flag to reduce the length of the coupled step
-                                  tooMuchMelt,                & ! intent(out)   : flag to denote that ice is insufficient to support melt
-                                  dt_out,					   & ! intent(out)
-                                  err,cmessage)                 ! intent(out)   : error code and error message
-  
-                                  dt = dt_out
-  
-                    case(bEuler)
-                      call varSubstep(&
-                                  ! input: model control
-                                  dt,                         & ! intent(in)    : time step (s)
-                                  dtInit,                     & ! intent(in)    : initial time step (seconds)
-                                  dt_min,                     & ! intent(in)    : minimum time step (seconds)
-                                  nSubset,                    & ! intent(in)    : total number of variables in the state subset
-                                  doAdjustTemp,               & ! intent(in)    : flag to indicate if we adjust the temperature
-                                  firstSubStep,               & ! intent(in)    : flag to denote first sub-step
-                                  firstFluxCall,              & ! intent(inout) : flag to indicate if we are processing the first flux call
-                                  computeVegFlux,             & ! intent(in)    : flag to denote if computing energy flux over vegetation
-                                  (ixSolution==scalar),       & ! intent(in)    : flag to denote computing the scalar solution
-                                  iStateSplit,                & ! intent(in)    : index of the layer in the splitting operation
-                                  fluxMask,                   & ! intent(in)    : mask for the fluxes used in this given state subset
-                                  fluxCount,                  & ! intent(inout) : number of times fluxes are updated (should equal nsubstep)
-                                  ! input/output: data structures
-                                  model_decisions,            & ! intent(in)    : model decisions
-                                  lookup_data,                & ! intent(in)    : lookup tables
-                                  type_data,                  & ! intent(in)    : type of vegetation and soil
-                                  attr_data,                  & ! intent(in)    : spatial attributes
-                                  forc_data,                  & ! intent(in)    : model forcing data
-                                  mpar_data,                  & ! intent(in)    : model parameters
-                                  indx_data,                  & ! intent(inout) : index data
-                                  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
-                                  deriv_data,                 & ! intent(inout) : derivatives in model fluxes w.r.t. relevant state variables
-                                  bvar_data,                  & ! intent(in)    : model variables for the local basin
-                                  ! output: control
-                                  ixSaturation,               & ! intent(inout) : index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                                  dtMultiplier,               & ! intent(out)   : substep multiplier (-)
-                                  nSubsteps,                  & ! intent(out)   : number of substeps taken for a given split
-                                  failedMinimumStep,          & ! intent(out)   : flag for failed substeps
-                                  reduceCoupledStep,          & ! intent(out)   : flag to reduce the length of the coupled step
-                                  tooMuchMelt,                & ! intent(out)   : flag to denote that ice is insufficient to support melt
-                                  err,cmessage)                 ! intent(out)   : error code and error message
-                                ! check
-                    case default; err=20; message=trim(message)//'expect num_method to be sundials or bEuler (or itertive, which is bEuler)'; return
+                                  endif  ! if hydrology split and scalar
+
+                                endif    ! if the layer is active
+                              end do   ! looping through layers
+
+                            ! check
+                            case default; err=20; message=trim(message)//'unable to identify split based on domain type'; return
+                          end select  ! domain split
+
+                        endif  ! if flux is desired
+
+                      endif  ! domain splitting
+                    endif  ! not fully coupled
+
+                    ! define if the flux is desired
+                    if(desiredFlux) neededFlux(iVar)=.true.
+                    !if(desiredFlux) print*, flux_meta(iVar)%varname, fluxMask%var(iVar)%dat
+
+                    ! * check
+                    if( globalPrintFlag .and. count(fluxMask%var(iVar)%dat)>0 )&
+                    print*, trim(flux_meta(iVar)%varname)
+
+                  end do  ! (loop through fluxes)
+
+                end associate stateSubset
+
+                ! *******************************************************************************************************************************
+                ! *******************************************************************************************************************************
+                ! *******************************************************************************************************************************
+                ! ***** trial with a given solution method...
+
+                ! check that we do not attempt the scalar solution for the fully coupled case
+                if(ixCoupling==fullyCoupled .and. ixSolution==scalar)then
+                  message=trim(message)//'only apply the scalar solution to the fully split coupling strategy'
+                  err=20; return
+                endif
+
+                ! reset the flag for the first flux call
+                if(.not.firstSuccess) firstFluxCall=.true.
+
+                ! save/recover copies of prognostic variables
+                do iVar=1,size(prog_data%var)
+                  select case(failure)
+                    case(.false.); prog_temp%var(iVar)%dat(:) = prog_data%var(iVar)%dat(:)
+                    case(.true.);  prog_data%var(iVar)%dat(:) = prog_temp%var(iVar)%dat(:)
                   end select
-         
-                  if(err/=0)then
-                    message=trim(message)//trim(cmessage)
-                    if(err>0) return
-                  endif  ! (check for errors)
-  
-                  ! reduce coupled step if failed the minimum step for the scalar solution
-                  if(failedMinimumStep .and. ixSolution==scalar) reduceCoupledStep=.true.
-  
-                  ! if too much melt (or some other need to reduce the coupled step) then return
-                  ! NOTE: need to go all the way back to coupled_em and merge snow layers, as all splitting operations need to occur with the same layer geometry
-                  if(tooMuchMelt .or. reduceCoupledStep)then
-                    stepFailure=.true.
-                    err=0 ! recovering
-                    return
-                  endif
-  
-                  ! define failure
-                  failure = (failedMinimumStep .or. err<0)
-                  if(.not.failure) firstSuccess=.true.
-  
-                  ! if failed, need to reset the flux counter
-                  if(failure)then
-                    do iVar=1,size(flux_meta)
-                      iMin=lbound(flux_data%var(iVar)%dat)
-                      iMax=ubound(flux_data%var(iVar)%dat)
-                      do iLayer=iMin(1),iMax(1)
-                        if(fluxMask%var(iVar)%dat(iLayer)) fluxCount%var(iVar)%dat(iLayer) = fluxCount%var(iVar)%dat(iLayer) - nSubsteps
-                      end do
+                end do  ! looping through variables
+
+                ! save/recover copies of diagnostic variables
+                do iVar=1,size(diag_data%var)
+                  select case(failure)
+                    case(.false.); diag_temp%var(iVar)%dat(:) = diag_data%var(iVar)%dat(:)
+                    case(.true.);  diag_data%var(iVar)%dat(:) = diag_temp%var(iVar)%dat(:)
+                  end select
+                end do  ! looping through variables
+
+                ! save/recover copies of model fluxes
+                do iVar=1,size(flux_data%var)
+                  select case(failure)
+                    case(.false.); flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
+                    case(.true.);  flux_data%var(iVar)%dat(:) = flux_temp%var(iVar)%dat(:)
+                  end select
+                end do  ! looping through variables
+
+                ! -----
+                ! * solve variable subset for one time step...
+                ! --------------------------------------------
+
+                ! keep track of the number of scalar solutions
+                if(ixSolution==scalar) numberScalarSolutions = numberScalarSolutions + 1
+
+                ! solve variable subset for one full time step
+                select case(ixNumericalMethod)
+                  case(sundials)
+                    call varSubstepSundials(&
+                                ! input: model control
+                                dt,                         & ! intent(in)    : time step (s)
+                                dtInit,                     & ! intent(in)    : initial time step (seconds)
+                                dt_min,                     & ! intent(in)    : minimum time step (seconds)
+                                nSubset,                    & ! intent(in)    : total number of variables in the state subset
+                                doAdjustTemp,               & ! intent(in)    : flag to indicate if we adjust the temperature
+                                firstSubStep,               & ! intent(in)    : flag to denote first sub-step
+                                firstFluxCall,              & ! intent(inout) : flag to indicate if we are processing the first flux call
+                                computeVegFlux,             & ! intent(in)    : flag to denote if computing energy flux over vegetation
+                                (ixSolution==scalar),       & ! intent(in)    : flag to denote computing the scalar solution
+                                iStateSplit,                & ! intent(in)    : index of the layer in the splitting operation
+                                fluxMask,                   & ! intent(in)    : mask for the fluxes used in this given state subset
+                                fluxCount,                  & ! intent(inout) : number of times fluxes are updated (should equal nsubstep)
+                                ! input/output: data structures
+                                model_decisions,            & ! intent(in)    : model decisions
+                                lookup_data,                & ! intent(in)    : lookup tables
+                                type_data,                  & ! intent(in)    : type of vegetation and soil
+                                attr_data,                  & ! intent(in)    : spatial attributes
+                                forc_data,                  & ! intent(in)    : model forcing data
+                                mpar_data,                  & ! intent(in)    : model parameters
+                                indx_data,                  & ! intent(inout) : index data
+                                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
+                                deriv_data,                 & ! intent(inout) : derivatives in model fluxes w.r.t. relevant state variables
+                                bvar_data,                  & ! intent(in)    : model variables for the local basin
+                                ! output: control
+                                ixSaturation,               & ! intent(inout) : index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                                dtMultiplier,               & ! intent(out)   : substep multiplier (-)
+                                nSubsteps,                  & ! intent(out)   : number of substeps taken for a given split
+                                failedMinimumStep,          & ! intent(out)   : flag for failed substeps
+                                reduceCoupledStep,          & ! intent(out)   : flag to reduce the length of the coupled step
+                                tooMuchMelt,                & ! intent(out)   : flag to denote that ice is insufficient to support melt
+                                dt_out,					   & ! intent(out)
+                                err,cmessage)                 ! intent(out)   : error code and error message
+
+                                dt = dt_out
+
+                  case(bEuler)
+                    call varSubstep(&
+                                ! input: model control
+                                dt,                         & ! intent(in)    : time step (s)
+                                dtInit,                     & ! intent(in)    : initial time step (seconds)
+                                dt_min,                     & ! intent(in)    : minimum time step (seconds)
+                                nSubset,                    & ! intent(in)    : total number of variables in the state subset
+                                doAdjustTemp,               & ! intent(in)    : flag to indicate if we adjust the temperature
+                                firstSubStep,               & ! intent(in)    : flag to denote first sub-step
+                                firstFluxCall,              & ! intent(inout) : flag to indicate if we are processing the first flux call
+                                computeVegFlux,             & ! intent(in)    : flag to denote if computing energy flux over vegetation
+                                (ixSolution==scalar),       & ! intent(in)    : flag to denote computing the scalar solution
+                                iStateSplit,                & ! intent(in)    : index of the layer in the splitting operation
+                                fluxMask,                   & ! intent(in)    : mask for the fluxes used in this given state subset
+                                fluxCount,                  & ! intent(inout) : number of times fluxes are updated (should equal nsubstep)
+                                ! input/output: data structures
+                                model_decisions,            & ! intent(in)    : model decisions
+                                lookup_data,                & ! intent(in)    : lookup tables
+                                type_data,                  & ! intent(in)    : type of vegetation and soil
+                                attr_data,                  & ! intent(in)    : spatial attributes
+                                forc_data,                  & ! intent(in)    : model forcing data
+                                mpar_data,                  & ! intent(in)    : model parameters
+                                indx_data,                  & ! intent(inout) : index data
+                                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
+                                deriv_data,                 & ! intent(inout) : derivatives in model fluxes w.r.t. relevant state variables
+                                bvar_data,                  & ! intent(in)    : model variables for the local basin
+                                ! output: control
+                                ixSaturation,               & ! intent(inout) : index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                                dtMultiplier,               & ! intent(out)   : substep multiplier (-)
+                                nSubsteps,                  & ! intent(out)   : number of substeps taken for a given split
+                                failedMinimumStep,          & ! intent(out)   : flag for failed substeps
+                                reduceCoupledStep,          & ! intent(out)   : flag to reduce the length of the coupled step
+                                tooMuchMelt,                & ! intent(out)   : flag to denote that ice is insufficient to support melt
+                                err,cmessage)                 ! intent(out)   : error code and error message
+                              ! check
+                  case default; err=20; message=trim(message)//'expect num_method to be sundials or bEuler (or itertive, which is bEuler)'; return
+                end select
+        
+                if(err/=0)then
+                  message=trim(message)//trim(cmessage)
+                  if(err>0) return
+                endif  ! (check for errors)
+
+                ! reduce coupled step if failed the minimum step for the scalar solution
+                if(failedMinimumStep .and. ixSolution==scalar) reduceCoupledStep=.true.
+
+                ! if too much melt (or some other need to reduce the coupled step) then return
+                ! NOTE: need to go all the way back to coupled_em and merge snow layers, as all splitting operations need to occur with the same layer geometry
+                if(tooMuchMelt .or. reduceCoupledStep)then
+                  stepFailure=.true.
+                  err=0 ! recovering
+                  return
+                endif
+
+                ! define failure
+                failure = (failedMinimumStep .or. err<0)
+                if(.not.failure) firstSuccess=.true.
+
+                ! if failed, need to reset the flux counter
+                if(failure)then
+                  do iVar=1,size(flux_meta)
+                    iMin=lbound(flux_data%var(iVar)%dat)
+                    iMax=ubound(flux_data%var(iVar)%dat)
+                    do iLayer=iMin(1),iMax(1)
+                      if(fluxMask%var(iVar)%dat(iLayer)) fluxCount%var(iVar)%dat(iLayer) = fluxCount%var(iVar)%dat(iLayer) - nSubsteps
                     end do
-                  endif
-  
-                  ! try the fully split solution if failed to converge with a minimum time step in the coupled solution
-                  if(ixCoupling==fullyCoupled .and. failure) cycle coupling
-  
-                  ! try the scalar solution if failed to converge with a minimum time step in the split solution
-                  if(ixCoupling/=fullyCoupled)then
-                    select case(ixStateThenDomain)
-                      case(fullDomain); if(failure) cycle stateThenDomain
-                      case(subDomain);  if(failure) cycle solution
-                      case default; err=20; message=trim(message)//'unknown ixStateThenDomain case'
-                    end select
-                  endif
-  
-                  ! check that state variables updated
-                  where(stateMask) stateCheck = stateCheck+1
-                  if(any(stateCheck>1))then
-                    message=trim(message)//'state variable updated more than once!'
+                  end do
+                endif
+
+                ! try the fully split solution if failed to converge with a minimum time step in the coupled solution
+                if(ixCoupling==fullyCoupled .and. failure) cycle coupling
+
+                ! try the scalar solution if failed to converge with a minimum time step in the split solution
+                if(ixCoupling/=fullyCoupled)then
+                  select case(ixStateThenDomain)
+                    case(fullDomain); if(failure) cycle stateThenDomain
+                    case(subDomain);  if(failure) cycle solution
+                    case default; err=20; message=trim(message)//'unknown ixStateThenDomain case'
+                  end select
+                endif
+
+                ! check that state variables updated
+                where(stateMask) stateCheck = stateCheck+1
+                if(any(stateCheck>1))then
+                  message=trim(message)//'state variable updated more than once!'
+                  err=20; return
+                endif
+
+                ! success = exit solution
+                if(.not.failure)then
+                  select case(ixStateThenDomain)
+                    case(fullDomain); if(iStateSplit==nStateSplit) exit stateThenDomain
+                    case(subDomain);  if(iStateSplit==nStateSplit) exit solution
+                    case default; err=20; message=trim(message)//'unknown ixStateThenDomain case'
+                  end select
+                else
+
+                  ! check that we did not fail for the scalar solution (last resort)
+                  if(ixSolution==scalar)then
+                    message=trim(message)//'failed the minimum step for the scalar solution'
                     err=20; return
-                  endif
-  
-                  ! success = exit solution
-                  if(.not.failure)then
-                    select case(ixStateThenDomain)
-                      case(fullDomain); if(iStateSplit==nStateSplit) exit stateThenDomain
-                      case(subDomain);  if(iStateSplit==nStateSplit) exit solution
-                      case default; err=20; message=trim(message)//'unknown ixStateThenDomain case'
-                    end select
+
+                  ! check for an unexpected failure
                   else
-  
-                    ! check that we did not fail for the scalar solution (last resort)
-                    if(ixSolution==scalar)then
-                      message=trim(message)//'failed the minimum step for the scalar solution'
-                      err=20; return
-  
-                    ! check for an unexpected failure
-                    else
-                      message=trim(message)//'unexpected failure'
-                      err=20; return
-                    endif
-  
-                  endif  ! success check
-  
-                end do stateSplit ! solution with split layers
-  
-              end do solution ! trial with the full layer solution then the split layer solution
-  
-            ! ***** trial with a given solution method...
-            ! *******************************************************************************************************************************
-            ! *******************************************************************************************************************************
-            ! *******************************************************************************************************************************
-  
-            end do domainSplit ! domain type splitting loop
-  
-  
-          end do stateThenDomain  ! switch between the state and the domain
-  
-  
-          ! -----
-          ! * reset state variables for the mass split...
-          ! ---------------------------------------------
-          ! modify the state type names associated with the state vector
-          if(ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)then
-            if(computeVegFlux)then
-              where(ixStateType(ixHydCanopy)==iname_liqCanopy) ixStateType(ixHydCanopy)=iname_watCanopy
-            endif
-            where(ixStateType(ixHydLayer) ==iname_liqLayer)  ixStateType(ixHydLayer) =iname_watLayer
-            where(ixStateType(ixHydLayer) ==iname_lmpLayer)  ixStateType(ixHydLayer) =iname_matLayer
-          endif  ! if modifying state variables for the mass split
-  
-        end do stateTypeSplit ! state type splitting loop
-  
-        ! success = exit the coupling loop
-        if(ixCoupling==fullyCoupled .and. .not.failure) exit coupling
-  
-      end do coupling ! coupling method
-  
-      ! check that all state variables were updated
-      if(any(stateCheck==0))then
-        message=trim(message)//'some state variables were not updated!'
+                    message=trim(message)//'unexpected failure'
+                    err=20; return
+                  endif
+
+                endif  ! success check
+
+              end do stateSplit ! solution with split layers
+
+            end do solution ! trial with the full layer solution then the split layer solution
+
+          ! ***** trial with a given solution method...
+          ! *******************************************************************************************************************************
+          ! *******************************************************************************************************************************
+          ! *******************************************************************************************************************************
+
+          end do domainSplit ! domain type splitting loop
+
+
+        end do stateThenDomain  ! switch between the state and the domain
+
+
+        ! -----
+        ! * reset state variables for the mass split...
+        ! ---------------------------------------------
+        ! modify the state type names associated with the state vector
+        if(ixCoupling/=fullyCoupled .and. iStateTypeSplit==massSplit)then
+          if(computeVegFlux)then
+            where(ixStateType(ixHydCanopy)==iname_liqCanopy) ixStateType(ixHydCanopy)=iname_watCanopy
+          endif
+          where(ixStateType(ixHydLayer) ==iname_liqLayer)  ixStateType(ixHydLayer) =iname_watLayer
+          where(ixStateType(ixHydLayer) ==iname_lmpLayer)  ixStateType(ixHydLayer) =iname_matLayer
+        endif  ! if modifying state variables for the mass split
+
+      end do stateTypeSplit ! state type splitting loop
+
+      ! success = exit the coupling loop
+      if(ixCoupling==fullyCoupled .and. .not.failure) exit coupling
+
+    end do coupling ! coupling method
+
+    ! check that all state variables were updated
+    if(any(stateCheck==0))then
+      message=trim(message)//'some state variables were not updated!'
+      err=20; return
+    endif
+
+    ! check that the desired fluxes were computed
+    do iVar=1,size(flux_meta)
+      if(neededFlux(iVar) .and. any(fluxCount%var(iVar)%dat==0))then
+        print*, 'fluxCount%var(iVar)%dat = ', fluxCount%var(iVar)%dat
+        message=trim(message)//'flux '//trim(flux_meta(iVar)%varname)//' was not computed'
         err=20; return
       endif
-  
-      ! check that the desired fluxes were computed
-      do iVar=1,size(flux_meta)
-        if(neededFlux(iVar) .and. any(fluxCount%var(iVar)%dat==0))then
-          print*, 'fluxCount%var(iVar)%dat = ', fluxCount%var(iVar)%dat
-          message=trim(message)//'flux '//trim(flux_meta(iVar)%varname)//' was not computed'
-          err=20; return
-        endif
-      end do
-  
-      ! use step halving if unable to complete the fully coupled solution in one substep
-      if(ixCoupling/=fullyCoupled .or. nSubsteps>1) dtMultiplier=0.5_rkind
-  
-      ! compute the melt in each snow and soil layer
-      if(nSnow>0)then
-        diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat(1:nSnow) = -( mLayerVolFracIce(1:nSnow) - mLayerVolFracIceInit(1:nSnow) ) * iden_ice
-        diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat(nSnow+1:nLayers) = -(mLayerVolFracIce(nSnow+1:nLayers) - mLayerVolFracIceInit(nSnow+1:nLayers))*iden_water
-      endif
-  
-      ! end associate statements
-    end associate globalVars
-  
-  end subroutine opSplittin
-  
-  
-  ! **********************************************************************************************************
-  ! private subroutine stateFilter: get a mask for the desired state variables
-  ! **********************************************************************************************************
-  subroutine stateFilter(ixCoupling,ixSolution,ixStateThenDomain,iStateTypeSplit,iDomainSplit,iStateSplit,&
-                        indx_data,stateMask,nSubset,err,message)
-  
-    USE indexState_module,only:indxSubset                            ! get state indices
-    implicit none
-    ! input
-    integer(i4b),intent(in)         :: ixCoupling                    ! index of coupling method (1,2)
-    integer(i4b),intent(in)         :: ixSolution                    ! index of solution method (1,2)
-    integer(i4b),intent(in)         :: ixStateThenDomain             ! switch between full domain and sub domains
-    integer(i4b),intent(in)         :: iStateTypeSplit               ! index of the state type split
-    integer(i4b),intent(in)         :: iDomainSplit                  ! index of the domain split
-    integer(i4b),intent(in)         :: iStateSplit                   ! index of the layer split
-    type(var_ilength),intent(inout) :: indx_data                     ! indices for a local HRU
-    ! output
-    logical(lgt),intent(out)        :: stateMask(:)                  ! mask defining desired state variables
-    integer(i4b),intent(out)        :: nSubset                       ! number of selected state variables for a given split
-    integer(i4b),intent(out)        :: err                           ! error code
-    character(*),intent(out)        :: message                       ! error message
-    ! local
-    integer(i4b),allocatable        :: ixSubset(:)                   ! list of indices in the state subset
-    character(len=256)              :: cmessage                      ! error message
+    end do
+
+    ! use step halving if unable to complete the fully coupled solution in one substep
+    if(ixCoupling/=fullyCoupled .or. nSubsteps>1) dtMultiplier=0.5_rkind
+
+    ! compute the melt in each snow and soil layer
+    if(nSnow>0)then
+      diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat(1:nSnow) = -( mLayerVolFracIce(1:nSnow) - mLayerVolFracIceInit(1:nSnow) ) * iden_ice
+      diag_data%var(iLookDIAG%mLayerMeltFreeze)%dat(nSnow+1:nLayers) = -(mLayerVolFracIce(nSnow+1:nLayers) - mLayerVolFracIceInit(nSnow+1:nLayers))*iden_water
+    endif
+
+    ! end associate statements
+  end associate globalVars
+
+end subroutine opSplittin
+
+
+! **********************************************************************************************************
+! private subroutine stateFilter: get a mask for the desired state variables
+! **********************************************************************************************************
+subroutine stateFilter(ixCoupling,ixSolution,ixStateThenDomain,iStateTypeSplit,iDomainSplit,iStateSplit,&
+                      indx_data,stateMask,nSubset,err,message)
+
+  USE indexState_module,only:indxSubset                            ! get state indices
+  implicit none
+  ! input
+  integer(i4b),intent(in)         :: ixCoupling                    ! index of coupling method (1,2)
+  integer(i4b),intent(in)         :: ixSolution                    ! index of solution method (1,2)
+  integer(i4b),intent(in)         :: ixStateThenDomain             ! switch between full domain and sub domains
+  integer(i4b),intent(in)         :: iStateTypeSplit               ! index of the state type split
+  integer(i4b),intent(in)         :: iDomainSplit                  ! index of the domain split
+  integer(i4b),intent(in)         :: iStateSplit                   ! index of the layer split
+  type(var_ilength),intent(inout) :: indx_data                     ! indices for a local HRU
+  ! output
+  logical(lgt),intent(out)        :: stateMask(:)                  ! mask defining desired state variables
+  integer(i4b),intent(out)        :: nSubset                       ! number of selected state variables for a given split
+  integer(i4b),intent(out)        :: err                           ! error code
+  character(*),intent(out)        :: message                       ! error message
+  ! local
+  integer(i4b),allocatable        :: ixSubset(:)                   ! list of indices in the state subset
+  character(len=256)              :: cmessage                      ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+  ! data structures
+  associate(&
+    ! indices of model state variables
+    ixStateType  => indx_data%var(iLookINDEX%ixStateType)%dat      ,& ! intent(in): [i4b(:)] indices defining the type of the state (ixNrgState...)
+    ixNrgCanair  => indx_data%var(iLookINDEX%ixNrgCanair)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in canopy air space domain
+    ixNrgCanopy  => indx_data%var(iLookINDEX%ixNrgCanopy)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in the canopy domain
+    ixHydCanopy  => indx_data%var(iLookINDEX%ixHydCanopy)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the canopy domain
+    ixNrgLayer   => indx_data%var(iLookINDEX%ixNrgLayer)%dat       ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in the snow+soil domain
+    ixHydLayer   => indx_data%var(iLookINDEX%ixHydLayer)%dat       ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the snow+soil domain
+    ixWatAquifer => indx_data%var(iLookINDEX%ixWatAquifer)%dat     ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for water storage in the aquifer
+    ixAllState   => indx_data%var(iLookINDEX%ixAllState)%dat       ,& ! intent(in): [i4b(:)] list of indices for all model state variables (1,2,3,...nState)
+    ! number of layers
+    nSnow        => indx_data%var(iLookINDEX%nSnow)%dat(1)         ,& ! intent(in): [i4b]    number of snow layers
+    nSoil        => indx_data%var(iLookINDEX%nSoil)%dat(1)         ,& ! intent(in): [i4b]    number of soil layers
+    nLayers      => indx_data%var(iLookINDEX%nLayers)%dat(1)        & ! intent(in): [i4b]    total number of layers
+    ) ! data structures
     ! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-    ! data structures
-    associate(&
-      ! indices of model state variables
-      ixStateType  => indx_data%var(iLookINDEX%ixStateType)%dat      ,& ! intent(in): [i4b(:)] indices defining the type of the state (ixNrgState...)
-      ixNrgCanair  => indx_data%var(iLookINDEX%ixNrgCanair)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in canopy air space domain
-      ixNrgCanopy  => indx_data%var(iLookINDEX%ixNrgCanopy)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in the canopy domain
-      ixHydCanopy  => indx_data%var(iLookINDEX%ixHydCanopy)%dat      ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the canopy domain
-      ixNrgLayer   => indx_data%var(iLookINDEX%ixNrgLayer)%dat       ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for energy states in the snow+soil domain
-      ixHydLayer   => indx_data%var(iLookINDEX%ixHydLayer)%dat       ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for hydrology states in the snow+soil domain
-      ixWatAquifer => indx_data%var(iLookINDEX%ixWatAquifer)%dat     ,& ! intent(in): [i4b(:)] indices IN THE FULL VECTOR for water storage in the aquifer
-      ixAllState   => indx_data%var(iLookINDEX%ixAllState)%dat       ,& ! intent(in): [i4b(:)] list of indices for all model state variables (1,2,3,...nState)
-      ! number of layers
-      nSnow        => indx_data%var(iLookINDEX%nSnow)%dat(1)         ,& ! intent(in): [i4b]    number of snow layers
-      nSoil        => indx_data%var(iLookINDEX%nSoil)%dat(1)         ,& ! intent(in): [i4b]    number of soil layers
-      nLayers      => indx_data%var(iLookINDEX%nLayers)%dat(1)        & ! intent(in): [i4b]    total number of layers
-      ) ! data structures
-      ! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-      ! initialize error control
-      err=0; message='stateFilter/'
-  
-      ! identify splitting option
-      select case(ixCoupling)
-  
-        ! -----
-        ! - fully coupled...
-        ! ------------------
-  
-        ! use all state variables
-        case(fullyCoupled); stateMask(:) = .true.
-  
-        ! -----
-        ! - splitting by state type...
-        ! ----------------------------
-  
-        ! initial split by state type
-        case(stateTypeSplit)
-  
-          ! switch between full domain and sub domains
-          select case(ixStateThenDomain)
-  
-            ! split into energy and mass
-            case(fullDomain)
-              select case(iStateTypeSplit)
-                case(nrgSplit);  stateMask = (ixStateType==iname_nrgCanair .or. ixStateType==iname_nrgCanopy .or. ixStateType==iname_nrgLayer)
-                case(massSplit); stateMask = (ixStateType==iname_liqCanopy .or. ixStateType==iname_liqLayer  .or. ixStateType==iname_lmpLayer .or. ixStateType==iname_watAquifer)
-                case default; err=20; message=trim(message)//'unable to identify split based on state type'; return
-              end select
-  
-            ! split into vegetation, snow, and soil
-            case(subDomain)
-  
-              ! define state mask
-              stateMask=.false. ! (initialize state mask)
-              select case(iStateTypeSplit)
-  
-                ! define mask for energy
-                case(nrgSplit)
-                  select case(iDomainSplit)
-                    case(vegSplit)
-                      if(ixNrgCanair(1)/=integerMissing) stateMask(ixNrgCanair) = .true.  ! energy of the canopy air space
-                      if(ixNrgCanopy(1)/=integerMissing) stateMask(ixNrgCanopy) = .true.  ! energy of the vegetation canopy
-                      stateMask(ixNrgLayer(1)) = .true.  ! energy of the upper-most layer in the snow+soil domain
-                    case(snowSplit);   if(nSnow>1) stateMask(ixNrgLayer(2:nSnow)) = .true.    ! NOTE: (2:) because the top layer in the snow+soil domain included in vegSplit
-                    case(soilSplit);   stateMask(ixNrgLayer(max(2,nSnow+1):nLayers)) = .true. ! NOTE: max(2,nSnow+1) gives second layer unless more than 2 snow layers
-                    case(aquiferSplit) ! do nothing: no energy state variable for the aquifer domain
-                    case default; err=20; message=trim(message)//'unable to identify model sub-domain'; return
-                  end select
-  
-                ! define mask for water
-                case(massSplit)
-                  select case(iDomainSplit)
-                    case(vegSplit);     if(ixHydCanopy(1)/=integerMissing) stateMask(ixHydCanopy) = .true.  ! hydrology of the vegetation canopy
-                    case(snowSplit);    stateMask(ixHydLayer(1:nSnow)) = .true.  ! snow hydrology
-                    case(soilSplit);    stateMask(ixHydLayer(nSnow+1:nLayers)) = .true.  ! soil hydrology
-                    case(aquiferSplit); if(ixWatAquifer(1)/=integerMissing) stateMask(ixWatAquifer) = .true.  ! aquifer storage
-                    case default; err=20; message=trim(message)//'unable to identify model sub-domain'; return
-                  end select
-  
-                ! check
-                case default; err=20; message=trim(message)//'unable to identify the state type'; return
-              end select  ! (split based on state type)
-  
-            ! check
-            case default; err=20; message=trim(message)//'unable to identify the switch between full domains and sub domains'; return
-          end select ! (switch between full domains and sub domains)
-  
+    ! initialize error control
+    err=0; message='stateFilter/'
+
+    ! identify splitting option
+    select case(ixCoupling)
+
+      ! -----
+      ! - fully coupled...
+      ! ------------------
+
+      ! use all state variables
+      case(fullyCoupled); stateMask(:) = .true.
+
+      ! -----
+      ! - splitting by state type...
+      ! ----------------------------
+
+      ! initial split by state type
+      case(stateTypeSplit)
+
+        ! switch between full domain and sub domains
+        select case(ixStateThenDomain)
+
+          ! split into energy and mass
+          case(fullDomain)
+            select case(iStateTypeSplit)
+              case(nrgSplit);  stateMask = (ixStateType==iname_nrgCanair .or. ixStateType==iname_nrgCanopy .or. ixStateType==iname_nrgLayer)
+              case(massSplit); stateMask = (ixStateType==iname_liqCanopy .or. ixStateType==iname_liqLayer  .or. ixStateType==iname_lmpLayer .or. ixStateType==iname_watAquifer)
+              case default; err=20; message=trim(message)//'unable to identify split based on state type'; return
+            end select
+
+          ! split into vegetation, snow, and soil
+          case(subDomain)
+
+            ! define state mask
+            stateMask=.false. ! (initialize state mask)
+            select case(iStateTypeSplit)
+
+              ! define mask for energy
+              case(nrgSplit)
+                select case(iDomainSplit)
+                  case(vegSplit)
+                    if(ixNrgCanair(1)/=integerMissing) stateMask(ixNrgCanair) = .true.  ! energy of the canopy air space
+                    if(ixNrgCanopy(1)/=integerMissing) stateMask(ixNrgCanopy) = .true.  ! energy of the vegetation canopy
+                    stateMask(ixNrgLayer(1)) = .true.  ! energy of the upper-most layer in the snow+soil domain
+                  case(snowSplit);   if(nSnow>1) stateMask(ixNrgLayer(2:nSnow)) = .true.    ! NOTE: (2:) because the top layer in the snow+soil domain included in vegSplit
+                  case(soilSplit);   stateMask(ixNrgLayer(max(2,nSnow+1):nLayers)) = .true. ! NOTE: max(2,nSnow+1) gives second layer unless more than 2 snow layers
+                  case(aquiferSplit) ! do nothing: no energy state variable for the aquifer domain
+                  case default; err=20; message=trim(message)//'unable to identify model sub-domain'; return
+                end select
+
+              ! define mask for water
+              case(massSplit)
+                select case(iDomainSplit)
+                  case(vegSplit);     if(ixHydCanopy(1)/=integerMissing) stateMask(ixHydCanopy) = .true.  ! hydrology of the vegetation canopy
+                  case(snowSplit);    stateMask(ixHydLayer(1:nSnow)) = .true.  ! snow hydrology
+                  case(soilSplit);    stateMask(ixHydLayer(nSnow+1:nLayers)) = .true.  ! soil hydrology
+                  case(aquiferSplit); if(ixWatAquifer(1)/=integerMissing) stateMask(ixWatAquifer) = .true.  ! aquifer storage
+                  case default; err=20; message=trim(message)//'unable to identify model sub-domain'; return
+                end select
+
+              ! check
+              case default; err=20; message=trim(message)//'unable to identify the state type'; return
+            end select  ! (split based on state type)
+
           ! check
-        case default; err=20; message=trim(message)//'unable to identify coupling method'; return
-      end select  ! (selecting solution method)
-  
-      ! identify scalar solutions
-      if(ixSolution==scalar)then
-  
-        ! get the subset of indices
-        call indxSubset(ixSubset, ixAllState, stateMask, err, cmessage)
-        if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-  
-        ! get the mask
-        stateMask(:) = .false.
-        stateMask( ixSubset(iStateSplit) ) = .true.
-  
+          case default; err=20; message=trim(message)//'unable to identify the switch between full domains and sub domains'; return
+        end select ! (switch between full domains and sub domains)
+
         ! check
-        if(count(stateMask)/=1)then
-          message=trim(message)//'expect size=1 (scalar)'
-          err=20; return
-        endif
-  
+      case default; err=20; message=trim(message)//'unable to identify coupling method'; return
+    end select  ! (selecting solution method)
+
+    ! identify scalar solutions
+    if(ixSolution==scalar)then
+
+      ! get the subset of indices
+      call indxSubset(ixSubset, ixAllState, stateMask, err, cmessage)
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+
+      ! get the mask
+      stateMask(:) = .false.
+      stateMask( ixSubset(iStateSplit) ) = .true.
+
+      ! check
+      if(count(stateMask)/=1)then
+        message=trim(message)//'expect size=1 (scalar)'
+        err=20; return
       endif
-  
-      ! get the number of selected state variables
-      nSubset = count(stateMask)
-  
-      ! end associations
-    end associate
-  
-  end subroutine stateFilter
-  
-  end module opSplittin_module
-  
\ No newline at end of file
+
+    endif
+
+    ! get the number of selected state variables
+    nSubset = count(stateMask)
+
+    ! end associations
+  end associate
+
+end subroutine stateFilter
+
+end module opSplittin_module
diff --git a/build/source/engine/snow_utils.f90 b/build/source/engine/snow_utils.f90
index 496ecfce531be08042893ab6adb813b046e72d6c..2008a9adaa77ecd2680ad342a10a144596444da8 100755
--- a/build/source/engine/snow_utils.f90
+++ b/build/source/engine/snow_utils.f90
@@ -42,73 +42,73 @@ public::tcond_snow
 contains
 
 
- ! ***********************************************************************************************************
- ! public function fracliquid: compute fraction of liquid water
- ! ***********************************************************************************************************
- function fracliquid(Tk,fc_param)
- implicit none
- real(dp),intent(in) :: Tk         ! temperature (K)
- real(dp),intent(in) :: fc_param   ! freezing curve parameter (K-1)
- real(dp)            :: fracliquid ! fraction of liquid water (-)
- ! compute fraction of liquid water (-)
- fracliquid = 1._dp / ( 1._dp + (fc_param*( Tfreeze - min(Tk,Tfreeze) ))**2._dp )
- end function fracliquid
+! ***********************************************************************************************************
+! public function fracliquid: compute fraction of liquid water
+! ***********************************************************************************************************
+function fracliquid(Tk,fc_param)
+  implicit none
+  real(rkind),intent(in) :: Tk         ! temperature (K)
+  real(rkind),intent(in) :: fc_param   ! freezing curve parameter (K-1)
+  real(rkind)            :: fracliquid ! fraction of liquid water (-)
+  ! compute fraction of liquid water (-)
+  fracliquid = 1._rkind / ( 1._rkind + (fc_param*( Tfreeze - min(Tk,Tfreeze) ))**2._rkind )
+end function fracliquid
 
 
- ! ***********************************************************************************************************
- ! public function templiquid: invert the fraction of liquid water function
- ! ***********************************************************************************************************
- function templiquid(fracliquid,fc_param)
- implicit none
- real(dp),intent(in) :: fracliquid ! fraction of liquid water (-)
- real(dp),intent(in) :: fc_param   ! freezing curve parameter (K-1)
- real(dp)            :: templiquid ! temperature (K)
- ! compute temperature based on the fraction of liquid water (K)
- templiquid = Tfreeze - ((1._dp/fracliquid - 1._dp)/fc_param**2._dp)**(0.5_dp)
- end function templiquid
+! ***********************************************************************************************************
+! public function templiquid: invert the fraction of liquid water function
+! ***********************************************************************************************************
+function templiquid(fracliquid,fc_param)
+  implicit none
+  real(rkind),intent(in) :: fracliquid ! fraction of liquid water (-)
+  real(rkind),intent(in) :: fc_param   ! freezing curve parameter (K-1)
+  real(rkind)            :: templiquid ! temperature (K)
+  ! compute temperature based on the fraction of liquid water (K)
+  templiquid = Tfreeze - ((1._rkind/fracliquid - 1._rkind)/fc_param**2._rkind)**(0.5_rkind)
+end function templiquid
 
 
- ! ***********************************************************************************************************
- ! public function dFracLiq_dTk: differentiate the freezing curve
- ! ***********************************************************************************************************
- function dFracLiq_dTk(Tk,fc_param)
- implicit none
- ! dummies
- real(dp),intent(in) :: Tk           ! temperature (K)
- real(dp),intent(in) :: fc_param     ! freezing curve parameter (K-1)
- real(dp)            :: dFracLiq_dTk ! differentiate the freezing curve (K-1)
- ! locals
- real(dp)            :: Tdep         ! temperature depression (K)
- real(dp)            :: Tdim         ! dimensionless temperature (-)
- ! compute local variables (just to make things more efficient)
- Tdep = Tfreeze - min(Tk,Tfreeze)
- Tdim = fc_param*Tdep
- ! differentiate the freezing curve w.r.t temperature
- dFracLiq_dTk = (fc_param*2._dp*Tdim) / ( ( 1._dp + Tdim**2._dp)**2._dp )
- end function dFracLiq_dTk
+! ***********************************************************************************************************
+! public function dFracLiq_dTk: differentiate the freezing curve
+! ***********************************************************************************************************
+function dFracLiq_dTk(Tk,fc_param)
+  implicit none
+  ! dummies
+  real(rkind),intent(in) :: Tk           ! temperature (K)
+  real(rkind),intent(in) :: fc_param     ! freezing curve parameter (K-1)
+  real(rkind)            :: dFracLiq_dTk ! differentiate the freezing curve (K-1)
+  ! locals
+  real(rkind)            :: Tdep         ! temperature depression (K)
+  real(rkind)            :: Tdim         ! dimensionless temperature (-)
+  ! compute local variables (just to make things more efficient)
+  Tdep = Tfreeze - min(Tk,Tfreeze)
+  Tdim = fc_param*Tdep
+  ! differentiate the freezing curve w.r.t temperature
+  dFracLiq_dTk = (fc_param*2._rkind*Tdim) / ( ( 1._rkind + Tdim**2._rkind)**2._rkind )
+end function dFracLiq_dTk
 
 
- ! ***********************************************************************************************************
- ! public subroutine tcond_snow: compute thermal conductivity of snow
- ! ***********************************************************************************************************
- subroutine tcond_snow(BulkDenIce,thermlcond,err,message)
- implicit none
- real(dp),intent(in)      :: BulkDenIce     ! bulk density of ice (kg m-3)
- real(dp),intent(out)     :: thermlcond     ! thermal conductivity of snow (W m-1 K-1)
- integer(i4b),intent(out) :: err            ! error code
- character(*),intent(out) :: message        ! error message
- ! initialize error control
- err=0; message="tcond_snow/"
- ! compute thermal conductivity of snow
- select case(model_decisions(iLookDECISIONS%thCondSnow)%iDecision)
-  case(Yen1965);      thermlcond = 3.217d-6 * BulkDenIce**2._dp               ! Yen (1965)
-  case(Mellor1977);   thermlcond = 2.576d-6 * BulkDenIce**2._dp + 7.4d-2      ! Mellor (1977)
-  case(Jordan1991);   thermlcond = lambda_air + (7.75d-5*BulkDenIce + 1.105d-6*(BulkDenIce**2._dp)) &
-                                     * (lambda_ice-lambda_air)                ! Jordan (1991)
+! ***********************************************************************************************************
+! public subroutine tcond_snow: compute thermal conductivity of snow
+! ***********************************************************************************************************
+subroutine tcond_snow(BulkDenIce,thermlcond,err,message)
+  implicit none
+  real(rkind),intent(in)      :: BulkDenIce     ! bulk density of ice (kg m-3)
+  real(rkind),intent(out)     :: thermlcond     ! thermal conductivity of snow (W m-1 K-1)
+  integer(i4b),intent(out) :: err            ! error code
+  character(*),intent(out) :: message        ! error message
+  ! initialize error control
+  err=0; message="tcond_snow/"
+  ! compute thermal conductivity of snow
+  select case(model_decisions(iLookDECISIONS%thCondSnow)%iDecision)
+  case(Yen1965);      thermlcond = 3.217d-6 * BulkDenIce**2._rkind               ! Yen (1965)
+  case(Mellor1977);   thermlcond = 2.576d-6 * BulkDenIce**2._rkind + 7.4d-2      ! Mellor (1977)
+  case(Jordan1991);   thermlcond = lambda_air + (7.75d-5*BulkDenIce + 1.105d-6*(BulkDenIce**2._rkind)) &
+                                    * (lambda_ice-lambda_air)                ! Jordan (1991)
   case default
-   err=10; message=trim(message)//"unknownOption"; return
- end select
- end subroutine tcond_snow
+    err=10; message=trim(message)//"unknownOption"; return
+  end select
+end subroutine tcond_snow
 
 
 end module snow_utils_module
diff --git a/build/source/engine/soil_utils.f90 b/build/source/engine/soil_utils.f90
index 747618ed4e6aab31630a6514b22594c4aaa4217e..baab0fbce882a221cf2f05e4ac951a6c53a1a620 100755
--- a/build/source/engine/soil_utils.f90
+++ b/build/source/engine/soil_utils.f90
@@ -24,9 +24,9 @@ module soil_utils_module
 USE nrtype
 
 USE multiconst,only: gravity, & ! acceleration of gravity       (m s-2)
-                     Tfreeze, & ! temperature at freezing    (K)
-                     LH_fus,  & ! latent heat of fusion      (J kg-1, or m2 s-2)
-                     R_wv       ! gas constant for water vapor  (J kg-1 K-1; [J = Pa m3])
+                      Tfreeze, & ! temperature at freezing    (K)
+                      LH_fus,  & ! latent heat of fusion      (J kg-1, or m2 s-2)
+                      R_wv       ! gas constant for water vapor  (J kg-1 K-1; [J = Pa m3])
 
 ! privacy
 implicit none
@@ -52,666 +52,664 @@ public::liquidHead
 public::gammp
 
 ! constant parameters
-real(dp),parameter     :: valueMissing=-9999._dp    ! missing value parameter
-real(dp),parameter     :: verySmall=epsilon(1.0_dp) ! a very small number (used to avoid divide by zero)
-real(dp),parameter     :: dx=-1.e-12_dp             ! finite difference increment
+real(rkind),parameter     :: valueMissing=-9999._rkind    ! missing value parameter
+real(rkind),parameter     :: verySmall=epsilon(1.0_rkind) ! a very small number (used to avoid divide by zero)
+real(rkind),parameter     :: dx=-1.e-12_rkind             ! finite difference increment
 contains
 
 
- ! ******************************************************************************************************************************
- ! public subroutine iceImpede: compute the ice impedence factor
- ! ******************************************************************************************************************************
- subroutine iceImpede(volFracIce,f_impede, &            ! input
-                      iceImpedeFactor,dIceImpede_dLiq)  ! output
- ! computes the ice impedence factor (separate function, as used multiple times)
- implicit none
- ! input variables
- real(dp),intent(in)     :: volFracIce        ! volumetric fraction of ice (-)
- real(dp),intent(in)     :: f_impede          ! ice impedence parameter (-)
- ! output variables
- real(dp)                :: iceImpedeFactor   ! ice impedence factor (-)
- real(dp)                :: dIceImpede_dLiq   ! derivative in ice impedence factor w.r.t. volumetric liquid water content (-)
- ! compute ice impedance factor as a function of volumetric ice content
- iceImpedeFactor = 10._dp**(-f_impede*volFracIce)
- dIceImpede_dLiq = 0._dp
-
- end subroutine iceImpede
-
-
- ! ******************************************************************************************************************************
- ! public subroutine dIceImpede_dTemp: compute the derivative in the ice impedence factor w.r.t. temperature
- ! ******************************************************************************************************************************
- subroutine dIceImpede_dTemp(volFracIce,dTheta_dT,f_impede,dIceImpede_dT)
- ! computes the derivative in the ice impedance factor w.r.t. temperature
- implicit none
- ! input variables
- real(dp),intent(in)     :: volFracIce        ! volumetric fraction of ice (-)
- real(dp),intent(in)     :: dTheta_dT         ! derivative in volumetric liquid water content w.r.t temperature (K-1)
- real(dp),intent(in)     :: f_impede          ! ice impedence parameter (-)
- ! output variables
- real(dp)                :: dIceImpede_dT     ! derivative in the ice impedance factor w.r.t. temperature (K-1)
- ! --
- dIceImpede_dT = log(10._dp)*f_impede*(10._dp**(-f_impede*volFracIce))*dTheta_dT
- end subroutine dIceImpede_dTemp
-
-
- ! ******************************************************************************************************************************
- ! public subroutine: compute the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
- ! ******************************************************************************************************************************
- subroutine liquidHead(&
-                       ! input
-                       matricHeadTotal                          ,& ! intent(in)    : total water matric potential (m)
-                       volFracLiq                               ,& ! intent(in)    : volumetric fraction of liquid water (-)
-                       volFracIce                               ,& ! intent(in)    : volumetric fraction of ice (-)
-                       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)
-                       ! output
-                       matricHeadLiq                            ,& ! intent(out)   : liquid water matric potential (m)
-                       dPsiLiq_dPsi0                            ,& ! intent(out)   : derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
-                       dPsiLiq_dTemp                            ,& ! intent(out)   : derivative in the liquid water matric potential w.r.t. temperature (m K-1)
-                       err,message)                                ! intent(out)   : error control
- ! computes the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
- implicit none
- ! input
- real(dp),intent(in)            :: matricHeadTotal                           ! total water matric potential (m)
- real(dp),intent(in)            :: volFracLiq                                ! volumetric fraction of liquid water (-)
- real(dp),intent(in)            :: volFracIce                                ! volumetric fraction of ice (-)
- real(dp),intent(in)            :: vGn_alpha,vGn_n,theta_sat,theta_res,vGn_m ! soil parameters
- real(dp),intent(in)  ,optional :: dVolTot_dPsi0                             ! derivative in the soil water characteristic (m-1)
- real(dp),intent(in)  ,optional :: dTheta_dT                                 ! derivative in volumetric total water w.r.t. temperature (K-1)
- ! output
- real(dp),intent(out)           :: matricHeadLiq                             ! liquid water matric potential (m)
- real(dp),intent(out) ,optional :: dPsiLiq_dPsi0                             ! derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
- real(dp),intent(out) ,optional :: dPsiLiq_dTemp                             ! derivative in the liquid water matric potential w.r.t. temperature (m K-1)
- ! output: error control
- integer(i4b),intent(out)       :: err                                       ! error code
- character(*),intent(out)       :: message                                   ! error message
- ! local
- real(dp)                       :: xNum,xDen                                 ! temporary variables (numeratir, denominator)
- real(dp)                       :: effSat                                    ! effective saturation (-)
- real(dp)                       :: dPsiLiq_dEffSat                           ! derivative in liquid water matric potential w.r.t. effective saturation (m)
- real(dp)                       :: dEffSat_dTemp                             ! derivative in effective saturation w.r.t. temperature (K-1)
- ! ------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='liquidHead/'
-
- ! ** partially frozen soil
- if(volFracIce > verySmall .and. matricHeadTotal < 0._dp)then  ! check that ice exists and that the soil is unsaturated
-
-  ! -----
-  ! - compute liquid water matric potential...
-  ! ------------------------------------------
-
-  ! - compute effective saturation
-  ! NOTE: include ice content as part of the solid porosity - major effect of ice is to reduce the pore size; ensure that effSat=1 at saturation
-  ! (from Zhao et al., J. Hydrol., 1997: Numerical analysis of simultaneous heat and mass transfer...)
-  xNum   = volFracLiq - theta_res
-  xDen   = theta_sat - volFracIce - theta_res
-  effSat = xNum/xDen          ! effective saturation
-
-  ! - matric head associated with liquid water
-  matricHeadLiq = matricHead(effSat,vGn_alpha,0._dp,1._dp,vGn_n,vGn_m)  ! argument is effective saturation, so theta_res=0 and theta_sat=1
-
-  ! compute derivative in liquid water matric potential w.r.t. effective saturation (m)
-  if(present(dPsiLiq_dPsi0).or.present(dPsiLiq_dTemp))then
-   dPsiLiq_dEffSat = dPsi_dTheta(effSat,vGn_alpha,0._dp,1._dp,vGn_n,vGn_m)
-  endif
-
-  ! -----
-  ! - compute derivative in the liquid water matric potential w.r.t. the total water matric potential...
-  ! ----------------------------------------------------------------------------------------------------
-
-  ! check if the derivative is desired
-  if(present(dPsiLiq_dTemp))then
-
-   ! (check required input derivative is present)
-   if(.not.present(dVolTot_dPsi0))then
-    message=trim(message)//'dVolTot_dPsi0 argument is missing'
-    err=20; return
-   endif
-
-   ! (compute derivative in the liquid water matric potential w.r.t. the total water matric potential)
-   dPsiLiq_dPsi0 = dVolTot_dPsi0*dPsiLiq_dEffSat*xNum/(xDen**2._dp)
-
-  endif  ! if dPsiLiq_dTemp is desired
-
-  ! -----
-  ! - compute the derivative in the liquid water matric potential w.r.t. temperature...
-  ! -----------------------------------------------------------------------------------
-
-  ! check if the derivative is desired
-  if(present(dPsiLiq_dTemp))then
-
-   ! (check required input derivative is present)
-   if(.not.present(dTheta_dT))then
-    message=trim(message)//'dTheta_dT argument is missing'
-    err=20; return
-   endif
-
-   ! (compute the derivative in the liquid water matric potential w.r.t. temperature)
-   dEffSat_dTemp = -dTheta_dT*xNum/(xDen**2._dp) + dTheta_dT/xDen
-   dPsiLiq_dTemp = dPsiLiq_dEffSat*dEffSat_dTemp
-
-  endif  ! if dPsiLiq_dTemp is desired
-
- ! ** unfrozen soil
- else   ! (no ice)
-  matricHeadLiq = matricHeadTotal
-  if(present(dPsiLiq_dTemp)) dPsiLiq_dPsi0 = 1._dp  ! derivative=1 because values are identical
-  if(present(dPsiLiq_dTemp)) dPsiLiq_dTemp = 0._dp  ! derivative=0 because no impact of temperature for unfrozen conditions
- end if  ! (if ice exists)
-
- end subroutine liquidHead
-
- ! ******************************************************************************************************************************
- ! public function hydCondMP_liq: compute the hydraulic conductivity of macropores as a function of liquid water content (m s-1)
- ! ******************************************************************************************************************************
- function hydCondMP_liq(volFracLiq,theta_sat,theta_mp,mpExp,satHydCond_ma,satHydCond_mi)
- ! computes hydraulic conductivity given volFracLiq and soil hydraulic parameters
- !  theta_sat, theta_mp, mpExp, satHydCond_ma, and satHydCond_mi
- implicit none
- ! dummies
- real(dp),intent(in) :: volFracLiq    ! volumetric liquid water content (-)
- real(dp),intent(in) :: theta_sat     ! soil porosity (-)
- real(dp),intent(in) :: theta_mp      ! minimum volumetric liquid water content for macropore flow (-)
- real(dp),intent(in) :: mpExp         ! empirical exponent in macropore flow equation (-)
- real(dp),intent(in) :: satHydCond_ma ! saturated hydraulic conductivity for macropores (m s-1)
- real(dp),intent(in) :: satHydCond_mi ! saturated hydraulic conductivity for micropores (m s-1)
- real(dp)            :: hydCondMP_liq ! hydraulic conductivity (m s-1)
- ! locals
- real(dp)            :: theta_e     ! effective soil moisture
- if(volFracLiq > theta_mp)then
+! ******************************************************************************************************************************
+! public subroutine iceImpede: compute the ice impedence factor
+! ******************************************************************************************************************************
+subroutine iceImpede(volFracIce,f_impede, &            ! input
+                    iceImpedeFactor,dIceImpede_dLiq)  ! output
+  ! computes the ice impedence factor (separate function, as used multiple times)
+  implicit none
+  ! input variables
+  real(rkind),intent(in)     :: volFracIce        ! volumetric fraction of ice (-)
+  real(rkind),intent(in)     :: f_impede          ! ice impedence parameter (-)
+  ! output variables
+  real(rkind)                :: iceImpedeFactor   ! ice impedence factor (-)
+  real(rkind)                :: dIceImpede_dLiq   ! derivative in ice impedence factor w.r.t. volumetric liquid water content (-)
+  ! compute ice impedance factor as a function of volumetric ice content
+  iceImpedeFactor = 10._rkind**(-f_impede*volFracIce)
+  dIceImpede_dLiq = 0._rkind
+
+end subroutine iceImpede
+
+
+! ******************************************************************************************************************************
+! public subroutine dIceImpede_dTemp: compute the derivative in the ice impedence factor w.r.t. temperature
+! ******************************************************************************************************************************
+subroutine dIceImpede_dTemp(volFracIce,dTheta_dT,f_impede,dIceImpede_dT)
+  ! computes the derivative in the ice impedance factor w.r.t. temperature
+  implicit none
+  ! input variables
+  real(rkind),intent(in)     :: volFracIce        ! volumetric fraction of ice (-)
+  real(rkind),intent(in)     :: dTheta_dT         ! derivative in volumetric liquid water content w.r.t temperature (K-1)
+  real(rkind),intent(in)     :: f_impede          ! ice impedence parameter (-)
+  ! output variables
+  real(rkind)                :: dIceImpede_dT     ! derivative in the ice impedance factor w.r.t. temperature (K-1)
+  ! --
+  dIceImpede_dT = log(10._rkind)*f_impede*(10._rkind**(-f_impede*volFracIce))*dTheta_dT
+end subroutine dIceImpede_dTemp
+
+
+! ******************************************************************************************************************************
+! public subroutine: compute the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
+! ******************************************************************************************************************************
+subroutine liquidHead(&
+                      ! input
+                      matricHeadTotal                          ,& ! intent(in)    : total water matric potential (m)
+                      volFracLiq                               ,& ! intent(in)    : volumetric fraction of liquid water (-)
+                      volFracIce                               ,& ! intent(in)    : volumetric fraction of ice (-)
+                      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)
+                      ! output
+                      matricHeadLiq                            ,& ! intent(out)   : liquid water matric potential (m)
+                      dPsiLiq_dPsi0                            ,& ! intent(out)   : derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
+                      dPsiLiq_dTemp                            ,& ! intent(out)   : derivative in the liquid water matric potential w.r.t. temperature (m K-1)
+                      err,message)                                ! intent(out)   : error control
+  ! computes the liquid water matric potential (and the derivatives w.r.t. total matric potential and temperature)
+  implicit none
+  ! input
+  real(rkind),intent(in)            :: matricHeadTotal                           ! total water matric potential (m)
+  real(rkind),intent(in)            :: volFracLiq                                ! volumetric fraction of liquid water (-)
+  real(rkind),intent(in)            :: volFracIce                                ! volumetric fraction of ice (-)
+  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)
+  ! output
+  real(rkind),intent(out)           :: matricHeadLiq                             ! liquid water matric potential (m)
+  real(rkind),intent(out) ,optional :: dPsiLiq_dPsi0                             ! derivative in the liquid water matric potential w.r.t. the total water matric potential (-)
+  real(rkind),intent(out) ,optional :: dPsiLiq_dTemp                             ! derivative in the liquid water matric potential w.r.t. temperature (m K-1)
+  ! output: error control
+  integer(i4b),intent(out)       :: err                                       ! error code
+  character(*),intent(out)       :: message                                   ! error message
+  ! local
+  real(rkind)                       :: xNum,xDen                                 ! temporary variables (numeratir, denominator)
+  real(rkind)                       :: effSat                                    ! effective saturation (-)
+  real(rkind)                       :: dPsiLiq_dEffSat                           ! derivative in liquid water matric potential w.r.t. effective saturation (m)
+  real(rkind)                       :: dEffSat_dTemp                             ! derivative in effective saturation w.r.t. temperature (K-1)
+  ! ------------------------------------------------------------------------------------------------------------------------------
+  ! initialize error control
+  err=0; message='liquidHead/'
+
+  ! ** partially frozen soil
+  if(volFracIce > verySmall .and. matricHeadTotal < 0._rkind)then  ! check that ice exists and that the soil is unsaturated
+
+    ! -----
+    ! - compute liquid water matric potential...
+    ! ------------------------------------------
+
+    ! - compute effective saturation
+    ! NOTE: include ice content as part of the solid porosity - major effect of ice is to reduce the pore size; ensure that effSat=1 at saturation
+    ! (from Zhao et al., J. Hydrol., 1997: Numerical analysis of simultaneous heat and mass transfer...)
+    xNum   = volFracLiq - theta_res
+    xDen   = theta_sat - volFracIce - theta_res
+    effSat = xNum/xDen          ! effective saturation
+
+    ! - matric head associated with liquid water
+    matricHeadLiq = matricHead(effSat,vGn_alpha,0._rkind,1._rkind,vGn_n,vGn_m)  ! argument is effective saturation, so theta_res=0 and theta_sat=1
+
+    ! compute derivative in liquid water matric potential w.r.t. effective saturation (m)
+    if(present(dPsiLiq_dPsi0).or.present(dPsiLiq_dTemp))then
+    dPsiLiq_dEffSat = dPsi_dTheta(effSat,vGn_alpha,0._rkind,1._rkind,vGn_n,vGn_m)
+    endif
+
+    ! -----
+    ! - compute derivative in the liquid water matric potential w.r.t. the total water matric potential...
+    ! ----------------------------------------------------------------------------------------------------
+
+    ! check if the derivative is desired
+    if(present(dPsiLiq_dTemp))then
+
+    ! (check required input derivative is present)
+    if(.not.present(dVolTot_dPsi0))then
+      message=trim(message)//'dVolTot_dPsi0 argument is missing'
+      err=20; return
+    endif
+
+    ! (compute derivative in the liquid water matric potential w.r.t. the total water matric potential)
+    dPsiLiq_dPsi0 = dVolTot_dPsi0*dPsiLiq_dEffSat*xNum/(xDen**2._rkind)
+
+    endif  ! if dPsiLiq_dTemp is desired
+
+    ! -----
+    ! - compute the derivative in the liquid water matric potential w.r.t. temperature...
+    ! -----------------------------------------------------------------------------------
+
+    ! check if the derivative is desired
+    if(present(dPsiLiq_dTemp))then
+
+    ! (check required input derivative is present)
+    if(.not.present(dTheta_dT))then
+      message=trim(message)//'dTheta_dT argument is missing'
+      err=20; return
+    endif
+
+    ! (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
+
+    endif  ! if dPsiLiq_dTemp is desired
+
+  ! ** unfrozen soil
+  else   ! (no ice)
+    matricHeadLiq = matricHeadTotal
+    if(present(dPsiLiq_dTemp)) dPsiLiq_dPsi0 = 1._rkind  ! derivative=1 because values are identical
+    if(present(dPsiLiq_dTemp)) dPsiLiq_dTemp = 0._rkind  ! derivative=0 because no impact of temperature for unfrozen conditions
+  end if  ! (if ice exists)
+
+end subroutine liquidHead
+
+! ******************************************************************************************************************************
+! public function hydCondMP_liq: compute the hydraulic conductivity of macropores as a function of liquid water content (m s-1)
+! ******************************************************************************************************************************
+function hydCondMP_liq(volFracLiq,theta_sat,theta_mp,mpExp,satHydCond_ma,satHydCond_mi)
+  ! computes hydraulic conductivity given volFracLiq and soil hydraulic parameters
+  !  theta_sat, theta_mp, mpExp, satHydCond_ma, and satHydCond_mi
+  implicit none
+  ! dummies
+  real(rkind),intent(in) :: volFracLiq    ! volumetric liquid water content (-)
+  real(rkind),intent(in) :: theta_sat     ! soil porosity (-)
+  real(rkind),intent(in) :: theta_mp      ! minimum volumetric liquid water content for macropore flow (-)
+  real(rkind),intent(in) :: mpExp         ! empirical exponent in macropore flow equation (-)
+  real(rkind),intent(in) :: satHydCond_ma ! saturated hydraulic conductivity for macropores (m s-1)
+  real(rkind),intent(in) :: satHydCond_mi ! saturated hydraulic conductivity for micropores (m s-1)
+  real(rkind)            :: hydCondMP_liq ! hydraulic conductivity (m s-1)
+  ! locals
+  real(rkind)            :: theta_e     ! effective soil moisture
+  if(volFracLiq > theta_mp)then
   theta_e       = (volFracLiq - theta_mp) / (theta_sat - theta_mp)
   hydCondMP_liq = (satHydCond_ma - satHydCond_mi) * (theta_e**mpExp)
- else
-  hydCondMP_liq = 0._dp
- end if
- !write(*,'(a,4(f9.3,1x),2(e20.10))') 'in soil_utils: theta_mp, theta_sat, volFracLiq, hydCondMP_liq, satHydCond_ma, satHydCond_mi = ', &
- !                                                    theta_mp, theta_sat, volFracLiq, hydCondMP_liq, satHydCond_ma, satHydCond_mi
- end function hydCondMP_liq
-
-
- ! ******************************************************************************************************************************
- ! public function hydCond_psi: compute the hydraulic conductivity as a function of matric head (m s-1)
- ! ******************************************************************************************************************************
- function hydCond_psi(psi,k_sat,alpha,n,m)
- ! computes hydraulic conductivity given psi and soil hydraulic parameters k_sat, alpha, n, and m
- implicit none
- ! dummies
- real(dp),intent(in)     :: psi           ! soil water suction (m)
- real(dp),intent(in)     :: k_sat         ! saturated hydraulic conductivity (m s-1)
- real(dp),intent(in)     :: alpha         ! scaling parameter (m-1)
- real(dp),intent(in)     :: n             ! vGn "n" parameter (-)
- real(dp),intent(in)     :: m             ! vGn "m" parameter (-)
- real(dp)                :: hydCond_psi   ! hydraulic conductivity (m s-1)
- if(psi<0._dp)then
+  else
+  hydCondMP_liq = 0._rkind
+  end if
+end function hydCondMP_liq
+
+
+! ******************************************************************************************************************************
+! public function hydCond_psi: compute the hydraulic conductivity as a function of matric head (m s-1)
+! ******************************************************************************************************************************
+function hydCond_psi(psi,k_sat,alpha,n,m)
+  ! computes hydraulic conductivity given psi and soil hydraulic parameters k_sat, alpha, n, and m
+  implicit none
+  ! dummies
+  real(rkind),intent(in)     :: psi           ! soil water suction (m)
+  real(rkind),intent(in)     :: k_sat         ! saturated hydraulic conductivity (m s-1)
+  real(rkind),intent(in)     :: alpha         ! scaling parameter (m-1)
+  real(rkind),intent(in)     :: n             ! vGn "n" parameter (-)
+  real(rkind),intent(in)     :: m             ! vGn "m" parameter (-)
+  real(rkind)                :: hydCond_psi   ! hydraulic conductivity (m s-1)
+  if(psi<0._rkind)then
   hydCond_psi = k_sat * &
-                ( ( (1._dp - (psi*alpha)**(n-1._dp) * (1._dp + (psi*alpha)**n)**(-m))**2._dp ) &
-                 / ( (1._dp + (psi*alpha)**n)**(m/2._dp) ) )
- else
+                ( ( (1._rkind - (psi*alpha)**(n-1._rkind) * (1._rkind + (psi*alpha)**n)**(-m))**2._rkind ) &
+                  / ( (1._rkind + (psi*alpha)**n)**(m/2._rkind) ) )
+  else
   hydCond_psi = k_sat
- end if
- end function hydCond_psi
-
-
- ! ******************************************************************************************************************************
- ! public function hydCond_liq: compute the hydraulic conductivity as a function of volumetric liquid water content (m s-1)
- ! ******************************************************************************************************************************
- function hydCond_liq(volFracLiq,k_sat,theta_res,theta_sat,m)
- ! computes hydraulic conductivity given volFracLiq and soil hydraulic parameters k_sat, theta_sat, theta_res, and m
- implicit none
- ! dummies
- real(dp),intent(in) :: volFracLiq  ! volumetric liquid water content (-)
- real(dp),intent(in) :: k_sat       ! saturated hydraulic conductivity (m s-1)
- real(dp),intent(in) :: theta_res   ! residual volumetric liquid water content (-)
- real(dp),intent(in) :: theta_sat   ! soil porosity (-)
- real(dp),intent(in) :: m           ! vGn "m" parameter (-)
- real(dp)            :: hydCond_liq ! hydraulic conductivity (m s-1)
- ! locals
- real(dp)            :: theta_e     ! effective soil moisture
- if(volFracLiq < theta_sat)then
+  end if
+end function hydCond_psi
+
+
+! ******************************************************************************************************************************
+! public function hydCond_liq: compute the hydraulic conductivity as a function of volumetric liquid water content (m s-1)
+! ******************************************************************************************************************************
+function hydCond_liq(volFracLiq,k_sat,theta_res,theta_sat,m)
+  ! computes hydraulic conductivity given volFracLiq and soil hydraulic parameters k_sat, theta_sat, theta_res, and m
+  implicit none
+  ! dummies
+  real(rkind),intent(in) :: volFracLiq  ! volumetric liquid water content (-)
+  real(rkind),intent(in) :: k_sat       ! saturated hydraulic conductivity (m s-1)
+  real(rkind),intent(in) :: theta_res   ! residual volumetric liquid water content (-)
+  real(rkind),intent(in) :: theta_sat   ! soil porosity (-)
+  real(rkind),intent(in) :: m           ! vGn "m" parameter (-)
+  real(rkind)            :: hydCond_liq ! hydraulic conductivity (m s-1)
+  ! locals
+  real(rkind)            :: theta_e     ! effective soil moisture
+  if(volFracLiq < theta_sat)then
   theta_e = (volFracLiq - theta_res) / (theta_sat - theta_res)
-  hydCond_liq = k_sat*theta_e**(1._dp/2._dp) * (1._dp - (1._dp - theta_e**(1._dp/m) )**m)**2._dp
- else
+  hydCond_liq = k_sat*theta_e**(1._rkind/2._rkind) * (1._rkind - (1._rkind - theta_e**(1._rkind/m) )**m)**2._rkind
+  else
   hydCond_liq = k_sat
- end if
- end function hydCond_liq
-
-
- ! ******************************************************************************************************************************
- ! public function volFracLiq: compute the volumetric liquid water content (-)
- ! ******************************************************************************************************************************
- function volFracLiq(psi,alpha,theta_res,theta_sat,n,m)
- ! computes the volumetric liquid water content given psi and soil hydraulic parameters theta_res, theta_sat, alpha, n, and m
- implicit none
- real(dp),intent(in) :: psi         ! soil water suction (m)
- real(dp),intent(in) :: alpha       ! scaling parameter (m-1)
- real(dp),intent(in) :: theta_res   ! residual volumetric water content (-)
- real(dp),intent(in) :: theta_sat   ! porosity (-)
- real(dp),intent(in) :: n           ! vGn "n" parameter (-)
- real(dp),intent(in) :: m           ! vGn "m" parameter (-)
- real(dp)            :: volFracLiq  ! volumetric liquid water content (-)
- if(psi<0._dp)then
-  volFracLiq = theta_res + (theta_sat - theta_res)*(1._dp + (alpha*psi)**n)**(-m)
- else
+  end if
+end function hydCond_liq
+
+
+! ******************************************************************************************************************************
+! public function volFracLiq: compute the volumetric liquid water content (-)
+! ******************************************************************************************************************************
+function volFracLiq(psi,alpha,theta_res,theta_sat,n,m)
+  ! computes the volumetric liquid water content given psi and soil hydraulic parameters theta_res, theta_sat, alpha, n, and m
+  implicit none
+  real(rkind),intent(in) :: psi         ! soil water suction (m)
+  real(rkind),intent(in) :: alpha       ! scaling parameter (m-1)
+  real(rkind),intent(in) :: theta_res   ! residual volumetric water content (-)
+  real(rkind),intent(in) :: theta_sat   ! porosity (-)
+  real(rkind),intent(in) :: n           ! vGn "n" parameter (-)
+  real(rkind),intent(in) :: m           ! vGn "m" parameter (-)
+  real(rkind)            :: volFracLiq  ! volumetric liquid water content (-)
+  if(psi<0._rkind)then
+  volFracLiq = theta_res + (theta_sat - theta_res)*(1._rkind + (alpha*psi)**n)**(-m)
+  else
   volFracLiq = theta_sat
- end if
- end function volFracLiq
-
-
- ! ******************************************************************************************************************************
- ! public function matricHead: compute the matric head (m) based on the volumetric liquid water content
- ! ******************************************************************************************************************************
- function matricHead(theta,alpha,theta_res,theta_sat,n,m)
- ! computes the volumetric liquid water content given psi and soil hydraulic parameters theta_res, theta_sat, alpha, n, and m
- implicit none
- ! dummy variables
- real(dp),intent(in) :: theta       ! volumetric liquid water content (-)
- real(dp),intent(in) :: alpha       ! scaling parameter (m-1)
- real(dp),intent(in) :: theta_res   ! residual volumetric water content (-)
- real(dp),intent(in) :: theta_sat   ! porosity (-)
- real(dp),intent(in) :: n           ! vGn "n" parameter (-)
- real(dp),intent(in) :: m           ! vGn "m" parameter (-)
- real(dp)            :: matricHead  ! matric head (m)
- ! local variables
- real(dp)            :: effSat      ! effective saturation (-)
- real(dp),parameter  :: verySmall=epsilon(1._dp)  ! a very small number (avoid effective saturation of zero)
- ! compute effective saturation
- effSat = max(verySmall, (theta - theta_res) / (theta_sat - theta_res))
- ! compute matric head
- if (effSat < 1._dp .and. effSat > 0._dp)then
-  matricHead = (1._dp/alpha)*( effSat**(-1._dp/m) - 1._dp)**(1._dp/n)
- else
-  matricHead = 0._dp
- end if
- end function matricHead
-
-
- ! ******************************************************************************************************************************
- ! public function dTheta_dPsi: compute the derivative of the soil water characteristic (m-1)
- ! ******************************************************************************************************************************
- function dTheta_dPsi(psi,alpha,theta_res,theta_sat,n,m)
- implicit none
- real(dp),intent(in) :: psi         ! soil water suction (m)
- real(dp),intent(in) :: alpha       ! scaling parameter (m-1)
- real(dp),intent(in) :: theta_res   ! residual volumetric water content (-)
- real(dp),intent(in) :: theta_sat   ! porosity (-)
- real(dp),intent(in) :: n           ! vGn "n" parameter (-)
- real(dp),intent(in) :: m           ! vGn "m" parameter (-)
- real(dp)            :: dTheta_dPsi ! derivative of the soil water characteristic (m-1)
- if(psi<=0._dp)then
+  end if
+end function volFracLiq
+
+
+! ******************************************************************************************************************************
+! public function matricHead: compute the matric head (m) based on the volumetric liquid water content
+! ******************************************************************************************************************************
+function matricHead(theta,alpha,theta_res,theta_sat,n,m)
+  ! computes the volumetric liquid water content given psi and soil hydraulic parameters theta_res, theta_sat, alpha, n, and m
+  implicit none
+  ! dummy variables
+  real(rkind),intent(in) :: theta       ! volumetric liquid water content (-)
+  real(rkind),intent(in) :: alpha       ! scaling parameter (m-1)
+  real(rkind),intent(in) :: theta_res   ! residual volumetric water content (-)
+  real(rkind),intent(in) :: theta_sat   ! porosity (-)
+  real(rkind),intent(in) :: n           ! vGn "n" parameter (-)
+  real(rkind),intent(in) :: m           ! vGn "m" parameter (-)
+  real(rkind)            :: matricHead  ! matric head (m)
+  ! local variables
+  real(rkind)            :: effSat      ! effective saturation (-)
+  real(rkind),parameter  :: verySmall=epsilon(1._rkind)  ! a very small number (avoid effective saturation of zero)
+  ! compute effective saturation
+  effSat = max(verySmall, (theta - theta_res) / (theta_sat - theta_res))
+  ! compute matric head
+  if (effSat < 1._rkind .and. effSat > 0._rkind)then
+  matricHead = (1._rkind/alpha)*( effSat**(-1._rkind/m) - 1._rkind)**(1._rkind/n)
+  else
+  matricHead = 0._rkind
+  end if
+end function matricHead
+
+
+! ******************************************************************************************************************************
+! public function dTheta_dPsi: compute the derivative of the soil water characteristic (m-1)
+! ******************************************************************************************************************************
+function dTheta_dPsi(psi,alpha,theta_res,theta_sat,n,m)
+  implicit none
+  real(rkind),intent(in) :: psi         ! soil water suction (m)
+  real(rkind),intent(in) :: alpha       ! scaling parameter (m-1)
+  real(rkind),intent(in) :: theta_res   ! residual volumetric water content (-)
+  real(rkind),intent(in) :: theta_sat   ! porosity (-)
+  real(rkind),intent(in) :: n           ! vGn "n" parameter (-)
+  real(rkind),intent(in) :: m           ! vGn "m" parameter (-)
+  real(rkind)            :: dTheta_dPsi ! derivative of the soil water characteristic (m-1)
+  if(psi<=0._rkind)then
   dTheta_dPsi = (theta_sat-theta_res) * &
-     (-m*(1._dp + (psi*alpha)**n)**(-m-1._dp)) * n*(psi*alpha)**(n-1._dp) * alpha
+      (-m*(1._rkind + (psi*alpha)**n)**(-m-1._rkind)) * n*(psi*alpha)**(n-1._rkind) * alpha
   if(abs(dTheta_dPsi) < epsilon(psi)) dTheta_dPsi = epsilon(psi)
- else
+  else
   dTheta_dPsi = epsilon(psi)
- end if
- end function dTheta_dPsi
-
-
- ! ******************************************************************************************************************************
- ! public function dPsi_dTheta: compute the derivative of the soil water characteristic (m-1)
- ! ******************************************************************************************************************************
- function dPsi_dTheta(volFracLiq,alpha,theta_res,theta_sat,n,m)
- implicit none
- ! dummies
- real(dp),intent(in) :: volFracLiq  ! volumetric liquid water content (-)
- real(dp),intent(in) :: alpha       ! scaling parameter (m-1)
- real(dp),intent(in) :: theta_res   ! residual volumetric water content (-)
- real(dp),intent(in) :: theta_sat   ! porosity (-)
- real(dp),intent(in) :: n           ! vGn "n" parameter (-)
- real(dp),intent(in) :: m           ! vGn "m" parameter (-)
- real(dp)            :: dPsi_dTheta ! derivative of the soil water characteristic (m)
- ! locals
- real(dp)            :: y1,d1       ! 1st function and derivative
- real(dp)            :: y2,d2       ! 2nd function and derivative
- real(dp)            :: theta_e     ! effective soil moisture
- ! check if less than saturation
- if(volFracLiq < theta_sat)then
+  end if
+end function dTheta_dPsi
+
+
+! ******************************************************************************************************************************
+! public function dPsi_dTheta: compute the derivative of the soil water characteristic (m-1)
+! ******************************************************************************************************************************
+function dPsi_dTheta(volFracLiq,alpha,theta_res,theta_sat,n,m)
+  implicit none
+  ! dummies
+  real(rkind),intent(in) :: volFracLiq  ! volumetric liquid water content (-)
+  real(rkind),intent(in) :: alpha       ! scaling parameter (m-1)
+  real(rkind),intent(in) :: theta_res   ! residual volumetric water content (-)
+  real(rkind),intent(in) :: theta_sat   ! porosity (-)
+  real(rkind),intent(in) :: n           ! vGn "n" parameter (-)
+  real(rkind),intent(in) :: m           ! vGn "m" parameter (-)
+  real(rkind)            :: dPsi_dTheta ! derivative of the soil water characteristic (m)
+  ! locals
+  real(rkind)            :: y1,d1       ! 1st function and derivative
+  real(rkind)            :: y2,d2       ! 2nd function and derivative
+  real(rkind)            :: theta_e     ! effective soil moisture
+  ! check if less than saturation
+  if(volFracLiq < theta_sat)then
   ! compute effective water content
   theta_e = max(0.001,(volFracLiq - theta_res) / (theta_sat - theta_res))
   ! compute the 1st function and derivative
-  y1 = theta_e**(-1._dp/m) - 1._dp
-  d1 = (-1._dp/m)*theta_e**(-1._dp/m - 1._dp) / (theta_sat - theta_res)
+  y1 = theta_e**(-1._rkind/m) - 1._rkind
+  d1 = (-1._rkind/m)*theta_e**(-1._rkind/m - 1._rkind) / (theta_sat - theta_res)
   ! compute the 2nd function and derivative
-  y2 = y1**(1._dp/n)
-  d2 = (1._dp/n)*y1**(1._dp/n - 1._dp)
+  y2 = y1**(1._rkind/n)
+  d2 = (1._rkind/n)*y1**(1._rkind/n - 1._rkind)
   ! compute the final function value
   dPsi_dTheta = d1*d2/alpha
- else
-  dPsi_dTheta = 0._dp
- end if
- end function dPsi_dTheta
-
-
- ! ******************************************************************************************************************************
- ! public function dPsi_dTheta2: compute the derivative of dPsi_dTheta (m-1)
- ! ******************************************************************************************************************************
- function dPsi_dTheta2(volFracLiq,alpha,theta_res,theta_sat,n,m,lTangent)
- implicit none
- ! dummies
- real(dp),intent(in)     :: volFracLiq   ! volumetric liquid water content (-)
- real(dp),intent(in)     :: alpha        ! scaling parameter (m-1)
- real(dp),intent(in)     :: theta_res    ! residual volumetric water content (-)
- real(dp),intent(in)     :: theta_sat    ! porosity (-)
- real(dp),intent(in)     :: n            ! vGn "n" parameter (-)
- real(dp),intent(in)     :: m            ! vGn "m" parameter (-)
- logical(lgt),intent(in) :: lTangent     ! method used to compute derivative (.true. = analytical)
- real(dp)                :: dPsi_dTheta2 ! derivative of the soil water characteristic (m)
- ! locals for analytical derivatives
- real(dp)                :: xx           ! temporary variable
- real(dp)                :: y1,d1        ! 1st function and derivative
- real(dp)                :: y2,d2        ! 2nd function and derivative
- real(dp)                :: theta_e      ! effective soil moisture
- ! locals for numerical derivative
- real(dp)                :: func0,func1  ! function evaluations
- ! check if less than saturation
- if(volFracLiq < theta_sat)then
+  else
+  dPsi_dTheta = 0._rkind
+  end if
+end function dPsi_dTheta
+
+
+! ******************************************************************************************************************************
+! public function dPsi_dTheta2: compute the derivative of dPsi_dTheta (m-1)
+! ******************************************************************************************************************************
+function dPsi_dTheta2(volFracLiq,alpha,theta_res,theta_sat,n,m,lTangent)
+  implicit none
+  ! dummies
+  real(rkind),intent(in)     :: volFracLiq   ! volumetric liquid water content (-)
+  real(rkind),intent(in)     :: alpha        ! scaling parameter (m-1)
+  real(rkind),intent(in)     :: theta_res    ! residual volumetric water content (-)
+  real(rkind),intent(in)     :: theta_sat    ! porosity (-)
+  real(rkind),intent(in)     :: n            ! vGn "n" parameter (-)
+  real(rkind),intent(in)     :: m            ! vGn "m" parameter (-)
+  logical(lgt),intent(in) :: lTangent     ! method used to compute derivative (.true. = analytical)
+  real(rkind)                :: dPsi_dTheta2 ! derivative of the soil water characteristic (m)
+  ! locals for analytical derivatives
+  real(rkind)                :: xx           ! temporary variable
+  real(rkind)                :: y1,d1        ! 1st function and derivative
+  real(rkind)                :: y2,d2        ! 2nd function and derivative
+  real(rkind)                :: theta_e      ! effective soil moisture
+  ! locals for numerical derivative
+  real(rkind)                :: func0,func1  ! function evaluations
+  ! check if less than saturation
+  if(volFracLiq < theta_sat)then
   ! ***** compute analytical derivatives
   if(lTangent)then
-   ! compute the effective saturation
-   theta_e = (volFracLiq - theta_res) / (theta_sat - theta_res)
-   ! get the first function and derivative
-   y1 = (-1._dp/m)*theta_e**(-1._dp/m - 1._dp) / (theta_sat - theta_res)
-   d1 = ( (m + 1._dp) / (m**2._dp * (theta_sat - theta_res)**2._dp) ) * theta_e**(-1._dp/m - 2._dp)
-   ! get the second function and derivative
-   xx = theta_e**(-1._dp/m) - 1._dp
-   y2 = (1._dp/n)*xx**(1._dp/n - 1._dp)
-   d2 = ( -(1._dp - n)/((theta_sat - theta_res)*m*n**2._dp) ) * xx**(1._dp/n - 2._dp) * theta_e**(-1._dp/m - 1._dp)
-   ! return the derivative
-   dPsi_dTheta2 = (d1*y2 + y1*d2)/alpha
+    ! compute the effective saturation
+    theta_e = (volFracLiq - theta_res) / (theta_sat - theta_res)
+    ! get the first function and derivative
+    y1 = (-1._rkind/m)*theta_e**(-1._rkind/m - 1._rkind) / (theta_sat - theta_res)
+    d1 = ( (m + 1._rkind) / (m**2._rkind * (theta_sat - theta_res)**2._rkind) ) * theta_e**(-1._rkind/m - 2._rkind)
+    ! get the second function and derivative
+    xx = theta_e**(-1._rkind/m) - 1._rkind
+    y2 = (1._rkind/n)*xx**(1._rkind/n - 1._rkind)
+    d2 = ( -(1._rkind - n)/((theta_sat - theta_res)*m*n**2._rkind) ) * xx**(1._rkind/n - 2._rkind) * theta_e**(-1._rkind/m - 1._rkind)
+    ! return the derivative
+    dPsi_dTheta2 = (d1*y2 + y1*d2)/alpha
   ! ***** compute numerical derivatives
   else
-   func0 = dPsi_dTheta(volFracLiq,   alpha,theta_res,theta_sat,n,m)
-   func1 = dPsi_dTheta(volFracLiq+dx,alpha,theta_res,theta_sat,n,m)
-   dPsi_dTheta2 = (func1 - func0)/dx
+    func0 = dPsi_dTheta(volFracLiq,   alpha,theta_res,theta_sat,n,m)
+    func1 = dPsi_dTheta(volFracLiq+dx,alpha,theta_res,theta_sat,n,m)
+    dPsi_dTheta2 = (func1 - func0)/dx
   end if
- ! (case where volumetric liquid water content exceeds porosity)
- else
-  dPsi_dTheta2 = 0._dp
- end if
- end function dPsi_dTheta2
-
-
- ! ******************************************************************************************************************************
- ! public function dHydCond_dPsi: compute the derivative in hydraulic conductivity w.r.t. matric head (s-1)
- ! ******************************************************************************************************************************
- function dHydCond_dPsi(psi,k_sat,alpha,n,m,lTangent)
- ! computes the derivative in hydraulic conductivity w.r.t matric head,
- !  given psi and soil hydraulic parameters k_sat, alpha, n, and m
- implicit none
- ! dummies
- real(dp),intent(in)     :: psi        ! soil water suction (m)
- real(dp),intent(in)     :: k_sat      ! saturated hydraulic conductivity (m s-1)
- real(dp),intent(in)     :: alpha      ! scaling parameter (m-1)
- real(dp),intent(in)     :: n          ! vGn "n" parameter (-)
- real(dp),intent(in)     :: m          ! vGn "m" parameter (-)
- logical(lgt),intent(in) :: lTangent   ! method used to compute derivative (.true. = analytical)
- real(dp)                :: dHydCond_dPsi  ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
- ! locals for analytical derivatives
- real(dp)                :: f_x1          ! f(x) for part of the numerator
- real(dp)                :: f_x2          ! f(x) for part of the numerator
- real(dp)                :: f_nm          ! f(x) for the numerator
- real(dp)                :: f_dm          ! f(x) for the denominator
- real(dp)                :: d_x1          ! df(x)/dpsi for part of the numerator
- real(dp)                :: d_x2          ! df(x)/dpsi for part of the numerator
- real(dp)                :: d_nm          ! df(x)/dpsi for the numerator
- real(dp)                :: d_dm          ! df(x)/dpsi for the denominator
- ! locals for numerical derivatives
- real(dp)                :: hydCond0   ! hydraulic condictivity value for base case
- real(dp)                :: hydCond1   ! hydraulic condictivity value for perturbed case
- ! derivative is zero if saturated
- if(psi<0._dp)then
+  ! (case where volumetric liquid water content exceeds porosity)
+  else
+  dPsi_dTheta2 = 0._rkind
+  end if
+end function dPsi_dTheta2
+
+
+! ******************************************************************************************************************************
+! public function dHydCond_dPsi: compute the derivative in hydraulic conductivity w.r.t. matric head (s-1)
+! ******************************************************************************************************************************
+function dHydCond_dPsi(psi,k_sat,alpha,n,m,lTangent)
+  ! computes the derivative in hydraulic conductivity w.r.t matric head,
+  !  given psi and soil hydraulic parameters k_sat, alpha, n, and m
+  implicit none
+  ! dummies
+  real(rkind),intent(in)     :: psi        ! soil water suction (m)
+  real(rkind),intent(in)     :: k_sat      ! saturated hydraulic conductivity (m s-1)
+  real(rkind),intent(in)     :: alpha      ! scaling parameter (m-1)
+  real(rkind),intent(in)     :: n          ! vGn "n" parameter (-)
+  real(rkind),intent(in)     :: m          ! vGn "m" parameter (-)
+  logical(lgt),intent(in) :: lTangent   ! method used to compute derivative (.true. = analytical)
+  real(rkind)                :: dHydCond_dPsi  ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
+  ! locals for analytical derivatives
+  real(rkind)                :: f_x1          ! f(x) for part of the numerator
+  real(rkind)                :: f_x2          ! f(x) for part of the numerator
+  real(rkind)                :: f_nm          ! f(x) for the numerator
+  real(rkind)                :: f_dm          ! f(x) for the denominator
+  real(rkind)                :: d_x1          ! df(x)/dpsi for part of the numerator
+  real(rkind)                :: d_x2          ! df(x)/dpsi for part of the numerator
+  real(rkind)                :: d_nm          ! df(x)/dpsi for the numerator
+  real(rkind)                :: d_dm          ! df(x)/dpsi for the denominator
+  ! locals for numerical derivatives
+  real(rkind)                :: hydCond0   ! hydraulic condictivity value for base case
+  real(rkind)                :: hydCond1   ! hydraulic condictivity value for perturbed case
+  ! derivative is zero if saturated
+  if(psi<0._rkind)then
   ! ***** compute analytical derivatives
   if(lTangent)then
-   ! compute the derivative for the numerator
-   f_x1 = (psi*alpha)**(n - 1._dp)
-   f_x2 = (1._dp + (psi*alpha)**n)**(-m)
-   d_x1 = alpha * (n - 1._dp)*(psi*alpha)**(n - 2._dp)
-   d_x2 = alpha * n*(psi*alpha)**(n - 1._dp) * (-m)*(1._dp + (psi*alpha)**n)**(-m - 1._dp)
-   f_nm = (1._dp - f_x1*f_x2)**2._dp
-   d_nm = (-d_x1*f_x2 - f_x1*d_x2) * 2._dp*(1._dp - f_x1*f_x2)
-   ! compute the derivative for the denominator
-   f_dm = (1._dp + (psi*alpha)**n)**(m/2._dp)
-   d_dm = alpha * n*(psi*alpha)**(n - 1._dp) * (m/2._dp)*(1._dp + (psi*alpha)**n)**(m/2._dp - 1._dp)
-   ! and combine
-   dHydCond_dPsi = k_sat*(d_nm*f_dm - d_dm*f_nm) / (f_dm**2._dp)
+    ! compute the derivative for the numerator
+    f_x1 = (psi*alpha)**(n - 1._rkind)
+    f_x2 = (1._rkind + (psi*alpha)**n)**(-m)
+    d_x1 = alpha * (n - 1._rkind)*(psi*alpha)**(n - 2._rkind)
+    d_x2 = alpha * n*(psi*alpha)**(n - 1._rkind) * (-m)*(1._rkind + (psi*alpha)**n)**(-m - 1._rkind)
+    f_nm = (1._rkind - f_x1*f_x2)**2._rkind
+    d_nm = (-d_x1*f_x2 - f_x1*d_x2) * 2._rkind*(1._rkind - f_x1*f_x2)
+    ! compute the derivative for the denominator
+    f_dm = (1._rkind + (psi*alpha)**n)**(m/2._rkind)
+    d_dm = alpha * n*(psi*alpha)**(n - 1._rkind) * (m/2._rkind)*(1._rkind + (psi*alpha)**n)**(m/2._rkind - 1._rkind)
+    ! and combine
+    dHydCond_dPsi = k_sat*(d_nm*f_dm - d_dm*f_nm) / (f_dm**2._rkind)
+  else
+    ! ***** compute numerical derivatives
+    hydcond0  = hydCond_psi(psi,   k_sat,alpha,n,m)
+    hydcond1  = hydCond_psi(psi+dx,k_sat,alpha,n,m)
+    dHydCond_dPsi = (hydcond1 - hydcond0)/dx
+  end if
   else
-   ! ***** compute numerical derivatives
-   hydcond0  = hydCond_psi(psi,   k_sat,alpha,n,m)
-   hydcond1  = hydCond_psi(psi+dx,k_sat,alpha,n,m)
-   dHydCond_dPsi = (hydcond1 - hydcond0)/dx
+  dHydCond_dPsi = 0._rkind
   end if
- else
-  dHydCond_dPsi = 0._dp
- end if
- end function dHydCond_dPsi
-
-
- ! ******************************************************************************************************************************
- ! public function dHydCond_dLiq: compute the derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
- ! ******************************************************************************************************************************
- ! computes the derivative in hydraulic conductivity w.r.t the volumetric fraction of liquid water,
- ! given volFracLiq and soil hydraulic parameters k_sat, theta_sat, theta_res, and m
- ! ******************************************************************************************************************************
- function dHydCond_dLiq(volFracLiq,k_sat,theta_res,theta_sat,m,lTangent)
- implicit none
- ! dummies
- real(dp),intent(in)     :: volFracLiq ! volumetric fraction of liquid water (-)
- real(dp),intent(in)     :: k_sat      ! saturated hydraulic conductivity (m s-1)
- real(dp),intent(in)     :: theta_res  ! soil residual volumetric water content (-)
- real(dp),intent(in)     :: theta_sat  ! soil porosity (-)
- real(dp),intent(in)     :: m          ! vGn "m" parameter (-)
- logical(lgt),intent(in) :: lTangent   ! method used to compute derivative (.true. = analytical)
- real(dp)                :: dHydCond_dLiq  ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
- ! locals for analytical derivatives
- real(dp)                :: theta_e  ! effective soil moisture
- real(dp)                :: f1       ! f(x) for the first function
- real(dp)                :: d1       ! df(x)/dLiq for the first function
- real(dp)                :: x1,x2    ! f(x) for different parts of the second function
- real(dp)                :: p1,p2,p3 ! df(x)/dLiq for different parts of the second function
- real(dp)                :: f2       ! f(x) for the second function
- real(dp)                :: d2       ! df(x)/dLiq for the second function
- ! locals for numerical derivatives
- real(dp)                :: hydCond0 ! hydraulic condictivity value for base case
- real(dp)                :: hydCond1 ! hydraulic condictivity value for perturbed case
- ! derivative is zero if super-saturated
- if(volFracLiq < theta_sat)then
+end function dHydCond_dPsi
+
+
+! ******************************************************************************************************************************
+! public function dHydCond_dLiq: compute the derivative in hydraulic conductivity w.r.t. volumetric liquid water content (m s-1)
+! ******************************************************************************************************************************
+! computes the derivative in hydraulic conductivity w.r.t the volumetric fraction of liquid water,
+! given volFracLiq and soil hydraulic parameters k_sat, theta_sat, theta_res, and m
+! ******************************************************************************************************************************
+function dHydCond_dLiq(volFracLiq,k_sat,theta_res,theta_sat,m,lTangent)
+  implicit none
+  ! dummies
+  real(rkind),intent(in)     :: volFracLiq ! volumetric fraction of liquid water (-)
+  real(rkind),intent(in)     :: k_sat      ! saturated hydraulic conductivity (m s-1)
+  real(rkind),intent(in)     :: theta_res  ! soil residual volumetric water content (-)
+  real(rkind),intent(in)     :: theta_sat  ! soil porosity (-)
+  real(rkind),intent(in)     :: m          ! vGn "m" parameter (-)
+  logical(lgt),intent(in) :: lTangent   ! method used to compute derivative (.true. = analytical)
+  real(rkind)                :: dHydCond_dLiq  ! derivative in hydraulic conductivity w.r.t. matric head (s-1)
+  ! locals for analytical derivatives
+  real(rkind)                :: theta_e  ! effective soil moisture
+  real(rkind)                :: f1       ! f(x) for the first function
+  real(rkind)                :: d1       ! df(x)/dLiq for the first function
+  real(rkind)                :: x1,x2    ! f(x) for different parts of the second function
+  real(rkind)                :: p1,p2,p3 ! df(x)/dLiq for different parts of the second function
+  real(rkind)                :: f2       ! f(x) for the second function
+  real(rkind)                :: d2       ! df(x)/dLiq for the second function
+  ! locals for numerical derivatives
+  real(rkind)                :: hydCond0 ! hydraulic condictivity value for base case
+  real(rkind)                :: hydCond1 ! hydraulic condictivity value for perturbed case
+  ! derivative is zero if super-saturated
+  if(volFracLiq < theta_sat)then
   ! ***** compute analytical derivatives
   if(lTangent)then
-   ! compute the effective saturation
-   theta_e = (volFracLiq - theta_res) / (theta_sat - theta_res)
-   ! compute the function and derivative of the first fuction
-   f1 = k_sat*theta_e**0.5_dp
-   d1 = k_sat*0.5_dp*theta_e**(-0.5_dp) / (theta_sat - theta_res)
-   ! compute the function and derivative of the second function
-   ! (first part)
-   x1 = 1._dp - theta_e**(1._dp/m)
-   p1 = (-1._dp/m)*theta_e**(1._dp/m - 1._dp) / (theta_sat - theta_res)   ! differentiate (1.d - theta_e**(1.d/m)
-   ! (second part)
-   x2 = x1**m
-   p2 = m*x1**(m - 1._dp)
-   ! (final)
-   f2 = (1._dp - x2)**2._dp
-   p3 = -2._dp*(1._dp - x2)
-   ! (combine)
-   d2 = p1*p2*p3
-   ! pull it all together
-   dHydCond_dLiq = (d1*f2 + d2*f1)
+    ! compute the effective saturation
+    theta_e = (volFracLiq - theta_res) / (theta_sat - theta_res)
+    ! compute the function and derivative of the first fuction
+    f1 = k_sat*theta_e**0.5_rkind
+    d1 = k_sat*0.5_rkind*theta_e**(-0.5_rkind) / (theta_sat - theta_res)
+    ! compute the function and derivative of the second function
+    ! (first part)
+    x1 = 1._rkind - theta_e**(1._rkind/m)
+    p1 = (-1._rkind/m)*theta_e**(1._rkind/m - 1._rkind) / (theta_sat - theta_res)   ! differentiate (1.d - theta_e**(1.d/m)
+    ! (second part)
+    x2 = x1**m
+    p2 = m*x1**(m - 1._rkind)
+    ! (final)
+    f2 = (1._rkind - x2)**2._rkind
+    p3 = -2._rkind*(1._rkind - x2)
+    ! (combine)
+    d2 = p1*p2*p3
+    ! pull it all together
+    dHydCond_dLiq = (d1*f2 + d2*f1)
   else
-   ! ***** compute numerical derivatives
-   hydcond0 = hydCond_liq(volFracLiq,   k_sat,theta_res,theta_sat,m)
-   hydcond1 = hydCond_liq(volFracLiq+dx,k_sat,theta_res,theta_sat,m)
-   dHydCond_dLiq = (hydcond1 - hydcond0)/dx
+    ! ***** compute numerical derivatives
+    hydcond0 = hydCond_liq(volFracLiq,   k_sat,theta_res,theta_sat,m)
+    hydcond1 = hydCond_liq(volFracLiq+dx,k_sat,theta_res,theta_sat,m)
+    dHydCond_dLiq = (hydcond1 - hydcond0)/dx
   end if
- else
-  dHydCond_dLiq = 0._dp
- end if
- end function dHydCond_dLiq
-
-
- ! ******************************************************************************************************************************
- ! public function RH_soilair: compute relative humidity of air in soil pore space
- ! ******************************************************************************************************************************
- function RH_soilair(matpot,Tk)
- implicit none
- real(dp),intent(in) :: matpot        ! soil water suction -- matric potential (m)
- real(dp),intent(in) :: Tk            ! temperature (K)
- real(dp)            :: RH_soilair    ! relative humidity of air in soil pore space
- ! compute relative humidity (UNITS NOTE: Pa = kg m-1 s-2, so R_wv units = m2 s-2 K-1)
- RH_soilair = exp( (gravity*matpot) / (R_wv*Tk) )
- end function RH_soilair
-
-
- ! ******************************************************************************************************************************
- ! public function crit_soilT: compute the critical temperature above which all water is unfrozen
- ! ******************************************************************************************************************************
- function crit_soilT(psi)
- implicit none
- real(dp),intent(in) :: psi           ! matric head (m)
- real(dp)            :: crit_soilT    ! critical soil temperature (K)
- crit_soilT = Tfreeze + min(psi,0._dp)*gravity*Tfreeze/LH_fus
- end function crit_soilT
-
-
- ! ******************************************************************************************************************************
- ! public function dTheta_dTk: differentiate the freezing curve w.r.t. temperature
- ! ******************************************************************************************************************************
- function dTheta_dTk(Tk,theta_res,theta_sat,alpha,n,m)
- implicit none
- real(dp),intent(in) :: Tk            ! temperature (K)
- real(dp),intent(in) :: theta_res     ! residual liquid water content (-)
- real(dp),intent(in) :: theta_sat     ! porosity (-)
- real(dp),intent(in) :: alpha         ! vGn scaling parameter (m-1)
- real(dp),intent(in) :: n             ! vGn "n" parameter (-)
- real(dp),intent(in) :: m             ! vGn "m" parameter (-)
- real(dp)            :: dTheta_dTk    ! derivative of the freezing curve w.r.t. temperature (K-1)
- ! local variables
- real(dp)            :: kappa         ! constant (m K-1)
- real(dp)            :: xtemp         ! alpha*kappa*(Tk-Tfreeze) -- dimensionless variable (used more than once)
- ! compute kappa (m K-1)
- kappa =  LH_fus/(gravity*Tfreeze)    ! NOTE: J = kg m2 s-2
- ! define a tempory variable that is used more than once (-)
- xtemp = alpha*kappa*(Tk-Tfreeze)
- ! differentiate the freezing curve w.r.t. temperature -- making use of the chain rule
- dTheta_dTk = (alpha*kappa) * n*xtemp**(n - 1._dp) * (-m)*(1._dp + xtemp**n)**(-m - 1._dp) * (theta_sat - theta_res)
- end function dTheta_dTk
-
-
- ! ******************************************************************************************************************************
- ! public function gammp: compute cumulative probability using the Gamma distribution
- ! ******************************************************************************************************************************
- FUNCTION gammp(a,x)
- IMPLICIT NONE
- REAL(DP), INTENT(IN) :: a,x
- REAL(DP) :: gammp
- if (x<a+1.0_dp) then
+  else
+  dHydCond_dLiq = 0._rkind
+  end if
+end function dHydCond_dLiq
+
+
+! ******************************************************************************************************************************
+! public function RH_soilair: compute relative humidity of air in soil pore space
+! ******************************************************************************************************************************
+function RH_soilair(matpot,Tk)
+  implicit none
+  real(rkind),intent(in) :: matpot        ! soil water suction -- matric potential (m)
+  real(rkind),intent(in) :: Tk            ! temperature (K)
+  real(rkind)            :: RH_soilair    ! relative humidity of air in soil pore space
+  ! compute relative humidity (UNITS NOTE: Pa = kg m-1 s-2, so R_wv units = m2 s-2 K-1)
+  RH_soilair = exp( (gravity*matpot) / (R_wv*Tk) )
+end function RH_soilair
+
+
+! ******************************************************************************************************************************
+! public function crit_soilT: compute the critical temperature above which all water is unfrozen
+! ******************************************************************************************************************************
+function crit_soilT(psi)
+  implicit none
+  real(rkind),intent(in) :: psi           ! matric head (m)
+  real(rkind)            :: crit_soilT    ! critical soil temperature (K)
+  crit_soilT = Tfreeze + min(psi,0._rkind)*gravity*Tfreeze/LH_fus
+end function crit_soilT
+
+
+! ******************************************************************************************************************************
+! public function dTheta_dTk: differentiate the freezing curve w.r.t. temperature
+! ******************************************************************************************************************************
+function dTheta_dTk(Tk,theta_res,theta_sat,alpha,n,m)
+  implicit none
+  real(rkind),intent(in) :: Tk            ! temperature (K)
+  real(rkind),intent(in) :: theta_res     ! residual liquid water content (-)
+  real(rkind),intent(in) :: theta_sat     ! porosity (-)
+  real(rkind),intent(in) :: alpha         ! vGn scaling parameter (m-1)
+  real(rkind),intent(in) :: n             ! vGn "n" parameter (-)
+  real(rkind),intent(in) :: m             ! vGn "m" parameter (-)
+  real(rkind)            :: dTheta_dTk    ! derivative of the freezing curve w.r.t. temperature (K-1)
+  ! local variables
+  real(rkind)            :: kappa         ! constant (m K-1)
+  real(rkind)            :: xtemp         ! alpha*kappa*(Tk-Tfreeze) -- dimensionless variable (used more than once)
+  ! compute kappa (m K-1)
+  kappa =  LH_fus/(gravity*Tfreeze)    ! NOTE: J = kg m2 s-2
+  ! define a tempory variable that is used more than once (-)
+  xtemp = alpha*kappa*(Tk-Tfreeze)
+  ! differentiate the freezing curve w.r.t. temperature -- making use of the chain rule
+  dTheta_dTk = (alpha*kappa) * n*xtemp**(n - 1._rkind) * (-m)*(1._rkind + xtemp**n)**(-m - 1._rkind) * (theta_sat - theta_res)
+end function dTheta_dTk
+
+
+! ******************************************************************************************************************************
+! public function gammp: compute cumulative probability using the Gamma distribution
+! ******************************************************************************************************************************
+FUNCTION gammp(a,x)
+  IMPLICIT NONE
+  real(rkind), INTENT(IN) :: a,x
+  real(rkind) :: gammp
+  if (x<a+1.0_rkind) then
   gammp=gser(a,x)
- else
-  gammp=1.0_dp-gcf(a,x)
- end if
- END FUNCTION gammp
-
-
- ! ******************************************************************************************************************************
- ! private function gcf: continued fraction development of the incomplete Gamma function
- ! ******************************************************************************************************************************
- FUNCTION gcf(a,x,gln)
- IMPLICIT NONE
- REAL(DP), INTENT(IN) :: a,x
- REAL(DP), OPTIONAL, INTENT(OUT) :: gln
- REAL(DP) :: gcf
- INTEGER(I4B), PARAMETER :: ITMAX=100
- REAL(DP), PARAMETER :: EPS=epsilon(x),FPMIN=tiny(x)/EPS
- INTEGER(I4B) :: i
- REAL(DP) :: an,b,c,d,del,h
- if (x == 0.0) then
+  else
+  gammp=1.0_rkind-gcf(a,x)
+  end if
+END FUNCTION gammp
+
+
+! ******************************************************************************************************************************
+! private function gcf: continued fraction development of the incomplete Gamma function
+! ******************************************************************************************************************************
+FUNCTION gcf(a,x,gln)
+  IMPLICIT NONE
+  real(rkind), INTENT(IN) :: a,x
+  real(rkind), OPTIONAL, INTENT(OUT) :: gln
+  real(rkind) :: gcf
+  INTEGER(I4B), PARAMETER :: ITMAX=100
+  real(rkind), PARAMETER :: EPS=epsilon(x),FPMIN=tiny(x)/EPS
+  INTEGER(I4B) :: i
+  real(rkind) :: an,b,c,d,del,h
+  if (x == 0.0) then
   gcf=1.0
   RETURN
- end if
- b=x+1.0_dp-a
- c=1.0_dp/FPMIN
- d=1.0_dp/b
- h=d
- do i=1,ITMAX
+  end if
+  b=x+1.0_rkind-a
+  c=1.0_rkind/FPMIN
+  d=1.0_rkind/b
+  h=d
+  do i=1,ITMAX
   an=-i*(i-a)
-  b=b+2.0_dp
+  b=b+2.0_rkind
   d=an*d+b
   if (abs(d) < FPMIN) d=FPMIN
   c=b+an/c
   if (abs(c) < FPMIN) c=FPMIN
-  d=1.0_dp/d
+  d=1.0_rkind/d
   del=d*c
   h=h*del
-  if (abs(del-1.0_dp) <= EPS) exit
- end do
- if (i > ITMAX) stop 'a too large, ITMAX too small in gcf'
- if (present(gln)) then
+  if (abs(del-1.0_rkind) <= EPS) exit
+  end do
+  if (i > ITMAX) stop 'a too large, ITMAX too small in gcf'
+  if (present(gln)) then
   gln=gammln(a)
   gcf=exp(-x+a*log(x)-gln)*h
- else
+  else
   gcf=exp(-x+a*log(x)-gammln(a))*h
- end if
- END FUNCTION gcf
-
-
- ! ******************************************************************************************************************************
- ! private function gser: series development of the incomplete Gamma function
- ! ******************************************************************************************************************************
- FUNCTION gser(a,x,gln)
- IMPLICIT NONE
- REAL(DP), INTENT(IN) :: a,x
- REAL(DP), OPTIONAL, INTENT(OUT) :: gln
- REAL(DP) :: gser
- INTEGER(I4B), PARAMETER :: ITMAX=100
- REAL(DP), PARAMETER :: EPS=epsilon(x)
- INTEGER(I4B) :: n
- REAL(DP) :: ap,del,summ
- if (x == 0.0) then
+  end if
+END FUNCTION gcf
+
+
+! ******************************************************************************************************************************
+! private function gser: series development of the incomplete Gamma function
+! ******************************************************************************************************************************
+FUNCTION gser(a,x,gln)
+  IMPLICIT NONE
+  real(rkind), INTENT(IN) :: a,x
+  real(rkind), OPTIONAL, INTENT(OUT) :: gln
+  real(rkind) :: gser
+  INTEGER(I4B), PARAMETER :: ITMAX=100
+  real(rkind), PARAMETER :: EPS=epsilon(x)
+  INTEGER(I4B) :: n
+  real(rkind) :: ap,del,summ
+  if (x == 0.0) then
   gser=0.0
   RETURN
- end if
- ap=a
- summ=1.0_dp/a
- del=summ
- do n=1,ITMAX
-  ap=ap+1.0_dp
+  end if
+  ap=a
+  summ=1.0_rkind/a
+  del=summ
+  do n=1,ITMAX
+  ap=ap+1.0_rkind
   del=del*x/ap
   summ=summ+del
   if (abs(del) < abs(summ)*EPS) exit
- end do
- if (n > ITMAX) stop 'a too large, ITMAX too small in gser'
- if (present(gln)) then
+  end do
+  if (n > ITMAX) stop 'a too large, ITMAX too small in gser'
+  if (present(gln)) then
   gln=gammln(a)
   gser=summ*exp(-x+a*log(x)-gln)
- else
+  else
   gser=summ*exp(-x+a*log(x)-gammln(a))
- end if
- END FUNCTION gser
-
-
- ! ******************************************************************************************************************************
- ! private function gammln: gamma function
- ! ******************************************************************************************************************************
- FUNCTION gammln(xx)
- USE nr_utility_module,only:arth  ! use to build vectors with regular increments
- IMPLICIT NONE
- REAL(DP), INTENT(IN) :: xx
- REAL(DP) :: gammln
- REAL(DP) :: tmp,x
- REAL(DP) :: stp = 2.5066282746310005_dp
- REAL(DP), DIMENSION(6) :: coef = (/76.18009172947146_dp,&
-  -86.50532032941677_dp,24.01409824083091_dp,&
-  -1.231739572450155_dp,0.1208650973866179e-2_dp,&
-  -0.5395239384953e-5_dp/)
- if(xx <= 0._dp) stop 'xx > 0 in gammln'
- x=xx
- tmp=x+5.5_dp
- tmp=(x+0.5_dp)*log(tmp)-tmp
- gammln=tmp+log(stp*(1.000000000190015_dp+&
-  sum(coef(:)/arth(x+1.0_dp,1.0_dp,size(coef))))/x)
- END FUNCTION gammln
+  end if
+END FUNCTION gser
+
+
+! ******************************************************************************************************************************
+! private function gammln: gamma function
+! ******************************************************************************************************************************
+FUNCTION gammln(xx)
+  USE nr_utility_module,only:arth  ! use to build vectors with regular increments
+  IMPLICIT NONE
+  real(rkind), INTENT(IN) :: xx
+  real(rkind) :: gammln
+  real(rkind) :: tmp,x
+  real(rkind) :: stp = 2.5066282746310005_rkind
+  real(rkind), DIMENSION(6) :: coef = (/76.18009172947146_rkind,&
+                                        -86.50532032941677_rkind,24.01409824083091_rkind,&
+                                        -1.231739572450155_rkind,0.1208650973866179e-2_rkind,&
+                                        -0.5395239384953e-5_rkind/)
+  if(xx <= 0._rkind) stop 'xx > 0 in gammln'
+  x=xx
+  tmp=x+5.5_rkind
+  tmp=(x+0.5_rkind)*log(tmp)-tmp
+  gammln=tmp+log(stp*(1.000000000190015_rkind+&
+  sum(coef(:)/arth(x+1.0_rkind,1.0_rkind,size(coef))))/x)
+END FUNCTION gammln
 
 
 end module soil_utils_module
diff --git a/build/source/engine/updatState.f90 b/build/source/engine/updatState.f90
index 698c8b1cdb9a32d8f9e92ed9cfb8c3292e33b124..29c82f15b4188c39e394b705f10457e5c27ba93b 100755
--- a/build/source/engine/updatState.f90
+++ b/build/source/engine/updatState.f90
@@ -35,121 +35,127 @@ public::updateSoil
 contains
 
 
- ! *************************************************************************************************************
- ! public subroutine updateSnow: compute phase change impacts on volumetric liquid water and ice
- ! *************************************************************************************************************
- subroutine updateSnow(&
-                       ! input
-                       mLayerTemp       ,& ! intent(in): temperature (K)
-                       mLayerTheta      ,& ! intent(in): volume fraction of total water (-)
-                       snowfrz_scale    ,& ! intent(in): scaling parameter for the snow freezing curve (K-1)
-                       ! output
-                       mLayerVolFracLiq ,& ! intent(out): volumetric fraction of liquid water (-)
-                       mLayerVolFracIce ,& ! intent(out): volumetric fraction of ice (-)
-                       fLiq             ,& ! intent(out): fraction of liquid water (-)
-                       err,message)        ! intent(out): error control
- ! utility routines
- USE snow_utils_module,only:fracliquid     ! compute volumetric fraction of liquid water
- implicit none
- ! input variables
- real(dp),intent(in)           :: mLayerTemp           ! temperature (K)
- real(dp),intent(in)           :: mLayerTheta          ! volume fraction of total water (-)
- real(dp),intent(in)           :: snowfrz_scale        ! scaling parameter for the snow freezing curve (K-1)
- ! output variables
- real(dp),intent(out)          :: mLayerVolFracLiq     ! volumetric fraction of liquid water (-)
- real(dp),intent(out)          :: mLayerVolFracIce     ! volumetric fraction of ice (-)
- real(dp),intent(out)          :: fLiq                 ! fraction of liquid water (-)
- ! error control
- integer(i4b),intent(out)      :: err                  ! error code
- character(*),intent(out)      :: message              ! error message
- ! initialize error control
- err=0; message="updateSnow/"
-
- ! compute the volumetric fraction of liquid water and ice (-)
- fLiq = fracliquid(mLayerTemp,snowfrz_scale)
- mLayerVolFracLiq = fLiq*mLayerTheta
- mLayerVolFracIce = (1._dp - fLiq)*mLayerTheta*(iden_water/iden_ice)
- !print*, 'mLayerTheta - (mLayerVolFracIce*(iden_ice/iden_water) + mLayerVolFracLiq) = ', mLayerTheta - (mLayerVolFracIce*(iden_ice/iden_water) + mLayerVolFracLiq)
- !write(*,'(a,1x,4(f20.10,1x))') 'in updateSnow: fLiq, mLayerTheta, mLayerVolFracIce = ', &
- !                                               fLiq, mLayerTheta, mLayerVolFracIce
- !pause
-
- end subroutine updateSnow
-
- ! *************************************************************************************************************
- ! public subroutine updateSoil: compute phase change impacts on matric head and volumetric liquid water and ice
- ! *************************************************************************************************************
- subroutine updateSoil(&
-                       ! input
-                       mLayerTemp       ,& ! intent(in): temperature vector (K)
-                       mLayerMatricHead ,& ! intent(in): matric head (m)
-                       vGn_alpha        ,& ! intent(in): van Genutchen "alpha" parameter
-                       vGn_n            ,& ! intent(in): van Genutchen "n" parameter
-                       theta_sat        ,& ! intent(in): soil porosity (-)
-                       theta_res        ,& ! intent(in): soil residual volumetric water content (-)
-                       vGn_m            ,& ! intent(in): van Genutchen "m" parameter (-)
-                       ! output
-                       mLayerVolFracWat ,& ! intent(out): volumetric fraction of total water (-)
-                       mLayerVolFracLiq ,& ! intent(out): volumetric fraction of liquid water (-)
-                       mLayerVolFracIce ,& ! intent(out): volumetric fraction of ice (-)
-                       err,message)        ! intent(out): error control
- ! utility routines
- USE soil_utils_module,only:volFracLiq     ! compute volumetric fraction of liquid water based on matric head
- USE soil_utils_module,only:matricHead     ! compute the matric head based on volumetric liquid water content
- implicit none
- ! input variables
- real(dp),intent(in)           :: mLayerTemp           ! estimate of temperature (K)
- real(dp),intent(in)           :: mLayerMatricHead     ! matric head (m)
- real(dp),intent(in)           :: vGn_alpha            ! van Genutchen "alpha" parameter
- real(dp),intent(in)           :: vGn_n                ! van Genutchen "n" parameter
- real(dp),intent(in)           :: theta_sat            ! soil porosity (-)
- real(dp),intent(in)           :: theta_res            ! soil residual volumetric water content (-)
- real(dp),intent(in)           :: vGn_m                ! van Genutchen "m" parameter (-)
- ! output variables
- real(dp),intent(out)          :: mLayerVolFracWat     ! fractional volume of total water (-)
- real(dp),intent(out)          :: mLayerVolFracLiq     ! volumetric fraction of liquid water (-)
- real(dp),intent(out)          :: mLayerVolFracIce     ! volumetric fraction of ice (-)
- integer(i4b),intent(out)      :: err                  ! error code
- character(*),intent(out)      :: message              ! error message
- ! define local variables
- real(dp)                      :: TcSoil               ! critical soil temperature when all water is unfrozen (K)
- real(dp)                      :: xConst               ! constant in the freezing curve function (m K-1)
- real(dp)                      :: mLayerPsiLiq         ! liquid water matric potential (m)
- ! initialize error control
- err=0; message="updateSoil/"
-
- ! compute fractional **volume** of total water (liquid plus ice)
- mLayerVolFracWat = volFracLiq(mLayerMatricHead,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
- if(mLayerVolFracWat > theta_sat)then; err=20; message=trim(message)//'volume of liquid and ice exceeds porosity'; return; end if
-
- ! compute the critical soil temperature where all water is unfrozen (K)
- ! (eq 17 in Dall'Amico 2011)
- TcSoil = Tfreeze + min(mLayerMatricHead,0._dp)*gravity*Tfreeze/LH_fus  ! (NOTE: J = kg m2 s-2, so LH_fus is in units of m2 s-2)
-
- ! *** compute volumetric fraction of liquid water and ice for partially frozen soil
- if(mLayerTemp < TcSoil)then ! (check if soil temperature is less than the critical temperature)
-
-  ! - volumetric liquid water content (-)
-  ! NOTE: mLayerPsiLiq is the liquid water matric potential from the Clapeyron equation, used to separate the total water into liquid water and ice
-  !       mLayerPsiLiq is DIFFERENT from the liquid water matric potential used in the flux calculations
-  xConst           = LH_fus/(gravity*Tfreeze)        ! m K-1 (NOTE: J = kg m2 s-2)
-  mLayerPsiLiq     = xConst*(mLayerTemp - Tfreeze)   ! liquid water matric potential from the Clapeyron eqution
-  mLayerVolFracLiq = volFracLiq(mLayerPsiLiq,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
-
-  ! - volumetric ice content (-)
-  mLayerVolFracIce = mLayerVolFracWat - mLayerVolFracLiq
-
- ! *** compute volumetric fraction of liquid water and ice for unfrozen soil
- else
-
-  ! all water is unfrozen
-  mLayerPsiLiq     = mLayerMatricHead
-  mLayerVolFracLiq = mLayerVolFracWat
-  mLayerVolFracIce = 0._dp
-
- end if  ! (check if soil is partially frozen)
-
- end subroutine updateSoil
-
-
-end module updatState_module
+! *************************************************************************************************************
+! public subroutine updateSnow: compute phase change impacts on volumetric liquid water and ice (veg or soil)
+! *************************************************************************************************************
+subroutine updateSnow(&
+                  ! input
+                  mLayerTemp       ,& ! intent(in): temperature (K)
+                  mLayerTheta      ,& ! intent(in): volume fraction of total water (-)
+                  snowfrz_scale    ,& ! intent(in): scaling parameter for the snow freezing curve (K-1)
+                  ! output
+                  mLayerVolFracLiq ,& ! intent(out): volumetric fraction of liquid water (-)
+                  mLayerVolFracIce ,& ! intent(out): volumetric fraction of ice (-)
+                  fLiq             ,& ! intent(out): fraction of liquid water (-)
+                  err,message)        ! intent(out): error control
+  ! utility routines
+  USE snow_utils_module,only:fracliquid     ! compute volumetric fraction of liquid water
+  implicit none
+  ! input variables
+  real(rkind),intent(in)           :: mLayerTemp              ! temperature (K)
+  real(rkind),intent(in)           :: mLayerTheta             ! volume fraction of total water (-)
+  real(rkind),intent(in)           :: snowfrz_scale           ! scaling parameter for the snow freezing curve (K-1)
+  ! output variables
+  real(rkind),intent(out)          :: mLayerVolFracLiq        ! volumetric fraction of liquid water (-)
+  real(rkind),intent(out)          :: mLayerVolFracIce        ! volumetric fraction of ice (-)
+  real(rkind),intent(out)          :: fLiq                    ! fraction of liquid water (-)
+  ! error control
+  integer(i4b),intent(out)      :: err                     ! error code
+  character(*),intent(out)      :: message                 ! error message
+  ! initialize error control
+  err=0; message="updateSnow/"
+
+  ! compute the volumetric fraction of liquid water and ice (-)
+  fLiq = fracliquid(mLayerTemp,snowfrz_scale)
+  mLayerVolFracLiq = fLiq*mLayerTheta
+  mLayerVolFracIce = (1._rkind - fLiq)*mLayerTheta*(iden_water/iden_ice)
+end subroutine updateSnow
+
+! *************************************************************************************************************
+! public subroutine updateSoil: compute phase change impacts on matric head and volumetric liquid water and ice
+! *************************************************************************************************************
+subroutine updateSoil(&
+                      ! input
+                      mLayerTemp       ,& ! intent(in): temperature vector (K)
+                      mLayerMatricHead ,& ! intent(in): matric head (m)
+                      vGn_alpha        ,& ! intent(in): van Genutchen "alpha" parameter
+                      vGn_n            ,& ! intent(in): van Genutchen "n" parameter
+                      theta_sat        ,& ! intent(in): soil porosity (-)
+                      theta_res        ,& ! intent(in): soil residual volumetric water content (-)
+                      vGn_m            ,& ! intent(in): van Genutchen "m" parameter (-)
+                      ! output
+                      mLayerVolFracWat ,& ! intent(out): volumetric fraction of total water (-)
+                      mLayerVolFracLiq ,& ! intent(out): volumetric fraction of liquid water (-)
+                      mLayerVolFracIce ,& ! intent(out): volumetric fraction of ice (-)
+                      err,message)        ! intent(out): error control
+  ! utility routines
+  USE soil_utils_module,only:volFracLiq     ! compute volumetric fraction of liquid water based on matric head
+  USE soil_utils_module,only:matricHead     ! compute the matric head based on volumetric liquid water content
+  implicit none
+  ! input variables
+  real(rkind),intent(in)           :: mLayerTemp           ! estimate of temperature (K)
+  real(rkind),intent(in)           :: mLayerMatricHead     ! matric head (m)
+  real(rkind),intent(in)           :: vGn_alpha            ! van Genutchen "alpha" parameter
+  real(rkind),intent(in)           :: vGn_n                ! van Genutchen "n" parameter
+  real(rkind),intent(in)           :: theta_sat            ! soil porosity (-)
+  real(rkind),intent(in)           :: theta_res            ! soil residual volumetric water content (-)
+  real(rkind),intent(in)           :: vGn_m                ! van Genutchen "m" parameter (-)
+  ! output variables
+  real(rkind),intent(out)          :: mLayerVolFracWat     ! fractional volume of total water (-)
+  real(rkind),intent(out)          :: mLayerVolFracLiq     ! volumetric fraction of liquid water (-)
+  real(rkind),intent(out)          :: mLayerVolFracIce     ! volumetric fraction of ice (-)
+  integer(i4b),intent(out)      :: err                  ! error code
+  character(*),intent(out)      :: message              ! error message
+  ! define local variables
+  real(rkind)                      :: TcSoil               ! critical soil temperature when all water is unfrozen (K)
+  real(rkind)                      :: xConst               ! constant in the freezing curve function (m K-1)
+  real(rkind)                      :: mLayerPsiLiq         ! liquid water matric potential (m)
+  real(rkind),parameter            :: tinyVal=epsilon(1._rkind) ! used in balance check
+  ! initialize error control
+  err=0; message="updateSoil/"
+
+  ! compute fractional **volume** of total water (liquid plus ice)
+  mLayerVolFracWat = volFracLiq(mLayerMatricHead,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+  if(mLayerVolFracWat > (theta_sat + tinyVal)) then
+    err=20
+    message=trim(message)//'volume of liquid and ice (mLayerVolFracWat) exceeds porosity'
+    print*, 'mLayerVolFracWat     = ', mLayerVolFracWat
+    print*, 'theta_sat (porosity) = ', theta_sat
+    print*, 'mLayerMatricHead     = ', mLayerMatricHead
+    print*, 'theta_res            = ', theta_res
+    print*, 'vGn_alpha            = ', vGn_alpha
+    print*, 'vGn_n                = ', vGn_n
+    print*, 'vGn_m                = ', vGn_m
+    return
+  end if
+
+  ! compute the critical soil temperature where all water is unfrozen (K)
+  ! (eq 17 in Dall'Amico 2011)
+  TcSoil = Tfreeze + min(mLayerMatricHead,0._rkind)*gravity*Tfreeze/LH_fus  ! (NOTE: J = kg m2 s-2, so LH_fus is in units of m2 s-2)
+
+  ! *** compute volumetric fraction of liquid water and ice for partially frozen soil
+  if(mLayerTemp < TcSoil)then ! (check if soil temperature is less than the critical temperature)
+
+    ! - volumetric liquid water content (-)
+    ! NOTE: mLayerPsiLiq is the liquid water matric potential from the Clapeyron equation, used to separate the total water into liquid water and ice
+    !       mLayerPsiLiq is DIFFERENT from the liquid water matric potential used in the flux calculations
+    xConst           = LH_fus/(gravity*Tfreeze)        ! m K-1 (NOTE: J = kg m2 s-2)
+    mLayerPsiLiq     = xConst*(mLayerTemp - Tfreeze)   ! liquid water matric potential from the Clapeyron eqution
+    mLayerVolFracLiq = volFracLiq(mLayerPsiLiq,vGn_alpha,theta_res,theta_sat,vGn_n,vGn_m)
+
+    ! - volumetric ice content (-)
+    mLayerVolFracIce = mLayerVolFracWat - mLayerVolFracLiq
+
+  ! *** compute volumetric fraction of liquid water and ice for unfrozen soil
+  else
+
+    ! all water is unfrozen
+    mLayerPsiLiq     = mLayerMatricHead
+    mLayerVolFracLiq = mLayerVolFracWat
+    mLayerVolFracIce = 0._rkind
+
+  end if  ! (check if soil is partially frozen)
+
+end subroutine updateSoil
+
+end module updatState_module
\ No newline at end of file