From eab9be49d857969ffd73498a05ed566b090ca457 Mon Sep 17 00:00:00 2001
From: Kyle <kyle.c.klenk@gmail.com>
Date: Tue, 27 Sep 2022 18:02:49 +0000
Subject: [PATCH] Can run the celia and colbeck tests

---
 build/makefile_sundials                       |   11 +-
 build/source/actors/job_actor/job_actor.f90   |    2 +-
 build/source/driver/init_hru_actor.f90        |    4 +-
 build/source/engine/allocspaceActors.f90      |    4 +-
 build/source/engine/coupled_em.f90            |    4 +-
 build/source/engine/eval8summa.f90            | 1096 ++++----
 build/source/engine/ffile_info.f90            |    2 +-
 build/source/engine/getVectorz.f90            |  880 +++----
 build/source/engine/opSplittin.f90            | 2330 ++++++++---------
 .../engine/sundials/computJacobSundials.f90   | 2055 +++++++--------
 build/source/engine/sundials/eval8JacDAE.f90  |  343 +++
 .../engine/sundials/eval8summaSundials.f90    | 1548 +++++------
 build/source/engine/sundials/evalDAE4IDA.f90  |  165 ++
 build/source/engine/sundials/evalJac4IDA.f90  |  132 +
 .../engine/sundials/getVectorzAddSundials.f90 |  488 ++--
 .../engine/sundials/summaSolveSundialsIDA.f90 | 1344 +++++-----
 .../engine/sundials/systemSolvSundials.f90    | 1076 ++++----
 .../engine/sundials/varSubstepSundials.f90    | 1909 +++++++-------
 build/source/engine/systemSolv.f90            |    2 +-
 build/source/engine/varSubstep.f90            | 1021 ++++----
 .../BE/colbeck1976/run_test_summa_actors.sh   |    4 +-
 21 files changed, 7309 insertions(+), 7111 deletions(-)
 create mode 100644 build/source/engine/sundials/eval8JacDAE.f90
 create mode 100644 build/source/engine/sundials/evalDAE4IDA.f90
 create mode 100644 build/source/engine/sundials/evalJac4IDA.f90

diff --git a/build/makefile_sundials b/build/makefile_sundials
index 583ee6d..d159927 100644
--- a/build/makefile_sundials
+++ b/build/makefile_sundials
@@ -19,10 +19,10 @@ ACTORS_LIBRARIES = -L/usr/lib -L/usr/local/lib -L/Summa-Actors/bin -lcaf_core -l
 
 
 # Production runs
-FLAGS_NOAH = -g -O0 -ffree-form -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
-FLAGS_COMM = -g -O0 -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
-FLAGS_SUMMA = -g -O0 -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
-FLAGS_ACTORS = -g -O0 -Wfatal-errors -std=c++17
+FLAGS_NOAH = -g -O3 -ffree-form -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
+FLAGS_COMM = -g -O3 -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
+FLAGS_SUMMA = -g -O3 -ffree-line-length-none -fmax-errors=0 -fPIC -Wfatal-errors
+FLAGS_ACTORS = -g -O3 -Wfatal-errors -std=c++17
 
 # Debug runs
 # FLAGS_NOAH = -g -O0 -ffree-form -ffree-line-length-none -fmax-errors=0 -fbacktrace -Wno-unused -Wno-unused-dummy-argument -fPIC
@@ -140,7 +140,10 @@ SUMMA_SOLVER= \
 		sundials/computThermConduct.f90 \
 		sundials/computResidSundials.f90 \
 		sundials/eval8summaSundials.f90 \
+		sundials/evalDAE4IDA.f90 \
 		sundials/computJacobSundials.f90 \
+		sundials/eval8JacDAE.f90 \
+		sundials/evalJac4IDA.f90 \
 		sundials/computSnowDepth.f90 \
 		sundials/summaSolveSundialsIDA.f90 \
 		sundials/systemSolvSundials.f90 \
diff --git a/build/source/actors/job_actor/job_actor.f90 b/build/source/actors/job_actor/job_actor.f90
index eaffeb8..18f5fb7 100644
--- a/build/source/actors/job_actor/job_actor.f90
+++ b/build/source/actors/job_actor/job_actor.f90
@@ -10,7 +10,7 @@ module job_actor
 
 subroutine allocateTimeStructure(err) bind(C, name="allocateTimeStructure")
     USE globalData,only:startTime,finshTime,refTime,oldTime
-    USE allocspace4chm_module,only:allocLocal
+    USE allocspace_module,only:allocLocal
     USE globalData,only:time_meta
 
     implicit none
diff --git a/build/source/driver/init_hru_actor.f90 b/build/source/driver/init_hru_actor.f90
index 961c385..cc4c37c 100755
--- a/build/source/driver/init_hru_actor.f90
+++ b/build/source/driver/init_hru_actor.f90
@@ -83,8 +83,8 @@ contains
   USE nrtype                                                  ! variable types, etc.
   USE time_utils_module,only:elapsedSec                       ! calculate the elapsed time
   ! subroutines and functions: allocate space
-  USE allocspace4chm_module,only:allocGlobal              ! module to allocate space for global data structures
-  USE allocspace4chm_module,only:allocLocal
+  USE allocspace_module,only:allocGlobal              ! module to allocate space for global data structures
+  USE allocspace_module,only:allocLocal
   ! timing variables
   USE globalData,only:startInit,endInit                       ! date/time for the start and end of the initialization
   USE globalData,only:elapsedRead                             ! elapsed time for the data read
diff --git a/build/source/engine/allocspaceActors.f90 b/build/source/engine/allocspaceActors.f90
index fcc3074..b2635b7 100755
--- a/build/source/engine/allocspaceActors.f90
+++ b/build/source/engine/allocspaceActors.f90
@@ -18,7 +18,7 @@
 ! You should have received a copy of the GNU General Public License
 ! along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-module allocspace4chm_module
+module allocspace_module
 
 ! data types
 USE nrtype
@@ -637,4 +637,4 @@ contains
 
  end subroutine allocateDat_flag
 
-end module allocspace4chm_module
+end module allocspace_module
diff --git a/build/source/engine/coupled_em.f90 b/build/source/engine/coupled_em.f90
index 5891dac..f11a0a8 100755
--- a/build/source/engine/coupled_em.f90
+++ b/build/source/engine/coupled_em.f90
@@ -123,8 +123,8 @@ subroutine coupled_em(&
                        ! error control
                        err,message)         ! intent(out):   error control
   ! structure allocations
-  USE allocspace4chm_module,only:allocLocal      ! allocate local data structures
-  USE allocspace4chm_module,only:resizeData      ! clone a data structure
+  USE allocspace_module,only:allocLocal      ! allocate local data structures
+  USE allocspace_module,only:resizeData      ! clone a data structure
   ! preliminary subroutines
   USE vegPhenlgy_module,only:vegPhenlgy      ! compute vegetation phenology
   USE vegNrgFlux_module,only:wettedFrac      ! compute wetted fraction of the canopy (used in sw radiation fluxes)
diff --git a/build/source/engine/eval8summa.f90 b/build/source/engine/eval8summa.f90
index 2c198cf..e6882cd 100755
--- a/build/source/engine/eval8summa.f90
+++ b/build/source/engine/eval8summa.f90
@@ -20,562 +20,570 @@
 
 module eval8summa_module
 
-  ! data types
-  USE nrtype
-  
-  ! 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 the global print flag
-  USE globalData,only:globalPrintFlag
-  
-  ! define access to state variables to print
-  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_veg       ! named variables for vegetation
-  USE globalData,only:iname_snow      ! named variables for snow
-  USE globalData,only:iname_soil      ! named variables for soil
-  
-  ! named variables to describe the state variable type
-  USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
-  USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
-  USE globalData,only:iname_watCanopy ! named variable defining the mass of 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
-  
-  ! constants
-  USE multiconst,only:&
-                      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 the derived types to define the data structures
-  USE data_types,only:&
-                      var_i,        & ! data vector (i4b)
-                      var_d,        & ! data vector (rkind)
-                      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
-  
-  ! indices that define elements of the data structures
-  USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
-  USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
-  USE var_lookup,only:iLookPROG                    ! named variables for structure elements
-  USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
-  
-  ! 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
-  
-  ! look-up values for the form of Richards' equation
-  USE mDecisions_module,only:  &
-   moisture,                   & ! moisture-based form of Richards' equation
-   mixdform                      ! mixed form of Richards' equation
-  
+! data types
+USE nrtype
+
+! 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 the global print flag
+USE globalData,only:globalPrintFlag
+
+! define access to state variables to print
+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_veg       ! named variables for vegetation
+USE globalData,only:iname_snow      ! named variables for snow
+USE globalData,only:iname_soil      ! named variables for soil
+
+! named variables to describe the state variable type
+USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
+USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
+USE globalData,only:iname_watCanopy ! named variable defining the mass of 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
+
+! constants
+USE multiconst,only:&
+                    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 the derived types to define the data structures
+USE data_types,only:&
+                    var_i,        & ! data vector (i4b)
+                    var_d,        & ! data vector (rkind)
+                    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
+
+! indices that define elements of the data structures
+USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
+USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
+USE var_lookup,only:iLookPROG                    ! named variables for structure elements
+USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
+
+! 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
+
+! look-up values for the form of Richards' equation
+USE mDecisions_module,only:  &
+  moisture,                   & ! moisture-based form of Richards' equation
+  mixdform                      ! mixed form of Richards' equation
+
+implicit none
+private
+public::eval8summa
+
+contains
+
+
+! **********************************************************************************************************
+! public subroutine eval8summa: compute the residual vector and the Jacobian matrix
+! **********************************************************************************************************
+subroutine eval8summa(&
+                      ! input: model control
+                      dt,                      & ! intent(in):    length of the time step (seconds)
+                      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
+                      firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                      firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
+                      firstSplitOper,          & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                      computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                      ! input: state vectors
+                      stateVecTrial,           & ! intent(in):    model state vector
+                      fScale,                  & ! intent(in):    function scaling vector
+                      sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
+                      ! input: 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
+                      mpar_data,               & ! intent(in):    model parameters
+                      forc_data,               & ! intent(in):    model forcing data
+                      bvar_data,               & ! intent(in):    average model variables for the entire basin
+                      prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                      ! input-output: data structures
+                      indx_data,               & ! intent(inout): index data
+                      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
+                      ! input-output: baseflow
+                      ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                      dBaseflow_dMatric,       & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
+                      ! output: flux and residual vectors
+                      feasible,                & ! intent(out):   flag to denote the feasibility of the solution
+                      fluxVec,                 & ! intent(out):   flux vector
+                      resSink,                 & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                      resVec,                  & ! intent(out):   residual vector
+                      fEval,                   & ! intent(out):   function evaluation
+                      err,message)               ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! provide access to subroutines
+  USE getVectorz_module, only:varExtract           ! extract variables from the state vector
+  USE updateVars_module, only:updateVars           ! update prognostic variables
+  USE t2enthalpy_module, only:t2enthalpy           ! compute enthalpy
+  USE computFlux_module, only:soilCmpres           ! compute soil compression, use non-sundials version because sundials version needs mLayerMatricHeadPrime
+  USE computFlux_module, only:computFlux           ! compute fluxes given a state vector
+  USE computResid_module,only:computResid          ! compute residuals given a state vector
   implicit none
-  private
-  public::eval8summa
-  
-  contains
-  
-  
-   ! **********************************************************************************************************
-   ! public subroutine eval8summa: compute the residual vector and the Jacobian matrix
-   ! **********************************************************************************************************
-   subroutine eval8summa(&
-                         ! input: model control
-                         dt,                      & ! intent(in):    length of the time step (seconds)
-                         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
-                         firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                         firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
-                         firstSplitOper,          & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
-                         computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                         scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                         ! input: state vectors
-                         stateVecTrial,           & ! intent(in):    model state vector
-                         fScale,                  & ! intent(in):    function scaling vector
-                         sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
-                         ! input: 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
-                         mpar_data,               & ! intent(in):    model parameters
-                         forc_data,               & ! intent(in):    model forcing data
-                         bvar_data,               & ! intent(in):    average model variables for the entire basin
-                         prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                         ! input-output: data structures
-                         indx_data,               & ! intent(inout): index data
-                         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
-                         ! input-output: baseflow
-                         ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                         dBaseflow_dMatric,       & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
-                         ! output: flux and residual vectors
-                         feasible,                & ! intent(out):   flag to denote the feasibility of the solution
-                         fluxVec,                 & ! intent(out):   flux vector
-                         resSink,                 & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                         resVec,                  & ! intent(out):   residual vector
-                         fEval,                   & ! intent(out):   function evaluation
-                         err,message)               ! intent(out):   error control
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! provide access to subroutines
-   USE getVectorz_module, only:varExtract           ! extract variables from the state vector
-   USE updateVars_module, only:updateVars           ! update prognostic variables
-   USE t2enthalpy_module, only:t2enthalpy           ! compute enthalpy
-   USE computFlux_module, only:soilCmpres           ! compute soil compression, use non-sundials version because sundials version needs mLayerMatricHeadPrime
-   USE computFlux_module, only:computFlux           ! compute fluxes given a state vector
-   USE computResid_module,only:computResid          ! compute residuals given a state vector
-   implicit none
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! input: model control
-   real(rkind),intent(in)             :: dt                     ! length of the time step (seconds)
-   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
-   logical(lgt),intent(in)         :: firstSubStep           ! flag to indicate if we are processing the first sub-step
-   logical(lgt),intent(inout)      :: firstFluxCall          ! flag to indicate if we are processing the first flux call
-   logical(lgt),intent(in)         :: firstSplitOper         ! flag to indicate if we are processing the first flux call in a splitting operation
-   logical(lgt),intent(in)         :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
-   logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
-   ! input: state vectors
-   real(rkind),intent(in)             :: stateVecTrial(:)       ! model state vector
-   real(rkind),intent(in)             :: fScale(:)              ! function scaling vector
-   real(rkind),intent(in)             :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
-   ! input: data structures
-   type(model_options),intent(in)  :: model_decisions(:)     ! model decisions
-   type(zLookup),      intent(in)  :: lookup_data            ! lookup tables
-   type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
-   type(var_d),        intent(in)  :: attr_data              ! spatial attributes
-   type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
-   type(var_d),        intent(in)  :: forc_data              ! model forcing data
-   type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
-   type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
-   ! output: data structures
-   type(var_ilength),intent(inout) :: indx_data              ! indices defining model states and layers
-   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(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
-   ! input-output: baseflow
-   integer(i4b),intent(inout)      :: ixSaturation           ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
-   real(rkind),intent(out)            :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
-   ! output: flux and residual vectors
-   logical(lgt),intent(out)        :: feasible               ! flag to denote the feasibility of the solution
-   real(rkind),intent(out)            :: fluxVec(:)             ! flux vector
-   real(rkind),intent(out)            :: resSink(:)             ! sink terms on the RHS of the flux equation
-   real(rkind),intent(out)            :: resVec(:) ! NOTE: qp   ! residual vector
-   real(rkind),intent(out)            :: fEval                  ! function evaluation
-   ! output: error control
-   integer(i4b),intent(out)        :: err                    ! error code
-   character(*),intent(out)        :: message                ! error message
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! local variables
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! state variables
-   real(rkind)                        :: scalarCanairTempTrial     ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatTrial      ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempTrial           ! trial value for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial     ! trial value for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial     ! trial value for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial  ! trial value for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStorageTrial ! trial value of storage of water in the aquifer (m)
-   ! diagnostic variables
-   logical(lgt),parameter          :: needEnthalpy=.true.      ! flag to compute enthalpy
-   real(rkind)                        :: scalarCanopyLiqTrial      ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial     ! trial value for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial     ! trial value for volumetric fraction of ice (-)
-   ! other local variables
-   integer(i4b)                    :: iLayer                    ! index of model layer in the snow+soil domain
-   integer(i4b)                    :: jState(1)                 ! index of model state for the scalar solution within the soil domain
-   integer(i4b)                    :: ixBeg,ixEnd               ! index of indices for the soil compression routine
-   integer(i4b),parameter          :: ixVegVolume=1             ! index of the desired vegetation control volumne (currently only one veg layer)
-   real(rkind)                        :: xMin,xMax                 ! minimum and maximum values for water content
-   real(rkind)                        :: scalarCanopyHydTrial      ! trial value for mass of water on the vegetation canopy (kg m-2)
-   real(rkind),parameter              :: canopyTempMax=500._rkind     ! expected maximum value for the canopy temperature (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracHydTrial     ! trial value for volumetric fraction of water (-), general vector merged from Wat and Liq
-   real(rkind),dimension(nState)      :: rVecScaled                ! scaled residual vector
-   character(LEN=256)              :: cmessage                  ! error message of downwind routine
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   associate(&
-   ! model decisions
-   ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
-   ! snow parameters
-   snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,&  ! intent(in):  [dp]    scaling parameter for the snow freezing curve (K-1)
-   ! soil parameters
-   theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
-   theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
-   specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
-   ! canopy and layer depth
-   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)
-   ! model state variables from a previous solution
-   mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(in):  [dp(:)]  total water matric potential (m)
-   ! model diagnostic variables from a previous solution
-   scalarSfcMeltPond       => prog_data%var(iLookPROG%scalarSfcMeltPond)%dat(1)      ,&  ! intent(in):  [dp]    ponded water caused by melt of the "snow without a layer" (kg m-2)
-   mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,&  ! intent(in):  [dp(:)] volumetric fraction of ice (-)
-   ! enthalpy
-   scalarCanairEnthalpy    => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the canopy air space (J m-3)
-   scalarCanopyEnthalpy    => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the vegetation canopy (J m-3)
-   mLayerEnthalpy          => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(out): [dp(:)] enthalpy of the snow+soil layers (J m-3)
-   ! soil compression
-   scalarSoilCompress      => diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1)     ,&  ! intent(in): [dp]    total change in storage associated with compression of the soil matrix (kg m-2)
-   mLayerCompress          => diag_data%var(iLookDIAG%mLayerCompress)%dat            ,&  ! intent(in): [dp(:)] change in storage associated with compression of the soil matrix (-)
-   ! derivatives
-   dVolTot_dPsi0           => deriv_data%var(iLookDERIV%dVolTot_dPsi0)%dat           ,&  ! intent(in): [dp(:)] derivative in total water content w.r.t. total water matric potential
-   dCompress_dPsi          => deriv_data%var(iLookDERIV%dCompress_dPsi)%dat          ,&  ! intent(in): [dp(:)] derivative in compressibility w.r.t. matric head (m-1)
-   ! mapping
-   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)
-   ! indices
-   ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy air space energy state variable (nrg)
-   ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy energy state variable (nrg)
-   ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy hydrology state variable (mass)
-   ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,&  ! intent(in): [i4b(:)] indices for energy states in the snow subdomain
-   ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,&  ! intent(in): [i4b(:)] indices for hydrology states in the snow+soil subdomain
-   ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,&  ! intent(in): [i4b(:)] indices defining the type of the state (iname_nrgLayer...)
-   ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,&  ! intent(in): [i4b(:)] index of the hydrology states in the canopy domain
-   ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,&  ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
-   layerType               => indx_data%var(iLookINDEX%layerType)%dat                 &  ! intent(in): [i4b(:)] layer type (iname_soil or iname_snow)
-   ) ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! initialize error control
-   err=0; message="eval8summa/"
-  
-   ! check the feasibility of the solution
-   feasible=.true.
-  
-   ! check that the canopy air space temperature is reasonable
-   if(ixCasNrg/=integerMissing)then
-    if(stateVecTrial(ixCasNrg) > canopyTempMax) feasible=.false.
-    if(stateVecTrial(ixCasNrg) > canopyTempMax) message=trim(message)//'canopy air space temp high,'
-    if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVecTrial( ixCasNrg )', feasible, canopyTempMax, stateVecTrial(ixCasNrg)
-   endif
-  
-   ! check that the canopy air space temperature is reasonable
-   if(ixVegNrg/=integerMissing)then
-    if(stateVecTrial(ixVegNrg) > canopyTempMax) feasible=.false.
-    if(stateVecTrial(ixVegNrg) > canopyTempMax) message=trim(message)//'canopy temp high,'
-    if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVecTrial( ixVegNrg )', feasible, canopyTempMax, stateVecTrial(ixVegNrg)
-   endif
-  
-   ! check canopy liquid water is not negative
-   if(ixVegHyd/=integerMissing)then
-    if(stateVecTrial(ixVegHyd) < 0._rkind) feasible=.false.
-     if(stateVecTrial(ixVegHyd) < 0._rkind) message=trim(message)//'canopy water negative,'
-     if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, min, stateVecTrial( ixVegHyd )', feasible, 0._rkind, stateVecTrial(ixVegHyd)
-  
-   end if
-  
-   ! check snow temperature is below freezing
-   if(count(ixSnowOnlyNrg/=integerMissing)>0)then
-    if(any(stateVecTrial( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) feasible=.false.
-    if(any(stateVecTrial( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) message=trim(message)//'snow temp above freezing,'
-    do iLayer=1,nSnow
-     if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, max, stateVecTrial( ixSnowOnlyNrg(iLayer) )', iLayer, feasible, Tfreeze, stateVecTrial( ixSnowOnlyNrg(iLayer) )
-    enddo
-   endif
-  
-   ! loop through non-missing hydrology state variables in the snow+soil domain
-   do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)
-  
-    ! check the minimum and maximum water constraints
-    if(ixHydType(iLayer)==iname_watLayer .or. ixHydType(iLayer)==iname_liqLayer)then
-  
-     ! --> minimum
-     if (layerType(iLayer) == iname_soil) then
-      xMin = theta_res(iLayer-nSnow)
-     else
-      xMin = 0._rkind
-     endif
-  
-     ! --> maximum
-     select case( layerType(iLayer) )
-      case(iname_snow); xMax = merge(iden_ice,  1._rkind - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
-      case(iname_soil); xMax = merge(theta_sat(iLayer-nSnow), theta_sat(iLayer-nSnow) - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
-     end select
-  
-     ! --> check
-     if(stateVecTrial( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVecTrial( ixSnowSoilHyd(iLayer) ) > xMax) feasible=.false.
-     if(stateVecTrial( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVecTrial( ixSnowSoilHyd(iLayer) ) > xMax)  message=trim(message)//'layer water outside bounds,'
-     if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, stateVecTrial( ixSnowSoilHyd(iLayer) ), xMin, xMax = ', iLayer, feasible, stateVecTrial( ixSnowSoilHyd(iLayer) ), xMin, xMax
-  
-    endif  ! if water states
-  
-   end do  ! loop through non-missing hydrology state variables in the snow+soil domain
-  
-   ! early return for non-feasible solutions
-   if(.not.feasible)then
-    fluxVec(:) = realMissing
-    resVec(:)  = quadMissing
-    fEval      = realMissing
-    message=trim(message)//'non-feasible'
-    err=20; return
-   endif
-  
-   ! get the start and end indices for the soil compression calculations
-   if(scalarSolution)then
-    jState = pack(ixControlVolume, ixMapFull2Subset/=integerMissing)
-    ixBeg  = jState(1)
-    ixEnd  = jState(1)
-   else
-    ixBeg  = 1
-    ixEnd  = nSoil
-   endif
-  
-   ! extract variables from the model state vector
-   call varExtract(&
-                   ! input
-                   stateVecTrial,            & ! intent(in):    model state vector (mixed units)
-                   diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
-                   prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                & ! intent(in):    indices defining model states and layers
-                   ! output: variables for the vegetation canopy
-                   scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
-                   scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIceTrial,     & ! intent(out):   trial value of canopy ice content (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
-                   mLayerVolFracIceTrial,    & ! intent(out):   trial vector of volumetric ice water content (-)
-                   mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
-                   ! output: variables for the aquifer
-                   scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
-                   ! output: error control
-                   err,cmessage)               ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! update diagnostic variables and derivatives
-   call updateVars(&
-                   ! input
-                   .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
-                   lookup_data,                               & ! intent(in):    lookup tables for a local HRU
-                   mpar_data,                                 & ! intent(in):    model parameters for a local HRU
-                   indx_data,                                 & ! intent(in):    indices defining model states and layers
-                   prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                   diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
-                   deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! output: variables for the vegetation canopy
-                   scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
-                   mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
-                   ! output: error control
-                   err,cmessage)                                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! compute enthalpy (J m-3)
-   if(needEnthalpy)then
-    call t2enthalpy(&
-                    ! input: data structures
-                    diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
-                    mpar_data,                   & ! intent(in):  parameter data structure
-                    indx_data,                   & ! intent(in):  model indices
-                    lookup_data,                 & ! intent(in):  lookup table data structure
-                    ! input: state variables for the vegetation canopy
-                    scalarCanairTempTrial,       & ! intent(in):  trial value of canopy air temperature (K)
-                    scalarCanopyTempTrial,       & ! intent(in):  trial value of canopy temperature (K)
-                    scalarCanopyWatTrial,        & ! intent(in):  trial value of canopy total water (kg m-2)
-                    scalarCanopyIceTrial,        & ! intent(in):  trial value of canopy ice content (kg m-2)
-                    ! input: variables for the snow-soil domain
-                    mLayerTempTrial,             & ! intent(in):  trial vector of layer temperature (K)
-                    mLayerVolFracWatTrial,       & ! intent(in):  trial vector of volumetric total water content (-)
-                    mLayerMatricHeadTrial,       & ! intent(in):  trial vector of total water matric potential (m)
-                    mLayerVolFracIceTrial,       & ! intent(in):  trial vector of volumetric fraction of ice (-)
-                    ! output: enthalpy
-                    scalarCanairEnthalpy,        & ! intent(out):  enthalpy of the canopy air space (J m-3)
-                    scalarCanopyEnthalpy,        & ! intent(out):  enthalpy of the vegetation canopy (J m-3)
-                    mLayerEnthalpy,              & ! intent(out):  enthalpy of each snow+soil layer (J m-3)
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: model control
+  real(rkind),intent(in)             :: dt                     ! length of the time step (seconds)
+  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
+  logical(lgt),intent(in)         :: firstSubStep           ! flag to indicate if we are processing the first sub-step
+  logical(lgt),intent(inout)      :: firstFluxCall          ! flag to indicate if we are processing the first flux call
+  logical(lgt),intent(in)         :: firstSplitOper         ! flag to indicate if we are processing the first flux call in a splitting operation
+  logical(lgt),intent(in)         :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
+  logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
+  ! input: state vectors
+  real(rkind),intent(in)             :: stateVecTrial(:)       ! model state vector
+  real(rkind),intent(in)             :: fScale(:)              ! function scaling vector
+  real(rkind),intent(in)             :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
+  ! input: data structures
+  type(model_options),intent(in)  :: model_decisions(:)     ! model decisions
+  type(zLookup),      intent(in)  :: lookup_data            ! lookup tables
+  type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
+  type(var_d),        intent(in)  :: attr_data              ! spatial attributes
+  type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
+  type(var_d),        intent(in)  :: forc_data              ! model forcing data
+  type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
+  type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
+  ! output: data structures
+  type(var_ilength),intent(inout) :: indx_data              ! indices defining model states and layers
+  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(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
+  ! input-output: baseflow
+  integer(i4b),intent(inout)      :: ixSaturation           ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
+  real(rkind),intent(out)            :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
+  ! output: flux and residual vectors
+  logical(lgt),intent(out)        :: feasible               ! flag to denote the feasibility of the solution
+  real(rkind),intent(out)            :: fluxVec(:)             ! flux vector
+  real(rkind),intent(out)            :: resSink(:)             ! sink terms on the RHS of the flux equation
+  real(rkind),intent(out)            :: resVec(:) ! NOTE: qp   ! residual vector
+  real(rkind),intent(out)            :: fEval                  ! function evaluation
+  ! output: error control
+  integer(i4b),intent(out)        :: err                    ! error code
+  character(*),intent(out)        :: message                ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! state variables
+  real(rkind)                        :: scalarCanairTempTrial     ! trial value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
+  real(rkind)                        :: scalarCanopyWatTrial      ! trial value for liquid water storage in the canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerTempTrial           ! trial value for temperature of layers in the snow and soil domains (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial     ! trial value for volumetric fraction of total water (-)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial     ! trial value for total water matric potential (m)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial  ! trial value for liquid water matric potential (m)
+  real(rkind)                        :: scalarAquiferStorageTrial ! trial value of storage of water in the aquifer (m)
+  ! diagnostic variables
+  logical(lgt),parameter          :: needEnthalpy=.true.      ! flag to compute enthalpy
+  real(rkind)                        :: scalarCanopyLiqTrial      ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
+  real(rkind)                        :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial     ! trial value for volumetric fraction of liquid water (-)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial     ! trial value for volumetric fraction of ice (-)
+  ! other local variables
+  integer(i4b)                    :: iLayer                    ! index of model layer in the snow+soil domain
+  integer(i4b)                    :: jState(1)                 ! index of model state for the scalar solution within the soil domain
+  integer(i4b)                    :: ixBeg,ixEnd               ! index of indices for the soil compression routine
+  integer(i4b),parameter          :: ixVegVolume=1             ! index of the desired vegetation control volumne (currently only one veg layer)
+  real(rkind)                        :: xMin,xMax                 ! minimum and maximum values for water content
+  real(rkind)                        :: scalarCanopyHydTrial      ! trial value for mass of water on the vegetation canopy (kg m-2)
+  real(rkind),parameter              :: canopyTempMax=500._rkind     ! expected maximum value for the canopy temperature (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracHydTrial     ! trial value for volumetric fraction of water (-), general vector merged from Wat and Liq
+  real(rkind),dimension(nState)      :: rVecScaled                ! scaled residual vector
+  character(LEN=256)              :: cmessage                  ! error message of downwind routine
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! association to variables in the data structures
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  associate(&
+    ! model decisions
+    ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
+    ! snow parameters
+    snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,&  ! intent(in):  [dp]    scaling parameter for the snow freezing curve (K-1)
+    ! soil parameters
+    theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
+    theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
+    specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
+    ! canopy and layer depth
+    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)
+    ! model state variables
+    scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in):  [dp]     temperature of the canopy air space (K)
+    scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in):  [dp]     temperature of the vegetation canopy (K)
+    scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in):  [dp]     mass of total water on the vegetation canopy (kg m-2)
+    mLayerTemp              => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(in):  [dp(:)]  temperature of each snow/soil layer (K)
+    mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in):  [dp(:)]  volumetric fraction of total water (-)
+    mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(in):  [dp(:)]  total water matric potential (m)
+    mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,& ! intent(in):  [dp(:)]  liquid water matric potential (m)
+    scalarAquiferStorage    => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)   ,& ! intent(in):  [dp]     storage of water in the aquifer (m)
+    ! model diagnostic variables from a previous solution
+    scalarSfcMeltPond       => prog_data%var(iLookPROG%scalarSfcMeltPond)%dat(1)      ,&  ! intent(in):  [dp]    ponded water caused by melt of the "snow without a layer" (kg m-2)
+    scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(in):  [dp(:)]  mass of liquid water on the vegetation canopy (kg m-2)
+    scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(in):  [dp(:)]  mass of ice on the vegetation canopy (kg m-2)
+    mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in):  [dp(:)]  volumetric fraction of liquid water (-)
+    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(in):  [dp(:)]  volumetric fraction of ice (-)
+    scalarFracLiqVeg        => diag_data%var(iLookDIAG%scalarFracLiqVeg)%dat(1)       ,&  ! intent(in):  [dp]    fraction of liquid water on vegetation (-)
+    mLayerFracLiqSnow       => diag_data%var(iLookDIAG%mLayerFracLiqSnow)%dat         ,&  ! intent(in):  [dp(:)] fraction of liquid water in each snow layer (-)
+    ! enthalpy
+    scalarCanairEnthalpy    => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the canopy air space (J m-3)
+    scalarCanopyEnthalpy    => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the vegetation canopy (J m-3)
+    mLayerEnthalpy          => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(out): [dp(:)] enthalpy of the snow+soil layers (J m-3)
+    ! soil compression
+    scalarSoilCompress      => diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1)     ,&  ! intent(in): [dp]    total change in storage associated with compression of the soil matrix (kg m-2)
+    mLayerCompress          => diag_data%var(iLookDIAG%mLayerCompress)%dat            ,&  ! intent(in): [dp(:)] change in storage associated with compression of the soil matrix (-)
+    ! derivatives
+    dVolTot_dPsi0           => deriv_data%var(iLookDERIV%dVolTot_dPsi0)%dat           ,&  ! intent(in): [dp(:)] derivative in total water content w.r.t. total water matric potential
+    dCompress_dPsi          => deriv_data%var(iLookDERIV%dCompress_dPsi)%dat          ,&  ! intent(in): [dp(:)] derivative in compressibility w.r.t. matric head (m-1)
+    ! mapping
+    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)
+    ! indices
+    ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy air space energy state variable (nrg)
+    ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy energy state variable (nrg)
+    ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy hydrology state variable (mass)
+    ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,&  ! intent(in): [i4b(:)] indices for energy states in the snow subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,&  ! intent(in): [i4b(:)] indices for hydrology states in the snow+soil subdomain
+    ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,&  ! intent(in): [i4b(:)] indices defining the type of the state (iname_nrgLayer...)
+    ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,&  ! intent(in): [i4b(:)] index of the hydrology states in the canopy domain
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,&  ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
+    layerType               => indx_data%var(iLookINDEX%layerType)%dat                 &  ! intent(in): [i4b(:)] layer type (iname_soil or iname_snow)
+    ) ! association to variables in the data structures
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message="eval8summa/"
+
+    ! check the feasibility of the solution
+    feasible=.true.
+
+    ! check that the canopy air space temperature is reasonable
+    if(ixCasNrg/=integerMissing)then
+      if(stateVecTrial(ixCasNrg) > canopyTempMax) feasible=.false.
+      if(stateVecTrial(ixCasNrg) > canopyTempMax) message=trim(message)//'canopy air space temp high,'
+      if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVecTrial( ixCasNrg )', feasible, canopyTempMax, stateVecTrial(ixCasNrg)
+    endif
+
+    ! check that the canopy air space temperature is reasonable
+    if(ixVegNrg/=integerMissing)then
+      if(stateVecTrial(ixVegNrg) > canopyTempMax) feasible=.false.
+      if(stateVecTrial(ixVegNrg) > canopyTempMax) message=trim(message)//'canopy temp high,'
+      if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVecTrial( ixVegNrg )', feasible, canopyTempMax, stateVecTrial(ixVegNrg)
+    endif
+
+    ! check canopy liquid water is not negative
+    if(ixVegHyd/=integerMissing)then
+      if(stateVecTrial(ixVegHyd) < 0._rkind) feasible=.false.
+      if(stateVecTrial(ixVegHyd) < 0._rkind) message=trim(message)//'canopy water negative,'
+      if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, min, stateVecTrial( ixVegHyd )', feasible, 0._rkind, stateVecTrial(ixVegHyd)
+    end if
+
+    ! check snow temperature is below freezing
+    if(count(ixSnowOnlyNrg/=integerMissing)>0)then
+      if(any(stateVecTrial( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) feasible=.false.
+      if(any(stateVecTrial( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) message=trim(message)//'snow temp above freezing,'
+      do iLayer=1,nSnow
+        if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, max, stateVecTrial( ixSnowOnlyNrg(iLayer) )', iLayer, feasible, Tfreeze, stateVecTrial( ixSnowOnlyNrg(iLayer) )
+      enddo
+    endif
+
+    ! loop through non-missing hydrology state variables in the snow+soil domain
+    do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)
+
+      ! check the minimum and maximum water constraints
+      if(ixHydType(iLayer)==iname_watLayer .or. ixHydType(iLayer)==iname_liqLayer)then
+
+        ! --> minimum
+        if (layerType(iLayer) == iname_soil) then
+          xMin = theta_res(iLayer-nSnow)
+        else
+          xMin = 0._rkind
+        endif
+
+        ! --> maximum
+        select case( layerType(iLayer) )
+          case(iname_snow); xMax = merge(iden_ice,  1._rkind - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
+          case(iname_soil); xMax = merge(theta_sat(iLayer-nSnow), theta_sat(iLayer-nSnow) - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
+        end select
+
+        ! --> check
+        if(stateVecTrial( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVecTrial( ixSnowSoilHyd(iLayer) ) > xMax) feasible=.false.
+        if(stateVecTrial( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVecTrial( ixSnowSoilHyd(iLayer) ) > xMax)  message=trim(message)//'layer water outside bounds,'
+        if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, stateVecTrial( ixSnowSoilHyd(iLayer) ), xMin, xMax = ', iLayer, feasible, stateVecTrial( ixSnowSoilHyd(iLayer) ), xMin, xMax
+
+        endif  ! if water states
+
+    end do  ! loop through non-missing hydrology state variables in the snow+soil domain
+
+    ! early return for non-feasible solutions
+    if(.not.feasible)then
+      fluxVec(:) = realMissing
+      resVec(:)  = quadMissing
+      fEval      = realMissing
+      message=trim(message)//'non-feasible'
+      err=20; return
+    endif
+
+    ! get the start and end indices for the soil compression calculations
+    if(scalarSolution)then
+      jState = pack(ixControlVolume, ixMapFull2Subset/=integerMissing)
+      ixBeg  = jState(1)
+      ixEnd  = jState(1)
+    else
+      ixBeg  = 1
+      ixEnd  = nSoil
+    endif
+
+    ! initialize to state variable from the last update
+    scalarCanairTempTrial = scalarCanairTemp
+    scalarCanopyTempTrial = scalarCanopyTemp
+    scalarCanopyWatTrial  = scalarCanopyWat
+    scalarCanopyLiqTrial  = scalarCanopyLiq
+    scalarCanopyIceTrial  = scalarCanopyIce
+    mLayerTempTrial           = mLayerTemp
+    mLayerVolFracWatTrial     = mLayerVolFracWat
+    mLayerVolFracLiqTrial     = mLayerVolFracLiq
+    mLayerVolFracIceTrial     = mLayerVolFracIce
+    mLayerMatricHeadTrial     = mLayerMatricHead      ! total water matric potential
+    mLayerMatricHeadLiqTrial  = mLayerMatricHeadLiq   ! liquid water matric potential
+    scalarAquiferStorageTrial = scalarAquiferStorage
+
+    ! extract variables from the model state vector
+    call varExtract(&
+                    ! input
+                    stateVecTrial,            & ! intent(in):    model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
+                    scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
+                    scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
+                    mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
+                    mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
+                    mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
+                    mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! update diagnostic variables and derivatives
+    call updateVars(&
+                    ! input
+                    .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
+                    lookup_data,                               & ! intent(in):    lookup tables for a local HRU
+                    mpar_data,                                 & ! intent(in):    model parameters for a local HRU
+                    indx_data,                                 & ! intent(in):    indices defining model states and layers
+                    prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                    diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
+                    deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                    ! output: variables for the vegetation canopy
+                    scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
+                    scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                    scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
+                    mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
+                    mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
+                    mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
+                    mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
+                    mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
                     ! output: error control
-                    err,cmessage)                  ! intent(out): error control
-    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-   endif  ! if computing enthalpy
-  
-   ! print the states in the canopy domain
-   !print*, 'dt = ', dt
-   !write(*,'(a,1x,10(f20.10,1x))') 'scalarCanopyTempTrial    = ', scalarCanopyTempTrial
-   !write(*,'(a,1x,10(f20.10,1x))') 'scalarCanopyWatTrial     = ', scalarCanopyWatTrial
-   !write(*,'(a,1x,10(f20.10,1x))') 'scalarCanopyLiqTrial     = ', scalarCanopyLiqTrial
-   !write(*,'(a,1x,10(f20.10,1x))') 'scalarCanopyIceTrial     = ', scalarCanopyIceTrial
-  
-   ! print the states in the snow+soil domain
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerTempTrial          = ', mLayerTempTrial(iJac1:min(nLayers,iJac2))
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerVolFracWatTrial    = ', mLayerVolFracWatTrial(iJac1:min(nLayers,iJac2))
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerVolFracLiqTrial    = ', mLayerVolFracLiqTrial(iJac1:min(nLayers,iJac2))
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerVolFracIceTrial    = ', mLayerVolFracIceTrial(iJac1:min(nLayers,iJac2))
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerMatricHeadTrial    = ', mLayerMatricHeadTrial(iJac1:min(nSoil,iJac2))
-   !write(*,'(a,1x,10(f20.10,1x))') 'mLayerMatricHeadLiqTrial = ', mLayerMatricHeadLiqTrial(iJac1:min(nSoil,iJac2))
-  
-   ! print the water content
-   if(globalPrintFlag)then
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracWatTrial = ', mLayerVolFracWatTrial(iJac1:min(iJac2,nSnow))
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial(iJac1:min(iJac2,nSnow))
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial(iJac1:min(iJac2,nSnow))
-   endif
-  
-   ! save the number of flux calls per time step
-   indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) = indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) + 1
-  
-   ! compute the fluxes for a given state vector
-   call computFlux(&
-                   ! input-output: model control
-                   nSnow,                     & ! intent(in):    number of snow layers
-                   nSoil,                     & ! intent(in):    number of soil layers
-                   nLayers,                   & ! intent(in):    total number of layers
-                   firstSubStep,              & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   firstFluxCall,             & ! intent(inout): flag to denote the first flux call
-                   firstSplitOper,            & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
-                   computeVegFlux,            & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   scalarSolution,            & ! intent(in):    flag to indicate the scalar solution
-                   .false.,                   & ! intent(in):    not inside Sundials solver loop
-                   scalarSfcMeltPond/dt,      & ! intent(in):    drainage from the surface melt pond (kg m-2 s-1)
-                   ! input: state variables
-                   scalarCanairTempTrial,     & ! intent(in):    trial value for the temperature of the canopy air space (K)
-                   scalarCanopyTempTrial,     & ! intent(in):    trial value for the temperature of the vegetation canopy (K)
-                   mLayerTempTrial,           & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
-                   mLayerMatricHeadLiqTrial,  & ! intent(in):    trial value for the liquid water matric potential in each soil layer (m)
-                   mLayerMatricHeadTrial,     & ! intent(in):    trial vector of total water matric potential (m)
-                   scalarAquiferStorageTrial, & ! intent(in):    trial value of storage of water in the aquifer (m)
-                   ! input: diagnostic variables defining the liquid water and ice content
-                   scalarCanopyLiqTrial,      & ! intent(in):    trial value for the liquid water on the vegetation canopy (kg m-2)
-                   scalarCanopyIceTrial,      & ! intent(in):    trial value for the ice on the vegetation canopy (kg m-2)
-                   mLayerVolFracLiqTrial,     & ! intent(in):    trial value for the volumetric liquid water content in each snow and soil layer (-)
-                   mLayerVolFracIceTrial,     & ! intent(in):    trial value for the volumetric ice in each snow and soil layer (-)
-                   ! input: data structures
-                   model_decisions,           & ! intent(in):    model decisions
-                   type_data,                 & ! intent(in):    type of vegetation and soil
-                   attr_data,                 & ! intent(in):    spatial attributes
-                   mpar_data,                 & ! intent(in):    model parameters
-                   forc_data,                 & ! intent(in):    model forcing data
-                   bvar_data,                 & ! intent(in):    average model variables for the entire basin
-                   prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                 & ! intent(in):    index data
-                   ! input-output: data structures
-                   diag_data,                 & ! intent(inout): model diagnostic variables for a local HRU
-                   flux_data,                 & ! intent(inout): model fluxes for a local HRU
-                   deriv_data,                & ! intent(out):   derivatives in model fluxes w.r.t. relevant state variables
-                   ! input-output: flux vector and baseflow derivatives
-                   ixSaturation,              & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                   dBaseflow_dMatric,         & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
-                   fluxVec,                   & ! intent(out):   flux vector (mixed units)
-                   ! output: error control
-                   err,cmessage)                ! intent(out):   error code and error message
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! compute soil compressibility (-) and its derivative w.r.t. matric head (m)
-   ! NOTE: we already extracted trial matrix head and volumetric liquid water as part of the flux calculations
-   ! use non-sundials version because sundials version needs mLayerMatricHeadPrime
-   call soilCmpres(&
-                   ! input:
-                   ixRichards,                             & ! intent(in): choice of option for Richards' equation
-                   ixBeg,ixEnd,                            & ! intent(in): start and end indices defining desired layers
-                   mLayerMatricHead(1:nSoil),              & ! intent(in): matric head at the start of the time step (m)
-                   mLayerMatricHeadTrial(1:nSoil),         & ! intent(in): trial value of matric head (m)
-                   mLayerVolFracLiqTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric liquid water content in each soil layer (-)
-                   mLayerVolFracIceTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric ice content in each soil layer (-)
-                   specificStorage,                        & ! intent(in): specific storage coefficient (m-1)
-                   theta_sat,                              & ! intent(in): soil porosity (-)
-                   ! output:
-                   mLayerCompress,                         & ! intent(inout): compressibility of the soil matrix (-)
-                   dCompress_dPsi,                         & ! intent(inout): derivative in compressibility w.r.t. matric head (m-1)
-                   err,cmessage)                             ! intent(out): error code and error message
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! compute the total change in storage associated with compression of the soil matrix (kg m-2)
-   scalarSoilCompress = sum(mLayerCompress(1:nSoil)*mLayerDepth(nSnow+1:nLayers))*iden_water
-  
-   ! vegetation domain: get the correct water states (total water, or liquid water, depending on the state type)
-   if(computeVegFlux)then
-    scalarCanopyHydTrial = merge(scalarCanopyWatTrial, scalarCanopyLiqTrial, (ixStateType( ixHydCanopy(ixVegVolume) )==iname_watCanopy) )
-   else
-    scalarCanopyHydTrial = realMissing
-   endif
-  
-   ! snow+soil domain: get the correct water states (total water, or liquid water, depending on the state type)
-   mLayerVolFracHydTrial = merge(mLayerVolFracWatTrial, mLayerVolFracLiqTrial, (ixHydType==iname_watLayer .or. ixHydType==iname_matLayer) )
-  
-   ! compute the residual vector
-   call computResid(&
-                    ! input: model control
-                    dt,                        & ! intent(in):    length of the time step (seconds)
+                    err,cmessage)                                ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! compute enthalpy (J m-3)
+    if(needEnthalpy)then
+      call t2enthalpy(&
+                      ! input: data structures
+                      diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
+                      mpar_data,                   & ! intent(in):  parameter data structure
+                      indx_data,                   & ! intent(in):  model indices
+                      lookup_data,                 & ! intent(in):  lookup table data structure
+                      ! input: state variables for the vegetation canopy
+                      scalarCanairTempTrial,       & ! intent(in):  trial value of canopy air temperature (K)
+                      scalarCanopyTempTrial,       & ! intent(in):  trial value of canopy temperature (K)
+                      scalarCanopyWatTrial,        & ! intent(in):  trial value of canopy total water (kg m-2)
+                      scalarCanopyIceTrial,        & ! intent(in):  trial value of canopy ice content (kg m-2)
+                      ! input: variables for the snow-soil domain
+                      mLayerTempTrial,             & ! intent(in):  trial vector of layer temperature (K)
+                      mLayerVolFracWatTrial,       & ! intent(in):  trial vector of volumetric total water content (-)
+                      mLayerMatricHeadTrial,       & ! intent(in):  trial vector of total water matric potential (m)
+                      mLayerVolFracIceTrial,       & ! intent(in):  trial vector of volumetric fraction of ice (-)
+                      ! output: enthalpy
+                      scalarCanairEnthalpy,        & ! intent(out):  enthalpy of the canopy air space (J m-3)
+                      scalarCanopyEnthalpy,        & ! intent(out):  enthalpy of the vegetation canopy (J m-3)
+                      mLayerEnthalpy,              & ! intent(out):  enthalpy of each snow+soil layer (J m-3)
+                      ! output: error control
+                      err,cmessage)                  ! intent(out): error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+    endif  ! if computing enthalpy
+
+    ! print the water content
+    if(globalPrintFlag)then
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracWatTrial = ', mLayerVolFracWatTrial(iJac1:min(iJac2,nSnow))
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial(iJac1:min(iJac2,nSnow))
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial(iJac1:min(iJac2,nSnow))
+    endif
+
+    ! save the number of flux calls per time step
+    indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) = indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) + 1
+
+    ! compute the fluxes for a given state vector
+    call computFlux(&
+                    ! input-output: model control
                     nSnow,                     & ! intent(in):    number of snow layers
                     nSoil,                     & ! intent(in):    number of soil layers
                     nLayers,                   & ! intent(in):    total number of layers
-                    ! input: flux vectors
-                    sMul,                      & ! intent(in):    state vector multiplier (used in the residual calculations)
-                    fluxVec,                   & ! intent(in):    flux vector
-                    ! input: state variables (already disaggregated into scalars and vectors)
+                    firstSubStep,              & ! intent(in):    flag to indicate if we are processing the first sub-step
+                    firstFluxCall,             & ! intent(inout): flag to denote the first flux call
+                    firstSplitOper,            & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                    computeVegFlux,            & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                    scalarSolution,            & ! intent(in):    flag to indicate the scalar solution
+                    .true.,                    & ! intent(in):    balance longwave
+                    scalarSfcMeltPond/dt,      & ! intent(in):    drainage from the surface melt pond (kg m-2 s-1)
+                    ! input: state variables
                     scalarCanairTempTrial,     & ! intent(in):    trial value for the temperature of the canopy air space (K)
                     scalarCanopyTempTrial,     & ! intent(in):    trial value for the temperature of the vegetation canopy (K)
-                    scalarCanopyHydTrial,      & ! intent(in):    trial value of canopy hydrology state variable (kg m-2)
                     mLayerTempTrial,           & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
-                    mLayerVolFracHydTrial,     & ! intent(in):    trial vector of volumetric water content (-)
+                    mLayerMatricHeadLiqTrial,  & ! intent(in):    trial value for the liquid water matric potential in each soil layer (m)
+                    mLayerMatricHeadTrial,     & ! intent(in):    trial vector of total water matric potential (m)
                     scalarAquiferStorageTrial, & ! intent(in):    trial value of storage of water in the aquifer (m)
-                    ! input: diagnostic variables defining the liquid water and ice content (function of state variables)
+                    ! input: diagnostic variables defining the liquid water and ice content
+                    scalarCanopyLiqTrial,      & ! intent(in):    trial value for the liquid water on the vegetation canopy (kg m-2)
                     scalarCanopyIceTrial,      & ! intent(in):    trial value for the ice on the vegetation canopy (kg m-2)
+                    mLayerVolFracLiqTrial,     & ! intent(in):    trial value for the volumetric liquid water content in each snow and soil layer (-)
                     mLayerVolFracIceTrial,     & ! intent(in):    trial value for the volumetric ice in each snow and soil layer (-)
                     ! input: data structures
+                    model_decisions,           & ! intent(in):    model decisions
+                    type_data,                 & ! intent(in):    type of vegetation and soil
+                    attr_data,                 & ! intent(in):    spatial attributes
+                    mpar_data,                 & ! intent(in):    model parameters
+                    forc_data,                 & ! intent(in):    model forcing data
+                    bvar_data,                 & ! intent(in):    average model variables for the entire basin
                     prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
-                    diag_data,                 & ! intent(in):    model diagnostic variables for a local HRU
-                    flux_data,                 & ! intent(in):    model fluxes for a local HRU
                     indx_data,                 & ! intent(in):    index data
-                    ! output
-                    resSink,                   & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                    resVec,                    & ! intent(out):   residual vector
-                    err,cmessage)                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! compute the function evaluation
-   rVecScaled = fScale(:)*real(resVec(:), rkind)   ! scale the residual vector (NOTE: residual vector is in quadruple precision)
-   fEval      = 0.5_rkind*dot_product(rVecScaled,rVecScaled)
-  
-   ! end association with the information in the data structures
-   end associate
-  
-   end subroutine eval8summa
-  
-  end module eval8summa_module
+                    ! input-output: data structures
+                    diag_data,                 & ! intent(inout): model diagnostic variables for a local HRU
+                    flux_data,                 & ! intent(inout): model fluxes for a local HRU
+                    deriv_data,                & ! intent(out):   derivatives in model fluxes w.r.t. relevant state variables
+                    ! input-output: flux vector and baseflow derivatives
+                    ixSaturation,              & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                    dBaseflow_dMatric,         & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
+                    fluxVec,                   & ! intent(out):   flux vector (mixed units)
+                    ! output: error control
+                    err,cmessage)                ! intent(out):   error code and error message
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! compute soil compressibility (-) and its derivative w.r.t. matric head (m)
+    ! NOTE: we already extracted trial matrix head and volumetric liquid water as part of the flux calculations
+    ! use non-sundials version because sundials version needs mLayerMatricHeadPrime
+    call soilCmpres(&
+                    ! input:
+                    ixRichards,                             & ! intent(in): choice of option for Richards' equation
+                    ixBeg,ixEnd,                            & ! intent(in): start and end indices defining desired layers
+                    mLayerMatricHead(1:nSoil),           & ! intent(in): matric head at the start of the time step (m)
+                    mLayerMatricHeadTrial(1:nSoil),      & ! intent(in): trial value of matric head (m)
+                    mLayerVolFracLiqTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric liquid water content in each soil layer (-)
+                    mLayerVolFracIceTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric ice content in each soil layer (-)
+                    specificStorage,                        & ! intent(in): specific storage coefficient (m-1)
+                    theta_sat,                              & ! intent(in): soil porosity (-)
+                    ! output:
+                    mLayerCompress,                         & ! intent(inout): compressibility of the soil matrix (-)
+                    dCompress_dPsi,                         & ! intent(inout): derivative in compressibility w.r.t. matric head (m-1)
+                    err,cmessage)                             ! intent(out): error code and error message
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! compute the total change in storage associated with compression of the soil matrix (kg m-2)
+    scalarSoilCompress = sum(mLayerCompress(1:nSoil)*mLayerDepth(nSnow+1:nLayers))*iden_water
+
+    ! vegetation domain: get the correct water states (total water, or liquid water, depending on the state type)
+    if(computeVegFlux)then
+      scalarCanopyHydTrial = merge(scalarCanopyWatTrial, scalarCanopyLiqTrial, (ixStateType( ixHydCanopy(ixVegVolume) )==iname_watCanopy) )
+    else
+      scalarCanopyHydTrial = realMissing
+    endif
+
+    ! snow+soil domain: get the correct water states (total water, or liquid water, depending on the state type)
+    mLayerVolFracHydTrial = merge(mLayerVolFracWatTrial, mLayerVolFracLiqTrial, (ixHydType==iname_watLayer .or. ixHydType==iname_matLayer) )
+
+    ! compute the residual vector
+    call computResid(&
+                      ! input: model control
+                      dt,                        & ! intent(in):    length of the time step (seconds)
+                      nSnow,                     & ! intent(in):    number of snow layers
+                      nSoil,                     & ! intent(in):    number of soil layers
+                      nLayers,                   & ! intent(in):    total number of layers
+                      ! input: flux vectors
+                      sMul,                      & ! intent(in):    state vector multiplier (used in the residual calculations)
+                      fluxVec,                   & ! intent(in):    flux vector
+                      ! input: state variables (already disaggregated into scalars and vectors)
+                      scalarCanairTempTrial,     & ! intent(in):    trial value for the temperature of the canopy air space (K)
+                      scalarCanopyTempTrial,     & ! intent(in):    trial value for the temperature of the vegetation canopy (K)
+                      scalarCanopyHydTrial,      & ! intent(in):    trial value of canopy hydrology state variable (kg m-2)
+                      mLayerTempTrial,           & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
+                      mLayerVolFracHydTrial,     & ! intent(in):    trial vector of volumetric water content (-)
+                      scalarAquiferStorageTrial, & ! intent(in):    trial value of storage of water in the aquifer (m)
+                      ! input: diagnostic variables defining the liquid water and ice content (function of state variables)
+                      scalarCanopyIceTrial,      & ! intent(in):    trial value for the ice on the vegetation canopy (kg m-2)
+                      mLayerVolFracIceTrial,     & ! intent(in):    trial value for the volumetric ice in each snow and soil layer (-)
+                      ! input: data structures
+                      prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
+                      diag_data,                 & ! intent(in):    model diagnostic variables for a local HRU
+                      flux_data,                 & ! intent(in):    model fluxes for a local HRU
+                      indx_data,                 & ! intent(in):    index data
+                      ! output
+                      resSink,                   & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                      resVec,                    & ! intent(out):   residual vector
+                      err,cmessage)                ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! compute the function evaluation
+    rVecScaled = fScale(:)*real(resVec(:), rkind)   ! scale the residual vector (NOTE: residual vector is in quadruple precision)
+    fEval      = 0.5_rkind*dot_product(rVecScaled,rVecScaled)
+
+  ! end association with the information in the data structures
+  end associate
+
+end subroutine eval8summa
+
+end module eval8summa_module
   
\ No newline at end of file
diff --git a/build/source/engine/ffile_info.f90 b/build/source/engine/ffile_info.f90
index 32ff329..a89c1a5 100755
--- a/build/source/engine/ffile_info.f90
+++ b/build/source/engine/ffile_info.f90
@@ -49,7 +49,7 @@ subroutine ffile_info(indxGRU,forcFileInfo,numFiles,err,message)
   USE globalData,only:gru_struc                      ! gru-hru mapping structure
   USE time_utils_module,only:extractTime
   USE globalData,only:time_meta
-  USE allocspace4chm_module,only:allocLocal
+  USE allocspace_module,only:allocLocal
   USE time_utils_module,only:extractTime     ! extract time info from units string
   USE summaActors_FileManager,only: SIM_START_TM, SIM_END_TM, FORCING_START ! time info from control file module
   USE var_lookup,only:iLookTIME              ! named variables that identify indices in the time structures
diff --git a/build/source/engine/getVectorz.f90 b/build/source/engine/getVectorz.f90
index ba31b4b..70a47b5 100755
--- a/build/source/engine/getVectorz.f90
+++ b/build/source/engine/getVectorz.f90
@@ -64,9 +64,9 @@ USE multiconst,only:&
 ! provide access to the derived types to define the data structures
 USE data_types,only:&
                     var_i,        & ! data vector (i4b)
-                    var_d,        & ! data vector (dp)
+                    var_d,        & ! data vector (rkind)
                     var_ilength,  & ! data vector with variable length dimension (i4b)
-                    var_dlength     ! data vector with variable length dimension (dp)
+                    var_dlength     ! data vector with variable length dimension (rkind)
 
 ! provide access to indices that define elements of the data structures
 USE var_lookup,only:iLookDIAG             ! named variables for structure elements
@@ -97,14 +97,14 @@ public::getScaling
 public::varExtract
 
 ! common variables
-real(dp),parameter :: valueMissing=-9999._dp ! missing value
+real(rkind),parameter :: valueMissing=-9999._rkind ! missing value
 
 contains
 
- ! **********************************************************************************************************
- ! public subroutine popStateVec: populate model state vectors
- ! **********************************************************************************************************
- subroutine popStateVec(&
+! **********************************************************************************************************
+! public subroutine popStateVec: populate model state vectors
+! **********************************************************************************************************
+subroutine popStateVec(&
                         ! input: data structures
                         nState,                  & ! intent(in):    number of desired state variables
                         prog_data,               & ! intent(in):    model prognostic variables for a local HRU
@@ -113,457 +113,419 @@ contains
                         ! output
                         stateVec,                & ! intent(out):   model state vector
                         err,message)               ! intent(out):   error control
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! input: data structures
- integer(i4b),intent(in)         :: nState                 ! number of desired state variables
- type(var_dlength),intent(in)    :: prog_data              ! prognostic variables for a local HRU
- type(var_dlength),intent(in)    :: diag_data              ! diagnostic variables for a local HRU
- type(var_ilength),intent(in)    :: indx_data              ! indices defining model states and layers
- ! output
- real(dp),intent(out)            :: stateVec(:)            ! model state vector (mixed units)
- integer(i4b),intent(out)        :: err                    ! error code
- character(*),intent(out)        :: message                ! error message
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! local variables
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! state subsets
- integer(i4b)                    :: iState                 ! index of state within the snow+soil domain
- integer(i4b)                    :: iLayer                 ! index of layer within the snow+soil domain
- integer(i4b)                    :: ixStateSubset          ! index within the state subset
- logical(lgt),dimension(nState)  :: stateFlag              ! flag to denote that the state is populated
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! make association with variables in the data structures
- fixedLength: associate(&
- ! model states for the vegetation canopy
- scalarCanairTemp    => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in) : [dp]     temperature of the canopy air space (K)
- scalarCanopyTemp    => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in) : [dp]     temperature of the vegetation canopy (K)
- scalarCanopyWat     => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in) : [dp]     mass of total water on the vegetation canopy (kg m-2)
- scalarCanopyLiq     => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(in) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
- ! model state variable vectors for the snow-soil layers
- mLayerTemp          => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(in) : [dp(:)]  temperature of each snow/soil layer (K)
- mLayerVolFracWat    => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in) : [dp(:)]  volumetric fraction of total water (-)
- mLayerVolFracLiq    => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in) : [dp(:)]  volumetric fraction of liquid water (-)
- mLayerMatricHead    => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(in) : [dp(:)]  matric head (m)
- mLayerMatricHeadLiq => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,& ! intent(in) : [dp(:)]  matric potential of liquid water (m)
- ! model state variables for the aquifer
- scalarAquiferStorage=> prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)   ,& ! intent(in) : [dp]     storage of water in the aquifer (m)
- ! indices defining specific model states
- ixCasNrg            => indx_data%var(iLookINDEX%ixCasNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable
- ixVegNrg            => indx_data%var(iLookINDEX%ixVegNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable
- ixVegHyd            => indx_data%var(iLookINDEX%ixVegHyd)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass)
- ixAqWat             => indx_data%var(iLookINDEX%ixAqWat)%dat                  ,& ! intent(in) : [i4b(:)] [length=1] index of aquifer storage state variable
- ! 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
- ! type of model state variabless
- ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables
- ixHydType           => indx_data%var(iLookINDEX%ixHydType)%dat                ,& ! intent(in) : [i4b(:)] index of the type of hydrology states in snow+soil domain
- ! 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
- )  ! end association with variables in the data structures
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='popStateVec/'
-
- ! -----
- ! * initialize state vectors...
- ! -----------------------------
-
- ! initialize flags
- stateFlag(:) = .false.
-
- ! build the state vector for the temperature of the canopy air space
- ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
- do concurrent (iState=1:size(ixCasNrg),ixCasNrg(iState)/=integerMissing)
-  stateVec( ixCasNrg(iState) )  = scalarCanairTemp       ! transfer canopy air temperature to the state vector
-  stateFlag( ixCasNrg(iState) ) = .true.                 ! flag to denote that the state is populated
- end do
-
- ! build the state vector for the temperature of the vegetation canopy
- ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
- do concurrent (iState=1:size(ixVegNrg),ixVegNrg(iState)/=integerMissing)
-  stateVec( ixVegNrg(iState) )  = scalarCanopyTemp       ! transfer vegetation temperature to the state vector
-  stateFlag( ixVegNrg(iState) ) = .true.                 ! flag to denote that the state is populated
- end do
-
- ! build the state vector for the water in the vegetation canopy
- ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
- do concurrent (iState=1:size(ixVegHyd),ixVegHyd(iState)/=integerMissing)
-  stateFlag( ixVegHyd(iState) ) = .true.                 ! flag to denote that the state is populated
-  select case(ixStateType_subset( ixVegHyd(iState) ))
-   case(iname_watCanopy); stateVec( ixVegHyd(iState) )  = scalarCanopyWat        ! transfer total canopy water to the state vector
-   case(iname_liqCanopy); stateVec( ixVegHyd(iState) )  = scalarCanopyLiq        ! transfer liquid canopy water to the state vector
-   case default; stateFlag( ixVegHyd(iState) ) = .false. ! flag to denote that the state is populated
-  end select
- end do
-
- ! build the energy state vector for the snow and soil domain
- if(nSnowSoilNrg>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
-   ixStateSubset            = ixSnowSoilNrg(iLayer)  ! index within the state vector
-   stateVec(ixStateSubset)  = mLayerTemp(iLayer)     ! transfer temperature from a layer to the state vector
-   stateFlag(ixStateSubset) = .true.                 ! flag to denote that the state is populated
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! build the hydrology state vector for the snow+soil domains
- ! NOTE: ixVolFracWat  and ixVolFracLiq can also include states in the soil domain, hence enable primary variable switching
- if(nSnowSoilHyd>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing hydrology state variables in the snow+soil domain)
-   ixStateSubset            = ixSnowSoilHyd(iLayer)   ! index within the state vector
-   stateFlag(ixStateSubset) = .true.                  ! flag to denote that the state is populated
-   select case( ixHydType(iLayer) )
-    case(iname_watLayer); stateVec(ixStateSubset) = mLayerVolFracWat(iLayer)           ! total water state variable for snow+soil layers
-    case(iname_liqLayer); stateVec(ixStateSubset) = mLayerVolFracLiq(iLayer)           ! liquid water state variable for snow+soil layers
-    case(iname_matLayer); stateVec(ixStateSubset) = mLayerMatricHead(iLayer-nSnow)     ! total water matric potential variable for soil layers
-    case(iname_lmpLayer); stateVec(ixStateSubset) = mLayerMatricHeadLiq(iLayer-nSnow)  ! liquid matric potential state variable for soil layers
-    case default; stateFlag(ixStateSubset) = .false.  ! flag to denote that the state is populated
-   end select
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! build the state vector for the aquifer storage
- ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer aquifer
- do concurrent (iState=1:size(ixAqWat),ixAqWat(iState)/=integerMissing)
-  stateVec( ixAqWat(iState) )  = scalarAquiferStorage    ! transfer aquifer storage to the state vector
-  stateFlag( ixAqWat(iState) ) = .true.                  ! flag to denote that the state is populated
- end do
-
- ! check that we populated all state variables
- if(count(stateFlag)/=nState)then
-  print*, 'stateFlag = ', stateFlag
-  message=trim(message)//'some state variables unpopulated'
-  err=20; return
- endif
-
- end associate fixedLength      ! end association to variables in the data structure where vector length does not change
- end subroutine popStateVec
-
-
- ! **********************************************************************************************************
- ! public subroutine getScaling: get scale factors
- ! **********************************************************************************************************
- subroutine getScaling(&
-                       ! input: data structures
-                       diag_data,               & ! intent(in):    model diagnostic variables for a local HRU
-                       indx_data,               & ! intent(in):    indices defining model states and layers
-                       ! output
-                       fScale,                  & ! intent(out):   function scaling vector (mixed units)
-                       xScale,                  & ! intent(out):   variable scaling vector (mixed units)
-                       sMul,                    & ! intent(out):   multiplier for state vector (used in the residual calculations)
-                       dMat,                    & ! intent(out):   diagonal of the Jacobian matrix (excludes fluxes)
-                       err,message)               ! intent(out):   error control
- ! --------------------------------------------------------------------------------------------------------------------------------
- USE nr_utility_module,only:arth                   ! get a sequence of numbers arth(start, incr, count)
- USE f2008funcs_module,only:findIndex              ! finds the index of the first value within a vector
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! input: data structures
- type(var_dlength),intent(in)    :: diag_data              ! diagnostic variables for a local HRU
- type(var_ilength),intent(in)    :: indx_data              ! indices defining model states and layers
- ! output: state vectors
- real(dp),intent(out)            :: fScale(:)              ! function scaling vector (mixed units)
- real(dp),intent(out)            :: xScale(:)              ! variable scaling vector (mixed units)
- real(qp),intent(out)            :: sMul(:)    ! NOTE: qp  ! multiplier for state vector (used in the residual calculations)
- real(dp),intent(out)            :: dMat(:)                ! diagonal of the Jacobian matrix (excludes fluxes)
- ! output: error control
- integer(i4b),intent(out)        :: err                    ! error code
- character(*),intent(out)        :: message                ! error message
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! local variables
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! scaling parameters
- real(dp),parameter              :: fScaleLiq=0.01_dp      ! func eval: characteristic scale for volumetric liquid water content (-)
- real(dp),parameter              :: fScaleMat=10._dp       ! func eval: characteristic scale for matric head (m)
- real(dp),parameter              :: fScaleNrg=1000000._dp  ! func eval: characteristic scale for energy (J m-3)
- real(dp),parameter              :: xScaleLiq=0.1_dp       ! state var: characteristic scale for volumetric liquid water content (-)
- real(dp),parameter              :: xScaleMat=10._dp       ! state var: characteristic scale for matric head (m)
- real(dp),parameter              :: xScaleTemp=1._dp       ! state var: characteristic scale for temperature (K)
- ! state subsets
- integer(i4b)                    :: iLayer                 ! index of layer within the snow+soil domain
- integer(i4b)                    :: ixStateSubset          ! index within the state subset
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! make association with variables in the data structures
- fixedLength: associate(&
- ! model diagnostic variables
- canopyDepth         => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1)      ,& ! intent(in):  [dp]     canopy depth (m)
- volHeatCapVeg       => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1),& ! intent(in) : [dp]     bulk volumetric heat capacity of vegetation (J m-3 K-1)
- mLayerVolHeatCap    => diag_data%var(iLookDIAG%mLayerVolHtCapBulk)%dat        ,& ! intent(in) : [dp(:)]  bulk volumetric heat capacity in each snow and soil layer (J m-3 K-1)
- ! indices defining specific model states
- ixCasNrg            => indx_data%var(iLookINDEX%ixCasNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable
- ixVegNrg            => indx_data%var(iLookINDEX%ixVegNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable
- ixVegHyd            => indx_data%var(iLookINDEX%ixVegHyd)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass)
- ! 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
- ! type of model state variabless
- ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables
- ! 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
- )  ! end association with variables in the data structures
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='getScaling/'
-
- ! -----
- ! * define scaling vectors...
- ! ---------------------------
-
- ! define the function and variable scaling factors for energy
- where(ixStateType_subset==iname_nrgCanair .or. ixStateType_subset==iname_nrgCanopy .or. ixStateType_subset==iname_nrgLayer)
-  fScale = 1._dp / fScaleNrg  ! 1/(J m-3)
-  xScale = 1._dp  ! K
- endwhere
-
- ! define the function and variable scaling factors for water on the vegetation canopy
- where(ixStateType_subset==iname_watCanopy .or. ixStateType_subset==iname_liqCanopy)
-  fScale = 1._dp / (fScaleLiq*canopyDepth*iden_water)  ! 1/(kg m-2)
-  xScale = 1._dp  ! (kg m-2)
- endwhere
-
- ! define the function and variable scaling factors for water in the snow+soil domain
- where(ixStateType_subset==iname_watLayer .or. ixStateType_subset==iname_liqLayer)
-  fScale = 1._dp / fScaleLiq  ! (-)
-  xScale = 1._dp  ! (-)
- end where
-
- ! define the function and variable scaling factors for water in the snow+soil domain
- where(ixStateType_subset==iname_matLayer .or. ixStateType_subset==iname_lmpLayer)
-  fScale = 1._dp / fScaleLiq  ! (-)
-  xScale = 1._dp  ! (m)
- end where
-
- ! define the function and variable scaling factors for water storage in the aquifer
- where(ixStateType_subset==iname_watAquifer)
-  fScale = 1._dp
-  xScale = 1._dp
- endwhere
-
- ! -----
- ! * define components of derivative matrices that are constant over a time step (substep)...
- ! ------------------------------------------------------------------------------------------
-
- ! define the multiplier for the state vector for residual calculations (vegetation canopy)
- ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer)
-
- where(ixStateType_subset==iname_nrgCanair) sMul = Cp_air*iden_air   ! volumetric heat capacity of air (J m-3 K-1)
- where(ixStateType_subset==iname_nrgCanopy) sMul = volHeatCapVeg     ! volumetric heat capacity of the vegetation (J m-3 K-1)
- where(ixStateType_subset==iname_watCanopy) sMul = 1._dp             ! nothing else on the left hand side
- where(ixStateType_subset==iname_liqCanopy) sMul = 1._dp             ! nothing else on the left hand side
-
- ! compute terms in the Jacobian for vegetation (excluding fluxes)
- ! NOTE: This is computed outside the iteration loop because it does not depend on state variables
- ! NOTE: Energy for vegetation is computed *within* the iteration loop as it includes phase change
- ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer)
- where(ixStateType_subset==iname_nrgCanair) dMat = Cp_air*iden_air   ! volumetric heat capacity of air (J m-3 K-1)
- where(ixStateType_subset==iname_nrgCanopy) dMat = realMissing       ! populated within the iteration loop
- where(ixStateType_subset==iname_watCanopy) dMat = 1._dp             ! nothing else on the left hand side
- where(ixStateType_subset==iname_liqCanopy) dMat = 1._dp             ! nothing else on the left hand side
-
- ! define the energy multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain)
- if(nSnowSoilNrg>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
-   ixStateSubset        = ixSnowSoilNrg(iLayer)      ! index within the state vector
-   sMul(ixStateSubset)  = mLayerVolHeatCap(iLayer)   ! transfer volumetric heat capacity to the state multiplier
-   dMat(ixStateSubset)  = realMissing                ! diagonal element populated within the iteration loop
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! define the hydrology multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain)
- if(nSnowSoilHyd>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
-   ixStateSubset        = ixSnowSoilHyd(iLayer)      ! index within the state vector
-   sMul(ixStateSubset)  = 1._dp                      ! state multiplier = 1 (nothing else on the left-hand-side)
-   dMat(ixStateSubset)  = 1._dp                      ! diagonal element = 1 (nothing else on the left-hand-side)
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! define the scaling factor and diagonal elements for the aquifer
- where(ixStateType_subset==iname_watAquifer)
-  sMul = 1._dp
-  dMat = 1._dp
- endwhere
-
- ! ------------------------------------------------------------------------------------------
- ! ------------------------------------------------------------------------------------------
-
- end associate fixedLength      ! end association to variables in the data structure where vector length does not change
- end subroutine getScaling
-
-
-
- ! **********************************************************************************************************
- ! public subroutine varExtract: extract variables from the state vector and compute diagnostic variables
- ! **********************************************************************************************************
- subroutine varExtract(&
-                       ! input
-                       stateVec,                                  & ! intent(in):    model state vector (mixed units)
-                       diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
-                       prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                       indx_data,                                 & ! intent(in):    indices defining model states and layers
-                       ! output: variables for the vegetation canopy
-                       scalarCanairTempTrial,                     & ! intent(out):   trial value of canopy air temperature (K)
-                       scalarCanopyTempTrial,                     & ! intent(out):   trial value of canopy temperature (K)
-                       scalarCanopyWatTrial,                      & ! intent(out):   trial value of canopy total water (kg m-2)
-                       scalarCanopyLiqTrial,                      & ! intent(out):   trial value of canopy liquid water (kg m-2)
-                       scalarCanopyIceTrial,                      & ! intent(out):   trial value of canopy ice content (kg m-2)
-                       ! output: variables for the snow-soil domain
-                       mLayerTempTrial,                           & ! intent(out):   trial vector of layer temperature (K)
-                       mLayerVolFracWatTrial,                     & ! intent(out):   trial vector of volumetric total water content (-)
-                       mLayerVolFracLiqTrial,                     & ! intent(out):   trial vector of volumetric liquid water content (-)
-                       mLayerVolFracIceTrial,                     & ! intent(out):   trial vector of volumetric ice water content (-)
-                       mLayerMatricHeadTrial,                     & ! intent(out):   trial vector of total water matric potential (m)
-                       mLayerMatricHeadLiqTrial,                  & ! intent(out):   trial vector of liquid water matric potential (m)
-                       ! output: variables for the aquifer
-                       scalarAquiferStorageTrial,                 & ! intent(out):   trial value of storage of water in the aquifer (m)
-                       ! output: error control
-                       err,message)                                 ! intent(out):   error control
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! --------------------------------------------------------------------------------------------------------------------------------
- implicit none
- ! input
- real(dp),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
- type(var_dlength),intent(in)    :: diag_data                       ! diagnostic variables for a local HRU
- type(var_dlength),intent(in)    :: prog_data                       ! prognostic variables for a local HRU
- type(var_ilength),intent(in)    :: indx_data                       ! indices defining model states and layers
- ! output: variables for the vegetation canopy
- real(dp),intent(out)            :: scalarCanairTempTrial           ! trial value of canopy air temperature (K)
- real(dp),intent(out)            :: scalarCanopyTempTrial           ! trial value of canopy temperature (K)
- real(dp),intent(out)            :: scalarCanopyWatTrial            ! trial value of canopy total water (kg m-2)
- real(dp),intent(out)            :: scalarCanopyLiqTrial            ! trial value of canopy liquid water (kg m-2)
- real(dp),intent(out)            :: scalarCanopyIceTrial            ! trial value of canopy ice content (kg m-2)
- ! output: variables for the snow-soil domain
- real(dp),intent(out)            :: mLayerTempTrial(:)              ! trial vector of layer temperature (K)
- real(dp),intent(out)            :: mLayerVolFracWatTrial(:)        ! trial vector of volumetric total water content (-)
- real(dp),intent(out)            :: mLayerVolFracLiqTrial(:)        ! trial vector of volumetric liquid water content (-)
- real(dp),intent(out)            :: mLayerVolFracIceTrial(:)        ! trial vector of volumetric ice water content (-)
- real(dp),intent(out)            :: mLayerMatricHeadTrial(:)        ! trial vector of total water matric potential (m)
- real(dp),intent(out)            :: mLayerMatricHeadLiqTrial(:)     ! trial vector of liquid water matric potential (m)
- ! output: variables for the aquifer
- real(dp),intent(out)            :: scalarAquiferStorageTrial       ! trial value of storage of water in the aquifer (m)
- ! output: error control
- integer(i4b),intent(out)        :: err                             ! error code
- character(*),intent(out)        :: message                         ! error message
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! local variables
- integer(i4b)                    :: iLayer                          ! index of layer within the snow+soil domain
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! make association with variables in the data structures
- associate(&
- ! number of model layers, and layer type
- nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1)                 ,& ! intent(in):  [i4b]    total number of snow layers
- nSoil                   => indx_data%var(iLookINDEX%nSoil)%dat(1)                 ,& ! intent(in):  [i4b]    total number of soil layers
- nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1)               ,& ! intent(in):  [i4b]    total number of snow and soil layers
- ! indices defining model states and layers
- 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)
- ixAqWat                 => indx_data%var(iLookINDEX%ixAqWat)%dat(1)               ,& ! intent(in):  [i4b]    index of the squifer storage state variable
- ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for energy states in the snow+soil subdomain
- ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for hydrology states in the snow+soil subdomain
- 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 variables in the snow+soil domain
- ! indices defining type of model state variables
- ixStateType_subset      => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in):  [i4b(:)] [state subset] type of desired model state variables
- ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,& ! intent(in):  [i4b(:)] index of the type of hydrology states in snow+soil domain
- ! model states for the vegetation canopy
- scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in):  [dp]     temperature of the canopy air space (K)
- scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in):  [dp]     temperature of the vegetation canopy (K)
- scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in):  [dp]     mass of total water on the vegetation canopy (kg m-2)
- ! model state variable vectors for the snow-soil layers
- mLayerTemp              => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(in):  [dp(:)]  temperature of each snow/soil layer (K)
- mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in):  [dp(:)]  volumetric fraction of total water (-)
- mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(in):  [dp(:)]  total water matric potential (m)
- mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,& ! intent(in):  [dp(:)]  liquid water matric potential (m)
- ! model state variables for the aquifer
- scalarAquiferStorage    => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)   ,& ! intent(in):  [dp]     storage of water in the aquifer (m)
- ! model diagnostic variables from a previous solution
- scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(in):  [dp(:)]  mass of liquid water on the vegetation canopy (kg m-2)
- scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(in):  [dp(:)]  mass of ice on the vegetation canopy (kg m-2)
- mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in):  [dp(:)]  volumetric fraction of liquid water (-)
- mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat           & ! intent(in):  [dp(:)]  volumetric fraction of ice (-)
- ) ! association with variables in the data structures
-
- ! --------------------------------------------------------------------------------------------------------------------------------
- ! --------------------------------------------------------------------------------------------------------------------------------
-
- ! initialize error control
- err=0; message='varExtract/'
-
- ! *** extract state variables for the vegetation canopy
-
- ! initialize to state variable from the last update
- scalarCanairTempTrial = scalarCanairTemp
- scalarCanopyTempTrial = scalarCanopyTemp
- scalarCanopyWatTrial  = scalarCanopyWat
- scalarCanopyLiqTrial  = scalarCanopyLiq
- scalarCanopyIceTrial  = scalarCanopyIce
-
- ! check if computing the vegetation flux
- if(ixCasNrg/=integerMissing .or. ixVegNrg/=integerMissing .or. ixVegHyd/=integerMissing)then
-
-  ! extract temperature of the canopy air space
-  if(ixCasNrg/=integerMissing) scalarCanairTempTrial = stateVec(ixCasNrg)
-
-  ! extract canopy temperature
-  if(ixVegNrg/=integerMissing) scalarCanopyTempTrial = stateVec(ixVegNrg)
-
-  ! extract intercepted water
-  if(ixVegHyd/=integerMissing)then
-   select case( ixStateType_subset(ixVegHyd) )
-    case(iname_liqCanopy); scalarCanopyLiqTrial = stateVec(ixVegHyd)
-    case(iname_watCanopy); scalarCanopyWatTrial = stateVec(ixVegHyd)
-    case default; err=20; message=trim(message)//'case not found: expect iname_liqCanopy or iname_watCanopy'; return
-   end select
-  endif
-
- endif  ! not computing the vegetation flux
-
- ! *** extract state variables from the snow+soil sub-domain
-
- ! initialize to the state variable from the last update
- mLayerTempTrial           = mLayerTemp
- mLayerVolFracWatTrial     = mLayerVolFracWat
- mLayerVolFracLiqTrial     = mLayerVolFracLiq
- mLayerVolFracIceTrial     = mLayerVolFracIce
- mLayerMatricHeadTrial     = mLayerMatricHead      ! total water matric potential
- mLayerMatricHeadLiqTrial  = mLayerMatricHeadLiq   ! liquid water matric potential
- scalarAquiferStorageTrial = scalarAquiferStorage
-
- ! overwrite with the energy values from the state vector
- if(nSnowSoilNrg>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
-   mLayerTempTrial(iLayer) = stateVec( ixSnowSoilNrg(iLayer) )
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! overwrite with the hydrology values from the state vector
- if(nSnowSoilHyd>0)then
-  do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing hydrology state variables in the snow+soil domain)
-   select case( ixHydType(iLayer) )
-    case(iname_watLayer); mLayerVolFracWatTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! total water state variable for snow+soil layers
-    case(iname_liqLayer); mLayerVolFracLiqTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid water state variable for snow+soil layers
-    case(iname_matLayer); mLayerMatricHeadTrial(iLayer-nSnow)    = stateVec( ixSnowSoilHyd(iLayer) ) ! total water matric potential variable for soil layers
-    case(iname_lmpLayer); mLayerMatricHeadLiqTrial(iLayer-nSnow) = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid matric potential state variable for soil layers
-    case default ! do nothing
-   end select
-  end do  ! looping through non-missing energy state variables in the snow+soil domain
- endif
-
- ! extract temperature of the canopy air space
- if(ixAqWat/=integerMissing) scalarAquiferStorageTrial = stateVec(ixAqWat)
-
- end associate
-
- end subroutine varExtract
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: data structures
+  integer(i4b),intent(in)         :: nState                 ! number of desired state variables
+  type(var_dlength),intent(in)    :: prog_data              ! prognostic variables for a local HRU
+  type(var_dlength),intent(in)    :: diag_data              ! diagnostic variables for a local HRU
+  type(var_ilength),intent(in)    :: indx_data              ! indices defining model states and layers
+  ! output
+  real(rkind),intent(out)            :: stateVec(:)            ! model state vector (mixed units)
+  integer(i4b),intent(out)        :: err                    ! error code
+  character(*),intent(out)        :: message                ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! state subsets
+  integer(i4b)                    :: iState                 ! index of state within the snow+soil domain
+  integer(i4b)                    :: iLayer                 ! index of layer within the snow+soil domain
+  integer(i4b)                    :: ixStateSubset          ! index within the state subset
+  logical(lgt),dimension(nState)  :: stateFlag              ! flag to denote that the state is populated
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! make association with variables in the data structures
+  fixedLength: associate(&
+    ! model states for the vegetation canopy
+    scalarCanairTemp    => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in) : [dp]     temperature of the canopy air space (K)
+    scalarCanopyTemp    => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in) : [dp]     temperature of the vegetation canopy (K)
+    scalarCanopyWat     => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in) : [dp]     mass of total water on the vegetation canopy (kg m-2)
+    scalarCanopyLiq     => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(in) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+    ! model state variable vectors for the snow-soil layers
+    mLayerTemp          => prog_data%var(iLookPROG%mLayerTemp)%dat                ,& ! intent(in) : [dp(:)]  temperature of each snow/soil layer (K)
+    mLayerVolFracWat    => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in) : [dp(:)]  volumetric fraction of total water (-)
+    mLayerVolFracLiq    => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in) : [dp(:)]  volumetric fraction of liquid water (-)
+    mLayerMatricHead    => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(in) : [dp(:)]  matric head (m)
+    mLayerMatricHeadLiq => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,& ! intent(in) : [dp(:)]  matric potential of liquid water (m)
+    ! model state variables for the aquifer
+    scalarAquiferStorage=> prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)   ,& ! intent(in) : [dp]     storage of water in the aquifer (m)
+    ! indices defining specific model states
+    ixCasNrg            => indx_data%var(iLookINDEX%ixCasNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable
+    ixVegNrg            => indx_data%var(iLookINDEX%ixVegNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable
+    ixVegHyd            => indx_data%var(iLookINDEX%ixVegHyd)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass)
+    ixAqWat             => indx_data%var(iLookINDEX%ixAqWat)%dat                  ,& ! intent(in) : [i4b(:)] [length=1] index of aquifer storage state variable
+    ! 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
+    ! type of model state variabless
+    ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables
+    ixHydType           => indx_data%var(iLookINDEX%ixHydType)%dat                ,& ! intent(in) : [i4b(:)] index of the type of hydrology states in snow+soil domain
+    ! 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
+    )  ! end association with variables in the data structures
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message='popStateVec/'
+
+    ! -----
+    ! * initialize state vectors...
+    ! -----------------------------
+
+    ! initialize flags
+    stateFlag(:) = .false.
+
+    ! build the state vector for the temperature of the canopy air space
+    ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
+    do concurrent (iState=1:size(ixCasNrg),ixCasNrg(iState)/=integerMissing)
+      stateVec( ixCasNrg(iState) )  = scalarCanairTemp       ! transfer canopy air temperature to the state vector
+      stateFlag( ixCasNrg(iState) ) = .true.                 ! flag to denote that the state is populated
+    end do
+
+    ! build the state vector for the temperature of the vegetation canopy
+    ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
+    do concurrent (iState=1:size(ixVegNrg),ixVegNrg(iState)/=integerMissing)
+      stateVec( ixVegNrg(iState) )  = scalarCanopyTemp       ! transfer vegetation temperature to the state vector
+      stateFlag( ixVegNrg(iState) ) = .true.                 ! flag to denote that the state is populated
+    end do
+
+    ! build the state vector for the water in the vegetation canopy
+    ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer canopy
+    do concurrent (iState=1:size(ixVegHyd),ixVegHyd(iState)/=integerMissing)
+      stateFlag( ixVegHyd(iState) ) = .true.                 ! flag to denote that the state is populated
+      select case(ixStateType_subset( ixVegHyd(iState) ))
+        case(iname_watCanopy); stateVec( ixVegHyd(iState) )  = scalarCanopyWat        ! transfer total canopy water to the state vector
+        case(iname_liqCanopy); stateVec( ixVegHyd(iState) )  = scalarCanopyLiq        ! transfer liquid canopy water to the state vector
+        case default; stateFlag( ixVegHyd(iState) ) = .false. ! flag to denote that the state is populated
+      end select
+    end do
+
+    ! build the energy state vector for the snow and soil domain
+    if(nSnowSoilNrg>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        ixStateSubset            = ixSnowSoilNrg(iLayer)  ! index within the state vector
+        stateVec(ixStateSubset)  = mLayerTemp(iLayer)     ! transfer temperature from a layer to the state vector
+        stateFlag(ixStateSubset) = .true.                 ! flag to denote that the state is populated
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! build the hydrology state vector for the snow+soil domains
+    ! NOTE: ixVolFracWat  and ixVolFracLiq can also include states in the soil domain, hence enable primary variable switching
+    if(nSnowSoilHyd>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing hydrology state variables in the snow+soil domain)
+        ixStateSubset            = ixSnowSoilHyd(iLayer)   ! index within the state vector
+        stateFlag(ixStateSubset) = .true.                  ! flag to denote that the state is populated
+        select case( ixHydType(iLayer) )
+          case(iname_watLayer); stateVec(ixStateSubset) = mLayerVolFracWat(iLayer)           ! total water state variable for snow+soil layers
+          case(iname_liqLayer); stateVec(ixStateSubset) = mLayerVolFracLiq(iLayer)           ! liquid water state variable for snow+soil layers
+          case(iname_matLayer); stateVec(ixStateSubset) = mLayerMatricHead(iLayer-nSnow)     ! total water matric potential variable for soil layers
+          case(iname_lmpLayer); stateVec(ixStateSubset) = mLayerMatricHeadLiq(iLayer-nSnow)  ! liquid matric potential state variable for soil layers
+          case default; stateFlag(ixStateSubset) = .false.  ! flag to denote that the state is populated
+        end select
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! build the state vector for the aquifer storage
+    ! NOTE: currently vector length=1, and use "do concurrent" to generalize to a multi-layer aquifer
+    do concurrent (iState=1:size(ixAqWat),ixAqWat(iState)/=integerMissing)
+      stateVec( ixAqWat(iState) )  = scalarAquiferStorage    ! transfer aquifer storage to the state vector
+      stateFlag( ixAqWat(iState) ) = .true.                  ! flag to denote that the state is populated
+    end do
+
+    ! check that we populated all state variables
+    if(count(stateFlag)/=nState)then
+      print*, 'stateFlag = ', stateFlag
+      message=trim(message)//'some state variables unpopulated'
+      err=20; return
+    endif
+
+  end associate fixedLength      ! end association to variables in the data structure where vector length does not change
+end subroutine popStateVec
+
+
+! **********************************************************************************************************
+! public subroutine getScaling: get scale factors
+! **********************************************************************************************************
+subroutine getScaling(&
+                      ! input: data structures
+                      diag_data,               & ! intent(in):    model diagnostic variables for a local HRU
+                      indx_data,               & ! intent(in):    indices defining model states and layers
+                      ! output
+                      fScale,                  & ! intent(out):   function scaling vector (mixed units)
+                      xScale,                  & ! intent(out):   variable scaling vector (mixed units)
+                      sMul,                    & ! intent(out):   multiplier for state vector (used in the residual calculations)
+                      dMat,                    & ! intent(out):   diagonal of the Jacobian matrix (excludes fluxes)
+                      err,message)               ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  USE nr_utility_module,only:arth                   ! get a sequence of numbers arth(start, incr, count)
+  USE f2008funcs_module,only:findIndex              ! finds the index of the first value within a vector
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: data structures
+  type(var_dlength),intent(in)    :: diag_data              ! diagnostic variables for a local HRU
+  type(var_ilength),intent(in)    :: indx_data              ! indices defining model states and layers
+  ! output: state vectors
+  real(rkind),intent(out)            :: fScale(:)              ! function scaling vector (mixed units)
+  real(rkind),intent(out)            :: xScale(:)              ! variable scaling vector (mixed units)
+  real(rkind),intent(out)            :: sMul(:)    ! NOTE: qp  ! multiplier for state vector (used in the residual calculations)
+  real(rkind),intent(out)            :: dMat(:)                ! diagonal of the Jacobian matrix (excludes fluxes)
+  ! output: error control
+  integer(i4b),intent(out)        :: err                    ! error code
+  character(*),intent(out)        :: message                ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! scaling parameters
+  real(rkind),parameter              :: fScaleLiq=0.01_rkind      ! func eval: characteristic scale for volumetric liquid water content (-)
+  real(rkind),parameter              :: fScaleMat=10._rkind       ! func eval: characteristic scale for matric head (m)
+  real(rkind),parameter              :: fScaleNrg=1000000._rkind  ! func eval: characteristic scale for energy (J m-3)
+  real(rkind),parameter              :: xScaleLiq=0.1_rkind       ! state var: characteristic scale for volumetric liquid water content (-)
+  real(rkind),parameter              :: xScaleMat=10._rkind       ! state var: characteristic scale for matric head (m)
+  real(rkind),parameter              :: xScaleTemp=1._rkind       ! state var: characteristic scale for temperature (K)
+  ! state subsets
+  integer(i4b)                    :: iLayer                 ! index of layer within the snow+soil domain
+  integer(i4b)                    :: ixStateSubset          ! index within the state subset
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! make association with variables in the data structures
+  fixedLength: associate(&
+    ! model diagnostic variables
+    canopyDepth         => diag_data%var(iLookDIAG%scalarCanopyDepth)%dat(1)      ,& ! intent(in):  [dp]     canopy depth (m)
+    volHeatCapVeg       => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1),& ! intent(in) : [dp]     bulk volumetric heat capacity of vegetation (J m-3 K-1)
+    mLayerVolHeatCap    => diag_data%var(iLookDIAG%mLayerVolHtCapBulk)%dat        ,& ! intent(in) : [dp(:)]  bulk volumetric heat capacity in each snow and soil layer (J m-3 K-1)
+    ! indices defining specific model states
+    ixCasNrg            => indx_data%var(iLookINDEX%ixCasNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy air space energy state variable
+    ixVegNrg            => indx_data%var(iLookINDEX%ixVegNrg)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy energy state variable
+    ixVegHyd            => indx_data%var(iLookINDEX%ixVegHyd)%dat                 ,& ! intent(in) : [i4b(:)] [length=1] index of canopy hydrology state variable (mass)
+    ! 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
+    ! type of model state variabless
+    ixStateType_subset  => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in) : [i4b(:)] [state subset] type of desired model state variables
+    ! 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
+    )  ! end association with variables in the data structures
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message='getScaling/'
+
+    ! -----
+    ! * define scaling vectors...
+    ! ---------------------------
+
+    ! define the function and variable scaling factors for energy
+    where(ixStateType_subset==iname_nrgCanair .or. ixStateType_subset==iname_nrgCanopy .or. ixStateType_subset==iname_nrgLayer)
+      fScale = 1._rkind / fScaleNrg  ! 1/(J m-3)
+      xScale = 1._rkind  ! K
+    endwhere
+
+    ! define the function and variable scaling factors for water on the vegetation canopy
+    where(ixStateType_subset==iname_watCanopy .or. ixStateType_subset==iname_liqCanopy)
+      fScale = 1._rkind / (fScaleLiq*canopyDepth*iden_water)  ! 1/(kg m-2)
+      xScale = 1._rkind  ! (kg m-2)
+    endwhere
+
+    ! define the function and variable scaling factors for water in the snow+soil domain
+    where(ixStateType_subset==iname_watLayer .or. ixStateType_subset==iname_liqLayer)
+      fScale = 1._rkind / fScaleLiq  ! (-)
+      xScale = 1._rkind  ! (-)
+    end where
+
+    ! define the function and variable scaling factors for water in the snow+soil domain
+    where(ixStateType_subset==iname_matLayer .or. ixStateType_subset==iname_lmpLayer)
+      fScale = 1._rkind / fScaleLiq  ! (-)
+      xScale = 1._rkind  ! (m)
+    end where
+
+    ! define the function and variable scaling factors for water storage in the aquifer
+    where(ixStateType_subset==iname_watAquifer)
+      fScale = 1._rkind
+      xScale = 1._rkind
+    endwhere
+
+    ! -----
+    ! * define components of derivative matrices that are constant over a time step (substep)...
+    ! ------------------------------------------------------------------------------------------
+
+    ! define the multiplier for the state vector for residual calculations (vegetation canopy)
+    ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer)
+
+    where(ixStateType_subset==iname_nrgCanair) sMul = Cp_air*iden_air   ! volumetric heat capacity of air (J m-3 K-1)
+    where(ixStateType_subset==iname_nrgCanopy) sMul = volHeatCapVeg     ! volumetric heat capacity of the vegetation (J m-3 K-1)
+    where(ixStateType_subset==iname_watCanopy) sMul = 1._rkind             ! nothing else on the left hand side
+    where(ixStateType_subset==iname_liqCanopy) sMul = 1._rkind             ! nothing else on the left hand side
+
+    ! compute terms in the Jacobian for vegetation (excluding fluxes)
+    ! NOTE: This is computed outside the iteration loop because it does not depend on state variables
+    ! NOTE: Energy for vegetation is computed *within* the iteration loop as it includes phase change
+    ! NOTE: Use the "where" statement to generalize to multiple canopy layers (currently one canopy layer)
+    where(ixStateType_subset==iname_nrgCanair) dMat = Cp_air*iden_air   ! volumetric heat capacity of air (J m-3 K-1)
+    where(ixStateType_subset==iname_nrgCanopy) dMat = realMissing       ! populated within the iteration loop
+    where(ixStateType_subset==iname_watCanopy) dMat = 1._rkind             ! nothing else on the left hand side
+    where(ixStateType_subset==iname_liqCanopy) dMat = 1._rkind             ! nothing else on the left hand side
+
+    ! define the energy multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain)
+    if(nSnowSoilNrg>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        ixStateSubset        = ixSnowSoilNrg(iLayer)      ! index within the state vector
+        sMul(ixStateSubset)  = mLayerVolHeatCap(iLayer)   ! transfer volumetric heat capacity to the state multiplier
+        dMat(ixStateSubset)  = realMissing                ! diagonal element populated within the iteration loop
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! define the hydrology multiplier and diagonal elements for the state vector for residual calculations (snow-soil domain)
+    if(nSnowSoilHyd>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        ixStateSubset        = ixSnowSoilHyd(iLayer)      ! index within the state vector
+        sMul(ixStateSubset)  = 1._rkind                      ! state multiplier = 1 (nothing else on the left-hand-side)
+        dMat(ixStateSubset)  = 1._rkind                      ! diagonal element = 1 (nothing else on the left-hand-side)
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! define the scaling factor and diagonal elements for the aquifer
+    where(ixStateType_subset==iname_watAquifer)
+      sMul = 1._rkind
+      dMat = 1._rkind
+    endwhere
+
+  end associate fixedLength      ! end association to variables in the data structure where vector length does not change
+end subroutine getScaling
+
+
+! **********************************************************************************************************
+! public subroutine varExtract: extract variables from the state vector and compute diagnostic variables
+!  This routine does not initialize any of the variables
+! **********************************************************************************************************
+subroutine varExtract(&
+                        ! input
+                        stateVec,                                  & ! intent(in):    model state vector (mixed units)
+                        diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
+                        prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                        indx_data,                                 & ! intent(in):    indices defining model states and layers
+                        ! output: variables for the vegetation canopy
+                        scalarCanairTempTrial,                     & ! intent(out):   trial value of canopy air temperature (K)
+                        scalarCanopyTempTrial,                     & ! intent(out):   trial value of canopy temperature (K)
+                        scalarCanopyWatTrial,                      & ! intent(out):   trial value of canopy total water (kg m-2)
+                        scalarCanopyLiqTrial,                      & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                        ! output: variables for the snow-soil domain
+                        mLayerTempTrial,                           & ! intent(out):   trial vector of layer temperature (K)
+                        mLayerVolFracWatTrial,                     & ! intent(out):   trial vector of volumetric total water content (-)
+                        mLayerVolFracLiqTrial,                     & ! intent(out):   trial vector of volumetric liquid water content (-)
+                        mLayerMatricHeadTrial,                     & ! intent(out):   trial vector of total water matric potential (m)
+                        mLayerMatricHeadLiqTrial,                  & ! intent(out):   trial vector of liquid water matric potential (m)
+                        ! output: variables for the aquifer
+                        scalarAquiferStorageTrial,                 & ! intent(out):   trial value of storage of water in the aquifer (m)
+                        ! output: error control
+                        err,message)                                 ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  implicit none
+  ! input
+  real(rkind),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
+  type(var_dlength),intent(in)       :: diag_data                       ! diagnostic variables for a local HRU
+  type(var_dlength),intent(in)       :: prog_data                       ! prognostic variables for a local HRU
+  type(var_ilength),intent(in)       :: indx_data                       ! indices defining model states and layers
+  ! output: variables for the vegetation canopy
+  real(rkind),intent(out)            :: scalarCanairTempTrial           ! trial value of canopy air temperature (K)
+  real(rkind),intent(out)            :: scalarCanopyTempTrial           ! trial value of canopy temperature (K)
+  real(rkind),intent(out)            :: scalarCanopyWatTrial            ! trial value of canopy total water (kg m-2)
+  real(rkind),intent(out)            :: scalarCanopyLiqTrial            ! trial value of canopy liquid water (kg m-2)
+  ! output: variables for the snow-soil domain
+  real(rkind),intent(out)            :: mLayerTempTrial(:)              ! trial vector of layer temperature (K)
+  real(rkind),intent(out)            :: mLayerVolFracWatTrial(:)        ! trial vector of volumetric total water content (-)
+  real(rkind),intent(out)            :: mLayerVolFracLiqTrial(:)        ! trial vector of volumetric liquid water content (-)
+  real(rkind),intent(out)            :: mLayerMatricHeadTrial(:)        ! trial vector of total water matric potential (m)
+  real(rkind),intent(out)            :: mLayerMatricHeadLiqTrial(:)     ! trial vector of liquid water matric potential (m)
+  ! output: variables for the aquifer
+  real(rkind),intent(out)            :: scalarAquiferStorageTrial       ! trial value of storage of water in the aquifer (m)
+  ! output: error control
+  integer(i4b),intent(out)           :: err                             ! error code
+  character(*),intent(out)           :: message                         ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  integer(i4b)                    :: iLayer                          ! index of layer within the snow+soil domain
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! make association with variables in the data structures
+  associate(&
+    ! number of model layers, and layer type
+    nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1)                 ,& ! intent(in):  [i4b]    total number of snow layers
+    nSoil                   => indx_data%var(iLookINDEX%nSoil)%dat(1)                 ,& ! intent(in):  [i4b]    total number of soil layers
+    nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1)               ,& ! intent(in):  [i4b]    total number of snow and soil layers
+    ! indices defining model states and layers
+    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)
+    ixAqWat                 => indx_data%var(iLookINDEX%ixAqWat)%dat(1)               ,& ! intent(in):  [i4b]    index of the squifer storage state variable
+    ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for energy states in the snow+soil subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for hydrology states in the snow+soil subdomain
+    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 variables in the snow+soil domain
+    ! indices defining type of model state variables
+    ixStateType_subset      => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in):  [i4b(:)] [state subset] type of desired model state variables
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                & ! intent(in):  [i4b(:)] index of the type of hydrology states in snow+soil domain
+    )! association with variables in the data structures
+
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! --------------------------------------------------------------------------------------------------------------------------------
+
+    ! initialize error control
+    err=0; message='varExtract/'
+
+    ! *** extract state variables for the vegetation canopy
+
+    ! check if computing the vegetation flux
+    if(ixCasNrg/=integerMissing .or. ixVegNrg/=integerMissing .or. ixVegHyd/=integerMissing)then
+
+      ! extract temperature of the canopy air space
+      if(ixCasNrg/=integerMissing) scalarCanairTempTrial = stateVec(ixCasNrg)
+
+      ! extract canopy temperature
+      if(ixVegNrg/=integerMissing) scalarCanopyTempTrial = stateVec(ixVegNrg)
+
+      ! extract intercepted water
+      if(ixVegHyd/=integerMissing)then
+        select case( ixStateType_subset(ixVegHyd) )
+          case(iname_liqCanopy); scalarCanopyLiqTrial = stateVec(ixVegHyd)
+          case(iname_watCanopy); scalarCanopyWatTrial = stateVec(ixVegHyd)
+          case default; err=20; message=trim(message)//'case not found: expect iname_liqCanopy or iname_watCanopy'; return
+        end select
+      endif
+
+    endif  ! not computing the vegetation flux
+
+    ! *** extract state variables from the snow+soil sub-domain
+
+
+    ! overwrite with the energy values from the state vector
+    if(nSnowSoilNrg>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        mLayerTempTrial(iLayer) = stateVec( ixSnowSoilNrg(iLayer) )
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! overwrite with the hydrology values from the state vector
+    if(nSnowSoilHyd>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing hydrology state variables in the snow+soil domain)
+        select case( ixHydType(iLayer) )
+          case(iname_watLayer); mLayerVolFracWatTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! total water state variable for snow+soil layers
+          case(iname_liqLayer); mLayerVolFracLiqTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid water state variable for snow+soil layers
+          case(iname_matLayer); mLayerMatricHeadTrial(iLayer-nSnow)    = stateVec( ixSnowSoilHyd(iLayer) ) ! total water matric potential variable for soil layers
+          case(iname_lmpLayer); mLayerMatricHeadLiqTrial(iLayer-nSnow) = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid matric potential state variable for soil layers
+          case default ! do nothing
+        end select
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
+    endif
+
+    ! extract temperature of the canopy air space
+    if(ixAqWat/=integerMissing) scalarAquiferStorageTrial = stateVec(ixAqWat)
+
+  end associate
+
+end subroutine varExtract
 
 end module getVectorz_module
diff --git a/build/source/engine/opSplittin.f90 b/build/source/engine/opSplittin.f90
index 90393b6..ba0cbca 100755
--- a/build/source/engine/opSplittin.f90
+++ b/build/source/engine/opSplittin.f90
@@ -1,5 +1,5 @@
 ! SUMMA - Structure for Unifying Multiple Modeling Alternatives
-! Copyright (C) 2014-2020 NCAR/RAL; University of Saskatchewan; University of Washington
+! Copyright (C) 2014-2015 NCAR/RAL
 !
 ! This file is part of SUMMA
 !
@@ -20,1258 +20,1094 @@
 
 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 (dp)
-                    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 (dp)
-                    zLookup,      &
-                    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
- sundialIDA,                     & ! IDA solver from Sundials package
- backwEuler                        ! backward Euler method
-
-! 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(dp),parameter      :: valueMissing=-9999._dp     ! missing value
-real(dp),parameter      :: verySmall=1.e-12_dp        ! a very small number (used to check consistency)
-real(dp),parameter      :: veryBig=1.e+20_dp          ! a very big number
-real(dp),parameter      :: dx = 1.e-8_dp              ! 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 varSubstep).
-! **********************************************************************************************************
-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 allocspace4chm_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
-  ! identify name of variable type (for error message)
-  USE get_ixName_module,only:get_varTypeName           ! to access type strings for error messages
-  ! sundials var_substep
-  USE varSubstepSundials_module,only:varSubstepSundials                ! complete substeps for a given split
+  ! 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
-  ! ---------------------------------------------------------------------------------------
-  ! * 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(dp),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(dp),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(dp),dimension(nLayers)     :: mLayerVolFracIceInit           ! initial vector for volumetric fraction of ice (-)
-  ! ------------------------------------------------------------------------------------------------------
-  ! * operator splitting
-  ! ------------------------------------------------------------------------------------------------------
-  ! minimum timestep
-  real(dp),parameter              :: dtmin_coupled=1800._dp         ! minimum time step for the fully coupled solution (seconds)
-  real(dp),parameter              :: dtmin_split=60._dp             ! minimum time step for the fully split solution (seconds)
-  real(dp),parameter              :: dtmin_scalar=10._dp            ! minimum time step for the scalar solution (seconds)
-  real(dp)                        :: dt_min                         ! minimum time step (seconds)
-  real(dp)                        :: dtInit                         ! initial time step (seconds)
-  ! explicit error tolerance (depends on state type split, so defined here)
-  real(dp),parameter              :: errorTolLiqFlux=0.01_dp        ! error tolerance in the explicit solution (liquid flux)
-  real(dp),parameter              :: errorTolNrgFlux=10._dp         ! 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                      ! number of possible solutions
-  real(qp)                        :: dt_out                         !
-
+  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
+    ! ---------------------------------------------------------------------------------------
+  
+    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
   
-  ! ---------------------------------------------------------------------------------------
-  ! 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)
-  ! 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/"
-  ! print*, "BEFORE******"
-  ! print*, "scalarCanairTemp = ", scalarCanairTemp
-  ! print*, "scalarCanopyTemp = ", scalarCanopyTemp
-  ! print*, "scalarCanopyIce = ", scalarCanopyIce
-  ! print*, "scalarCanopyLiq = ", scalarCanopyLiq
-  ! print*, "scalarCanopyWat = ", scalarCanopyWat
-  ! print*, "mLayerTemp = ", mLayerTemp(1)
-  ! print*, "mLayerVolFracIce = ", mLayerVolFracIce(1)
-  ! print*, "mLayerVolFracLiq = ", mLayerVolFracLiq(1)
-  ! print*, "mLayerVolFracWat = ", mLayerVolFracWat(1)
-  ! print*, "mLayerMatricHead = ", mLayerMatricHead(1)
-  ! print*, "mLayerMatricHeadLiq = ", mLayerMatricHeadLiq(1)
-  
-  ! we just solve the fully coupled problem by ida
-  select case(model_decisions(iLookDECISIONS%diffEqSolv)%iDecision)
-    case(sundialIDA); nCoupling = 1
-    case(backwEuler); nCoupling = 2
-    case default
-        err=20
-        message=trim(message)//'expect case to be sundialIDA or backwEuler'
-        print*, message
-        return
-  end select
-  ! *****
-  ! (0) PRELIMINARIES...
-  ! ********************
-
-  ! -----
-  ! * 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)
-      print*, message
-      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)
-    print*, message
-    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)
-    print*, message
-    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)
-    print*, message
-    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)
-    print*, message
-    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)
-    print*, message
-    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._dp
-  end do
-
-  ! initialize derivatives
-  do iVar=1,size(deriv_meta)
-    deriv_data%var(iVar)%dat(:) = 0._dp
-  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
-    stateTypeSplitLoop: do iStateTypeSplit=1,nStateTypeSplit
-
-      !print*, 'iStateTypeSplit, nStateTypeSplit = ', iStateTypeSplit, 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
-
-        !print*, 'start of stateThenDomain loop'
-
-        ! 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'
-          print*, message
-          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
+      ! * 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
-
-            ! 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' 
-                print*, message
-                return
+            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
-
-            !print*, '*****'
-            !print*, 'computeVegFlux = ', computeVegFlux
-            !print*, '(ixSolution==scalar) = ', (ixSolution==scalar)
-            !print*, 'ixCoupling, iStateTypeSplit, ixStateThenDomain, iDomainSplit, nDomainSplit: ', ixCoupling, iStateTypeSplit, ixStateThenDomain, iDomainSplit, nDomainSplit
-            !print*, 'ixSoilOnlyHyd = ', indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat
-
-            ! 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)
-                print*, message
-                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
-
-              ! check
-              !print*, 'after stateFilter: stateMask   = ', stateMask
-              !print*, 'count(stateMask) = ', count(stateMask)
-
-              !if(ixSolution==scalar)then
-              ! print*, 'iStateSplit, nStateSplit = ', iStateSplit, nStateSplit
-              ! print*, 'start of scalar solution'
-              ! !print*, 'PAUSE'; read(*,*)
-              !endif
-
-              ! -----
-              ! * 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)
-                print*, message
-                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
-
-                    ! domain splitting
-                  else
-
-                    ! 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'
-                              print*, message
-                              err=20; return
-                            endif
-
-                          ! 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
-                              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'
-                          print*, message
-                          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'
-                print*, message
-                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...
-              ! --------------------------------------------
-
-              !print*, trim(message)//'before varSubstep: nSubset = ', nSubset
-
-              ! keep track of the number of scalar solutions
-              if(ixSolution==scalar) numberScalarSolutions = numberScalarSolutions + 1
-              
-              select case(model_decisions(iLookDECISIONS%diffEqSolv)%iDecision)
-                case(sundialIDA)
-                  call varSubstepSundials(&
-                                ! input: model control
-                                dt,                         & ! intent(inout) : 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
-                                ! solve variable subset for one full time step
-                case(backwEuler)
-                  call varSubstep(&
-                                ! input: model control
-                                dt,                         & ! intent(inout) : 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
-                case default
-                  err=20
-                  message=trim(message)//'expect case to backwEuler or sundialIDA'
-                  print*, message
-                  return
-              end select
-
-              dt = dt_out
-                              
-              if(err/=0)then
-                message=trim(message)//trim(cmessage)
-                print*, message
-                if(err>0) return
-              endif  ! (check for errors)
-
-              ! print*, trim(message)//'after varSubstep: scalarSnowDrainage = ', flux_data%var(iLookFLUX%scalarSnowDrainage)%dat
-              ! print*, trim(message)//'after varSubstep: iLayerLiqFluxSnow  = ', flux_data%var(iLookFLUX%iLayerLiqFluxSnow)%dat
-              ! print*, trim(message)//'after varSubstep: iLayerLiqFluxSoil  = ', flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat
-
-              ! check
-              !if(ixSolution==scalar)then
-              ! print*, 'PAUSE: check scalar'; read(*,*)
-              !endif
-
-              ! reduce coupled step if failed the minimum step for the scalar solution
-              if(failedMinimumStep .and. ixSolution==scalar) reduceCoupledStep=.true.
-
-              ! check
-              !if(ixCoupling/=fullyCoupled)then
-              ! print*, 'dt = ', dt
-              ! print*, 'after varSubstep: err              = ', err
-              ! print*, 'after varSubstep: cmessage         = ', trim(cmessage)
-              ! print*, 'after varSubstep: computeVegFlux   = ', computeVegFlux
-              ! print*, 'after varSubstep: stateMask        = ', stateMask
-              ! print*, 'after varSubstep: coupling         = ', (ixCoupling==fullyCoupled)
-              ! print*, 'after varSubstep: scalar solve     = ', (ixSolution==scalar)
-              ! print*, 'iStateTypeSplit, nStateTypeSplit = ', iStateTypeSplit, nStateTypeSplit
-              ! print*, 'iDomainSplit,    nDomainSplit    = ', iDomainSplit,    nDomainSplit
-              ! print*, 'nSubset           = ', nSubset
-              ! print*, 'tooMuchMelt       = ', tooMuchMelt
-              ! print*, 'reduceCoupledStep = ', reduceCoupledStep
-              ! print*, 'failedMinimumStep = ', failedMinimumStep, merge('coupled','opSplit',ixCoupling==fullyCoupled)
-              ! if(ixSolution==scalar)then; print*, 'PAUSE'; read(*,*); endif
-              !endif
-
-              !if(ixSolution==scalar)then
-              ! !print*, trim(message)//'stop: checking scalar solution'; stop
-              ! print*, trim(message)//'pause: checking scalar solution'; read(*,*)
-              !endif
-
-              !print*, 'tooMuchMelt, reduceCoupledStep = ', tooMuchMelt, reduceCoupledStep
-
-              ! 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
-                !print*, 'failure!'
-                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
-                  !if(iVar==iLookFLUX%mLayerTranspire) print*, flux_meta(iVar)%varname, fluxCount%var(iVar)%dat
-                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)
+  
+            ! 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
-                  message=trim(message)//'failed the minimum step for the scalar solution'
-                  print*, message
-                  err=20; return
-
-                ! check for an unexpected failure
-                else
-                  message=trim(message)//'unexpected failure'
-                  print*, message
-                  err=20; return
+                  dtInit = min(dtmin_split, dt)    ! initial time step
+                  dt_min = min(dtmin_scalar, dt)   ! minimum time step
                 endif
-
-              endif  ! success check
-
-            end do stateSplit ! solution with split layers
-            !print*, 'after stateSplit'
-
-          end do solution ! trial with the full layer solution then the split layer solution
-
-          !print*, 'after solution loop'
-
-          ! ***** trial with a given solution method...
-          ! *******************************************************************************************************************************
-          ! *******************************************************************************************************************************
-          ! *******************************************************************************************************************************
-
-        end do domainSplit ! domain type splitting loop
-
-        !print*, 'ixStateThenDomain = ', ixStateThenDomain
-        !print*, 'after domain split loop'
-
-      end do stateThenDomain  ! switch between the state and the domain
-
-      !print*, 'after stateThenDomain switch'
-
-      ! -----
-      ! * 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
+  
+                ! 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
+  
+                        ! 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
+                                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
+                                    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
+                  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
+                  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
+  
+                    ! 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!'
+        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
-        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 stateTypeSplitLoop ! state type splitting loop
-
-    ! check
-    !if(ixCoupling/=fullyCoupled)then
-    ! print*, 'PAUSE: end of splitting loop'; read(*,*)
-    !endif
-
-    ! ==========================================================================================================================================
-    ! ==========================================================================================================================================
-
-    ! 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!'
-    print*,message
-    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_dp
-   
-  ! 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
-
-
-  ! print*, "After******"
-  ! print*, "scalarCanairTemp = ", scalarCanairTemp
-  ! print*, "scalarCanopyTemp = ", scalarCanopyTemp
-  ! print*, "scalarCanopyIce = ", scalarCanopyIce
-  ! print*, "scalarCanopyLiq = ", scalarCanopyLiq
-  ! print*, "scalarCanopyWat = ", scalarCanopyWat
-  ! print*, "mLayerTemp = ", mLayerTemp(1)
-  ! print*, "mLayerVolFracIce = ", mLayerVolFracIce(1)
-  ! print*, "mLayerVolFracLiq = ", mLayerVolFracLiq(1)
-  ! print*, "mLayerVolFracWat = ", mLayerVolFracWat(1)
-  ! print*, "mLayerMatricHead = ", mLayerMatricHead(1)
-  ! print*, "mLayerMatricHeadLiq = ", mLayerMatricHeadLiq(1)
-  ! 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,&
+      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
- ! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- ! 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)
-
-  ! check
-  case default; err=20; message=trim(message)//'unable to identify coupling method'; return
- end select  ! (selecting solution method)
-
- !print*, 'stateMask = ', stateMask
-
- ! 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
-
- endif
-
- ! get the number of selected state variables
- nSubset = count(stateMask)
-
- ! end associations
- end associate
-
- end subroutine stateFilter
-
-end module opSplittin_module
+  
+    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
+      ! --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+      ! 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)
+  
+          ! 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.
+  
+        ! check
+        if(count(stateMask)/=1)then
+          message=trim(message)//'expect size=1 (scalar)'
+          err=20; return
+        endif
+  
+      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
diff --git a/build/source/engine/sundials/computJacobSundials.f90 b/build/source/engine/sundials/computJacobSundials.f90
index e0f6df8..9f6bf29 100644
--- a/build/source/engine/sundials/computJacobSundials.f90
+++ b/build/source/engine/sundials/computJacobSundials.f90
@@ -20,1101 +20,990 @@
 
 module computJacobSundials_module
 
-  ! data types
-  USE nrtype
-  USE type4IDA
-  
-  ! derived types to define the data structures
-  USE data_types,only:&
-                      var_i,        & ! data vector (i4b)
-                      var_d,        & ! data vector (rkind)
-                      var_ilength,  & ! data vector with variable length dimension (i4b)
-                      var_dlength,  & ! data vector with variable length dimension (rkind)
-                      model_options   ! defines the model decisions
-  
-  ! named variables for structure elements
-  USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
-  USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
-  USE var_lookup,only:iLookPROG                    ! named variables for structure elements
-  USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
-  
-  ! access the global print flag
-  USE globalData,only:globalPrintFlag
-  
-  ! access missing values
-  USE globalData,only:integerMissing  ! missing integer
-  USE globalData,only:realMissing     ! missing real number
-  USE globalData,only:quadMissing     ! missing quadruple precision number
-  
-  ! domain types
-  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
-  
-  ! named variables to describe the state variable type
-  USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
-  USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
-  USE globalData,only:iname_watCanopy ! named variable defining the mass of 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:model_decisions ! model decision structure
-  
-  ! access named variables to describe the form and structure of the matrices used in the numerical solver
-  USE globalData,only: ku             ! number of super-diagonal bands
-  USE globalData,only: kl             ! number of sub-diagonal bands
-  USE globalData,only: ixDiag         ! index for the diagonal band
-  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
-  
-  ! constants
-  USE multiconst,only:&
-                      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)
-  
-  ! 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
-  
-  ! look-up values for the form of Richards' equation
-  USE mDecisions_module,only:  &
-   moisture,                   & ! moisture-based form of Richards' equation
-   mixdform                      ! mixed form of Richards' equation
-  
-  use, intrinsic :: iso_c_binding
-  
+! data types
+USE nrtype
+
+! derived types to define the data structures
+USE data_types,only:&
+                    var_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength     ! data vector with variable length dimension (rkind)
+
+! 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:iLookINDEX      ! named variables for structure elements
+USE var_lookup,only:iLookDERIV      ! named variables for structure elements
+
+! look-up values for the form of Richards' equation
+USE mDecisions_module,only:       &
+  moisture,                        & ! moisture-based form of Richards' equation
+  mixdform                           ! mixed form of Richards' equation
+
+! access the global print flag
+USE globalData,only:globalPrintFlag
+
+! access missing values
+USE globalData,only:integerMissing  ! missing integer
+USE globalData,only:realMissing     ! missing real number
+
+! domain types
+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
+
+! named variables to describe the state variable type
+USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
+USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
+USE globalData,only:iname_watCanopy ! named variable defining the mass of 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
+
+! access named variables to describe the form and structure of the matrices used in the numerical solver
+USE globalData,only: ku             ! number of super-diagonal bands
+USE globalData,only: kl             ! number of sub-diagonal bands
+USE globalData,only: ixDiag         ! index for the diagonal band
+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
+
+! constants
+USE multiconst,only:&
+                    LH_fus,       & ! latent heat of fusion                (J kg-1)
+                    iden_water      ! intrinsic density of liquid water    (kg m-3)
+
+implicit none
+! define constants
+real(rkind),parameter     :: verySmall=tiny(1.0_rkind)     ! a very small number
+integer(i4b),parameter    :: ixBandOffset=kl+ku+1          ! offset in the band Jacobian matrix
+
+private
+public::computJacobSundials
+contains
+
+! **********************************************************************************************************
+! public subroutine computJacobSundials: compute the Jacobian matrix
+! **********************************************************************************************************
+subroutine computJacobSundials(&
+                      ! input: model control
+                      cj,                         & ! intent(in):    this scalar changes whenever the step size or method order changes
+                      dt,                         & ! intent(in):    length of the time step (seconds)
+                      nSnow,                      & ! intent(in):    number of snow layers
+                      nSoil,                      & ! intent(in):    number of soil layers
+                      nLayers,                    & ! intent(in):    total number of layers
+                      computeVegFlux,             & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      computeBaseflow,            & ! intent(in):    flag to indicate if we need to compute baseflow
+                      ixMatrix,                   & ! intent(in):    form of the Jacobian matrix
+                      specificStorage,            & ! intent(in):    specific storage coefficient (m-1)
+                      theta_sat,                  & ! intent(in):    soil porosity (-)
+                      ixRichards,                 & ! intent(in):    choice of option for Richards' equation
+                      ! input: data structures
+                      indx_data,                  & ! intent(in):    index data
+                      prog_data,                  & ! intent(in):    model prognostic variables for a local HRU
+                      diag_data,                  & ! intent(in):    model diagnostic variables for a local HRU
+                      deriv_data,                 & ! intent(in):    derivatives in model fluxes w.r.t. relevant state variables
+                      dBaseflow_dMatric,          & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
+                      ! input: state variables
+                      mLayerTemp,                 & ! intent(in):    vector of layer temperature (K)
+                      mLayerTempPrime,            & ! intent(in):    vector of derivative value for layer temperature (K)
+                      mLayerMatricHeadPrime,      & ! intent(in)
+                      mLayerMatricHeadLiqPrime,   & ! intent(in)
+                      mLayerVolFracWatPrime,      & ! intent(in)
+                      scalarCanopyTemp,           & ! intent(in):    temperature of the vegetation canopy (K)
+                      scalarCanopyTempPrime,      & ! intent(in):    derivative value for temperature of the vegetation canopy (K)
+                      scalarCanopyWatPrime,       & ! intent(in)
+                      ! input-output: Jacobian and its diagonal
+                      dMat,                       & ! intent(inout): diagonal of the Jacobian matrix
+                      aJac,                       & ! intent(out):   Jacobian matrix
+                      ! output: error control
+                      err,message)                  ! intent(out):   error code and error message
+  ! -----------------------------------------------------------------------------------------------------------------
   implicit none
-  ! define constants
-  real(rkind),parameter     :: verySmall=tiny(1.0_rkind)     ! a very small number
-  integer(i4b),parameter    :: ixBandOffset=kl+ku+1          ! offset in the band Jacobian matrix
-  
-  private
-  public::computJacobSundials
-  public::computJacobSetup
-  public::computJacob4IDA
-  contains
-  
-   ! **********************************************************************************************************
-   ! public subroutine computJacobSundials: compute the Jacobian matrix
-   ! **********************************************************************************************************
-   subroutine computJacobSundials(&
-                          ! input: model control
-                          cj,                         & ! intent(in):    this scalar changes whenever the step size or method order changes
-                          dt,                         & ! intent(in):    length of the time step (seconds)
-                          nSnow,                      & ! intent(in):    number of snow layers
-                          nSoil,                      & ! intent(in):    number of soil layers
-                          nLayers,                    & ! intent(in):    total number of layers
-                          computeVegFlux,             & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                          computeBaseflow,            & ! intent(in):    flag to indicate if we need to compute baseflow
-                          ixMatrix,                   & ! intent(in):    form of the Jacobian matrix
-                          specificStorage,            & ! intent(in):    specific storage coefficient (m-1)
-                          theta_sat,                  & ! intent(in):    soil porosity (-)
-                          ixRichards,                 & ! intent(in):    choice of option for Richards' equation
-                          ! input: data structures
-                          indx_data,                  & ! intent(in):    index data
-                          prog_data,                  & ! intent(in):    model prognostic variables for a local HRU
-                          diag_data,                  & ! intent(in):    model diagnostic variables for a local HRU
-                          deriv_data,                 & ! intent(in):    derivatives in model fluxes w.r.t. relevant state variables
-                          dBaseflow_dMatric,          & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
-                          ! input: state variables
-                          mLayerTempPrime,            & ! intent(in):    vector of derivative value for layer temperature (K)
-                          mLayerMatricHeadPrime,      & ! intent(in)
-                          mLayerMatricHeadLiqPrime,   & ! intent(in)
-                          mLayerVolFracWatPrime,      & ! intent(in)
-                          scalarCanopyTempPrime,      & ! intent(in):    derivative value for temperature of the vegetation canopy (K)
-                          scalarCanopyWatPrime,       & ! intent(in)
-                          ! input-output: Jacobian and its diagonal
-                          dMat,                       & ! intent(inout): diagonal of the Jacobian matrix
-                          aJac,                       & ! intent(out):   Jacobian matrix
-                          ! output: error control
-                          err,message)                  ! intent(out):   error code and error message
-   ! -----------------------------------------------------------------------------------------------------------------
-   implicit none
-   ! input: model control
-   real(rkind),intent(in)               :: cj
-   real(rkind),intent(in)               :: dt                         ! length of the time step (seconds)
-   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 in the snow+soil domain
-   logical(lgt),intent(in)              :: computeVegFlux             ! flag to indicate if computing fluxes over vegetation
-   logical(lgt),intent(in)              :: computeBaseflow            ! flag to indicate if computing baseflow
-   integer(i4b),intent(in)              :: ixMatrix                   ! form of the Jacobian matrix
-   real(rkind),intent(in)               :: specificStorage            ! specific storage coefficient (m-1)
-   real(rkind),intent(in)               :: theta_sat(:)               ! soil porosity (-)
-   integer(i4b),intent(in)              :: ixRichards                 ! choice of option for Richards' equation
-   ! input: data structures
-   type(var_ilength),intent(in)         :: indx_data                  ! indices defining model states and layers
-   type(var_dlength),intent(in)         :: prog_data                  ! prognostic variables for a local HRU
-   type(var_dlength),intent(in)         :: diag_data                  ! diagnostic variables for a local HRU
-   type(var_dlength),intent(in)         :: deriv_data                 ! derivatives in model fluxes w.r.t. relevant state variables
-   real(rkind),intent(in)               :: dBaseflow_dMatric(:,:)     ! derivative in baseflow w.r.t. matric head (s-1)
-   ! input: state variables
-   real(rkind),intent(in)               :: mLayerTempPrime(:)
-   real(rkind),intent(in)               :: mLayerMatricHeadPrime(:)
-   real(rkind),intent(in)               :: mLayerMatricHeadLiqPrime(:)
-   real(rkind),intent(in)               :: mLayerVolFracWatPrime(:)
-   real(rkind),intent(in)               :: scalarCanopyTempPrime     ! derivative value for temperature of the vegetation canopy (K)
-   real(rkind),intent(in)               :: scalarCanopyWatPrime
-   ! input-output: Jacobian and its diagonal
-   real(rkind),intent(inout)            :: dMat(:)         ! diagonal of the Jacobian matrix
-   real(rkind),intent(out)              :: aJac(:,:)       ! Jacobian matrix
-   ! output variables
-   integer(i4b),intent(out)             :: err             ! error code
-   character(*),intent(out)             :: message         ! error message
-   ! --------------------------------------------------------------
-   ! * local variables
-   ! --------------------------------------------------------------
-   ! indices of model state variables
-   integer(i4b)                         :: jState          ! index of state within the state subset
-   integer(i4b)                         :: qState          ! index of cross-derivative state variable for baseflow
-   integer(i4b)                         :: nrgState        ! energy state variable
-   integer(i4b)                         :: watState        ! hydrology state variable
-   integer(i4b)                         :: nState          ! number of state variables
-   ! indices of model layers
-   integer(i4b)                         :: iLayer          ! index of model layer
-   integer(i4b)                         :: jLayer          ! index of model layer within the full state vector (hydrology)
-   integer(i4b)                         :: pLayer          ! indices of soil layers (used for the baseflow derivatives)
-   ! conversion factors
-   real(rkind)                          :: convLiq2tot     ! factor to convert liquid water derivative to total water derivative
-   ! --------------------------------------------------------------
-   ! associate variables from data structures
-   associate(&
-   ! indices of model state variables
-   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)
-   ixTopNrg                     => indx_data%var(iLookINDEX%ixTopNrg)%dat(1)                       ,& ! intent(in): [i4b] index of upper-most energy state in the snow+soil subdomain
-   ixTopHyd                     => indx_data%var(iLookINDEX%ixTopHyd)%dat(1)                       ,& ! intent(in): [i4b] index of upper-most hydrology state in the snow+soil subdomain
-   ixAqWat                      => indx_data%var(iLookINDEX%ixAqWat)%dat(1)                        ,& ! intent(in): [i4b] index of water storage in the aquifer
-   ! vectors of indices for specfic state types within specific sub-domains IN THE FULL STATE VECTOR
-   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
-   ! vector of energy indices for the snow and soil domains
-   ! NOTE: states not in the subset are equal to integerMissing
-   ixSnowSoilNrg                => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the snow+soil domain
-   ixSnowOnlyNrg                => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the snow domain
-   ixSoilOnlyNrg                => indx_data%var(iLookINDEX%ixSoilOnlyNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the soil domain
-   ! vector of hydrology indices for the snow and soil domains
-   ! NOTE: states not in the subset are equal to integerMissing
-   ixSnowSoilHyd                => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain
-   ixSnowOnlyHyd                => indx_data%var(iLookINDEX%ixSnowOnlyHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the snow domain
-   ixSoilOnlyHyd                => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the soil domain
-   ! number of state variables of a specific type
-   nSnowSoilNrg                 => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the snow+soil domain
-   nSnowOnlyNrg                 => indx_data%var(iLookINDEX%nSnowOnlyNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the snow domain
-   nSoilOnlyNrg                 => indx_data%var(iLookINDEX%nSoilOnlyNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the soil domain
-   nSnowSoilHyd                 => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the snow+soil domain
-   nSnowOnlyHyd                 => indx_data%var(iLookINDEX%nSnowOnlyHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the snow domain
-   nSoilOnlyHyd                 => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the soil domain
-   ! type and index of model control volume
-   ixHydType                    => indx_data%var(iLookINDEX%ixHydType)%dat                         ,& ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
-   ixDomainType                 => indx_data%var(iLookINDEX%ixDomainType)%dat                      ,& ! intent(in): [i4b(:)] indices defining the type of the domain (iname_veg, iname_snow, iname_soil)
-   ixControlVolume              => indx_data%var(iLookINDEX%ixControlVolume)%dat                   ,& ! intent(in): [i4b(:)] index of the control volume for specific model domains
-   ! mapping between states and model layers
-   ixMapSubset2Full             => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat                  ,& ! intent(in): [i4b(:)] list of indices in the full state vector that are in the state subset
-   ixMapFull2Subset             => indx_data%var(iLookINDEX%ixMapFull2Subset)%dat                  ,& ! intent(in): [i4b(:)] list of indices in the state subset in each element of the full state vector
-   ! derivatives in net vegetation energy fluxes w.r.t. relevant state variables
-   dCanairNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. canopy air temperature
-   dCanairNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. canopy temperature
-   dCanairNetFlux_dGroundTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dGroundTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. ground temperature
-   dCanopyNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. canopy air temperature
-   dCanopyNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. canopy temperature
-   dCanopyNetFlux_dGroundTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dGroundTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. ground temperature
-   dCanopyNetFlux_dCanWat       => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanWat      )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy fluxes w.r.t. canopy total water content
-   dGroundNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground flux w.r.t. canopy air temperature
-   dGroundNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground flux w.r.t. canopy temperature
-   dGroundNetFlux_dCanWat       => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanWat      )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground fluxes w.r.t. canopy total water content
-   ! derivatives in evaporative fluxes w.r.t. relevant state variables
-   dCanopyEvaporation_dTCanair  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTCanair )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy air temperature
-   dCanopyEvaporation_dTCanopy  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTCanopy )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy temperature
-   dCanopyEvaporation_dTGround  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTGround )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. ground temperature
-   dCanopyEvaporation_dCanWat   => deriv_data%var(iLookDERIV%dCanopyEvaporation_dCanWat  )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy total water content
-   dGroundEvaporation_dTCanair  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTCanair )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy air temperature
-   dGroundEvaporation_dTCanopy  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTCanopy )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy temperature
-   dGroundEvaporation_dTGround  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTGround )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. ground temperature
-   dGroundEvaporation_dCanWat   => deriv_data%var(iLookDERIV%dGroundEvaporation_dCanWat  )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy total water content
-   ! derivatives in canopy water w.r.t canopy temperature
-   dCanLiq_dTcanopy             => deriv_data%var(iLookDERIV%dCanLiq_dTcanopy            )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy liquid storage w.r.t. temperature
-   dTheta_dTkCanopy             => deriv_data%var(iLookDERIV%dTheta_dTkCanopy            )%dat(1)  ,& ! intent(in): [dp]     derivative in volumetric liquid water content w.r.t. temperature
-   d2Theta_dTkCanopy2           => deriv_data%var(iLookDERIV%d2Theta_dTkCanopy2          )%dat(1)  ,& ! intent(in): [dp]     second derivative of volumetric liquid water content w.r.t. temperature
-   dFracLiqVeg_dTkCanopy        => deriv_data%var(iLookDERIV%dFracLiqVeg_dTkCanopy       )%dat(1)  ,& ! intent(in): [dp]     derivative in fraction of (throughfall + drainage)  w.r.t. temperature
-   ! derivatives in canopy liquid fluxes w.r.t. canopy water
-   scalarCanopyLiqDeriv         => deriv_data%var(iLookDERIV%scalarCanopyLiqDeriv        )%dat(1)  ,& ! intent(in): [dp]     derivative in (throughfall + drainage) w.r.t. canopy liquid water
-   ! derivatives in energy fluxes at the interface of snow+soil layers w.r.t. temperature in layers above and below
-   dNrgFlux_dTempAbove          => deriv_data%var(iLookDERIV%dNrgFlux_dTempAbove         )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. temperature in the layer above
-   dNrgFlux_dTempBelow          => deriv_data%var(iLookDERIV%dNrgFlux_dTempBelow         )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. temperature in the layer below
-   ! derivatives in energy fluxes at the interface of snow+soil layers w.r.t. water state in layers above and below
-   dNrgFlux_dWatAbove           => deriv_data%var(iLookDERIV%dNrgFlux_dWatAbove          )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. water state in the layer above
-   dNrgFlux_dWatBelow           => deriv_data%var(iLookDERIV%dNrgFlux_dWatBelow          )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. water state in the layer below
-   ! derivatives in soil transpiration w.r.t. canopy state variables
-   mLayerdTrans_dTCanair        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanair       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
-   mLayerdTrans_dTCanopy        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanopy       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy temperature
-   mLayerdTrans_dTGround        => deriv_data%var(iLookDERIV%mLayerdTrans_dTGround       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. ground temperature
-   mLayerdTrans_dCanWat         => deriv_data%var(iLookDERIV%mLayerdTrans_dCanWat        )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy total water
-   ! derivatives in aquifer transpiration w.r.t. canopy state variables
-   dAquiferTrans_dTCanair       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanair      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy air temperature
-   dAquiferTrans_dTCanopy       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanopy      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy temperature
-   dAquiferTrans_dTGround       => deriv_data%var(iLookDERIV%dAquiferTrans_dTGround      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. ground temperature
-   dAquiferTrans_dCanWat        => deriv_data%var(iLookDERIV%dAquiferTrans_dCanWat       )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy total water
-   ! derivative in liquid water fluxes at the interface of snow layers w.r.t. volumetric liquid water content in the layer above
-   iLayerLiqFluxSnowDeriv       => deriv_data%var(iLookDERIV%iLayerLiqFluxSnowDeriv      )%dat     ,& ! intent(in): [dp(:)]  derivative in vertical liquid water flux at layer interfaces
-   ! derivative in liquid water fluxes for the soil domain w.r.t hydrology state variables
-   dVolTot_dPsi0                => deriv_data%var(iLookDERIV%dVolTot_dPsi0               )%dat     ,& ! intent(in): [dp(:)]  derivative in total water content w.r.t. total water matric potential
-   d2VolTot_d2Psi0              => deriv_data%var(iLookDERIV%d2VolTot_d2Psi0             )%dat     ,& ! intent(in): [dp(:)]  second derivative in total water content w.r.t. total water matric potential
-   dCompress_dPsi               => deriv_data%var(iLookDERIV%dCompress_dPsi              )%dat     ,& ! intent(in): [dp(:)]  derivative in compressibility w.r.t matric head
-   dq_dHydStateAbove            => deriv_data%var(iLookDERIV%dq_dHydStateAbove           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer above
-   dq_dHydStateBelow            => deriv_data%var(iLookDERIV%dq_dHydStateBelow           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer below
-   dq_dHydStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dHydStateLayerSurfVec    )%dat     ,& ! intent(in): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
-   ! derivative in baseflow flux w.r.t. aquifer storage
-   dBaseflow_dAquifer           => deriv_data%var(iLookDERIV%dBaseflow_dAquifer          )%dat(1)  ,& ! intent(in): [dp(:)] derivative in baseflow flux w.r.t. aquifer storage (s-1)
-   ! derivative in liquid water fluxes for the soil domain w.r.t energy state variables
-   dq_dNrgStateAbove            => deriv_data%var(iLookDERIV%dq_dNrgStateAbove           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer above
-   dq_dNrgStateBelow            => deriv_data%var(iLookDERIV%dq_dNrgStateBelow           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer below
-   dq_dNrgStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dNrgStateLayerSurfVec    )%dat     ,& ! intent(in): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
-   ! derivative in liquid water fluxes for the soil and snow domain w.r.t temperature
-   dFracLiqSnow_dTk             => deriv_data%var(iLookDERIV%dFracLiqSnow_dTk            )%dat     ,& ! intent(in): [dp(:)]  derivative in fraction of liquid snow w.r.t. temperature
-   mLayerdTheta_dTk             => deriv_data%var(iLookDERIV%mLayerdTheta_dTk            )%dat     ,& ! intent(in): [dp(:)]  derivative in volumetric liquid water content w.r.t. temperature
-   mLayerd2Theta_dTk2           => deriv_data%var(iLookDERIV%mLayerd2Theta_dTk2          )%dat     ,& ! intent(in): [dp(:)]  second derivative of volumetric liquid water content w.r.t. temperature
-   ! derivate in bulk heat capacity w.r.t. relevant state variables
-   dVolHtCapBulk_dPsi0          => deriv_data%var(iLookDERIV%dVolHtCapBulk_dPsi0         )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. matric potential
-   dVolHtCapBulk_dTheta         => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTheta        )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. volumetric water content
-   dVolHtCapBulk_dCanWat        => deriv_data%var(iLookDERIV%dVolHtCapBulk_dCanWat       )%dat(1)  ,& ! intent(in): [dp]     derivative in bulk heat capacity w.r.t. volumetric water content
-   dVolHtCapBulk_dTk            => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTk           )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. temperature
-   dVolHtCapBulk_dTkCanopy      => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTkCanopy     )%dat(1)  ,& ! intent(in): [dp]     derivative in bulk heat capacity w.r.t. temperature
-   ! diagnostic variables
-   scalarFracLiqVeg             => diag_data%var(iLookDIAG%scalarFracLiqVeg              )%dat(1)  ,& ! intent(in): [dp]     fraction of liquid water on vegetation (-)
-   scalarBulkVolHeatCapVeg      => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg       )%dat(1)  ,& ! intent(in): [dp]     bulk volumetric heat capacity of vegetation (J m-3 K-1)
-   mLayerFracLiqSnow            => diag_data%var(iLookDIAG%mLayerFracLiqSnow             )%dat     ,& ! intent(in): [dp(:)]  fraction of liquid water in each snow layer (-)
-   mLayerVolHtCapBulk           => diag_data%var(iLookDIAG%mLayerVolHtCapBulk            )%dat     ,& ! intent(in): [dp(:)]  bulk volumetric heat capacity in each snow and soil layer (J m-3 K-1)
-   scalarSoilControl            => diag_data%var(iLookDIAG%scalarSoilControl             )%dat(1)  ,& ! intent(in): [dp]     soil control on infiltration, zero or one
-   ! canopy and layer depth
-   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)
-   layerType                    => indx_data%var(iLookINDEX%layerType                    )%dat      & ! intent(in): [i4b(:)] named variables defining the type of layer in snow+soil domain
-   ) ! making association with data in structures
-   ! --------------------------------------------------------------
-   ! initialize error control
-   err=0; message='computJacobSundials/'
-  
-   ! *********************************************************************************************************************************************************
-   ! *********************************************************************************************************************************************************
-   ! * PART 0: PRELIMINARIES (INITIALIZE JACOBIAN AND COMPUTE TIME-VARIABLE DIAGONAL TERMS)
-   ! *********************************************************************************************************************************************************
-   ! *********************************************************************************************************************************************************
-  
-   ! get the number of state variables
-   nState = size(dMat)
-  
-   ! initialize the Jacobian
-   ! NOTE: this needs to be done every time, since Jacobian matrix is modified in the solver
-   aJac(:,:) = 0._rkind  ! analytical Jacobian matrix
-  
-   ! compute terms in the Jacobian for vegetation (excluding fluxes)
-   ! NOTE: energy for vegetation is computed *within* the iteration loop as it includes phase change
-   if(ixVegNrg/=integerMissing)then
-    dMat(ixVegNrg) = ( scalarBulkVolHeatCapVeg + LH_fus*iden_water*dTheta_dTkCanopy ) * cj &
-                     + dVolHtCapBulk_dTkCanopy * scalarCanopyTempPrime &
-                     + LH_fus*iden_water * scalarCanopyTempPrime * d2Theta_dTkCanopy2 &
-                     + LH_fus            * dFracLiqVeg_dTkCanopy * scalarCanopyWatPrime / canopyDepth
-   endif
-  
-   ! compute additional terms for the Jacobian for the snow-soil domain (excluding fluxes)
-   ! NOTE: energy for snow+soil is computed *within* the iteration loop as it includes phase change
-   do iLayer=1,nLayers
-    if(ixSnowSoilNrg(iLayer)/=integerMissing)then
-     dMat(ixSnowSoilNrg(iLayer)) = ( mLayerVolHtCapBulk(iLayer) + LH_fus*iden_water*mLayerdTheta_dTk(iLayer) ) * cj &
-                                   + dVolHtCapBulk_dTk(iLayer) * mLayerTempPrime(iLayer) &
-                                   + LH_fus*iden_water * mLayerTempPrime(iLayer)  * mLayerd2Theta_dTk2(iLayer) &
-                                   + LH_fus*iden_water * dFracLiqSnow_dTk(iLayer) * mLayerVolFracWatPrime(iLayer)
-    endif
-   end do
-  
-   ! compute additional terms for the Jacobian for the soil domain (excluding fluxes)
-   do iLayer=1,nSoil
-    if(ixSoilOnlyHyd(iLayer)/=integerMissing)then
-     dMat(ixSoilOnlyHyd(iLayer)) = ( dVolTot_dPsi0(iLayer) + dCompress_dPsi(iLayer) ) * cj + d2VolTot_d2Psi0(iLayer) * mLayerMatricHeadPrime(iLayer)
-  
-     if(ixRichards==mixdform)then
-      dMat(ixSoilOnlyHyd(iLayer)) = dMat(ixSoilOnlyHyd(iLayer)) + specificStorage * dVolTot_dPsi0(iLayer) * mLayerMatricHeadPrime(iLayer) / theta_sat(iLayer)
-     endif
-  
-    endif
-   end do
-  
-   ! define the form of the matrix
-   select case(ixMatrix)
-  
-    ! *********************************************************************************************************************************************************
-    ! *********************************************************************************************************************************************************
-    ! * PART 1: BAND MATRIX
-    ! *********************************************************************************************************************************************************
-    ! *********************************************************************************************************************************************************
-    case(ixBandMatrix)  ! ixBandMatrix ixFullMatrix
-    print *, 'banded jacobian matrix needs to be implemented'
-    stop 1
-  
+  ! input: model control
+  real(rkind),intent(in)               :: cj
+  real(rkind),intent(in)               :: dt                         ! length of the time step (seconds)
+  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 in the snow+soil domain
+  logical(lgt),intent(in)              :: computeVegFlux             ! flag to indicate if computing fluxes over vegetation
+  logical(lgt),intent(in)              :: computeBaseflow            ! flag to indicate if computing baseflow
+  integer(i4b),intent(in)              :: ixMatrix                   ! form of the Jacobian matrix
+  real(rkind),intent(in)               :: specificStorage            ! specific storage coefficient (m-1)
+  real(rkind),intent(in)               :: theta_sat(:)               ! soil porosity (-)
+  integer(i4b),intent(in)              :: ixRichards                 ! choice of option for Richards' equation
+  ! input: data structures
+  type(var_ilength),intent(in)         :: indx_data                  ! indices defining model states and layers
+  type(var_dlength),intent(in)         :: prog_data                  ! prognostic variables for a local HRU
+  type(var_dlength),intent(in)         :: diag_data                  ! diagnostic variables for a local HRU
+  type(var_dlength),intent(in)         :: deriv_data                 ! derivatives in model fluxes w.r.t. relevant state variables
+  real(rkind),intent(in)               :: dBaseflow_dMatric(:,:)     ! derivative in baseflow w.r.t. matric head (s-1)
+  ! input: state variables
+  real(rkind),intent(in)               :: mLayerTemp(:)
+  real(rkind),intent(in)               :: mLayerTempPrime(:)
+  real(rkind),intent(in)               :: mLayerMatricHeadPrime(:)
+  real(rkind),intent(in)               :: mLayerMatricHeadLiqPrime(:)
+  real(rkind),intent(in)               :: mLayerVolFracWatPrime(:)
+  real(rkind),intent(in)               :: scalarCanopyTemp
+  real(rkind),intent(in)               :: scalarCanopyTempPrime     ! derivative value for temperature of the vegetation canopy (K)
+  real(rkind),intent(in)               :: scalarCanopyWatPrime
+  ! input-output: Jacobian and its diagonal
+  real(rkind),intent(inout)            :: dMat(:)         ! diagonal of the Jacobian matrix
+  real(rkind),intent(out)              :: aJac(:,:)       ! Jacobian matrix
+  ! output variables
+  integer(i4b),intent(out)             :: err             ! error code
+  character(*),intent(out)             :: message         ! error message
+  ! --------------------------------------------------------------
+  ! * local variables
+  ! --------------------------------------------------------------
+  ! indices of model state variables
+  integer(i4b)                         :: jState          ! index of state within the state subset
+  integer(i4b)                         :: qState          ! index of cross-derivative state variable for baseflow
+  integer(i4b)                         :: nrgState        ! energy state variable
+  integer(i4b)                         :: watState        ! hydrology state variable
+  integer(i4b)                         :: nState          ! number of state variables
+  ! indices of model layers
+  integer(i4b)                         :: iLayer          ! index of model layer
+  integer(i4b)                         :: jLayer          ! index of model layer within the full state vector (hydrology)
+  integer(i4b)                         :: pLayer          ! indices of soil layers (used for the baseflow derivatives)
+  ! conversion factors
+  real(rkind)                          :: convLiq2tot     ! factor to convert liquid water derivative to total water derivative
+  ! --------------------------------------------------------------
+  ! associate variables from data structures
+  associate(&
+    ! indices of model state variables
+    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)
+    ixTopNrg                     => indx_data%var(iLookINDEX%ixTopNrg)%dat(1)                       ,& ! intent(in): [i4b] index of upper-most energy state in the snow+soil subdomain
+    ixTopHyd                     => indx_data%var(iLookINDEX%ixTopHyd)%dat(1)                       ,& ! intent(in): [i4b] index of upper-most hydrology state in the snow+soil subdomain
+    ixAqWat                      => indx_data%var(iLookINDEX%ixAqWat)%dat(1)                        ,& ! intent(in): [i4b] index of water storage in the aquifer
+    ! vectors of indices for specfic state types within specific sub-domains IN THE FULL STATE VECTOR
+    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
+    ! vector of energy indices for the snow and soil domains
+    ! NOTE: states not in the subset are equal to integerMissing
+    ixSnowSoilNrg                => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the snow+soil domain
+    ixSnowOnlyNrg                => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the snow domain
+    ixSoilOnlyNrg                => indx_data%var(iLookINDEX%ixSoilOnlyNrg)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for energy state variables in the soil domain
+    ! vector of hydrology indices for the snow and soil domains
+    ! NOTE: states not in the subset are equal to integerMissing
+    ixSnowSoilHyd                => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the snow+soil domain
+    ixSnowOnlyHyd                => indx_data%var(iLookINDEX%ixSnowOnlyHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the snow domain
+    ixSoilOnlyHyd                => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                     ,& ! intent(in): [i4b(:)] index in the state subset for hydrology state variables in the soil domain
+    ! number of state variables of a specific type
+    nSnowSoilNrg                 => indx_data%var(iLookINDEX%nSnowSoilNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the snow+soil domain
+    nSnowOnlyNrg                 => indx_data%var(iLookINDEX%nSnowOnlyNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the snow domain
+    nSoilOnlyNrg                 => indx_data%var(iLookINDEX%nSoilOnlyNrg )%dat(1)                  ,& ! intent(in): [i4b]    number of energy state variables in the soil domain
+    nSnowSoilHyd                 => indx_data%var(iLookINDEX%nSnowSoilHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the snow+soil domain
+    nSnowOnlyHyd                 => indx_data%var(iLookINDEX%nSnowOnlyHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the snow domain
+    nSoilOnlyHyd                 => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)                  ,& ! intent(in): [i4b]    number of hydrology variables in the soil domain
+    ! type and index of model control volume
+    ixHydType                    => indx_data%var(iLookINDEX%ixHydType)%dat                         ,& ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
+    ixDomainType                 => indx_data%var(iLookINDEX%ixDomainType)%dat                      ,& ! intent(in): [i4b(:)] indices defining the type of the domain (iname_veg, iname_snow, iname_soil)
+    ixControlVolume              => indx_data%var(iLookINDEX%ixControlVolume)%dat                   ,& ! intent(in): [i4b(:)] index of the control volume for specific model domains
+    ! mapping between states and model layers
+    ixMapSubset2Full             => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat                  ,& ! intent(in): [i4b(:)] list of indices in the full state vector that are in the state subset
+    ixMapFull2Subset             => indx_data%var(iLookINDEX%ixMapFull2Subset)%dat                  ,& ! intent(in): [i4b(:)] list of indices in the state subset in each element of the full state vector
+    ! derivatives in net vegetation energy fluxes w.r.t. relevant state variables
+    dCanairNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. canopy air temperature
+    dCanairNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. canopy temperature
+    dCanairNetFlux_dGroundTemp   => deriv_data%var(iLookDERIV%dCanairNetFlux_dGroundTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy air space flux w.r.t. ground temperature
+    dCanopyNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. canopy air temperature
+    dCanopyNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. canopy temperature
+    dCanopyNetFlux_dGroundTemp   => deriv_data%var(iLookDERIV%dCanopyNetFlux_dGroundTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy flux w.r.t. ground temperature
+    dCanopyNetFlux_dCanWat       => deriv_data%var(iLookDERIV%dCanopyNetFlux_dCanWat      )%dat(1)  ,& ! intent(in): [dp]     derivative in net canopy fluxes w.r.t. canopy total water content
+    dGroundNetFlux_dCanairTemp   => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanairTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground flux w.r.t. canopy air temperature
+    dGroundNetFlux_dCanopyTemp   => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanopyTemp  )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground flux w.r.t. canopy temperature
+    dGroundNetFlux_dCanWat       => deriv_data%var(iLookDERIV%dGroundNetFlux_dCanWat      )%dat(1)  ,& ! intent(in): [dp]     derivative in net ground fluxes w.r.t. canopy total water content
+    ! derivatives in evaporative fluxes w.r.t. relevant state variables
+    dCanopyEvaporation_dTCanair  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTCanair )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy air temperature
+    dCanopyEvaporation_dTCanopy  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTCanopy )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy temperature
+    dCanopyEvaporation_dTGround  => deriv_data%var(iLookDERIV%dCanopyEvaporation_dTGround )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. ground temperature
+    dCanopyEvaporation_dCanWat   => deriv_data%var(iLookDERIV%dCanopyEvaporation_dCanWat  )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy evaporation w.r.t. canopy total water content
+    dGroundEvaporation_dTCanair  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTCanair )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy air temperature
+    dGroundEvaporation_dTCanopy  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTCanopy )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy temperature
+    dGroundEvaporation_dTGround  => deriv_data%var(iLookDERIV%dGroundEvaporation_dTGround )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. ground temperature
+    dGroundEvaporation_dCanWat   => deriv_data%var(iLookDERIV%dGroundEvaporation_dCanWat  )%dat(1)  ,& ! intent(in): [dp]     derivative in ground evaporation w.r.t. canopy total water content
+    ! derivatives in canopy water w.r.t canopy temperature
+    dCanLiq_dTcanopy             => deriv_data%var(iLookDERIV%dCanLiq_dTcanopy            )%dat(1)  ,& ! intent(in): [dp]     derivative in canopy liquid storage w.r.t. temperature
+    dTheta_dTkCanopy             => deriv_data%var(iLookDERIV%dTheta_dTkCanopy            )%dat(1)  ,& ! intent(in): [dp]     derivative in volumetric liquid water content w.r.t. temperature
+    d2Theta_dTkCanopy2           => deriv_data%var(iLookDERIV%d2Theta_dTkCanopy2          )%dat(1)  ,& ! intent(in): [dp]     second derivative of volumetric liquid water content w.r.t. temperature
+    dFracLiqVeg_dTkCanopy        => deriv_data%var(iLookDERIV%dFracLiqVeg_dTkCanopy       )%dat(1)  ,& ! intent(in): [dp]     derivative in fraction of (throughfall + drainage)  w.r.t. temperature
+    ! derivatives in canopy liquid fluxes w.r.t. canopy water
+    scalarCanopyLiqDeriv         => deriv_data%var(iLookDERIV%scalarCanopyLiqDeriv        )%dat(1)  ,& ! intent(in): [dp]     derivative in (throughfall + drainage) w.r.t. canopy liquid water
+    ! derivatives in energy fluxes at the interface of snow+soil layers w.r.t. temperature in layers above and below
+    dNrgFlux_dTempAbove          => deriv_data%var(iLookDERIV%dNrgFlux_dTempAbove         )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. temperature in the layer above
+    dNrgFlux_dTempBelow          => deriv_data%var(iLookDERIV%dNrgFlux_dTempBelow         )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. temperature in the layer below
+    ! derivatives in energy fluxes at the interface of snow+soil layers w.r.t. water state in layers above and below
+    dNrgFlux_dWatAbove           => deriv_data%var(iLookDERIV%dNrgFlux_dWatAbove          )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. water state in the layer above
+    dNrgFlux_dWatBelow           => deriv_data%var(iLookDERIV%dNrgFlux_dWatBelow          )%dat     ,& ! intent(in): [dp(:)]  derivatives in the flux w.r.t. water state in the layer below
+    ! derivatives in soil transpiration w.r.t. canopy state variables
+    mLayerdTrans_dTCanair        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanair       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy air temperature
+    mLayerdTrans_dTCanopy        => deriv_data%var(iLookDERIV%mLayerdTrans_dTCanopy       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy temperature
+    mLayerdTrans_dTGround        => deriv_data%var(iLookDERIV%mLayerdTrans_dTGround       )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. ground temperature
+    mLayerdTrans_dCanWat         => deriv_data%var(iLookDERIV%mLayerdTrans_dCanWat        )%dat     ,& ! intent(in): derivatives in the soil layer transpiration flux w.r.t. canopy total water
+    ! derivatives in aquifer transpiration w.r.t. canopy state variables
+    dAquiferTrans_dTCanair       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanair      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy air temperature
+    dAquiferTrans_dTCanopy       => deriv_data%var(iLookDERIV%dAquiferTrans_dTCanopy      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy temperature
+    dAquiferTrans_dTGround       => deriv_data%var(iLookDERIV%dAquiferTrans_dTGround      )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. ground temperature
+    dAquiferTrans_dCanWat        => deriv_data%var(iLookDERIV%dAquiferTrans_dCanWat       )%dat(1)  ,&  ! intent(in): derivatives in the aquifer transpiration flux w.r.t. canopy total water
+    ! derivative in liquid water fluxes at the interface of snow layers w.r.t. volumetric liquid water content in the layer above
+    iLayerLiqFluxSnowDeriv       => deriv_data%var(iLookDERIV%iLayerLiqFluxSnowDeriv      )%dat     ,& ! intent(in): [dp(:)]  derivative in vertical liquid water flux at layer interfaces
+    ! derivative in liquid water fluxes for the soil domain w.r.t hydrology state variables
+    dVolTot_dPsi0                => deriv_data%var(iLookDERIV%dVolTot_dPsi0               )%dat     ,& ! intent(in): [dp(:)]  derivative in total water content w.r.t. total water matric potential
+    d2VolTot_d2Psi0              => deriv_data%var(iLookDERIV%d2VolTot_d2Psi0             )%dat     ,& ! intent(in): [dp(:)]  second derivative in total water content w.r.t. total water matric potential
+    dCompress_dPsi               => deriv_data%var(iLookDERIV%dCompress_dPsi              )%dat     ,& ! intent(in): [dp(:)]  derivative in compressibility w.r.t matric head
+    dq_dHydStateAbove            => deriv_data%var(iLookDERIV%dq_dHydStateAbove           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer above
+    dq_dHydStateBelow            => deriv_data%var(iLookDERIV%dq_dHydStateBelow           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer below
+    dq_dHydStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dHydStateLayerSurfVec    )%dat     ,& ! intent(in): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
+    ! derivative in baseflow flux w.r.t. aquifer storage
+    dBaseflow_dAquifer           => deriv_data%var(iLookDERIV%dBaseflow_dAquifer          )%dat(1)  ,& ! intent(in): [dp(:)] derivative in baseflow flux w.r.t. aquifer storage (s-1)
+    ! derivative in liquid water fluxes for the soil domain w.r.t energy state variables
+    dq_dNrgStateAbove            => deriv_data%var(iLookDERIV%dq_dNrgStateAbove           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer above
+    dq_dNrgStateBelow            => deriv_data%var(iLookDERIV%dq_dNrgStateBelow           )%dat     ,& ! intent(in): [dp(:)]  change in flux at layer interfaces w.r.t. states in the layer below
+    dq_dNrgStateLayerSurfVec     => deriv_data%var(iLookDERIV%dq_dNrgStateLayerSurfVec    )%dat     ,& ! intent(in): [dp(:)] change in the flux in soil surface interface w.r.t. state variables in layers
+    ! derivative in liquid water fluxes for the soil and snow domain w.r.t temperature
+    dFracLiqSnow_dTk             => deriv_data%var(iLookDERIV%dFracLiqSnow_dTk            )%dat     ,& ! intent(in): [dp(:)]  derivative in fraction of liquid snow w.r.t. temperature
+    mLayerdTheta_dTk             => deriv_data%var(iLookDERIV%mLayerdTheta_dTk            )%dat     ,& ! intent(in): [dp(:)]  derivative in volumetric liquid water content w.r.t. temperature
+    mLayerd2Theta_dTk2           => deriv_data%var(iLookDERIV%mLayerd2Theta_dTk2          )%dat     ,& ! intent(in): [dp(:)]  second derivative of volumetric liquid water content w.r.t. temperature
+    ! derivate in bulk heat capacity w.r.t. relevant state variables
+    dVolHtCapBulk_dPsi0          => deriv_data%var(iLookDERIV%dVolHtCapBulk_dPsi0         )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. matric potential
+    dVolHtCapBulk_dTheta         => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTheta        )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. volumetric water content
+    dVolHtCapBulk_dCanWat        => deriv_data%var(iLookDERIV%dVolHtCapBulk_dCanWat       )%dat(1)  ,& ! intent(in): [dp]     derivative in bulk heat capacity w.r.t. volumetric water content
+    dVolHtCapBulk_dTk            => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTk           )%dat     ,& ! intent(in): [dp(:)]  derivative in bulk heat capacity w.r.t. temperature
+    dVolHtCapBulk_dTkCanopy      => deriv_data%var(iLookDERIV%dVolHtCapBulk_dTkCanopy     )%dat(1)  ,& ! intent(in): [dp]     derivative in bulk heat capacity w.r.t. temperature
+    ! diagnostic variables
+    scalarFracLiqVeg             => diag_data%var(iLookDIAG%scalarFracLiqVeg              )%dat(1)  ,& ! intent(in): [dp]     fraction of liquid water on vegetation (-)
+    scalarBulkVolHeatCapVeg      => diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg       )%dat(1)  ,& ! intent(in): [dp]     bulk volumetric heat capacity of vegetation (J m-3 K-1)
+    mLayerFracLiqSnow            => diag_data%var(iLookDIAG%mLayerFracLiqSnow             )%dat     ,& ! intent(in): [dp(:)]  fraction of liquid water in each snow layer (-)
+    mLayerVolHtCapBulk           => diag_data%var(iLookDIAG%mLayerVolHtCapBulk            )%dat     ,& ! intent(in): [dp(:)]  bulk volumetric heat capacity in each snow and soil layer (J m-3 K-1)
+    scalarSoilControl            => diag_data%var(iLookDIAG%scalarSoilControl             )%dat(1)  ,& ! intent(in): [dp]     soil control on infiltration, zero or one
+    ! canopy and layer depth
+    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)
+    layerType                    => indx_data%var(iLookINDEX%layerType                    )%dat      & ! intent(in): [i4b(:)] named variables defining the type of layer in snow+soil domain
+    ) ! making association with data in structures
+    ! --------------------------------------------------------------
+    ! initialize error control
+    err=0; message='computJacobSundials/'
+
     ! *********************************************************************************************************************************************************
     ! *********************************************************************************************************************************************************
-    ! * PART 2: FULL MATRIX
+    ! * PART 0: PRELIMINARIES (INITIALIZE JACOBIAN AND COMPUTE TIME-VARIABLE DIAGONAL TERMS)
     ! *********************************************************************************************************************************************************
     ! *********************************************************************************************************************************************************
-    case(ixFullMatrix)  ! ixFullMatrix ixBandMatrix
-  
-     ! check
-     if(size(aJac,1)/=size(dMat) .or. size(aJac,2)/=size(dMat))then
-      message=trim(message)//'unexpected shape of the Jacobian matrix: expect aJac(nState,nState)'
-      err=20; return
-     endif
-  
-     ! -----
-     ! * energy and liquid fluxes over vegetation...
-     ! ---------------------------------------------
-     if(computeVegFlux)then  ! (derivatives only defined when vegetation protrudes over the surface)
-  
-      ! * energy fluxes with the canopy water
-      if(ixVegHyd/=integerMissing)then
-  
-       ! * cross-derivative terms w.r.t. system temperatures (kg m-2 K-1)
-       if(ixCasNrg/=integerMissing) aJac(ixVegHyd,ixCasNrg) = -dCanopyEvaporation_dTCanair*dt
-       ! dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy is the derivative in throughfall and canopy drainage with canopy temperature
-       if(ixVegNrg/=integerMissing) aJac(ixVegHyd,ixVegNrg) = -dCanopyEvaporation_dTCanopy*dt + dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy
-       ! * liquid water fluxes for vegetation canopy (-), dt*scalarFracLiqVeg*scalarCanopyLiqDeriv is the derivative in throughfall and canopy drainage with canopy water
-                                    aJac(ixVegHyd,ixVegHyd) = -scalarFracLiqVeg*(dCanopyEvaporation_dCanWat - scalarCanopyLiqDeriv)*dt + 1._rkind * cj
-       if(ixTopNrg/=integerMissing) aJac(ixVegHyd,ixTopNrg) = -dCanopyEvaporation_dTGround*dt
-  
-       ! * cross-derivative terms w.r.t. canopy water (kg-1 m2)
-       if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegHyd) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarFracLiqVeg*scalarCanopyLiqDeriv)/iden_water
-  
-       ! * cross-derivative terms w.r.t. canopy liquid water (J m-1 kg-1)
-       ! NOTE: dIce/dLiq = (1 - scalarFracLiqVeg); dIce*LH_fus/canopyDepth = J m-3; dLiq = kg m-2
-       if(ixVegNrg/=integerMissing) aJac(ixVegNrg,ixVegHyd) = (-1._rkind + scalarFracLiqVeg)*LH_fus/canopyDepth * cj &
-                                                             + dVolHtCapBulk_dCanWat * scalarCanopyTempPrime - (dt/canopyDepth) * dCanopyNetFlux_dCanWat &
-                                                             + LH_fus * scalarCanopyTempPrime * dFracLiqVeg_dTkCanopy / canopyDepth ! dF/dLiq
-       if(ixTopNrg/=integerMissing) aJac(ixTopNrg,ixVegHyd) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanWat)
-      endif
-  
-      ! * -derivative terms w.r.t. canopy temperature (K-1)
-      if(ixVegNrg/=integerMissing)then
-       if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegNrg) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarCanopyLiqDeriv*dCanLiq_dTcanopy)/iden_water
-      endif
-  
-      ! * energy fluxes with the canopy air space (J m-3 K-1)
-      if(ixCasNrg/=integerMissing)then
-                                    aJac(ixCasNrg,ixCasNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanairTemp) + dMat(ixCasNrg) * cj
-       if(ixVegNrg/=integerMissing) aJac(ixCasNrg,ixVegNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanopyTemp)
-       if(ixTopNrg/=integerMissing) aJac(ixCasNrg,ixTopNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dGroundTemp)
-      endif
-  
-      ! * energy fluxes with the vegetation canopy (J m-3 K-1)
-      if(ixVegNrg/=integerMissing)then
-       if(ixCasNrg/=integerMissing) aJac(ixVegNrg,ixCasNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanairTemp)
-                                    aJac(ixVegNrg,ixVegNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanopyTemp) + dMat(ixVegNrg)
-       if(ixTopNrg/=integerMissing) aJac(ixVegNrg,ixTopNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dGroundTemp)
-      endif
-  
-      ! * energy fluxes with the surface (J m-3 K-1)
-      if(ixTopNrg/=integerMissing)then
-       if(ixCasNrg/=integerMissing) aJac(ixTopNrg,ixCasNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanairTemp)
-       if(ixVegNrg/=integerMissing) aJac(ixTopNrg,ixVegNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanopyTemp)
+
+    ! get the number of state variables
+    nState = size(dMat)
+
+    ! initialize the Jacobian
+    ! NOTE: this needs to be done every time, since Jacobian matrix is modified in the solver
+    aJac(:,:) = 0._rkind  ! analytical Jacobian matrix
+
+    ! compute terms in the Jacobian for vegetation (excluding fluxes)
+    ! NOTE: energy for vegetation is computed *within* the iteration loop as it includes phase change
+    if(ixVegNrg/=integerMissing)then
+      dMat(ixVegNrg) = ( scalarBulkVolHeatCapVeg + LH_fus*iden_water*dTheta_dTkCanopy ) * cj &
+                      + dVolHtCapBulk_dTkCanopy * scalarCanopyTempPrime &
+                      + LH_fus*iden_water * scalarCanopyTempPrime * d2Theta_dTkCanopy2 &
+                      + LH_fus            * dFracLiqVeg_dTkCanopy * scalarCanopyWatPrime / canopyDepth
+    endif
+
+    ! compute additional terms for the Jacobian for the snow-soil domain (excluding fluxes)
+    ! NOTE: energy for snow+soil is computed *within* the iteration loop as it includes phase change
+    do iLayer=1,nLayers
+      if(ixSnowSoilNrg(iLayer)/=integerMissing)then
+        dMat(ixSnowSoilNrg(iLayer)) = ( mLayerVolHtCapBulk(iLayer) + LH_fus*iden_water*mLayerdTheta_dTk(iLayer) ) * cj &
+                                    + dVolHtCapBulk_dTk(iLayer) * mLayerTempPrime(iLayer) &
+                                    + LH_fus*iden_water * mLayerTempPrime(iLayer)  * mLayerd2Theta_dTk2(iLayer) &
+                                    + LH_fus*iden_water * dFracLiqSnow_dTk(iLayer) * mLayerVolFracWatPrime(iLayer)
       endif
-  
-     endif  ! if there is a need to compute energy fluxes within vegetation
-  
-     ! -----
-     ! * energy fluxes for the snow+soil domain...
-     ! -------------------------------------------
-     if(nSnowSoilNrg>0)then
-      do iLayer=1,nLayers  ! loop through all layers in the snow+soil domain
-  
-       ! check if the state is in the subset
-       if(ixSnowSoilNrg(iLayer)==integerMissing) cycle
-  
-       ! - define index within the state subset and the full state vector
-       jState = ixSnowSoilNrg(iLayer)        ! index within the state subset
-  
-       ! - diagonal elements
-       aJac(jState,jState)   = (dt/mLayerDepth(iLayer))*(-dNrgFlux_dTempBelow(iLayer-1) + dNrgFlux_dTempAbove(iLayer)) + dMat(jState)
-  
-       ! - lower-diagonal elements
-       if(iLayer>1)then
-        if(ixSnowSoilNrg(iLayer-1)/=integerMissing) aJac(ixSnowSoilNrg(iLayer-1),jState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dTempBelow(iLayer-1) )
-       endif
-  
-       ! - upper diagonal elements
-       if(iLayer<nLayers)then
-        if(ixSnowSoilNrg(iLayer+1)/=integerMissing) aJac(ixSnowSoilNrg(iLayer+1),jState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dTempAbove(iLayer  ) )
-       endif
-  
-      end do  ! (looping through energy states in the snow+soil domain)
-     endif   ! (if the subset includes energy state variables in the snow+soil domain)
-  
-     ! -----
-     ! * liquid water fluxes for the snow domain...
-     ! --------------------------------------------
-     if(nSnowOnlyHyd>0)then
-      do iLayer=1,nSnow  ! loop through layers in the snow domain
-  
-       ! - check that the snow layer is desired
-       if(ixSnowOnlyHyd(iLayer)==integerMissing) cycle
-  
-       ! - define state indices for the current layer
-       watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
-  
-       ! compute factor to convert liquid water derivative to total water derivative
-       select case( ixHydType(iLayer) )
-        case(iname_watLayer); convLiq2tot = mLayerFracLiqSnow(iLayer)
-        case default;         convLiq2tot = 1._rkind
-       end select
-  
-       ! - diagonal elements
-       aJac(watState,watState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot + dMat(watState) * cj
-  
-       ! - lower-diagonal elements
-       if(iLayer>1)then
-        if(ixSnowOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSnowOnlyHyd(iLayer-1),watState) = 0._rkind  ! sub-diagonal: no dependence on other layers
-       endif
-  
-       ! - upper diagonal elements
-       if(iLayer<nSnow)then
-        if(ixSnowOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSnowOnlyHyd(iLayer+1),watState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot       ! dVol(below)/dLiq(above) -- (-)
-       endif
-  
-      end do  ! (looping through liquid water states in the snow domain)
-     endif   ! (if the subset includes hydrology state variables in the snow domain)
-  
-     ! -----
-     ! * cross derivatives in the snow domain...
-     ! ----------------------------------------
-     if(nSnowOnlyHyd>0 .and. nSnowOnlyNrg>0)then
-      do iLayer=1,nSnow  ! loop through layers in the snow domain
-  
-       ! - check that the snow layer is desired
-       if(ixSnowOnlyNrg(iLayer)==integerMissing) cycle
-  
-       ! (define the energy state)
-       nrgState = ixSnowOnlyNrg(iLayer)       ! index within the full state vector
-  
-       ! - define state indices for the current layer
-       watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
-  
-       if(watstate/=integerMissing)then       ! (energy state for the current layer is within the state subset)
-  
-        ! - include derivatives of energy fluxes w.r.t water fluxes for current layer
-        aJac(nrgState,watState) = (-1._rkind + mLayerFracLiqSnow(iLayer))*LH_fus*iden_water * cj &
-                                  + dVolHtCapBulk_dTheta(iLayer) * mLayerTempPrime(iLayer) &
-                                  + (dt/mLayerDepth(iLayer))*(-dNrgFlux_dWatBelow(iLayer-1) + dNrgFlux_dWatAbove(iLayer)) &
-                                  + LH_fus*iden_water * mLayerTempPrime(iLayer) * dFracLiqSnow_dTk(iLayer)    ! (dF/dLiq)
-  
-        ! - include derivatives of water fluxes w.r.t energy fluxes for current layer
-        aJac(watState,nrgState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)  ! (dVol/dT)
-  
-        ! (cross-derivative terms for the layer below)
-        if(iLayer<nSnow)then
-         aJac(ixSnowOnlyHyd(iLayer+1),nrgState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)    ! dVol(below)/dT(above) -- K-1
-        endif ! (if there is a water state in the layer below the current layer in the given state subset)
-  
-        ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
-        if(iLayer>1)then
-         if(ixSnowOnlyNrg(iLayer-1)/=integerMissing) aJac(ixSnowOnlyNrg(iLayer-1),watState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dWatBelow(iLayer-1) )
-        endif
-  
-        ! (cross-derivative terms for the layer below)
-        if(iLayer<nSnow)then
-         if(ixSnowOnlyNrg(iLayer+1)/=integerMissing) aJac(ixSnowOnlyNrg(iLayer+1),watState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dWatAbove(iLayer  ) )
-        elseif(iLayer==nSnow .and. nSoilOnlyNrg>0)then !bottom snow layer and there is soil below
-         if(ixSoilOnlyNrg(1)/=integerMissing) aJac(ixSoilOnlyNrg(1),watState) = (dt/mLayerDepth(nSnow+1))*(-dNrgFlux_dWatAbove(nSnow) )
-        endif
-  
-       endif   ! (if the energy state for the current layer is within the state subset)
-  
-      end do  ! (looping through snow layers)
-     endif   ! (if there are state variables for both water and energy in the snow domain)
-  
-     ! -----
-     ! * liquid water fluxes for the soil domain...
-     ! --------------------------------------------
-     if(nSoilOnlyHyd>0)then
-      do iLayer=1,nSoil
-  
-       ! - check that the soil layer is desired
-       if(ixSoilOnlyHyd(iLayer)==integerMissing) cycle
-  
-       ! - define state indices
-       watState = ixSoilOnlyHyd(iLayer)         ! hydrology state index within the state subset
-  
-       ! - define indices of the soil layers
-       jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
-  
-       ! - compute the diagonal elements
-       ! all terms *excluding* baseflow
-       aJac(watState,watState) = (dt/mLayerDepth(jLayer))*(-dq_dHydStateBelow(iLayer-1) + dq_dHydStateAbove(iLayer)) + dMat(watState)
-  
-       ! - compute the lower-diagonal elements
-       if(iLayer>1)then
-        if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer-1),watState) = (dt/mLayerDepth(jLayer-1))*( dq_dHydStateBelow(iLayer-1))
-       endif
-  
-       ! - compute the upper-diagonal elements
-       if(iLayer<nSoil)then
-        if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer+1),watState) = (dt/mLayerDepth(jLayer+1))*(-dq_dHydStateAbove(iLayer))
-       endif
-  
-       ! - include terms for baseflow
-       if(computeBaseflow .and. nSoilOnlyHyd==nSoil)then
-        do pLayer=1,nSoil
-         qState = ixSoilOnlyHyd(pLayer)  ! hydrology state index within the state subset
-         aJac(watState,qState) = (dt/mLayerDepth(jLayer))*dBaseflow_dMatric(iLayer,pLayer) + aJac(watState,qState)
-        end do
-       endif
-  
-       ! - include terms for surface infiltration below surface
-       if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),watState) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(iLayer) + aJac(ixSoilOnlyHyd(1),watState)
-  
-      end do  ! (looping through hydrology states in the soil domain)
-  
-      ! - include terms for surface infiltration above surface
-      if(nSnowOnlyHyd>0 .and. ixSnowOnlyHyd(nSnow)/=integerMissing)then
-       if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),ixSnowOnlyHyd(nSnow)) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(0)
-      elseif(computeVegFlux .and. ixVegHyd/=integerMissing)then !ixTopHyd = ixSoilOnlyHyd(1)
-       if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegHyd) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(0) + aJac(ixTopHyd,ixVegHyd)
+    end do
+
+    ! compute additional terms for the Jacobian for the soil domain (excluding fluxes)
+    do iLayer=1,nSoil
+      if(ixSoilOnlyHyd(iLayer)/=integerMissing)then
+        dMat(ixSoilOnlyHyd(iLayer)) = ( dVolTot_dPsi0(iLayer) + dCompress_dPsi(iLayer) ) * cj + d2VolTot_d2Psi0(iLayer) * mLayerMatricHeadPrime(iLayer)
+
+      if(ixRichards==mixdform)then
+        dMat(ixSoilOnlyHyd(iLayer)) = dMat(ixSoilOnlyHyd(iLayer)) + specificStorage * dVolTot_dPsi0(iLayer) * mLayerMatricHeadPrime(iLayer) / theta_sat(iLayer)
       endif
-  
-     endif   ! (if the subset includes hydrology state variables in the soil domain)
-  
-     ! -----
-     ! * liquid water fluxes for the aquifer...
-     ! ----------------------------------------
-     if(ixAqWat/=integerMissing) then
-      aJac(ixAqWat,ixAqWat) = -dBaseflow_dAquifer*dt + dMat(ixAqWat) * cj
-      aJac(ixAqWat,ixSoilOnlyNrg(nSoil)) = -dq_dNrgStateAbove(nSoil)*dt ! dAquiferRecharge_dTk  = d_iLayerLiqFluxSoil(nSoil)_dTk
-      aJac(ixAqWat,ixSoilOnlyHyd(nSoil)) = -dq_dHydStateAbove(nSoil)*dt ! dAquiferRecharge_dWat = d_iLayerLiqFluxSoil(nSoil)_dWat
-      ! - include derivatives of energy and water w.r.t soil transpiration (dependent on canopy transpiration)
-      if(computeVegFlux)then
-       aJac(ixAqWat,ixCasNrg) = -dAquiferTrans_dTCanair*dt ! dVol/dT (K-1)
-       aJac(ixAqWat,ixVegNrg) = -dAquiferTrans_dTCanopy*dt ! dVol/dT (K-1)
-       aJac(ixAqWat,ixVegHyd) = -dAquiferTrans_dCanWat*dt  ! dVol/dLiq (kg m-2)-1
-       aJac(ixAqWat,ixTopNrg) = -dAquiferTrans_dTGround*dt ! dVol/dT (K-1)
+
       endif
-     endif
-  
-     ! -----
-     ! * cross derivatives in the soil domain...
-     ! ----------------------------------------
-     if(nSoilOnlyHyd>0 .and. nSoilOnlyNrg>0)then
-      do iLayer=1,nSoilOnlyNrg
-  
-       ! - check that the soil layer is desired
-       if(ixSoilOnlyNrg(iLayer)==integerMissing) cycle
-  
-       ! - define indices of the soil layers
-       jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
-  
-       ! - define the energy state variable
-       nrgState = ixNrgLayer(jLayer)       ! index within the full state vector
-  
-       ! - define index of hydrology state variable within the state subset
-       watState = ixSoilOnlyHyd(iLayer)
-  
-       ! only compute derivatives if the water state for the current layer is within the state subset
-       if(watstate/=integerMissing)then
-  
-        ! - include derivatives in liquid water fluxes w.r.t. temperature for current layer
-        aJac(watState,nrgState) = (dt/mLayerDepth(jLayer))*(-dq_dNrgStateBelow(iLayer-1) + dq_dNrgStateAbove(iLayer))   ! dVol/dT (K-1) -- flux depends on ice impedance
-  
-        ! - compute lower diagonal elements
-        if(iLayer>1)then
-         if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer-1),nrgState) = (dt/mLayerDepth(jLayer-1))*( dq_dNrgStateBelow(iLayer-1))   ! K-1
-        endif
-  
-        ! compute upper-diagonal elements
-        if(iLayer<nSoil)then
-         if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer+1),nrgState) = (dt/mLayerDepth(jLayer+1))*(-dq_dNrgStateAbove(iLayer))     ! K-1
+    end do
+
+    ! define the form of the matrix
+    select case(ixMatrix)
+
+      ! *********************************************************************************************************************************************************
+      ! *********************************************************************************************************************************************************
+      ! * PART 1: BAND MATRIX
+      ! *********************************************************************************************************************************************************
+      ! *********************************************************************************************************************************************************
+      case(ixBandMatrix)
+        ! check
+        if(size(aJac,1)/=nBands .or. size(aJac,2)/=size(dMat))then
+          message=trim(message)//'unexpected shape of the Jacobian matrix: expect aJac(nBands,nState)'
+          err=20; return
         endif
-  
-        ! - include derivatives of energy w.r.t. ground evaporation
-        if(nSnow==0 .and. iLayer==1)then  ! upper-most soil layer
-         if(computeVegFlux)then
-          aJac(watState,ixVegHyd) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dCanWat/iden_water)  ! dVol/dLiq (kg m-2)-1
-          aJac(watState,ixCasNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanair/iden_water) ! dVol/dT (K-1)
-          aJac(watState,ixVegNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanopy/iden_water) ! dVol/dT (K-1)
-         endif
-         aJac(watState,ixTopNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTGround/iden_water) + aJac(watState,ixTopNrg) ! dVol/dT (K-1)
+    
+        ! -----
+        ! * energy and liquid fluxes over vegetation...
+        ! ---------------------------------------------
+        if(computeVegFlux)then  ! (derivatives only defined when vegetation protrudes over the surface)
+    
+          ! * energy fluxes with the canopy water
+          if(ixVegHyd/=integerMissing)then
+    
+            ! * cross-derivative terms w.r.t. system temperatures (kg m-2 K-1)
+            if(ixCasNrg/=integerMissing) aJac(ixOffDiag(ixVegHyd,ixCasNrg),ixCasNrg) = -dCanopyEvaporation_dTCanair*dt
+            ! dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy is the derivative in throughfall and canopy drainage with canopy temperature
+            if(ixVegNrg/=integerMissing) aJac(ixOffDiag(ixVegHyd,ixVegNrg),ixVegNrg) = -dCanopyEvaporation_dTCanopy*dt + dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy
+            ! * liquid water fluxes for vegetation canopy (-), dt*scalarFracLiqVeg*scalarCanopyLiqDeriv is the derivative in throughfall and canopy drainage with canopy water
+                                          aJac(ixDiag,                      ixVegHyd) = -scalarFracLiqVeg*(dCanopyEvaporation_dCanWat - scalarCanopyLiqDeriv)*dt + 1._rkind * cj
+            if(ixTopNrg/=integerMissing) aJac(ixOffDiag(ixVegHyd,ixTopNrg),ixTopNrg) = -dCanopyEvaporation_dTGround*dt
+      
+            ! * cross-derivative terms w.r.t. canopy water (kg-1 m2)
+            if(ixTopHyd/=integerMissing) aJac(ixOffDiag(ixTopHyd,ixVegHyd),ixVegHyd) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarFracLiqVeg*scalarCanopyLiqDeriv)/iden_water
+      
+            ! * cross-derivative terms w.r.t. canopy liquid water (J m-1 kg-1)
+            ! NOTE: dIce/dLiq = (1 - scalarFracLiqVeg); dIce*LH_fus/canopyDepth = J m-3; dLiq = kg m-2
+            if(ixVegNrg/=integerMissing) aJac(ixOffDiag(ixVegNrg,ixVegHyd),ixVegHyd) = (-1._rkind + scalarFracLiqVeg)*LH_fus/canopyDepth * cj &
+                                                                                        + dVolHtCapBulk_dCanWat * scalarCanopyTempPrime - (dt/canopyDepth) * dCanopyNetFlux_dCanWat &
+                                                                                        + LH_fus * scalarCanopyTempPrime * dFracLiqVeg_dTkCanopy / canopyDepth ! dF/dLiq
+            if(ixTopNrg/=integerMissing) aJac(ixOffDiag(ixTopNrg,ixVegHyd),ixVegHyd) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanWat)
+          endif
+    
+          ! * -derivative terms w.r.t. canopy temperature (K-1)
+          if(ixVegNrg/=integerMissing)then
+            if(ixTopHyd/=integerMissing) aJac(ixOffDiag(ixTopHyd,ixVegNrg),ixVegNrg) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarCanopyLiqDeriv*dCanLiq_dTcanopy)/iden_water
+          endif
+    
+          ! * energy fluxes with the canopy air space (J m-3 K-1)
+          if(ixCasNrg/=integerMissing)then
+            aJac(ixDiag, ixCasNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanairTemp) + dMat(ixCasNrg) * cj
+            if(ixVegNrg/=integerMissing) aJac(ixOffDiag(ixCasNrg,ixVegNrg),ixVegNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanopyTemp)
+            if(ixTopNrg/=integerMissing) aJac(ixOffDiag(ixCasNrg,ixTopNrg),ixTopNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dGroundTemp)
+          endif
+    
+          ! * energy fluxes with the vegetation canopy (J m-3 K-1)
+          if(ixVegNrg/=integerMissing)then
+            if(ixCasNrg/=integerMissing) aJac(ixOffDiag(ixVegNrg,ixCasNrg),ixCasNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanairTemp)
+            aJac(ixDiag, ixVegNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanopyTemp) + dMat(ixVegNrg)
+            if(ixTopNrg/=integerMissing) aJac(ixOffDiag(ixVegNrg,ixTopNrg),ixTopNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dGroundTemp)
+          endif
+    
+          ! * energy fluxes with the surface (J m-3 K-1)
+          if(ixTopNrg/=integerMissing)then
+            if(ixCasNrg/=integerMissing) aJac(ixOffDiag(ixTopNrg,ixCasNrg),ixCasNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanairTemp)
+            if(ixVegNrg/=integerMissing) aJac(ixOffDiag(ixTopNrg,ixVegNrg),ixVegNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanopyTemp)
+          endif
+    
+        endif  ! if there is a need to compute energy fluxes within vegetation
+    
+        ! -----
+        ! * energy fluxes for the snow+soil domain...
+        ! -------------------------------------------
+        if(nSnowSoilNrg>0)then
+          do iLayer=1,nLayers  ! loop through all layers in the snow+soil domain
+    
+            ! check if the state is in the subset
+            if(ixSnowSoilNrg(iLayer)==integerMissing) cycle
+      
+            ! - define index within the state subset and the full state vector
+            jState = ixSnowSoilNrg(iLayer)        ! index within the state subset
+      
+            ! - diagonal elements
+            aJac(ixDiag,jState)   = (dt/mLayerDepth(iLayer))*(-dNrgFlux_dTempBelow(iLayer-1) + dNrgFlux_dTempAbove(iLayer)) + dMat(jState)
+      
+            ! - lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSnowSoilNrg(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSnowSoilNrg(iLayer-1),jState),jState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dTempBelow(iLayer-1) )
+            endif
+      
+            ! - upper diagonal elements
+            if(iLayer<nLayers)then
+              if(ixSnowSoilNrg(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSnowSoilNrg(iLayer+1),jState),jState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dTempAbove(iLayer  ) )
+            endif
+    
+          end do  ! (looping through energy states in the snow+soil domain)
+        endif   ! (if the subset includes energy state variables in the snow+soil domain)
+    
+        ! -----
+        ! * liquid water fluxes for the snow domain...
+        ! --------------------------------------------
+        if(nSnowOnlyHyd>0)then
+          do iLayer=1,nSnow  ! loop through layers in the snow domain
+    
+            ! - check that the snow layer is desired
+            if(ixSnowOnlyHyd(iLayer)==integerMissing) cycle
+      
+            ! - define state indices for the current layer
+            watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
+    
+            ! compute factor to convert liquid water derivative to total water derivative
+            select case( ixHydType(iLayer) )
+              case(iname_watLayer); convLiq2tot = mLayerFracLiqSnow(iLayer)
+              case default;         convLiq2tot = 1._rkind
+            end select
+    
+            ! - diagonal elements
+            aJac(ixDiag,watState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot + dMat(watState) * cj
+      
+            ! - lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSnowOnlyHyd(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSnowOnlyHyd(iLayer-1),watState),watState) = 0._rkind  ! sub-diagonal: no dependence on other layers
+            endif
+    
+            ! - upper diagonal elements
+            if(iLayer<nSnow)then
+              if(ixSnowOnlyHyd(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSnowOnlyHyd(iLayer+1),watState),watState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot       ! dVol(below)/dLiq(above) -- (-)
+            endif
+    
+          end do  ! (looping through liquid water states in the snow domain)
+        endif   ! (if the subset includes hydrology state variables in the snow domain)
+    
+        ! -----
+        ! * cross derivatives in the snow domain...
+        ! ----------------------------------------
+        if(nSnowOnlyHyd>0 .and. nSnowOnlyNrg>0)then
+          do iLayer=1,nSnow  ! loop through layers in the snow domain
+    
+            ! - check that the snow layer is desired
+            if(ixSnowOnlyNrg(iLayer)==integerMissing) cycle
+      
+            ! (define the energy state)
+            nrgState = ixSnowOnlyNrg(iLayer)       ! index within the full state vector
+      
+            ! - define state indices for the current layer
+            watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
+      
+            if(watstate/=integerMissing)then       ! (energy state for the current layer is within the state subset)
+      
+                ! - include derivatives of energy fluxes w.r.t water fluxes for current layer
+              aJac(ixOffDiag(nrgState,watState),watState) = (-1._rkind + mLayerFracLiqSnow(iLayer))*LH_fus*iden_water * cj &
+                                          + dVolHtCapBulk_dTheta(iLayer) * mLayerTempPrime(iLayer) &
+                                          + (dt/mLayerDepth(iLayer))*(-dNrgFlux_dWatBelow(iLayer-1) + dNrgFlux_dWatAbove(iLayer)) &
+                                          + LH_fus*iden_water * mLayerTempPrime(iLayer) * dFracLiqSnow_dTk(iLayer)    ! (dF/dLiq)
+        
+              ! - include derivatives of water fluxes w.r.t energy fluxes for current layer
+              aJac(ixOffDiag(watState,nrgState),nrgState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)  ! (dVol/dT)
+      
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSnow)then
+                aJac(ixOffDiag(ixSnowOnlyHyd(iLayer+1),nrgState),nrgState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)    ! dVol(below)/dT(above) -- K-1
+              endif ! (if there is a water state in the layer below the current layer in the given state subset)
+      
+              ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
+              if(iLayer>1)then
+                if(ixSnowOnlyNrg(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSnowOnlyNrg(iLayer-1),watState),watState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dWatBelow(iLayer-1) )
+              endif
+      
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSnow)then
+                if(ixSnowOnlyNrg(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSnowOnlyNrg(iLayer+1),watState),watState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dWatAbove(iLayer  ) )
+              elseif(iLayer==nSnow .and. nSoilOnlyNrg>0)then !bottom snow layer and there is soil below
+                if(ixSoilOnlyNrg(1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyNrg(1),watState),watState) = (dt/mLayerDepth(nSnow+1))*(-dNrgFlux_dWatAbove(nSnow) )
+              endif
+    
+            endif   ! (if the energy state for the current layer is within the state subset)
+    
+          end do  ! (looping through snow layers)
+        endif   ! (if there are state variables for both water and energy in the snow domain)
+    
+        ! -----
+        ! * liquid water fluxes for the soil domain...
+        ! --------------------------------------------
+        if(nSoilOnlyHyd>0)then
+          do iLayer=1,nSoil
+    
+            ! - check that the soil layer is desired
+            if(ixSoilOnlyHyd(iLayer)==integerMissing) cycle
+      
+            ! - define state indices
+            watState = ixSoilOnlyHyd(iLayer)         ! hydrology state index within the state subset
+      
+            ! - define indices of the soil layers
+            jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
+      
+            ! - compute the diagonal elements
+            ! all terms *excluding* baseflow
+            aJac(ixDiag,watState) = (dt/mLayerDepth(jLayer))*(-dq_dHydStateBelow(iLayer-1) + dq_dHydStateAbove(iLayer)) + dMat(watState)
+      
+            ! - compute the lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyHyd(iLayer-1),watState),watState) = (dt/mLayerDepth(jLayer-1))*( dq_dHydStateBelow(iLayer-1))
+            endif
+      
+            ! - compute the upper-diagonal elements
+            if(iLayer<nSoil)then
+              if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyHyd(iLayer+1),watState),watState) = (dt/mLayerDepth(jLayer+1))*(-dq_dHydStateAbove(iLayer))
+            endif
+    
+          end do  ! (looping through hydrology states in the soil domain)
+
+        endif   ! (if the subset includes hydrology state variables in the soil domain)
+    
+        ! -----
+        ! * liquid water fluxes for the aquifer...
+        ! ----------------------------------------
+        if(ixAqWat/=integerMissing) then
+          aJac(ixDiag,ixAqWat) = -dBaseflow_dAquifer*dt + dMat(ixAqWat) * cj
+          aJac(ixOffDiag(ixAqWat,ixSoilOnlyNrg(nSoil)),ixSoilOnlyNrg(nSoil)) = -dq_dNrgStateAbove(nSoil)*dt
+          aJac(ixOffDiag(ixAqWat,ixSoilOnlyHyd(nSoil)),ixSoilOnlyHyd(nSoil)) = -dq_dHydStateAbove(nSoil)*dt 
         endif
-  
-        ! - include derivatives of energy and water w.r.t soil transpiration (dependent on canopy transpiration)
-        if(computeVegFlux)then
-         aJac(watState,ixCasNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTCanair(iLayer)) + aJac(watState,ixCasNrg) ! dVol/dT (K-1)
-         aJac(watState,ixVegNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTCanopy(iLayer)) + aJac(watState,ixVegNrg) ! dVol/dT (K-1)
-         aJac(watState,ixVegHyd) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dCanWat(iLayer))  + aJac(watState,ixVegHyd) ! dVol/dLiq (kg m-2)-1
-         aJac(watState,ixTopNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTGround(iLayer)) + aJac(watState,ixTopNrg) ! dVol/dT (K-1)
+    
+        ! -----
+        ! * cross derivatives in the soil domain...
+        ! ----------------------------------------
+        if(nSoilOnlyHyd>0 .and. nSoilOnlyNrg>0)then
+          do iLayer=1,nSoilOnlyNrg
+      
+            ! - check that the soil layer is desired
+            if(ixSoilOnlyNrg(iLayer)==integerMissing) cycle
+      
+            ! - define indices of the soil layers
+            jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
+      
+            ! - define the energy state variable
+            nrgState = ixNrgLayer(jLayer)       ! index within the full state vector
+      
+            ! - define index of hydrology state variable within the state subset
+            watState = ixSoilOnlyHyd(iLayer)
+      
+            ! only compute derivatives if the water state for the current layer is within the state subset
+            if(watstate/=integerMissing)then
+      
+              ! - include derivatives in liquid water fluxes w.r.t. temperature for current layer
+              aJac(ixOffDiag(watState,nrgState),nrgState) = (dt/mLayerDepth(jLayer))*(-dq_dNrgStateBelow(iLayer-1) + dq_dNrgStateAbove(iLayer))   ! dVol/dT (K-1) -- flux depends on ice impedance
+      
+              ! - compute lower diagonal elements
+              if(iLayer>1)then
+              if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyHyd(iLayer-1),nrgState),nrgState) = (dt/mLayerDepth(jLayer-1))*( dq_dNrgStateBelow(iLayer-1))   ! K-1
+              endif
+      
+              ! compute upper-diagonal elements
+              if(iLayer<nSoil)then
+              if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyHyd(iLayer+1),nrgState),nrgState) = (dt/mLayerDepth(jLayer+1))*(-dq_dNrgStateAbove(iLayer))     ! K-1
+              endif
+      
+              ! - include derivatives of energy w.r.t. ground evaporation
+              if(nSnow==0 .and. iLayer==1)then  ! upper-most soil layer
+              if(computeVegFlux)then
+                aJac(ixOffDiag(watState,ixCasNrg),ixCasNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanair/iden_water) ! dVol/dT (K-1)
+                aJac(ixOffDiag(watState,ixVegNrg),ixVegNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanopy/iden_water) ! dVol/dT (K-1)
+                aJac(ixOffDiag(watState,ixVegHyd),ixVegHyd) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dCanWat/iden_water)  ! dVol/dLiq (kg m-2)-1
+              endif
+              aJac(ixOffDiag(watState,ixTopNrg),ixTopNrg)  = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTGround/iden_water) + aJac(ixOffDiag(watState,ixTopNrg),ixTopNrg) ! dVol/dT (K-1)
+              endif
+      
+              ! - include derivatives in energy fluxes w.r.t. with respect to water for current layer
+              aJac(ixOffDiag(nrgState,watState),watState) = dVolHtCapBulk_dPsi0(iLayer) * mLayerTempPrime(jLayer) &
+                                                          + (dt/mLayerDepth(jLayer))*(-dNrgFlux_dWatBelow(jLayer-1) + dNrgFlux_dWatAbove(jLayer))
+              if(mLayerdTheta_dTk(jLayer) > verySmall)then  ! ice is present
+                aJac(ixOffDiag(nrgState,watState),watState) = -LH_fus*iden_water * dVolTot_dPsi0(iLayer) * cj &
+                                                            - LH_fus*iden_water * mLayerMatricHeadPrime(iLayer) * d2VolTot_d2Psi0(iLayer) + aJac(ixOffDiag(nrgState,watState),watState) ! dNrg/dMat (J m-3 m-1) -- dMat changes volumetric water, and hence ice content
+              endif
+    
+              ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
+              if(iLayer>1)then
+                if(ixSoilOnlyNrg(iLayer-1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyNrg(iLayer-1),watState),watState) = (dt/mLayerDepth(jLayer-1))*( dNrgFlux_dWatBelow(jLayer-1) )
+              elseif(iLayer==1 .and. nSnowOnlyNrg>0)then !top soil layer and there is snow above
+                if(ixSnowOnlyNrg(nSnow)/=integerMissing) aJac(ixOffDiag(ixSnowOnlyNrg(nSnow),watState),watState) = (dt/mLayerDepth(nSnow))*( dNrgFlux_dWatBelow(nSnow) )
+              endif
+    
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSoil)then
+                if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixOffDiag(ixSoilOnlyNrg(iLayer+1),watState),watState) = (dt/mLayerDepth(jLayer+1))*(-dNrgFlux_dWatAbove(jLayer  ) )
+              endif
+    
+            endif   ! (if the water state for the current layer is within the state subset)
+  
+          end do  ! (looping through soil layers)
+    
+        endif   ! (if there are state variables for both water and energy in the soil domain)
+    
+        if(globalPrintFlag)then
+          print*, '** banded analytical Jacobian:'
+          write(*,'(a4,1x,100(i17,1x))') 'xCol', (iLayer, iLayer=min(iJac1,nState),min(iJac2,nState))
+          do iLayer=kl+1,nBands
+            write(*,'(i4,1x,100(e17.10,1x))') iLayer, (aJac(iLayer,jLayer),jLayer=min(iJac1,nState),min(iJac2,nState))
+          end do
         endif
-  
-        ! - include derivatives in energy fluxes w.r.t. with respect to water for current layer
-        aJac(nrgState,watState) = dVolHtCapBulk_dPsi0(iLayer) * mLayerTempPrime(jLayer) &
-                                 + (dt/mLayerDepth(jLayer))*(-dNrgFlux_dWatBelow(jLayer-1) + dNrgFlux_dWatAbove(jLayer))
-        if(mLayerdTheta_dTk(jLayer) > verySmall)then  ! ice is present
-         aJac(nrgState,watState) = -LH_fus*iden_water * dVolTot_dPsi0(iLayer) * cj &
-                                   - LH_fus*iden_water * mLayerMatricHeadPrime(iLayer) * d2VolTot_d2Psi0(iLayer) + aJac(nrgState,watState) ! dNrg/dMat (J m-3 m-1) -- dMat changes volumetric water, and hence ice content
+    
+      ! *********************************************************************************************************************************************************
+      ! *********************************************************************************************************************************************************
+      ! * PART 2: FULL MATRIX
+      ! *********************************************************************************************************************************************************
+      ! *********************************************************************************************************************************************************
+      case(ixFullMatrix)
+
+        ! check
+        if(size(aJac,1)/=size(dMat) .or. size(aJac,2)/=size(dMat))then
+          message=trim(message)//'unexpected shape of the Jacobian matrix: expect aJac(nState,nState)'
+          err=20; return
         endif
-  
-        ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
-        if(iLayer>1)then
-         if(ixSoilOnlyNrg(iLayer-1)/=integerMissing) aJac(ixSoilOnlyNrg(iLayer-1),watState) = (dt/mLayerDepth(jLayer-1))*( dNrgFlux_dWatBelow(jLayer-1) )
-        elseif(iLayer==1 .and. nSnowOnlyNrg>0)then !top soil layer and there is snow above
-         if(ixSnowOnlyNrg(nSnow)/=integerMissing) aJac(ixSnowOnlyNrg(nSnow),watState) = (dt/mLayerDepth(nSnow))*( dNrgFlux_dWatBelow(nSnow) )
+
+        ! -----
+        ! * energy and liquid fluxes over vegetation...
+        ! ---------------------------------------------
+        if(computeVegFlux)then  ! (derivatives only defined when vegetation protrudes over the surface)
+
+          ! * energy fluxes with the canopy water
+          if(ixVegHyd/=integerMissing)then
+
+            ! * cross-derivative terms w.r.t. system temperatures (kg m-2 K-1)
+            if(ixCasNrg/=integerMissing) aJac(ixVegHyd,ixCasNrg) = -dCanopyEvaporation_dTCanair*dt
+            ! dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy is the derivative in throughfall and canopy drainage with canopy temperature
+            if(ixVegNrg/=integerMissing) aJac(ixVegHyd,ixVegNrg) = -dCanopyEvaporation_dTCanopy*dt + dt*scalarCanopyLiqDeriv*dCanLiq_dTcanopy
+            ! * liquid water fluxes for vegetation canopy (-), dt*scalarFracLiqVeg*scalarCanopyLiqDeriv is the derivative in throughfall and canopy drainage with canopy water
+                                          aJac(ixVegHyd,ixVegHyd) = -scalarFracLiqVeg*(dCanopyEvaporation_dCanWat - scalarCanopyLiqDeriv)*dt + 1._rkind * cj
+            if(ixTopNrg/=integerMissing) aJac(ixVegHyd,ixTopNrg) = -dCanopyEvaporation_dTGround*dt
+
+            ! * cross-derivative terms w.r.t. canopy water (kg-1 m2)
+            if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegHyd) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarFracLiqVeg*scalarCanopyLiqDeriv)/iden_water
+
+            ! * cross-derivative terms w.r.t. canopy liquid water (J m-1 kg-1)
+            ! NOTE: dIce/dLiq = (1 - scalarFracLiqVeg); dIce*LH_fus/canopyDepth = J m-3; dLiq = kg m-2
+            if(ixVegNrg/=integerMissing) aJac(ixVegNrg,ixVegHyd) = (-1._rkind + scalarFracLiqVeg)*LH_fus/canopyDepth * cj &
+                                                                  + dVolHtCapBulk_dCanWat * scalarCanopyTempPrime - (dt/canopyDepth) * dCanopyNetFlux_dCanWat &
+                                                                  + LH_fus * scalarCanopyTempPrime * dFracLiqVeg_dTkCanopy / canopyDepth ! dF/dLiq
+            if(ixTopNrg/=integerMissing) aJac(ixTopNrg,ixVegHyd) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanWat)
+          endif
+
+          ! * -derivative terms w.r.t. canopy temperature (K-1)
+          if(ixVegNrg/=integerMissing)then
+            if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegNrg) = (dt/mLayerDepth(1))*(-scalarSoilControl*scalarCanopyLiqDeriv*dCanLiq_dTcanopy)/iden_water
+          endif
+
+          ! * energy fluxes with the canopy air space (J m-3 K-1)
+          if(ixCasNrg/=integerMissing)then
+            aJac(ixCasNrg,ixCasNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanairTemp) + dMat(ixCasNrg) * cj
+            if(ixVegNrg/=integerMissing) aJac(ixCasNrg,ixVegNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dCanopyTemp)
+            if(ixTopNrg/=integerMissing) aJac(ixCasNrg,ixTopNrg) = (dt/canopyDepth)*(-dCanairNetFlux_dGroundTemp)
+          endif
+
+          ! * energy fluxes with the vegetation canopy (J m-3 K-1)
+          if(ixVegNrg/=integerMissing)then
+            if(ixCasNrg/=integerMissing) aJac(ixVegNrg,ixCasNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanairTemp)
+            aJac(ixVegNrg,ixVegNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dCanopyTemp) + dMat(ixVegNrg)
+            if(ixTopNrg/=integerMissing) aJac(ixVegNrg,ixTopNrg) = (dt/canopyDepth)*(-dCanopyNetFlux_dGroundTemp)
+          endif
+
+          ! * energy fluxes with the surface (J m-3 K-1)
+          if(ixTopNrg/=integerMissing)then
+            if(ixCasNrg/=integerMissing) aJac(ixTopNrg,ixCasNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanairTemp)
+            if(ixVegNrg/=integerMissing) aJac(ixTopNrg,ixVegNrg) = (dt/mLayerDepth(1))*(-dGroundNetFlux_dCanopyTemp)
+          endif
+
+        endif  ! if there is a need to compute energy fluxes within vegetation
+
+        ! -----
+        ! * energy fluxes for the snow+soil domain...
+        ! -------------------------------------------
+        if(nSnowSoilNrg>0)then
+          do iLayer=1,nLayers  ! loop through all layers in the snow+soil domain
+
+            ! check if the state is in the subset
+            if(ixSnowSoilNrg(iLayer)==integerMissing) cycle
+
+            ! - define index within the state subset and the full state vector
+            jState = ixSnowSoilNrg(iLayer)        ! index within the state subset
+
+            ! - diagonal elements
+            aJac(jState,jState)   = (dt/mLayerDepth(iLayer))*(-dNrgFlux_dTempBelow(iLayer-1) + dNrgFlux_dTempAbove(iLayer)) + dMat(jState)
+
+            ! - lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSnowSoilNrg(iLayer-1)/=integerMissing) aJac(ixSnowSoilNrg(iLayer-1),jState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dTempBelow(iLayer-1) )
+            endif
+
+            ! - upper diagonal elements
+            if(iLayer<nLayers)then
+              if(ixSnowSoilNrg(iLayer+1)/=integerMissing) aJac(ixSnowSoilNrg(iLayer+1),jState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dTempAbove(iLayer  ) )
+            endif
+
+          end do  ! (looping through energy states in the snow+soil domain)
+        endif   ! (if the subset includes energy state variables in the snow+soil domain)
+
+        ! -----
+        ! * liquid water fluxes for the snow domain...
+        ! --------------------------------------------
+        if(nSnowOnlyHyd>0)then
+          do iLayer=1,nSnow  ! loop through layers in the snow domain
+
+            ! - check that the snow layer is desired
+            if(ixSnowOnlyHyd(iLayer)==integerMissing) cycle
+
+            ! - define state indices for the current layer
+            watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
+
+            ! compute factor to convert liquid water derivative to total water derivative
+            select case( ixHydType(iLayer) )
+              case(iname_watLayer); convLiq2tot = mLayerFracLiqSnow(iLayer)
+              case default;         convLiq2tot = 1._rkind
+            end select
+
+            ! - diagonal elements
+            aJac(watState,watState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot + dMat(watState) * cj
+
+            ! - lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSnowOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSnowOnlyHyd(iLayer-1),watState) = 0._rkind  ! sub-diagonal: no dependence on other layers
+            endif
+
+            ! - upper diagonal elements
+            if(iLayer<nSnow)then
+              if(ixSnowOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSnowOnlyHyd(iLayer+1),watState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*convLiq2tot       ! dVol(below)/dLiq(above) -- (-)
+            endif
+
+          end do  ! (looping through liquid water states in the snow domain)
+        endif   ! (if the subset includes hydrology state variables in the snow domain)
+
+        ! -----
+        ! * cross derivatives in the snow domain...
+        ! ----------------------------------------
+        if(nSnowOnlyHyd>0 .and. nSnowOnlyNrg>0)then
+          do iLayer=1,nSnow  ! loop through layers in the snow domain
+
+            ! - check that the snow layer is desired
+            if(ixSnowOnlyNrg(iLayer)==integerMissing) cycle
+
+            ! (define the energy state)
+            nrgState = ixSnowOnlyNrg(iLayer)       ! index within the full state vector
+
+            ! - define state indices for the current layer
+            watState = ixSnowOnlyHyd(iLayer)   ! hydrology state index within the state subset
+
+            if(watstate/=integerMissing)then       ! (energy state for the current layer is within the state subset)
+
+              ! - include derivatives of energy fluxes w.r.t water fluxes for current layer
+              aJac(nrgState,watState) = (-1._rkind + mLayerFracLiqSnow(iLayer))*LH_fus*iden_water * cj &
+                                        + dVolHtCapBulk_dTheta(iLayer) * mLayerTempPrime(iLayer) &
+                                        + (dt/mLayerDepth(iLayer))*(-dNrgFlux_dWatBelow(iLayer-1) + dNrgFlux_dWatAbove(iLayer)) &
+                                        + LH_fus*iden_water * mLayerTempPrime(iLayer) * dFracLiqSnow_dTk(iLayer)    ! (dF/dLiq)
+
+              ! - include derivatives of water fluxes w.r.t energy fluxes for current layer
+              aJac(watState,nrgState) = (dt/mLayerDepth(iLayer))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)  ! (dVol/dT)
+
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSnow)then
+                aJac(ixSnowOnlyHyd(iLayer+1),nrgState) = -(dt/mLayerDepth(iLayer+1))*iLayerLiqFluxSnowDeriv(iLayer)*mLayerdTheta_dTk(iLayer)    ! dVol(below)/dT(above) -- K-1
+              endif ! (if there is a water state in the layer below the current layer in the given state subset)
+
+              ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
+              if(iLayer>1)then
+                if(ixSnowOnlyNrg(iLayer-1)/=integerMissing) aJac(ixSnowOnlyNrg(iLayer-1),watState) = (dt/mLayerDepth(iLayer-1))*( dNrgFlux_dWatBelow(iLayer-1) )
+              endif
+
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSnow)then
+                if(ixSnowOnlyNrg(iLayer+1)/=integerMissing) aJac(ixSnowOnlyNrg(iLayer+1),watState) = (dt/mLayerDepth(iLayer+1))*(-dNrgFlux_dWatAbove(iLayer  ) )
+              elseif(iLayer==nSnow .and. nSoilOnlyNrg>0)then !bottom snow layer and there is soil below
+                if(ixSoilOnlyNrg(1)/=integerMissing) aJac(ixSoilOnlyNrg(1),watState) = (dt/mLayerDepth(nSnow+1))*(-dNrgFlux_dWatAbove(nSnow) )
+              endif
+
+            endif   ! (if the energy state for the current layer is within the state subset)
+
+          end do  ! (looping through snow layers)
+        endif   ! (if there are state variables for both water and energy in the snow domain)
+
+        ! -----
+        ! * liquid water fluxes for the soil domain...
+        ! --------------------------------------------
+        if(nSoilOnlyHyd>0)then
+          do iLayer=1,nSoil
+
+            ! - check that the soil layer is desired
+            if(ixSoilOnlyHyd(iLayer)==integerMissing) cycle
+
+            ! - define state indices
+            watState = ixSoilOnlyHyd(iLayer)         ! hydrology state index within the state subset
+
+            ! - define indices of the soil layers
+            jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
+
+            ! - compute the diagonal elements
+            ! all terms *excluding* baseflow
+            aJac(watState,watState) = (dt/mLayerDepth(jLayer))*(-dq_dHydStateBelow(iLayer-1) + dq_dHydStateAbove(iLayer)) + dMat(watState)
+
+            ! - compute the lower-diagonal elements
+            if(iLayer>1)then
+              if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer-1),watState) = (dt/mLayerDepth(jLayer-1))*( dq_dHydStateBelow(iLayer-1))
+            endif
+
+            ! - compute the upper-diagonal elements
+            if(iLayer<nSoil)then
+              if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer+1),watState) = (dt/mLayerDepth(jLayer+1))*(-dq_dHydStateAbove(iLayer))
+            endif
+
+            ! - include terms for baseflow
+            if(computeBaseflow .and. nSoilOnlyHyd==nSoil)then
+              do pLayer=1,nSoil
+              qState = ixSoilOnlyHyd(pLayer)  ! hydrology state index within the state subset
+              aJac(watState,qState) = (dt/mLayerDepth(jLayer))*dBaseflow_dMatric(iLayer,pLayer) + aJac(watState,qState)
+              end do
+            endif
+
+            ! - include terms for surface infiltration below surface
+            if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),watState) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(iLayer) + aJac(ixSoilOnlyHyd(1),watState)
+
+          end do  ! (looping through hydrology states in the soil domain)
+
+          ! - include terms for surface infiltration above surface
+          if(nSnowOnlyNrg>0)then !have snow above first soil layer
+            if(ixSnowOnlyHyd(nSnow)/=integerMissing .and. ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),ixSnowOnlyHyd(nSnow)) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(0)
+          elseif(computeVegFlux)then !have vegetation above first soil layer, ixTopHyd = ixSoilOnlyHyd(1)
+            if(ixVegHyd/=integerMissing .and. ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegHyd) = -(dt/mLayerDepth(1+nSnow))*dq_dHydStateLayerSurfVec(0) + aJac(ixTopHyd,ixVegHyd)
+          endif
+
+        endif   ! (if the subset includes hydrology state variables in the soil domain)
+
+        ! -----
+        ! * liquid water fluxes for the aquifer...
+        ! ----------------------------------------
+        if(ixAqWat/=integerMissing) then
+          aJac(ixAqWat,ixAqWat) = -dBaseflow_dAquifer*dt + dMat(ixAqWat) * cj
+          aJac(ixAqWat,ixSoilOnlyNrg(nSoil)) = -dq_dNrgStateAbove(nSoil)*dt ! dAquiferRecharge_dTk  = d_iLayerLiqFluxSoil(nSoil)_dTk
+          aJac(ixAqWat,ixSoilOnlyHyd(nSoil)) = -dq_dHydStateAbove(nSoil)*dt ! dAquiferRecharge_dWat = d_iLayerLiqFluxSoil(nSoil)_dWat
+          ! - include derivatives of energy and water w.r.t soil transpiration (dependent on canopy transpiration)
+          if(computeVegFlux)then
+            aJac(ixAqWat,ixCasNrg) = -dAquiferTrans_dTCanair*dt ! dVol/dT (K-1)
+            aJac(ixAqWat,ixVegNrg) = -dAquiferTrans_dTCanopy*dt ! dVol/dT (K-1)
+            aJac(ixAqWat,ixVegHyd) = -dAquiferTrans_dCanWat*dt  ! dVol/dLiq (kg m-2)-1
+            aJac(ixAqWat,ixTopNrg) = -dAquiferTrans_dTGround*dt ! dVol/dT (K-1)
+          endif
         endif
-  
-        ! (cross-derivative terms for the layer below)
-        if(iLayer<nSoil)then
-         if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyNrg(iLayer+1),watState) = (dt/mLayerDepth(jLayer+1))*(-dNrgFlux_dWatAbove(jLayer  ) )
+
+        ! -----
+        ! * cross derivatives in the soil domain...
+        ! ----------------------------------------
+        if(nSoilOnlyHyd>0 .and. nSoilOnlyNrg>0)then
+          do iLayer=1,nSoilOnlyNrg
+
+            ! - check that the soil layer is desired
+            if(ixSoilOnlyNrg(iLayer)==integerMissing) cycle
+
+            ! - define indices of the soil layers
+            jLayer   = iLayer+nSnow                  ! index of layer in the snow+soil vector
+
+            ! - define the energy state variable
+            nrgState = ixNrgLayer(jLayer)       ! index within the full state vector
+
+            ! - define index of hydrology state variable within the state subset
+            watState = ixSoilOnlyHyd(iLayer)
+
+            ! only compute derivatives if the water state for the current layer is within the state subset
+            if(watstate/=integerMissing)then
+
+              ! - include derivatives in liquid water fluxes w.r.t. temperature for current layer
+              aJac(watState,nrgState) = (dt/mLayerDepth(jLayer))*(-dq_dNrgStateBelow(iLayer-1) + dq_dNrgStateAbove(iLayer))   ! dVol/dT (K-1) -- flux depends on ice impedance
+
+              ! - compute lower diagonal elements
+              if(iLayer>1)then
+                if(ixSoilOnlyHyd(iLayer-1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer-1),nrgState) = (dt/mLayerDepth(jLayer-1))*( dq_dNrgStateBelow(iLayer-1))   ! K-1
+              endif
+
+              ! compute upper-diagonal elements
+              if(iLayer<nSoil)then
+                if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyHyd(iLayer+1),nrgState) = (dt/mLayerDepth(jLayer+1))*(-dq_dNrgStateAbove(iLayer))     ! K-1
+              endif
+
+              ! - include derivatives of energy w.r.t. ground evaporation
+              if(nSnow==0 .and. iLayer==1)then  ! upper-most soil layer
+              if(computeVegFlux)then
+                aJac(watState,ixCasNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanair/iden_water) ! dVol/dT (K-1)
+                aJac(watState,ixVegNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTCanopy/iden_water) ! dVol/dT (K-1)
+                aJac(watState,ixVegHyd) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dCanWat/iden_water)  ! dVol/dLiq (kg m-2)-1
+              endif
+                aJac(watState,ixTopNrg) = (dt/mLayerDepth(jLayer))*(-dGroundEvaporation_dTGround/iden_water) + aJac(watState,ixTopNrg) ! dVol/dT (K-1)
+              endif
+
+              ! - include derivatives of energy and water w.r.t soil transpiration (dependent on canopy transpiration)
+              if(computeVegFlux)then
+                aJac(watState,ixCasNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTCanair(iLayer)) + aJac(watState,ixCasNrg) ! dVol/dT (K-1)
+                aJac(watState,ixVegNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTCanopy(iLayer)) + aJac(watState,ixVegNrg) ! dVol/dT (K-1)
+                aJac(watState,ixVegHyd) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dCanWat(iLayer))  + aJac(watState,ixVegHyd) ! dVol/dLiq (kg m-2)-1
+                aJac(watState,ixTopNrg) = (dt/mLayerDepth(jLayer))*(-mLayerdTrans_dTGround(iLayer)) + aJac(watState,ixTopNrg) ! dVol/dT (K-1)
+              endif
+
+              ! - include derivatives in energy fluxes w.r.t. with respect to water for current layer
+              aJac(nrgState,watState) = dVolHtCapBulk_dPsi0(iLayer) * mLayerTempPrime(jLayer) &
+                                      + (dt/mLayerDepth(jLayer))*(-dNrgFlux_dWatBelow(jLayer-1) + dNrgFlux_dWatAbove(jLayer))
+              if(mLayerdTheta_dTk(jLayer) > verySmall)then  ! ice is present
+                aJac(nrgState,watState) = -LH_fus*iden_water * dVolTot_dPsi0(iLayer) * cj &
+                                        - LH_fus*iden_water * mLayerMatricHeadPrime(iLayer) * d2VolTot_d2Psi0(iLayer) + aJac(nrgState,watState) ! dNrg/dMat (J m-3 m-1) -- dMat changes volumetric water, and hence ice content
+              endif
+
+              ! - include derivatives of heat capacity w.r.t water fluxes for surrounding layers starting with layer above
+              if(iLayer>1)then
+                if(ixSoilOnlyNrg(iLayer-1)/=integerMissing) aJac(ixSoilOnlyNrg(iLayer-1),watState) = (dt/mLayerDepth(jLayer-1))*( dNrgFlux_dWatBelow(jLayer-1) )
+              elseif(iLayer==1 .and. nSnowOnlyNrg>0)then !top soil layer and there is snow above
+                if(ixSnowOnlyNrg(nSnow)/=integerMissing) aJac(ixSnowOnlyNrg(nSnow),watState) = (dt/mLayerDepth(nSnow))*( dNrgFlux_dWatBelow(nSnow) )
+              endif
+
+              ! (cross-derivative terms for the layer below)
+              if(iLayer<nSoil)then
+                if(ixSoilOnlyHyd(iLayer+1)/=integerMissing) aJac(ixSoilOnlyNrg(iLayer+1),watState) = (dt/mLayerDepth(jLayer+1))*(-dNrgFlux_dWatAbove(jLayer  ) )
+              endif
+
+            endif   ! (if the water state for the current layer is within the state subset)
+
+            ! - include terms for surface infiltration below surface
+            if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),nrgState) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(iLayer) + aJac(ixSoilOnlyHyd(1),nrgState)
+
+          end do  ! (looping through soil layers)
+
+          ! - include terms for surface infiltration above surface
+          if(nSnowOnlyNrg>0)then !have snow above first soil layer
+            if(ixSnowOnlyNrg(nSnow)/=integerMissing .and. ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),ixSnowOnlyNrg(nSnow)) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(0)
+          elseif(computeVegFlux)then !have vegetation above first soil layer, ixTopHyd = ixSoilOnlyHyd(1)
+            if(ixVegNrg/=integerMissing .and. ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegNrg) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(0) + aJac(ixTopHyd,ixVegNrg)
+          endif
+
+        endif   ! (if there are state variables for both water and energy in the soil domain)
+
+        ! print the Jacobian
+        if(globalPrintFlag)then
+          print*, '** analytical Jacobian (full):'
+          write(*,'(a4,1x,100(i12,1x))') 'xCol', (iLayer, iLayer=min(iJac1,nState),min(iJac2,nState))
+          do iLayer=min(iJac1,nState),min(iJac2,nState)
+            write(*,'(i4,1x,100(e12.5,1x))') iLayer, aJac(min(iJac1,nState):min(iJac2,nState),iLayer)
+          end do
         endif
-  
-       endif   ! (if the water state for the current layer is within the state subset)
-  
-       ! - include terms for surface infiltration below surface
-       if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),nrgState) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(iLayer) + aJac(ixSoilOnlyHyd(1),nrgState)
-  
-      end do  ! (looping through soil layers)
-  
-      ! - include terms for surface infiltration above surface
-      if(nSnowOnlyHyd>0 .and. ixSnowOnlyNrg(nSnow)/=integerMissing)then
-       if(ixSoilOnlyHyd(1)/=integerMissing) aJac(ixSoilOnlyHyd(1),ixSnowOnlyNrg(nSnow)) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(0)
-      elseif(computeVegFlux .and. ixVegNrg/=integerMissing)then !ixTopHyd = ixSoilOnlyHyd(1)
-       if(ixTopHyd/=integerMissing) aJac(ixTopHyd,ixVegNrg) = -(dt/mLayerDepth(1+nSnow))*dq_dNrgStateLayerSurfVec(0) + aJac(ixTopHyd,ixVegNrg)
-      endif
-  
-     endif   ! (if there are state variables for both water and energy in the soil domain)
-  
-     ! print the Jacobian
-     if(globalPrintFlag)then
-      print*, '** analytical Jacobian (full):'
-      write(*,'(a4,1x,100(i12,1x))') 'xCol', (iLayer, iLayer=min(iJac1,nState),min(iJac2,nState))
-      do iLayer=min(iJac1,nState),min(iJac2,nState)
-       write(*,'(i4,1x,100(e12.5,1x))') iLayer, aJac(min(iJac1,nState):min(iJac2,nState),iLayer)
-      end do
-     endif
-  
-    !print*, '** analytical Jacobian (full):'
-    !write(*,'(a4,1x,100(i12,1x))') 'xCol', (iLayer, iLayer=1,size(aJac,2))
-    !do iLayer=1,size(aJac,1)
-    ! write(*,'(i4,1x,100(e12.5,1x))') iLayer, aJac(iLayer,1:size(aJac,2))
-    !end do
-    !print *, '--------------------------------------------------------------'
-  
-    ! ***
-    ! check
-    case default; err=20; message=trim(message)//'unable to identify option for the type of matrix'; return
-  
-   end select  ! type of matrix
-  
-   if(any(isNan(aJac)))then
-    print *, '******************************* WE FOUND NAN IN JACOBIAN ************************************'
-    stop 1
-    message=trim(message)//'we found NaN'
-    err=20; return
-   endif
-  
-   ! end association to variables in the data structures
-   end associate
-  
-   end subroutine computJacobSundials
-  
-  
-   ! **********************************************************************************************************
-   ! public subroutine computJacobSetup: this sets up the inputs for the Jacobian computation for the IDA function
-   ! **********************************************************************************************************
-   subroutine computJacobSetup(&
-                         ! input: model control
-                         cj,                      & ! intent(in):    this scalar changes whenever the step size or method order changes
-                         dt,                      & ! intent(in):    time step
-                         nSnow,                   & ! intent(in):    number of snow layers
-                         nSoil,                   & ! intent(in):    number of soil layers
-                         nLayers,                 & ! intent(in):    total number of layers
-                         ixMatrix,                & ! intent(in):    form of the Jacobian matrix
-                         computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                         scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                         ! input: state vectors
-                         stateVec,                & ! intent(in):    model state vector
-                         stateVecPrime,           & ! intent(in):    derivative of model state vector
-                         sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
-                         ! input: data structures
-                         model_decisions,         & ! intent(in):    model decisions
-                         mpar_data,               & ! intent(in):    model parameters
-                         prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                         ! input-output: data structures
-                         indx_data,               & ! intent(inout): index data
-                         diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
-                         deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                         ! input: baseflow
-                         dBaseflow_dMatric,       & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
-                         ! output: flux and residual vectors
-                         dMat,                    & ! intent(inout): diagonal of Jacobian Matrix
-                         Jac,                     & ! intent(out):   jacobian matrix
-                         err,message)               ! intent(out):   error control
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! provide access to subroutines
-   USE getVectorzAddSundials_module, only:varExtractSundials
-   USE updateVarsSundials_module, only:updateVarsSundials           ! update prognostic variables
-   implicit none
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! input: model control
-   real(rkind),intent(in)             :: cj                     ! this scalar changes whenever the step size or method order changes
-   real(rkind),intent(in)             :: dt                     ! time step
-   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)                       :: ixMatrix               ! form of matrix (band diagonal or full matrix)
-   logical(lgt),intent(in)            :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
-   logical(lgt),intent(in)            :: scalarSolution         ! flag to denote if implementing the scalar solution
-   ! input: state vectors
-   real(rkind),intent(in)             :: stateVec(:)            ! model state vector
-   real(rkind),intent(in)             :: stateVecPrime(:)       ! model state vector
-   real(qp),intent(in)                :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
-   ! input: data structures
-   type(model_options),intent(in)     :: model_decisions(:)     ! model decisions
-   type(var_dlength),  intent(in)     :: mpar_data              ! model parameters
-   type(var_dlength),  intent(in)     :: prog_data              ! prognostic variables for a local HRU
-   ! output: data structures
-   type(var_ilength),intent(inout)    :: indx_data              ! indices defining model states and layers
-   type(var_dlength),intent(inout)    :: diag_data              ! diagnostic variables for a local HRU
-   type(var_dlength),intent(inout)    :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
-   ! input-output: baseflow
-   real(rkind),intent(in)             :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
-   ! output: Jacobian
-   real(rkind), intent(inout)         :: dMat(:)
-   real(rkind), intent(out)           :: Jac(:,:)               ! jacobian matrix
-   ! output: error control
-   integer(i4b),intent(out)           :: err                    ! error code
-   character(*),intent(out)           :: message                ! error message
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! local variables
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! state variables
-   real(rkind)                        :: scalarCanairTempTrial     ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatTrial      ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempTrial           ! trial value for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial     ! trial value for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial     ! trial value for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial  ! trial value for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStorageTrial ! trial value of storage of water in the aquifer (m)
-   ! diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqTrial      ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial     ! trial value for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial     ! trial value for volumetric fraction of ice (-)
-    ! derivative of state variables
-   real(rkind)                        :: scalarCanairTempPrime     ! derivative value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempPrime     ! derivative value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatPrime      ! derivative value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempPrime           ! derivative value for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrime     ! derivative value for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrime     ! derivative value for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqPrime  ! derivative value for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStoragePrime ! derivative value of storage of water in the aquifer (m)
-   ! derivative of diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqPrime      ! derivative value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIcePrime      ! derivative value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqPrime     ! derivative value for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrime     ! derivative value for volumetric fraction of ice (-)
-   ! other local variables
-   character(LEN=256)              :: cmessage                     ! error message of downwind routine
-   real(rkind)                        :: dt1
-  
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   associate(&
-   ! model decisions
-   ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
-   ! soil parameters
-   theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
-   specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
-   ! decisions
-   ixGroundwater           => model_decisions(iLookDECISIONS%groundwatr)%iDecision    &
-   ) ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! initialize error control
-   err=0; message="computJacobSetup/"
-  
-   ! these will need to be initialized as they do not have updated prognostic structures in Sundials
-   ! should all be set to previous values if splits, but for now operator splitting is not hooked up
-   scalarCanairTempPrime    = realMissing
-   scalarCanopyTempPrime    = realMissing
-   scalarCanopyWatPrime     = realMissing
-   scalarCanopyLiqPrime     = realMissing
-   scalarCanopyIcePrime     = realMissing
-   mLayerTempPrime          = realMissing
-   mLayerVolFracWatPrime    = realMissing
-   mLayerVolFracLiqPrime    = realMissing
-   mLayerVolFracIcePrime    = realMissing
-   mLayerMatricHeadPrime    = realMissing
-   mLayerMatricHeadLiqPrime = realMissing
-   scalarAquiferStoragePrime= realMissing
-   scalarCanairTempTrial    = realMissing ! scalarCanairTemp prognostic not up to date
-   scalarCanopyTempTrial    = realMissing ! scalarCanopyTempTrial prognostic not up to date
-   scalarCanopyWatTrial     = realMissing ! scalarCanopyWat prognostic not up to date
-   scalarCanopyLiqTrial     = realMissing ! scalarCanopyLiq prognostic not up to date
-   scalarCanopyIceTrial     = realMissing ! scalarCanopyLIce prognostic not up to date
-   mLayerTempTrial          = realMissing ! mLayerTemp prognostic not up to date
-   mLayerVolFracWatTrial    = realMissing ! mLayerVolFracWat prognostic not up to date
-   mLayerVolFracLiqTrial    = realMissing ! mLayerVolFracLiq prognostic not up to date
-   mLayerVolFracIceTrial    = realMissing ! mLayerVolFracIce prognostic not up to date
-   mLayerMatricHeadTrial    = realMissing ! mLayerMatricHead prognostic not up to date
-   mLayerMatricHeadLiqTrial = realMissing ! mLayerMatricHeadLiq prognostic not up to date
-   scalarAquiferStorageTrial= realMissing ! scalarAquiferStorage prognostic not up to date
-  
-   ! extract variables from the model state vector
-   call varExtractSundials(&
-                   ! input
-                   stateVec,                 & ! intent(in):    model state vector (mixed units)
-                   stateVecPrime,            & ! intent(in):    model state vector (mixed units)
-                   diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
-                   prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                & ! intent(in):    indices defining model states and layers
-                   ! output: variables for the vegetation canopy
-                   scalarCanairTempTrial,    & ! intent(inout):   trial value of canopy air temperature (K)
-                   scalarCanopyTempTrial,    & ! intent(inout):   trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,     & ! intent(inout):   trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,     & ! intent(inout):   trial value of canopy liquid water (kg m-2)
-                   scalarCanairTempPrime,    & ! intent(inout):   derivative of canopy air temperature (K)
-                   scalarCanopyTempPrime,    & ! intent(inout):   derivative of canopy temperature (K)
-                   scalarCanopyWatPrime,     & ! intent(inout):   derivative of canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,     & ! intent(inout):   derivative of canopy liquid water (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,          & ! intent(inout):   trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,    & ! intent(inout):   trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,    & ! intent(inout):   trial vector of volumetric liquid water content (-)
-                   mLayerMatricHeadTrial,    & ! intent(inout):   trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial, & ! intent(inout):   trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,          & ! intent(inout):   derivative of layer temperature (K)
-                   mLayerVolFracWatPrime,    & ! intent(inout):   derivative of volumetric total water content (-)
-                   mLayerVolFracLiqPrime,    & ! intent(inout):   derivative of volumetric liquid water content (-)
-                   mLayerMatricHeadPrime,    & ! intent(inout):   derivative of total water matric potential (m)
-                   mLayerMatricHeadLiqPrime, & ! intent(inout):   derivative of liquid water matric potential (m)
-                   ! output: variables for the aquifer
-                   scalarAquiferStorageTrial,& ! intent(inout):   trial value of storage of water in the aquifer (m)
-                   scalarAquiferStoragePrime,& ! intent(inout):   derivative of storage of water in the aquifer (m)
-                   ! output: error control
-                   err,cmessage)               ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   call updateVarsSundials(&
-                   ! input
-                   dt,                                        & ! intent(in):    time step
-                   .true.,                                    & ! intent(in):    logical flag if computing Jacobian for Sundials solver
-                   .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
-                   mpar_data,                                 & ! intent(in):    model parameters for a local HRU
-                   indx_data,                                 & ! intent(in):    indices defining model states and layers
-                   prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                   mLayerVolFracWatTrial,                     & ! intent(in):    use current vector for prev vector of volumetric total water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(in):    use current vector for prev vector of total water matric potential (m)
-                   diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
-                   deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! output: variables for the vegetation canopy
-                   scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
-                   scalarCanopyTempPrime,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatPrime,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIcePrime,                      & ! intent(inout): trial value of canopy ice content (kg m-2
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
-                   mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,                           & !
-                   mLayerVolFracWatPrime,                     & ! intent(inout): Prime vector of volumetric total water content (-)
-                   mLayerVolFracLiqPrime,                     & ! intent(inout): Prime vector of volumetric liquid water content (-)
-                   mLayerVolFracIcePrime,                     & !
-                   mLayerMatricHeadPrime,                     & ! intent(inout): Prime vector of total water matric potential (m)
-                   mLayerMatricHeadLiqPrime,                  & ! intent(inout): Prime vector of liquid water matric potential (m)
-                   ! output: error control
-                   err,cmessage)                                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! -----
-   ! * compute the Jacobian matrix...
-   ! --------------------------------
-  
-   ! compute the analytical Jacobian matrix
-   ! NOTE: The derivatives were computed in the previous call to computFlux
-   !       This occurred either at the call to eval8summaSundials at the start of systemSolvSundials
-   !        or in the call to eval8summaSundials in the previous iteration
-   dt1 = 1._qp
-   call computJacobSundials(&
-                    ! input: model control
-                    cj,                             & ! intent(in):    this scalar changes whenever the step size or method order changes
-                    dt1,                            & ! intent(in):    length of the time step (seconds)
-                    nSnow,                          & ! intent(in):    number of snow layers
-                    nSoil,                          & ! intent(in):    number of soil layers
-                    nLayers,                        & ! intent(in):    total number of layers
-                    computeVegFlux,                 & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                    (ixGroundwater==qbaseTopmodel), & ! intent(in):    flag to indicate if we need to compute baseflow
-                    ixMatrix,                       & ! intent(in):    form of the Jacobian matrix
-                    specificStorage,                & ! intent(in):    specific storage coefficient (m-1)
-                    theta_sat,                      & ! intent(in):    soil porosity (-)
-                    ixRichards,                     & ! intent(in):    choice of option for Richards' equation
-                    ! input: data structures
-                    indx_data,                      & ! intent(in):    index data
-                    prog_data,                      & ! intent(in):    model prognostic variables for a local HRU
-                    diag_data,                      & ! intent(in):    model diagnostic variables for a local HRU
-                    deriv_data,                     & ! intent(in):    derivatives in model fluxes w.r.t. relevant state variables
-                    dBaseflow_dMatric,              & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
-                    ! input: state variables
-                    mLayerTempPrime,                & ! intent(in)
-                    mLayerMatricHeadPrime,          & ! intent(in)
-                    mLayerMatricHeadLiqPrime,       & ! intent(in)
-                    mLayerVolFracWatPrime,          & ! intent(in)
-                    scalarCanopyTempPrime,          & ! intent(in) derivative value for temperature of the vegetation canopy (K)
-                    scalarCanopyWatPrime,           & ! intent(in)
-                    ! input-output: Jacobian and its diagonal
-                    dMat,                           & ! intent(inout): diagonal of the Jacobian matrix
-                    Jac,                            & ! intent(out):   Jacobian matrix
-                    ! output: error control
-                    err,cmessage)                     ! intent(out):   error code and error message
-     if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! end association with the information in the data structures
-   end associate
-  
-   end subroutine computJacobSetup
-  
-  
-    ! **********************************************************************************************************
-    ! public function computJacob4IDA: the interface to compute the Jacobian matrix dF/dy + c dF/dy' for IDA solver
-    ! **********************************************************************************************************
-    ! Return values:
-    !    0 = success,
-    !    1 = recoverable error,
-    !   -1 = non-recoverable error
-    ! ----------------------------------------------------------------
-    integer(c_int) function computJacob4IDA(t, cj, sunvec_y, sunvec_yp, sunvec_r, &
-                        sunmat_J, user_data, sunvec_temp1, sunvec_temp2, sunvec_temp3) &
-                        result(ierr) bind(C,name='computJacob4IDA')
-  
-      !======= Inclusions ===========
-      use, intrinsic :: iso_c_binding
-      use fsundials_nvector_mod
-      use fsundials_matrix_mod
-      use fnvector_serial_mod
-      use fsunmatrix_dense_mod
-      use nrtype
-      use type4IDA
-      !======= Declarations =========
-      implicit none
-  
-      ! calling variables
-      real(rkind), value            :: t              ! current time
-      real(rkind), value            :: cj             ! step size scaling factor
-      type(N_Vector)                :: sunvec_y       ! solution N_Vector
-      type(N_Vector)                :: sunvec_yp      ! derivative N_Vector
-      type(N_Vector)                :: sunvec_r       ! residual N_Vector
-      type(SUNMatrix)               :: sunmat_J       ! Jacobian SUNMatrix
-      type(c_ptr), value            :: user_data      ! user-defined data
-      type(N_Vector)                :: sunvec_temp1   ! temporary N_Vector
-      type(N_Vector)                :: sunvec_temp2   ! temporary N_Vector
-      type(N_Vector)                :: sunvec_temp3   ! temporary N_Vector
-  
-      ! pointers to data in SUNDIALS vectors
-      real(rkind), pointer          :: stateVec(:)    ! state vector
-      real(rkind), pointer          :: stateVecPrime(:)! derivative of the state vector
-      real(rkind), pointer          :: rVec(:)        ! residual vector
-      real(rkind), pointer          :: Jac(:,:)       ! Jacobian matrix
-      type(eqnsData), pointer       :: eqns_data      ! equations data
-  
-  
-  
-      !======= Internals ============
-  
-      ! get equations data from user-defined data
-      call c_f_pointer(user_data, eqns_data)
-  
-  
-      ! get data arrays from SUNDIALS vectors
-      stateVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_y)
-      stateVecPrime(1:eqns_data%nState) => FN_VGetArrayPointer(sunvec_yp)
-      rVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_r)
-      Jac(1:eqns_data%nState, 1:eqns_data%nState) => FSUNDenseMatrix_Data(sunmat_J)
-  
-      ! compute Jacobian matrix
-      call computJacobSetup(&
-                   ! input: model control
-                   cj,                                & ! intent(in):    this scalar changes whenever the step size or method order changes
-                   eqns_data%dt,                      & ! intent(in):    data step
-                   eqns_data%nSnow,                   & ! intent(in):    number of snow layers
-                   eqns_data%nSoil,                   & ! intent(in):    number of soil layers
-                   eqns_data%nLayers,                 & ! intent(in):    number of layers
-                   eqns_data%ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
-                   eqns_data%computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   eqns_data%scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                   ! input: state vectors
-                   stateVec,                          & ! intent(in):    model state vector
-                   stateVecPrime,                     & ! intent(in):    model state vector
-                   eqns_data%sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
-                   ! input: data structures
-                   model_decisions,                   & ! intent(in):    model decisions
-                   eqns_data%mpar_data,               & ! intent(in):    model parameters
-                   eqns_data%prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                   ! input-output: data structures
-                   eqns_data%indx_data,               & ! intent(inou):  index data
-                   eqns_data%diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
-                   eqns_data%deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! input: baseflow
-                   eqns_data%dBaseflow_dMatric,       & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
-                   ! output
-                   eqns_data%dMat,                    & ! intetn(inout): diagonal of the Jacobian matrix
-                   Jac,                               & ! intent(out):   Jacobian matrix
-                   eqns_data%err,eqns_data%message)     ! intent(out):   error control
-  
-     if(eqns_data%err > 0)then; eqns_data%message=trim(eqns_data%message); ierr=-1; return; endif
-     if(eqns_data%err < 0)then; eqns_data%message=trim(eqns_data%message); ierr=1; return; endif
-  
-     ! return success
-     ierr = 0
-     return
-  
-  
-  
-   end function computJacob4IDA
-  
-  
-   ! **********************************************************************************************************
-   ! private function: get the off-diagonal index in the band-diagonal matrix
-   ! **********************************************************************************************************
-   function ixOffDiag(jState,iState)
-   implicit none
-   integer(i4b),intent(in)  :: jState    ! off-diagonal state
-   integer(i4b),intent(in)  :: iState    ! diagonal state
-   integer(i4b)             :: ixOffDiag ! off-diagonal index in gthe band-diagonal matrix
-   ixOffDiag = ixBandOffset + jState - iState
-   end function ixOffDiag
-  
-  end module computJacobSundials_module
+
+      ! check
+      case default; err=20; message=trim(message)//'unable to identify option for the type of matrix'; return
+
+    end select  ! type of matrix
+
+    if(any(isNan(aJac)))then
+      print *, '******************************* WE FOUND NAN IN JACOBIAN ************************************'
+      stop 1
+      message=trim(message)//'we found NaN'
+      err=20; return
+    endif
+
+  ! end association to variables in the data structures
+  end associate
+
+end subroutine computJacobSundials
+
+
+! **********************************************************************************************************
+! private function: get the off-diagonal index in the band-diagonal matrix
+! **********************************************************************************************************
+function ixOffDiag(jState,iState)
+  implicit none
+  integer(i4b),intent(in)  :: jState    ! off-diagonal state
+  integer(i4b),intent(in)  :: iState    ! diagonal state
+  integer(i4b)             :: ixOffDiag ! off-diagonal index in gthe band-diagonal matrix
+  ixOffDiag = ixBandOffset + jState - iState
+end function ixOffDiag
+
+end module computJacobSundials_module
   
\ No newline at end of file
diff --git a/build/source/engine/sundials/eval8JacDAE.f90 b/build/source/engine/sundials/eval8JacDAE.f90
new file mode 100644
index 0000000..e2cdcdd
--- /dev/null
+++ b/build/source/engine/sundials/eval8JacDAE.f90
@@ -0,0 +1,343 @@
+
+module eval8JacDAE_module
+
+! data types
+USE nrtype
+
+! 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 the global print flag
+USE globalData,only:globalPrintFlag
+
+! define access to state variables to print
+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_veg       ! named variables for vegetation
+USE globalData,only:iname_snow      ! named variables for snow
+USE globalData,only:iname_soil      ! named variables for soil
+
+! named variables to describe the state variable type
+USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
+USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
+USE globalData,only:iname_watCanopy ! named variable defining the mass of 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: ixFullMatrix   ! named variable for the full Jacobian matrix
+USE globalData,only: ixBandMatrix   ! named variable for the band diagonal matrix
+USE globalData,only:model_decisions        ! model decision structure
+
+! constants
+USE multiconst,only:&
+                    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 the derived types to define the data structures
+USE data_types,only:&
+                    var_i,        & ! data vector (i4b)
+                    var_d,        & ! data vector (rkind)
+                    var_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength,  & ! data vector with variable length dimension (rkind)
+                    model_options   ! defines the model decisions
+
+! indices that define elements of the data structures
+USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
+USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
+USE var_lookup,only:iLookPROG                    ! named variables for structure elements
+USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
+
+! 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
+
+! look-up values for the form of Richards' equation
+USE mDecisions_module,only:  &
+  moisture,                   & ! moisture-based form of Richards' equation
+  mixdform                      ! mixed form of Richards' equation
+
+implicit none
+private
+public::eval8JacDAE
+
+contains
+
+! **********************************************************************************************************
+! public subroutine eval8JacDAE: compute the Jacobian matrix
+! **********************************************************************************************************
+subroutine eval8JacDAE(&
+                      ! input: model control
+                      cj,                      & ! intent(in):    this scalar changes whenever the step size or method order changes
+                      dt,                      & ! intent(in):    time step
+                      nSnow,                   & ! intent(in):    number of snow layers
+                      nSoil,                   & ! intent(in):    number of soil layers
+                      nLayers,                 & ! intent(in):    total number of layers
+                      ixMatrix,                & ! intent(in):    form of the Jacobian matrix
+                      computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                      ! input: state vectors
+                      stateVec,                & ! intent(in):    model state vector
+                      stateVecPrime,           & ! intent(in):    derivative of model state vector
+                      sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
+                      ! input: data structures
+                      model_decisions,         & ! intent(in):    model decisions
+                      mpar_data,               & ! intent(in):    model parameters
+                      prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                      ! input-output: data structures
+                      indx_data,               & ! intent(inout): index data
+                      diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                      deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                      ! input: baseflow
+                      dBaseflow_dMatric,       & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
+                      ! output: flux and residual vectors
+                      dMat,                    & ! intent(inout): diagonal of Jacobian Matrix
+                      Jac,                     & ! intent(out):   jacobian matrix
+                      err,message)               ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! provide access to subroutines
+  USE getVectorz_module, only:varExtract                    ! extract variables from the state vector
+  USE updateVarsSundials_module, only:updateVarsSundials           ! update prognostic variables
+  USE computJacobSundials_module,only:computJacobSundials
+  implicit none
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: model control
+  real(rkind),intent(in)             :: cj                     ! this scalar changes whenever the step size or method order changes
+  real(rkind),intent(in)             :: dt                     ! time step
+  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)                       :: ixMatrix               ! form of matrix (band diagonal or full matrix)
+  logical(lgt),intent(in)            :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
+  logical(lgt),intent(in)            :: scalarSolution         ! flag to denote if implementing the scalar solution
+  ! input: state vectors
+  real(rkind),intent(in)             :: stateVec(:)            ! model state vector
+  real(rkind),intent(in)             :: stateVecPrime(:)       ! model state vector
+  real(qp),intent(in)                :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
+  ! input: data structures
+  type(model_options),intent(in)     :: model_decisions(:)     ! model decisions
+  type(var_dlength),  intent(in)     :: mpar_data              ! model parameters
+  type(var_dlength),  intent(in)     :: prog_data              ! prognostic variables for a local HRU
+  ! output: data structures
+  type(var_ilength),intent(inout)    :: indx_data              ! indices defining model states and layers
+  type(var_dlength),intent(inout)    :: diag_data              ! diagnostic variables for a local HRU
+  type(var_dlength),intent(inout)    :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
+  ! input-output: baseflow
+  real(rkind),intent(in)             :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
+  ! output: Jacobian
+  real(rkind), intent(inout)         :: dMat(:)
+  real(rkind), intent(out)           :: Jac(:,:)               ! jacobian matrix
+  ! output: error control
+  integer(i4b),intent(out)           :: err                    ! error code
+  character(*),intent(out)           :: message                ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! state variables
+  real(rkind)                        :: scalarCanairTempTrial     ! trial value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
+  real(rkind)                        :: scalarCanopyWatTrial      ! trial value for liquid water storage in the canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerTempTrial           ! trial value for temperature of layers in the snow and soil domains (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial     ! trial value for volumetric fraction of total water (-)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial     ! trial value for total water matric potential (m)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial  ! trial value for liquid water matric potential (m)
+  real(rkind)                        :: scalarAquiferStorageTrial ! trial value of storage of water in the aquifer (m)
+  ! diagnostic variables
+  real(rkind)                        :: scalarCanopyLiqTrial      ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
+  real(rkind)                        :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial     ! trial value for volumetric fraction of liquid water (-)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial     ! trial value for volumetric fraction of ice (-)
+    ! derivative of state variables
+  real(rkind)                        :: scalarCanairTempPrime     ! derivative value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyTempPrime     ! derivative value for temperature of the vegetation canopy (K)
+  real(rkind)                        :: scalarCanopyWatPrime      ! derivative value for liquid water storage in the canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerTempPrime           ! derivative value for temperature of layers in the snow and soil domains (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrime     ! derivative value for volumetric fraction of total water (-)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrime     ! derivative value for total water matric potential (m)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqPrime  ! derivative value for liquid water matric potential (m)
+  real(rkind)                        :: scalarAquiferStoragePrime ! derivative value of storage of water in the aquifer (m)
+  ! derivative of diagnostic variables
+  real(rkind)                        :: scalarCanopyLiqPrime      ! derivative value for mass of liquid water on the vegetation canopy (kg m-2)
+  real(rkind)                        :: scalarCanopyIcePrime      ! derivative value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracLiqPrime     ! derivative value for volumetric fraction of liquid water (-)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrime     ! derivative value for volumetric fraction of ice (-)
+  ! other local variables
+  character(LEN=256)              :: cmessage                     ! error message of downwind routine
+  real(rkind)                        :: dt1
+
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! association to variables in the data structures
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  associate(&
+    ! model decisions
+    ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
+    ! soil parameters
+    theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
+    specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
+    ! model state variables
+    mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,&  ! intent(in):  [dp(:)] volumetric fraction of liquid water (-)
+    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,&  ! intent(in):  [dp(:)] volumetric fraction of ice (-)
+    mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,&  ! intent(in):  [dp(:)] liquid water matric potential (m)
+    ixGroundwater           => model_decisions(iLookDECISIONS%groundwatr)%iDecision    &
+    ) ! association to variables in the data structures
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message="eval8JacDAE/"
+
+    ! extract variables from the model state vector
+    call varExtract(&
+                    ! input
+                    stateVec,                 & ! intent(in):    model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
+                    scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
+                    scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
+                    mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
+                    mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
+                    mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
+                    mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! extract derivative of variables from derivative of the model state vector
+    call varExtract(&
+                    ! input
+                    stateVecPrime,            & ! intent(in):    derivative of model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempPrime,    & ! intent(out):   derivative of canopy air temperature (K)
+                    scalarCanopyTempPrime,    & ! intent(out):   derivative of canopy temperature (K)
+                    scalarCanopyWatPrime,     & ! intent(out):   derivative of canopy total water (kg m-2)
+                    scalarCanopyLiqPrime,     & ! intent(out):   derivative of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempPrime,          & ! intent(out):   derivative of layer temperature (K)
+                    mLayerVolFracWatPrime,    & ! intent(out):   derivative of volumetric total water content (-)
+                    mLayerVolFracLiqPrime,    & ! intent(out):   derivative of volumetric liquid water content (-)
+                    mLayerMatricHeadPrime,    & ! intent(out):   derivative of total water matric potential (m)
+                    mLayerMatricHeadLiqPrime, & ! intent(out):   derivative of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStoragePrime,& ! intent(out):   derivative of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    call updateVarsSundials(&
+                  ! input
+                  dt,                                        & ! intent(in):    time step
+                  .true.,                                    & ! intent(in):    logical flag if computing Jacobian for sundials solver
+                  .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
+                  mpar_data,                                 & ! intent(in):    model parameters for a local HRU
+                  indx_data,                                 & ! intent(in):    indices defining model states and layers
+                  prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                  mLayerVolFracWatTrial,                     & ! intent(in):    use current vector for prev vector of volumetric total water content (-)
+                  mLayerMatricHeadTrial,                     & ! intent(in):    use current vector for prev vector of total water matric potential (m)
+                  diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
+                  deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                  ! output: variables for the vegetation canopy
+                  scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
+                  scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                  scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                  scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                  scalarCanopyTempPrime,                     & ! intent(inout): trial value of canopy temperature (K)
+                  scalarCanopyWatPrime,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                  scalarCanopyLiqPrime,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                  scalarCanopyIcePrime,                      & ! intent(inout): trial value of canopy ice content (kg m-2
+                  ! output: variables for the snow-soil domain
+                  mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
+                  mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
+                  mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
+                  mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
+                  mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
+                  mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
+                  mLayerTempPrime,                           & !
+                  mLayerVolFracWatPrime,                     & ! intent(inout): Prime vector of volumetric total water content (-)
+                  mLayerVolFracLiqPrime,                     & ! intent(inout): Prime vector of volumetric liquid water content (-)
+                  mLayerVolFracIcePrime,                     & !
+                  mLayerMatricHeadPrime,                     & ! intent(inout): Prime vector of total water matric potential (m)
+                  mLayerMatricHeadLiqPrime,                  & ! intent(inout): Prime vector of liquid water matric potential (m)
+                  ! output: error control
+                  err,cmessage)                                ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! -----
+    ! * compute the Jacobian matrix...
+    ! --------------------------------
+
+    ! compute the analytical Jacobian matrix
+    ! NOTE: The derivatives were computed in the previous call to computFlux
+    !       This occurred either at the call to eval8summaSundials at the start of sysSolveSundials
+    !        or in the call to eval8summaSundials in the previous iteration
+    dt1 = 1._qp
+    call computJacobSundials(&
+                      ! input: model control
+                      cj,                             & ! intent(in):    this scalar changes whenever the step size or method order changes
+                      dt1,                            & ! intent(in):    length of the time step (seconds)
+                      nSnow,                          & ! intent(in):    number of snow layers
+                      nSoil,                          & ! intent(in):    number of soil layers
+                      nLayers,                        & ! intent(in):    total number of layers
+                      computeVegFlux,                 & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      (ixGroundwater==qbaseTopmodel), & ! intent(in):    flag to indicate if we need to compute baseflow
+                      ixMatrix,                       & ! intent(in):    form of the Jacobian matrix
+                      specificStorage,                & ! intent(in):    specific storage coefficient (m-1)
+                      theta_sat,                      & ! intent(in):    soil porosity (-)
+                      ixRichards,                     & ! intent(in):    choice of option for Richards' equation
+                      ! input: data structures
+                      indx_data,                      & ! intent(in):    index data
+                      prog_data,                      & ! intent(in):    model prognostic variables for a local HRU
+                      diag_data,                      & ! intent(in):    model diagnostic variables for a local HRU
+                      deriv_data,                     & ! intent(in):    derivatives in model fluxes w.r.t. relevant state variables
+                      dBaseflow_dMatric,              & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
+                      ! input: state variables
+                      mLayerTempTrial,                & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
+                      mLayerTempPrime,                & ! intent(in)
+                      mLayerMatricHeadPrime,          & ! intent(in)
+                      mLayerMatricHeadLiqPrime,       & ! intent(in)
+                      mLayerVolFracWatPrime,          & ! intent(in)
+                      scalarCanopyTempTrial,          & ! intent(in)
+                      scalarCanopyTempPrime,          & ! intent(in) derivative value for temperature of the vegetation canopy (K)
+                      scalarCanopyWatPrime,           & ! intetn(in)
+                      ! input-output: Jacobian and its diagonal
+                      dMat,                           & ! intent(inout): diagonal of the Jacobian matrix
+                      Jac,                            & ! intent(out):   Jacobian matrix
+                      ! output: error control
+                      err,cmessage)                     ! intent(out):   error code and error message
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! end association with the information in the data structures
+  end associate
+
+end subroutine eval8JacDAE
+end module eval8JacDAE_module
diff --git a/build/source/engine/sundials/eval8summaSundials.f90 b/build/source/engine/sundials/eval8summaSundials.f90
index b5f5d42..0674236 100644
--- a/build/source/engine/sundials/eval8summaSundials.f90
+++ b/build/source/engine/sundials/eval8summaSundials.f90
@@ -1,506 +1,510 @@
 
 module eval8summaSundials_module
 
-  ! data types
-  USE nrtype
-  USE type4IDA
-  
-  ! 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 the global print flag
-  USE globalData,only:globalPrintFlag
-  
-  ! define access to state variables to print
-  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_veg       ! named variables for vegetation
-  USE globalData,only:iname_snow      ! named variables for snow
-  USE globalData,only:iname_soil      ! named variables for soil
-  
-  ! named variables to describe the state variable type
-  USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
-  USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
-  USE globalData,only:iname_watCanopy ! named variable defining the mass of 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:model_decisions ! model decision structure
-  USE globalData,only:flux_meta       ! metadata on the model fluxes
-  
-  ! constants
-  USE multiconst,only:&
-                      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 the derived types to define the data structures
-  USE data_types,only:&
-                      var_i,        & ! data vector (i4b)
-                      var_d,        & ! data vector (rkind)
-                      var_ilength,  & ! data vector with variable length dimension (i4b)
-                      var_dlength,  & ! data vector with variable length dimension (rkind)
-                      zlookup,      &
-                      model_options   ! defines the model decisions
-  
-  ! indices that define elements of the data structures
-  USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
-  USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
-  USE var_lookup,only:iLookPROG                    ! named variables for structure elements
-  USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
-  
-  ! 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
-   enthalpyFD                    ! heat capacity using enthalpy
-  
-  ! 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
-  
-  ! look-up values for the form of Richards' equation
-  USE mDecisions_module,only:  &
-   moisture,                   & ! moisture-based form of Richards' equation
-   mixdform                      ! mixed form of Richards' equation
-  
-  use, intrinsic :: iso_c_binding
-  
+! data types
+USE nrtype
+
+! 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 the global print flag
+USE globalData,only:globalPrintFlag
+
+! define access to state variables to print
+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_veg       ! named variables for vegetation
+USE globalData,only:iname_snow      ! named variables for snow
+USE globalData,only:iname_soil      ! named variables for soil
+
+! named variables to describe the state variable type
+USE globalData,only:iname_nrgCanair ! named variable defining the energy of the canopy air space
+USE globalData,only:iname_nrgCanopy ! named variable defining the energy of the vegetation canopy
+USE globalData,only:iname_watCanopy ! named variable defining the mass of 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:model_decisions        ! model decision structure
+
+
+! constants
+USE multiconst,only:&
+                    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 the derived types to define the data structures
+USE data_types,only:&
+                    var_i,        & ! data vector (i4b)
+                    var_d,        & ! data vector (rkind)
+                    var_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength,  & ! data vector with variable length dimension (rkind)
+                    zlookup,      &
+                    model_options   ! defines the model decisions
+
+! indices that define elements of the data structures
+USE var_lookup,only:iLookDECISIONS               ! named variables for elements of the decision structure
+USE var_lookup,only:iLookPARAM                   ! named variables for structure elements
+USE var_lookup,only:iLookPROG                    ! named variables for structure elements
+USE var_lookup,only:iLookINDEX                   ! 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:iLookDERIV                   ! named variables for structure elements
+
+! 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
+  enthalpyFD                    ! heat capacity using enthalpy
+
+! 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
+
+! look-up values for the form of Richards' equation
+USE mDecisions_module,only:  &
+  moisture,                   & ! moisture-based form of Richards' equation
+  mixdform                      ! mixed form of Richards' equation
+
+implicit none
+private
+public::eval8summaSundials
+
+contains
+
+! **********************************************************************************************************
+! public subroutine eval8summaSundials: compute the residual vector
+! **********************************************************************************************************
+subroutine eval8summaSundials(&
+                      ! input: model control
+                      dt_cur,                  & ! intent(in):    current stepsize
+                      dt,                      & ! intent(in):    entire time step
+                      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
+                      insideIDA,               & ! intent(in):    flag to indicate if we are inside Sundials solver
+                      firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                      firstFluxCall,			      & ! intent(inout)  flag to indicate if we are processing the first flux call
+                      firstSplitOper,		      & ! intent(inout)  flag to indicate if we are processing the first flux call in a splitting operation
+                      computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                      ! input: state vectors
+                      stateVec,                & ! intent(in):    model state vector
+                      stateVecPrime,           & ! intent(in):    derivative of model state vector
+                      sMul,                    & ! intent(inout):  state vector multiplier (used in the residual calculations)
+                      ! input: data structures
+                      model_decisions,         & ! intent(in):    model decisions
+                      lookup_data,             & ! intent(in):    lookup data
+                      type_data,               & ! intent(in):    type of vegetation and soil
+                      attr_data,               & ! intent(in):    spatial attributes
+                      mpar_data,               & ! intent(in):    model parameters
+                      forc_data,               & ! intent(in):    model forcing data
+                      bvar_data,               & ! intent(in):    average model variables for the entire basin
+                      prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                      ! input-output: data structures
+                      indx_data,               & ! intent(inout): index data
+                      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
+                      ! input-output:
+                      dBaseflow_dMatric,       & ! intent(out):    derivative in baseflow w.r.t. matric head (s-1)
+                      scalarCanopyTempTrial,   & ! intent(out):    trial value of canopy temperature (K)
+                      scalarCanopyTempPrev,    & ! intent(in):     value of canopy temperature (K)
+                      scalarCanopyIceTrial,    & ! intent(out):    trial value for mass of ice on the vegetation canopy (kg m-2)
+                      scalarCanopyIcePrev,	    & ! intent(in):     value for mass of ice on the vegetation canopy (kg m-2)
+                      scalarCanopyLiqTrial,    & ! intent(out):    trial value of canopy liquid water (kg m-2)
+                      scalarCanopyLiqPrev,	    & ! intent(in):     value of canopy liquid water (kg m-2)
+                      scalarCanopyEnthalpyTrial,& ! intent(out):   trial value for enthalpy of the vegetation canopy (J m-3)
+                      scalarCanopyEnthalpyPrev,& ! intent(in):     value for enthalpy of the vegetation canopy (J m-3)
+                      mLayerTempTrial,         & ! intent(out):    trial vector of layer temperature (K)
+                      mLayerTempPrev,          & ! intent(in):     vector of layer temperature (K)
+                      mLayerMatricHeadLiqTrial,& ! intent(out):    trial value for liquid water matric potential (m)
+                      mLayerMatricHeadTrial, 	& ! intent(out):    trial value for total water matric potential (m)
+                      mLayerMatricHeadPrev,    & ! intent(in):     value for total water matric potential (m)
+                      mLayerVolFracWatTrial,   & ! intent(out):    trial vector of volumetric total water content (-)
+                      mLayerVolFracWatPrev,    & ! intent(in):     vector of volumetric total water content (-)
+                      mLayerVolFracIceTrial,   & ! intent(out):    trial vector of volumetric ice water content (-)
+                      mLayerVolFracIcePrev,    & ! intent(in):     vector of volumetric ice water content (-)
+                      mLayerVolFracLiqTrial,   & ! intent(out):    trial vector of volumetric liquid water content (-)
+                      mLayerVolFracLiqPrev,    & ! intent(in):     vector of volumetric liquid water content (-)
+                      scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                        scalarAquiferStoragePrev,& ! intent(in):     value of storage of water in the aquifer (m)
+                      mLayerEnthalpyPrev,      & ! intent(in):     vector of enthalpy for snow+soil layers (J m-3)
+                      mLayerEnthalpyTrial,     & ! intent(out):    trial vector of enthalpy for snow+soil layers (J m-3)
+                      ixSaturation,            & ! intent(inout):  index of the lowest saturated layer
+                      feasible,                & ! intent(out):    flag to denote the feasibility of the solution
+                      fluxVec,                 & ! intent(out):    flux vector
+                      resSink,                 & ! intent(out):    additional (sink) terms on the RHS of the state equation
+                      resVec,                  & ! intent(out):    residual vector
+                      err,message)               ! intent(out):    error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! provide access to subroutines
+  USE getVectorz_module, only:varExtract           ! extract variables from the state vector
+  USE updateVarsSundials_module, only:updateVarsSundials           ! update variables
+  USE t2enthalpy_module, only:t2enthalpy_T           ! compute enthalpy
+  USE computFlux_module, only:soilCmpresSundials            ! compute soil compression
+  USE computFlux_module, only:computFlux           ! compute fluxes given a state vector
+  USE computHeatCap_module,only:computHeatCap      ! compute heat capacity
+  USE computHeatCap_module,only:computHeatCapAnalytic      ! compute heat capacity
+  USE computHeatCap_module,only:computCm
+  USE computHeatCap_module, only:computStatMult
+  USE computResidSundials_module,only:computResidSundials          ! compute residuals given a state vector
+  USE computThermConduct_module,only:computThermConduct
+  USE computEnthalpy_module,only:computEnthalpy
+  USE computEnthalpy_module,only:computEnthalpyPrime
   implicit none
-  private
-  public::eval8summaSundials
-  public::eval8summa4IDA
-  
-  contains
-  
-   ! **********************************************************************************************************
-   ! public subroutine eval8summaSundials: compute the residual vector
-   ! **********************************************************************************************************
-   subroutine eval8summaSundials(&
-                         ! input: model control
-                         dt_cur,                  & ! intent(in):    current stepsize
-                         dt,                      & ! intent(in):    entire time step
-                         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
-                         insideIDA,               & ! intent(in):    flag to indicate if we are inside Sundials solver
-                         firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                         firstFluxCall,			& ! intent(inout)  flag to indicate if we are processing the first flux call
-                         firstSplitOper,		    & ! intent(inout)  flag to indicate if we are processing the first flux call in a splitting operation
-                         computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                         scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                         ! input: state vectors
-                         stateVec,                & ! intent(in):    model state vector
-                         stateVecPrime,           & ! intent(in):    derivative of model state vector
-                         sMul,                    & ! intent(inout):  state vector multiplier (used in the residual calculations)
-                         ! input: data structures
-                         model_decisions,         & ! intent(in):    model decisions
-                         lookup_data,             & ! intent(in):    lookup data
-                         type_data,               & ! intent(in):    type of vegetation and soil
-                         attr_data,               & ! intent(in):    spatial attributes
-                         mpar_data,               & ! intent(in):    model parameters
-                         forc_data,               & ! intent(in):    model forcing data
-                         bvar_data,               & ! intent(in):    average model variables for the entire basin
-                         prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                         ! input-output: data structures
-                         indx_data,               & ! intent(inout): index data
-                         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
-                         ! input-output: here we need to pass some extra variables that do not get updated in in the Sundials loops
-                         scalarCanopyTempTrial,   & ! intent(inout): trial value of canopy temperature (K)
-                         scalarCanopyIceTrial,    & ! intent(inout): trial value for mass of ice on the vegetation canopy (kg m-2)
-                         scalarCanopyEnthalpyTrial,& ! intent(inout): trial value for enthalpy of the vegetation canopy (J m-3)
-                         mLayerTempTrial,         & ! intent(inout): trial vector of layer temperature (K)
-                         mLayerMatricHeadTrial,   & ! intent(inout): trial value for total water matric potential (m)
-                         mLayerMatricHeadLiqTrial,& ! intent(inout):   trial value for liquid water matric potential (m)
-                         mLayerVolFracWatTrial,   & ! intent(inout): trial vector of volumetric total water content (-)
-                         mLayerVolFracIceTrial,   & ! intent(inout): trial vector of volumetric ice water content (-)
-                         mLayerEnthalpyTrial,     & ! intent(inout): trial vector of enthalpy for snow+soil layers (J m-3)
-                         ! input-output: baseflow
-                         ixSaturation,            & ! intent(inout):  index of the lowest saturated layer
-                         dBaseflow_dMatric,       & ! intent(out):    derivative in baseflow w.r.t. matric head (s-1)
-                         ! output: flux and residual vectors
-                         feasible,                & ! intent(out):    flag to denote the feasibility of the solution
-                         fluxVec,                 & ! intent(out):    flux vector
-                         resSink,                 & ! intent(out):    additional (sink) terms on the RHS of the state equation
-                         resVec,                  & ! intent(out):    residual vector
-                         err,message)               ! intent(out):    error control
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! provide access to subroutines
-   USE getVectorzAddSundials_module, only:varExtractSundials           ! extract variables from the state vector
-   USE updateVarsSundials_module, only:updateVarsSundials           ! update variables
-   USE t2enthalpy_module, only:t2enthalpy_T           ! compute enthalpy
-   USE computFlux_module, only:soilCmpresSundials            ! compute soil compression
-   USE computFlux_module, only:computFlux           ! compute fluxes given a state vector
-   USE computHeatCap_module,only:computHeatCap      ! compute heat capacity
-   USE computHeatCap_module,only:computHeatCapAnalytic      ! compute heat capacity
-   USE computHeatCap_module,only:computCm
-   USE computHeatCap_module, only:computStatMult
-   USE computResidSundials_module,only:computResidSundials          ! compute residuals given a state vector
-   USE computThermConduct_module,only:computThermConduct
-   USE computEnthalpy_module,only:computEnthalpy
-   USE computEnthalpy_module,only:computEnthalpyPrime
-   implicit none
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! input: model control
-   real(rkind),intent(in)          :: dt_cur
-   real(rkind),intent(in)          :: dt                     ! time step
-   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,intent(in)              :: nState                 ! total number of state variables
-   logical(lgt),intent(in)         :: insideIDA              ! flag to indicate if we are inside Sundials solver
-   logical(lgt),intent(in)         :: firstSubStep           ! flag to indicate if we are processing the first sub-step
-   logical(lgt),intent(inout)      :: firstFluxCall
-   logical(lgt),intent(inout)      :: firstSplitOper         ! flag to indicate if we are processing the first flux call in a splitting operation
-   logical(lgt),intent(in)         :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
-   logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
-   ! input: state vectors
-   real(rkind),intent(in)          :: stateVec(:)            ! model state vector
-   real(rkind),intent(in)          :: stateVecPrime(:)       ! model state vector
-   real(qp),intent(inout)          :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
-   ! input: data structures
-   type(model_options),intent(in)  :: model_decisions(:)     ! model decisions
-   type(zLookup),intent(in)        :: lookup_data            ! lookup tables
-   type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
-   type(var_d),        intent(in)  :: attr_data              ! spatial attributes
-   type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
-   type(var_d),        intent(in)  :: forc_data              ! model forcing data
-   type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
-   type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
-   ! output: data structures
-   type(var_ilength),intent(inout) :: indx_data              ! indices defining model states and layers
-   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(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
-   ! input-output: here we need to pass some extra variables that do not get updated in in the Sundials loops
-   real(rkind),intent(inout)       :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
-   real(rkind),intent(inout)       :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),intent(inout)       :: scalarCanopyEnthalpyTrial ! trial value for enthalpy of the vegetation canopy (J m-3)
-   real(rkind),intent(inout)       :: mLayerTempTrial(:)        ! trial vector of layer temperature (K)
-   real(rkind),intent(inout)       :: mLayerMatricHeadTrial(:)  ! trial vector of total water matric potential (m)
-   real(rkind),intent(inout)       :: mLayerMatricHeadLiqTrial(:)! trial value for liquid water matric potential (m)
-   real(rkind),intent(inout)       :: mLayerVolFracWatTrial(:)  ! trial vector of volumetric total water content (-)
-   real(rkind),intent(inout)       :: mLayerVolFracIceTrial(:)  ! trial vector of volumetric ice water content (-)
-   real(rkind),intent(inout)       :: mLayerEnthalpyTrial(:)    ! trial vector of enthalpy for snow+soil layers (J m-3)
-   ! input-output: baseflow
-   integer(i4b),intent(inout)      :: ixSaturation              ! index of the lowest saturated layer
-   real(rkind),intent(out)         :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
-   ! output: flux and residual vectors
-   logical(lgt),intent(out)        :: feasible               ! flag to denote the feasibility of the solution
-   real(rkind),intent(out)         :: fluxVec(:)             ! flux vector
-   real(rkind),intent(out)         :: resSink(:)             ! sink terms on the RHS of the flux equation
-   real(qp),intent(out)            :: resVec(:) ! NOTE: qp   ! residual vector
-   ! output: error control
-   integer(i4b),intent(out)        :: err                    ! error code
-   character(*),intent(out)        :: message                ! error message
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! local variables
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! previous state variables
-   real(rkind)                        :: scalarCanopyTempPrev      ! previous value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyIcePrev       ! previous value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempPrev            ! previous vector of layer temperature (K)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrev      ! previous vector of total water matric potential (m)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrev      ! previous vector of volumetric total water content (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrev      ! previous vector of volumetric ice water content (-)
-   ! trial state variables
-   real(rkind)                        :: scalarCanairTempTrial          ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyWatTrial           ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind)                        :: scalarAquiferStorageTrial      ! trial value for storage of water in the aquifer (m)
-   ! diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqTrial           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial          ! trial vector for volumetric fraction of liquid water (-)
-   ! derivative of state variables
-   real(rkind)                        :: scalarCanairTempPrime          ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempPrime          ! trial value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatPrime           ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempPrime                ! trial vector for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrime          ! trial vector for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrime          ! trial vector for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqPrime       ! trial vector for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStoragePrime      ! trial value for storage of water in the aquifer (m)
-   ! derivative of diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqPrime           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIcePrime           ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqPrime          ! trial vector for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrime          ! trial vector for volumetric fraction of ice (-)
-   ! enthalpy
-   real(rkind)                        :: scalarCanopyEnthalpyPrev  ! previous value for enthalpy of the vegetation canopy (J m-3)
-   real(rkind)                        :: scalarCanairEnthalpy      ! enthalpy of the canopy air space (J m-3)
-   real(rkind),dimension(nLayers)     :: mLayerEnthalpyPrime       ! enthalpy of each snow+soil layer (J m-3)
-   real(rkind),dimension(nLayers)     :: mLayerEnthalpyPrev        ! previous vector of enthalpy for snow+soil layers (J m-3)
-   ! other local variables
-   integer(i4b)                       :: iLayer                    ! index of model layer in the snow+soil domain
-   integer(i4b)                       :: jState(1)                 ! index of model state for the scalar solution within the soil domain
-   integer(i4b)                       :: ixBeg,ixEnd               ! index of indices for the soil compression routine
-   integer(i4b),parameter             :: ixVegVolume=1             ! index of the desired vegetation control volumne (currently only one veg layer)
-   real(rkind)                        :: xMin,xMax                 ! minimum and maximum values for water content
-   real(rkind),parameter              :: canopyTempMax=500._rkind  ! expected maximum value for the canopy temperature (K)
-   character(LEN=256)                 :: cmessage                  ! error message of downwind routine
-   real(rkind)						:: scalarCanopyCmTrial       ! trial value of Cm for the canopy
-   real(rkind),dimension(nLayers)	    :: mLayerCmTrial             ! trial vector of Cm for snow+soil
-   logical(lgt),parameter			    :: updateCp=.true.           ! flag to indicate if we update Cp at each step
-   logical(lgt),parameter		        :: needCm=.false.            ! flag to indicate if the energy equation contains Cm = dH_T/dTheta_m
-  
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   associate(&
-   ! model decisions
-   ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
-   ! snow parameters
-   snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,&  ! intent(in):  [dp]    scaling parameter for the snow freezing curve (K-1)
-   ! soil parameters
-   theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
-   specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
-   theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
-   ! canopy and layer depth
-   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)
-   ! model state variables
-   scalarSfcMeltPond       => prog_data%var(iLookPROG%scalarSfcMeltPond)%dat(1)      ,&  ! intent(in):  [dp]    ponded water caused by melt of the "snow without a layer" (kg m-2)
-   ! soil compression
-   scalarSoilCompress      => diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1)     ,&  ! intent(in): [dp]    total change in storage associated with compression of the soil matrix (kg m-2)
-   mLayerCompress          => diag_data%var(iLookDIAG%mLayerCompress)%dat            ,&  ! intent(in): [dp(:)] change in storage associated with compression of the soil matrix (-)
-   ! derivatives
-   dVolTot_dPsi0           => deriv_data%var(iLookDERIV%dVolTot_dPsi0)%dat           ,&  ! intent(in): [dp(:)] derivative in total water content w.r.t. total water matric potential
-   dCompress_dPsi          => deriv_data%var(iLookDERIV%dCompress_dPsi)%dat          ,&  ! intent(in): [dp(:)] derivative in compressibility w.r.t. matric head (m-1)
-   ! mapping
-   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)
-   ! indices
-   ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy air space energy state variable (nrg)
-   ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy energy state variable (nrg)
-   ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy hydrology state variable (mass)
-   ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,&  ! intent(in): [i4b(:)] indices for energy states in the snow subdomain
-   ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,&  ! intent(in): [i4b(:)] indices for hydrology states in the snow+soil subdomain
-   ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,&  ! intent(in): [i4b(:)] indices defining the type of the state (iname_nrgLayer...)
-   ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,&  ! intent(in): [i4b(:)] index of the hydrology states in the canopy domain
-   ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,&  ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
-   layerType               => indx_data%var(iLookINDEX%layerType)%dat                ,&  ! intent(in): [i4b(:)] layer type (iname_soil or iname_snow)
-   heatCapVegTrial		 =>  diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1),& ! intent(out): volumetric heat capacity of vegetation canopy
-   mLayerHeatCapTrial	     =>  diag_data%var(iLookDIAG%mLayerVolHtCapBulk)%dat        &  ! intent(out): heat capacity for snow and soil
-   ) ! association to variables in the data structures
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! initialize error control
-   err=0; message="eval8summaSundials/"
-   feasible=.true.
-  
-   ! check the feasibility of the solution only if not inside Sundials solver
-   if (.not.insideIDA) then
-    ! check that the canopy air space temperature is reasonable
-    if(ixCasNrg/=integerMissing)then
-     if(stateVec(ixCasNrg) > canopyTempMax) feasible=.false.
-     if(stateVec(ixCasNrg) > canopyTempMax) message=trim(message)//'canopy air space temp high,'
-     if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVec( ixCasNrg )', feasible, canopyTempMax, stateVec(ixCasNrg)
-    endif
-  
-    ! check that the canopy temperature is reasonable
-    if(ixVegNrg/=integerMissing)then
-     if(stateVec(ixVegNrg) > canopyTempMax) feasible=.false.
-     if(stateVec(ixVegNrg) > canopyTempMax) message=trim(message)//'canopy temp high,'
-     if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVec( ixVegNrg )', feasible, canopyTempMax, stateVec(ixVegNrg)
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: model control
+  real(rkind),intent(in)          :: dt_cur
+  real(rkind),intent(in)          :: dt                     ! time step
+  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,intent(in)              :: nState                 ! total number of state variables
+  logical(lgt),intent(in)         :: insideIDA ! flag to indicate if we are inside Sundials solver
+  logical(lgt),intent(in)         :: firstSubStep           ! flag to indicate if we are processing the first sub-step
+  logical(lgt),intent(inout)      :: firstFluxCall
+  logical(lgt),intent(inout)      :: firstSplitOper         ! flag to indicate if we are processing the first flux call in a splitting operation
+  logical(lgt),intent(in)         :: computeVegFlux         ! flag to indicate if computing fluxes over vegetation
+  logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
+  ! input: state vectors
+  real(rkind),intent(in)          :: stateVec(:)            ! model state vector
+  real(rkind),intent(in)          :: stateVecPrime(:)       ! model state vector
+  real(qp),intent(inout)          :: sMul(:)   ! NOTE: qp   ! state vector multiplier (used in the residual calculations)
+  ! input: data structures
+  type(model_options),intent(in)  :: model_decisions(:)     ! model decisions
+  type(zLookup),intent(in)        :: lookup_data            ! lookup tables
+  type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
+  type(var_d),        intent(in)  :: attr_data              ! spatial attributes
+  type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
+  type(var_d),        intent(in)  :: forc_data              ! model forcing data
+  type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
+  type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
+  ! output: data structures
+  type(var_ilength),intent(inout) :: indx_data              ! indices defining model states and layers
+  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(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
+  ! input-output: baseflow
+  real(rkind),intent(out)         :: dBaseflow_dMatric(:,:) ! derivative in baseflow w.r.t. matric head (s-1)
+  ! output: flux and residual vectors
+  real(rkind),intent(out)         :: scalarCanopyTempTrial     ! trial value for temperature of the vegetation canopy (K)
+  real(rkind),intent(in)          :: scalarCanopyTempPrev      ! previous value for temperature of the vegetation canopy (K)
+  real(rkind),intent(out)         :: scalarCanopyIceTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),intent(in)          :: scalarCanopyIcePrev       ! previous value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),intent(out)         :: scalarCanopyLiqTrial      ! trial value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),intent(in)          :: scalarCanopyLiqPrev       ! previous value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),intent(out)         :: scalarCanopyEnthalpyTrial ! trial value for enthalpy of the vegetation canopy (J m-3)
+  real(rkind),intent(in)          :: scalarCanopyEnthalpyPrev  ! previous value of enthalpy of the vegetation canopy (J m-3)
+  real(rkind),intent(out)         :: mLayerTempTrial(:)        ! trial vector of layer temperature (K)
+  real(rkind),intent(in)          :: mLayerTempPrev(:)
+  real(rkind),intent(out)         :: mLayerMatricHeadLiqTrial(:)  ! trial value for liquid water matric potential (m)
+  real(rkind),intent(out)         :: mLayerMatricHeadTrial(:)  ! trial value for total water matric potential (m)
+  real(rkind),intent(in)          :: mLayerMatricHeadPrev(:) ! value for total water matric potential (m)
+  real(rkind),intent(out)         :: mLayerVolFracWatTrial(:)  ! trial vector of volumetric total water content (-)
+  real(rkind),intent(in)          :: mLayerVolFracWatPrev(:) ! vector of volumetric total water content (-)
+  real(rkind),intent(out)         :: mLayerVolFracIceTrial(:)  ! trial vector of volumetric ice water content (-)
+  real(rkind),intent(in)          :: mLayerVolFracIcePrev(:) ! vector of volumetric ice water content (-)
+  real(rkind),intent(out)         :: mLayerVolFracLiqTrial(:)  ! trial vector of volumetric liquid water content (-)
+  real(rkind),intent(in)          :: mLayerVolFracLiqPrev(:) ! vector of volumetric liquid water content (-)
+  real(rkind),intent(out)         :: scalarAquiferStorageTrial ! trial value of storage of water in the aquifer (m)
+  real(rkind),intent(in)          :: scalarAquiferStoragePrev  ! value of storage of water in the aquifer (m)
+  real(rkind),intent(in)          :: mLayerEnthalpyPrev(:)    ! vector of enthalpy for snow+soil layers (J m-3)
+  real(rkind),intent(out)         :: mLayerEnthalpyTrial(:)   ! trial vector of enthalpy for snow+soil layers (J m-3)
+  integer(i4b),intent(inout)      :: ixSaturation              ! index of the lowest saturated layer
+  logical(lgt),intent(out)        :: feasible               ! flag to denote the feasibility of the solution
+  real(rkind),intent(out)         :: fluxVec(:)             ! flux vector
+  real(rkind),intent(out)         :: resSink(:)             ! sink terms on the RHS of the flux equation
+  real(qp),intent(out)            :: resVec(:) ! NOTE: qp   ! residual vector
+  ! output: error control
+  integer(i4b),intent(out)        :: err                    ! error code
+  character(*),intent(out)        :: message                ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! state variables
+  real(rkind)                        :: scalarCanairTempTrial     ! trial value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyWatTrial      ! trial value for liquid water storage in the canopy (kg m-2)
+    ! derivative of state variables
+  real(rkind)                        :: scalarCanairTempPrime     ! derivative value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyTempPrime     ! derivative value for temperature of the vegetation canopy (K)
+  real(rkind)                        :: scalarCanopyWatPrime      ! derivative value for liquid water storage in the canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerTempPrime           ! derivative value for temperature of layers in the snow and soil domains (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrime     ! derivative value for volumetric fraction of total water (-)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrime     ! derivative value for total water matric potential (m)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqPrime  ! derivative value for liquid water matric potential (m)
+  real(rkind)                        :: scalarAquiferStoragePrime ! derivative value of storage of water in the aquifer (m)
+  ! derivative of diagnostic variables
+  real(rkind)                        :: scalarCanopyLiqPrime      ! derivative value for mass of liquid water on the vegetation canopy (kg m-2)
+  real(rkind)                        :: scalarCanopyIcePrime      ! derivative value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracLiqPrime     ! derivative value for volumetric fraction of liquid water (-)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrime     ! derivative value for volumetric fraction of ice (-)
+  ! enthalpy
+  real(rkind)                        :: scalarCanairEnthalpy      ! enthalpy of the canopy air space (J m-3)
+  real(rkind),dimension(nLayers)     :: mLayerEnthalpyPrime       ! enthalpy of each snow+soil layer (J m-3)
+  ! other local variables
+  integer(i4b)                       :: iLayer                    ! index of model layer in the snow+soil domain
+  integer(i4b)                       :: jState(1)                 ! index of model state for the scalar solution within the soil domain
+  integer(i4b)                       :: ixBeg,ixEnd               ! index of indices for the soil compression routine
+  integer(i4b),parameter             :: ixVegVolume=1             ! index of the desired vegetation control volumne (currently only one veg layer)
+  real(rkind)                        :: xMin,xMax                 ! minimum and maximum values for water content
+  real(rkind),parameter              :: canopyTempMax=500._rkind  ! expected maximum value for the canopy temperature (K)
+  character(LEN=256)                 :: cmessage                  ! error message of downwind routine
+  real(rkind)						            :: scalarCanopyCmTrial       ! trial value of Cm for the canopy
+  real(rkind),dimension(nLayers)	    :: mLayerCmTrial             ! trial vector of Cm for snow+soil
+  logical(lgt),parameter			        :: updateCp=.true.           ! flag to indicate if we update Cp at each step
+  logical(lgt),parameter			        :: needCm=.false.            ! flag to indicate if the energy equation contains Cm = dH_T/dTheta_m
+
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! association to variables in the data structures
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  associate(&
+    ! model decisions
+    ixRichards              => model_decisions(iLookDECISIONS%f_Richards)%iDecision   ,&  ! intent(in):  [i4b]   index of the form of Richards' equation
+    ! snow parameters
+    snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,&  ! intent(in):  [dp]    scaling parameter for the snow freezing curve (K-1)
+    ! soil parameters
+    theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
+    specificStorage         => mpar_data%var(iLookPARAM%specificStorage)%dat(1)       ,&  ! intent(in):  [dp]    specific storage coefficient (m-1)
+    theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
+    ! canopy and layer depth
+    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)
+    ! model state variables
+    scalarSfcMeltPond       => prog_data%var(iLookPROG%scalarSfcMeltPond)%dat(1)      ,&  ! intent(in):  [dp]    ponded water caused by melt of the "snow without a layer" (kg m-2)
+    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,&  ! intent(in):  [dp(:)] volumetric fraction of ice (-)
+    ! soil compression
+    scalarSoilCompress      => diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1)     ,&  ! intent(in): [dp]    total change in storage associated with compression of the soil matrix (kg m-2)
+    mLayerCompress          => diag_data%var(iLookDIAG%mLayerCompress)%dat            ,&  ! intent(in): [dp(:)] change in storage associated with compression of the soil matrix (-)
+    ! derivatives
+    dVolTot_dPsi0           => deriv_data%var(iLookDERIV%dVolTot_dPsi0)%dat           ,&  ! intent(in): [dp(:)] derivative in total water content w.r.t. total water matric potential
+    dCompress_dPsi          => deriv_data%var(iLookDERIV%dCompress_dPsi)%dat          ,&  ! intent(in): [dp(:)] derivative in compressibility w.r.t. matric head (m-1)
+    ! mapping
+    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)
+    ! indices
+    ixCasNrg                => indx_data%var(iLookINDEX%ixCasNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy air space energy state variable (nrg)
+    ixVegNrg                => indx_data%var(iLookINDEX%ixVegNrg)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy energy state variable (nrg)
+    ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,&  ! intent(in): [i4b]    index of canopy hydrology state variable (mass)
+    ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,&  ! intent(in): [i4b(:)] indices for energy states in the snow subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,&  ! intent(in): [i4b(:)] indices for hydrology states in the snow+soil subdomain
+    ixStateType             => indx_data%var(iLookINDEX%ixStateType)%dat              ,&  ! intent(in): [i4b(:)] indices defining the type of the state (iname_nrgLayer...)
+    ixHydCanopy             => indx_data%var(iLookINDEX%ixHydCanopy)%dat              ,&  ! intent(in): [i4b(:)] index of the hydrology states in the canopy domain
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,&  ! intent(in): [i4b(:)] index of the type of hydrology states in snow+soil domain
+    layerType               => indx_data%var(iLookINDEX%layerType)%dat                 ,&  ! intent(in): [i4b(:)] layer type (iname_soil or iname_snow)
+    heatCapVegTrial		     =>  diag_data%var(iLookDIAG%scalarBulkVolHeatCapVeg)%dat(1) ,& ! intent(out): volumetric heat capacity of vegetation canopy
+    mLayerHeatCapTrial		   =>  diag_data%var(iLookDIAG%mLayerVolHtCapBulk)%dat         &  ! intent(out): heat capacity for snow and soil
+    ) ! association to variables in the data structures
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message="eval8summaSundials/"
+    feasible=.true.
+
+    ! check the feasibility of the solution
+    if (.not.insideIDA) then
+      ! check that the canopy air space temperature is reasonable
+      if(ixCasNrg/=integerMissing)then
+        if(stateVec(ixCasNrg) > canopyTempMax) feasible=.false.
+        if(stateVec(ixCasNrg) > canopyTempMax) message=trim(message)//'canopy air space temp high,'
+        if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVec( ixCasNrg )', feasible, canopyTempMax, stateVec(ixCasNrg)
+      endif
+
+      ! check that the canopy temperature is reasonable
+      if(ixVegNrg/=integerMissing)then
+        if(stateVec(ixVegNrg) > canopyTempMax) feasible=.false.
+        if(stateVec(ixVegNrg) > canopyTempMax) message=trim(message)//'canopy temp high,'
+        if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, max, stateVec( ixVegNrg )', feasible, canopyTempMax, stateVec(ixVegNrg)
+      endif
+
+      ! check canopy liquid water is not negative
+      if(ixVegHyd/=integerMissing)then
+        if(stateVec(ixVegHyd) < 0._rkind) feasible=.false.
+        if(stateVec(ixVegHyd) < 0._rkind) message=trim(message)//'canopy water negative,'
+        if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, min, stateVec( ixVegHyd )', feasible, 0._rkind, stateVec(ixVegHyd)
+      end if
+
+      ! check snow temperature is below freezing
+      if(count(ixSnowOnlyNrg/=integerMissing)>0)then
+        if(any(stateVec( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) feasible=.false.
+        if(any(stateVec( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) message=trim(message)//'snow temp above freezing,'
+        do iLayer=1,nSnow
+          if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, max, stateVec( ixSnowOnlyNrg(iLayer) )', iLayer, feasible, Tfreeze, stateVec( ixSnowOnlyNrg(iLayer) )
+        enddo
+      endif
+
+      ! loop through non-missing hydrology state variables in the snow+soil domain
+      do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)
+
+        ! check the minimum and maximum water constraints
+        if(ixHydType(iLayer)==iname_watLayer .or. ixHydType(iLayer)==iname_liqLayer)then
+
+          ! --> minimum
+          if (layerType(iLayer) == iname_soil) then
+            xMin = theta_res(iLayer-nSnow)
+          else
+            xMin = 0._rkind
+          endif
+
+          ! --> maximum
+          select case( layerType(iLayer) )
+            case(iname_snow); xMax = merge(iden_ice,  1._rkind - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
+            case(iname_soil); xMax = merge(theta_sat(iLayer-nSnow), theta_sat(iLayer-nSnow) - mLayerVolFracIce(iLayer), ixHydType(iLayer)==iname_watLayer)
+          end select
+
+          ! --> check
+          if(stateVec( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVec( ixSnowSoilHyd(iLayer) ) > xMax) feasible=.false.
+          if(stateVec( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVec( ixSnowSoilHyd(iLayer) ) > xMax)  message=trim(message)//'layer water outside bounds,'
+          if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, stateVec( ixSnowSoilHyd(iLayer) ), xMin, xMax = ', iLayer, feasible, stateVec( ixSnowSoilHyd(iLayer) ), xMin, xMax
+
+        endif  ! if water states
+
+      end do  ! loop through non-missing hydrology state variables in the snow+soil domain
+
+      ! early return for non-feasible solutions
+      if(.not.feasible)then
+        fluxVec(:) = realMissing
+        resVec(:)  = quadMissing
+        message=trim(message)//'non-feasible'
+        err=20; return
+      end if
+
+    end if ! ( feasibility check )
+
+    ! get the start and end indices for the soil compression calculations
+    if(scalarSolution)then
+      jState = pack(ixControlVolume, ixMapFull2Subset/=integerMissing)
+      ixBeg  = jState(1)
+      ixEnd  = jState(1)
+    else
+      ixBeg  = 1
+      ixEnd  = nSoil
     endif
-  
-    ! check canopy liquid water is not negative
-    if(ixVegHyd/=integerMissing)then
-     if(stateVec(ixVegHyd) < 0._rkind) feasible=.false.
-     if(stateVec(ixVegHyd) < 0._rkind) message=trim(message)//'canopy water negative,'
-     if(.not.feasible) write(*,'(a,1x,L1,1x,10(f20.10,1x))') 'feasible, min, stateVec( ixVegHyd )', feasible, 0._rkind, stateVec(ixVegHyd)
-    end if
-  
-    ! check snow temperature is below freezing
-    if(count(ixSnowOnlyNrg/=integerMissing)>0)then
-     if(any(stateVec( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) feasible=.false.
-     if(any(stateVec( pack(ixSnowOnlyNrg,ixSnowOnlyNrg/=integerMissing) ) > Tfreeze)) message=trim(message)//'snow temp above freezing,'
-     do iLayer=1,nSnow
-      if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, max, stateVec( ixSnowOnlyNrg(iLayer) )', iLayer, feasible, Tfreeze, stateVec( ixSnowOnlyNrg(iLayer) )
-     enddo
+
+    ! initialize to state variable from the last update
+    scalarCanopyTempTrial     = scalarCanopyTempPrev
+    scalarCanopyLiqTrial      = scalarCanopyLiqPrev
+    scalarCanopyIceTrial      = scalarCanopyIcePrev
+    mLayerTempTrial           = mLayerTempPrev
+    mLayerVolFracWatTrial     = mLayerVolFracWatPrev
+    mLayerVolFracLiqTrial     = mLayerVolFracLiqPrev
+    mLayerVolFracIceTrial     = mLayerVolFracIcePrev
+    mLayerMatricHeadTrial     = mLayerMatricHeadPrev
+    scalarAquiferStorageTrial = scalarAquiferStoragePrev
+
+    ! extract variables from the model state vector
+    call varExtract(&
+                    ! input
+                    stateVec,                 & ! intent(in):    model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
+                    scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
+                    scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
+                    mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
+                    mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
+                    mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
+                    mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! Extract the variables for stateVecPrime
+    call varExtract(&
+                    ! input
+                    stateVecPrime,            & ! intent(in):    derivative of model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempPrime,    & ! intent(out):   derivative of canopy air temperature (K)
+                    scalarCanopyTempPrime,    & ! intent(out):   derivative of canopy temperature (K)
+                    scalarCanopyWatPrime,     & ! intent(out):   derivative of canopy total water (kg m-2)
+                    scalarCanopyLiqPrime,     & ! intent(out):   derivative of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempPrime,          & ! intent(out):   derivative of layer temperature (K)
+                    mLayerVolFracWatPrime,    & ! intent(out):   derivative of volumetric total water content (-)
+                    mLayerVolFracLiqPrime,    & ! intent(out):   derivative of volumetric liquid water content (-)
+                    mLayerMatricHeadPrime,    & ! intent(out):   derivative of total water matric potential (m)
+                    mLayerMatricHeadLiqPrime, & ! intent(out):   derivative of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStoragePrime,& ! intent(out):   derivative of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+
+    call updateVarsSundials(&
+                    ! input
+                    dt_cur,                                    &
+                    .false.,                                   & ! intent(in):    logical flag if computing Jacobian for Sundials solver
+                    .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy
+                    mpar_data,                                 & ! intent(in):    model parameters for a local HRU
+                    indx_data,                                 & ! intent(in):    indices defining model states and layers
+                    prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                    mLayerVolFracWatPrev,                      & ! intent(in):    previous vector of total water matric potential (m)
+                    mLayerMatricHeadPrev,                      & ! intent(in):    previous vector of volumetric total water content (-)
+                    diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
+                    deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                    ! output: variables for the vegetation canopy
+                    scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
+                    scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                    scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                    scalarCanopyTempPrime,                     & ! intent(inout): trial value of canopy temperature (K)
+                    scalarCanopyWatPrime,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                    scalarCanopyLiqPrime,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                    scalarCanopyIcePrime,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
+                    mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
+                    mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
+                    mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
+                    mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
+                    mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
+                    mLayerTempPrime,                           & !
+                    mLayerVolFracWatPrime,                     & ! intent(inout): Prime vector of volumetric total water content (-)
+                    mLayerVolFracLiqPrime,                     & ! intent(inout): Prime vector of volumetric liquid water content (-)
+                    mLayerVolFracIcePrime,                     & !
+                    mLayerMatricHeadPrime,                     & ! intent(inout): Prime vector of total water matric potential (m)
+                    mLayerMatricHeadLiqPrime,                  & ! intent(inout): Prime vector of liquid water matric potential (m)
+                    ! output: error control
+                    err,cmessage)                                ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    ! print the water content
+    if(globalPrintFlag)then
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracWatTrial = ', mLayerVolFracWatTrial(iJac1:min(iJac2,nSnow))
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial(iJac1:min(iJac2,nSnow))
+      if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial(iJac1:min(iJac2,nSnow))
     endif
-  
-   ! loop through non-missing hydrology state variables in the snow+soil domain
-    do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)
-  
-     ! check the minimum and maximum water constraints
-     if(ixHydType(iLayer)==iname_watLayer .or. ixHydType(iLayer)==iname_liqLayer)then
-  
-      ! --> minimum
-      if (layerType(iLayer) == iname_soil) then
-       xMin = theta_res(iLayer-nSnow)
-      else
-       xMin = 0._rkind
-      endif
-  
-      ! --> maximum
-      select case( layerType(iLayer) )
-       case(iname_snow); xMax = merge(iden_ice,  1._rkind - mLayerVolFracIceTrial(iLayer), ixHydType(iLayer)==iname_watLayer)
-       case(iname_soil); xMax = merge(theta_sat(iLayer-nSnow), theta_sat(iLayer-nSnow) - mLayerVolFracIceTrial(iLayer), ixHydType(iLayer)==iname_watLayer)
-      end select
-  
-      ! --> check
-      if(stateVec( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVec( ixSnowSoilHyd(iLayer) ) > xMax) feasible=.false.
-      if(stateVec( ixSnowSoilHyd(iLayer) ) < xMin .or. stateVec( ixSnowSoilHyd(iLayer) ) > xMax)  message=trim(message)//'layer water outside bounds,'
-      if(.not.feasible) write(*,'(a,1x,i4,1x,L1,1x,10(f20.10,1x))') 'iLayer, feasible, stateVec( ixSnowSoilHyd(iLayer) ), xMin, xMax = ', iLayer, feasible, stateVec( ixSnowSoilHyd(iLayer) ), xMin, xMax
-  
-     endif  ! if water states
-  
-    end do  ! loop through non-missing hydrology state variables in the snow+soil domain
-  
-    ! early return for non-feasible solutions
-    if(.not.feasible)then
-     fluxVec(:) = realMissing
-     resVec(:)  = quadMissing
-     message=trim(message)//'non-feasible'
-     err=20; return
-    end if
-  
-   end if ! ( feasibility check )
-  
-   ! get the start and end indices for the soil compression calculations
-   if(scalarSolution)then
-    jState = pack(ixControlVolume, ixMapFull2Subset/=integerMissing)
-    ixBeg  = jState(1)
-    ixEnd  = jState(1)
-   else
-    ixBeg  = 1
-    ixEnd  = nSoil
-   endif
-  
-   ! save previous step
-   scalarCanopyTempPrev     = scalarCanopyTempTrial
-   scalarCanopyIcePrev      = scalarCanopyIceTrial
-   scalarCanopyEnthalpyPrev = scalarCanopyEnthalpyTrial
-   mLayerTempPrev           = mLayerTempTrial
-   mLayerMatricHeadPrev     = mLayerMatricHeadTrial
-   mLayerVolFracWatPrev     = mLayerVolFracWatTrial
-   mLayerVolFracIcePrev     = mLayerVolFracIceTrial
-   mLayerEnthalpyPrev       = mLayerEnthalpyTrial
-  
-   ! these will need to be initialized as they do not have updated prognostic structures in Sundials
-   ! should all be set to previous values if splits, but for now operator splitting is not hooked up
-   scalarCanairTempPrime    = realMissing
-   scalarCanopyTempPrime    = realMissing
-   scalarCanopyWatPrime     = realMissing
-   scalarCanopyLiqPrime     = realMissing
-   scalarCanopyIcePrime     = realMissing
-   mLayerTempPrime          = realMissing
-   mLayerVolFracWatPrime    = realMissing
-   mLayerVolFracLiqPrime    = realMissing
-   mLayerVolFracIcePrime    = realMissing
-   mLayerMatricHeadPrime    = realMissing
-   mLayerMatricHeadLiqPrime = realMissing
-   scalarAquiferStoragePrime= realMissing
-   scalarCanairTempTrial    = realMissing ! scalarCanairTemp prognostic not up to date
-   scalarCanopyWatTrial     = realMissing ! scalarCanopyWat prognostic not up to date
-   scalarCanopyLiqTrial     = realMissing ! scalarCanopyLiq prognostic not up to date
-   mLayerVolFracLiqTrial    = realMissing ! mLayerVolFracLiq prognostic not up to date
-   scalarAquiferStorageTrial= realMissing ! scalarAquiferStorage prognostic not up to date
-  
-   ! extract variables from the model state vector
-   call varExtractSundials(&
-                   ! input
-                   stateVec,                 & ! intent(in):    model state vector (mixed units)
-                   stateVecPrime,            & ! intent(in):    model state vector (mixed units)
-                   diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
-                   prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                & ! intent(in):    indices defining model states and layers
-                   ! output: variables for the vegetation canopy
-                   scalarCanairTempTrial,    & ! intent(inout):   trial value of canopy air temperature (K)
-                   scalarCanopyTempTrial,    & ! intent(inout):   trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,     & ! intent(inout):   trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,     & ! intent(inout):   trial value of canopy liquid water (kg m-2)
-                   scalarCanairTempPrime,    & ! intent(inout):   derivative of canopy air temperature (K)
-                   scalarCanopyTempPrime,    & ! intent(inout):   derivative of canopy temperature (K)
-                   scalarCanopyWatPrime,     & ! intent(inout):   derivative of canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,     & ! intent(inout):   derivative of canopy liquid water (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,          & ! intent(inout):   trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,    & ! intent(inout):   trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,    & ! intent(inout):   trial vector of volumetric liquid water content (-)
-                   mLayerMatricHeadTrial,    & ! intent(inout):   trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial, & ! intent(inout):   trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,          & ! intent(inout):   derivative of layer temperature (K)
-                   mLayerVolFracWatPrime,    & ! intent(inout):   derivative of volumetric total water content (-)
-                   mLayerVolFracLiqPrime,    & ! intent(inout):   derivative of volumetric liquid water content (-)
-                   mLayerMatricHeadPrime,    & ! intent(inout):   derivative of total water matric potential (m)
-                   mLayerMatricHeadLiqPrime, & ! intent(inout):   derivative of liquid water matric potential (m)
-                   ! output: variables for the aquifer
-                   scalarAquiferStorageTrial,& ! intent(inout):   trial value of storage of water in the aquifer (m)
-                   scalarAquiferStoragePrime,& ! intent(inout):   derivative of storage of water in the aquifer (m)
-                   ! output: error control
-                   err,cmessage)               ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   call updateVarsSundials(&
-                   ! input
-                   dt_cur,                                    &
-                   .false.,                                   & ! intent(in):    logical flag if computing Jacobian for Sundials solver
-                   .false.,                                   & ! intent(in):    logical flag to adjust temperature to account for the energy
-                   mpar_data,                                 & ! intent(in):    model parameters for a local HRU
-                   indx_data,                                 & ! intent(in):    indices defining model states and layers
-                   prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                   mLayerVolFracWatPrev,                      & ! intent(in):    previous vector of total water matric potential (m)
-                   mLayerMatricHeadPrev,                      & ! intent(in):    previous vector of volumetric total water content (-)
-                   diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
-                   deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! output: variables for the vegetation canopy
-                   scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
-                   scalarCanopyTempPrime,                     & ! intent(inout): trial value of time derivative canopy temperature (K)
-                   scalarCanopyWatPrime,                      & ! intent(inout): trial value of time derivative canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,                      & ! intent(inout): trial value of time derivative canopy liquid water (kg m-2)
-                   scalarCanopyIcePrime,                      & ! intent(inout): trial value of time derivative canopy ice content (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
-                   mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,                           & !
-                   mLayerVolFracWatPrime,                     & ! intent(inout): trial vector of time derivative volumetric total water content (-)
-                   mLayerVolFracLiqPrime,                     & ! intent(inout): trial vector of time derivative volumetric liquid water content (-)
-                   mLayerVolFracIcePrime,                     & ! intent(inout): trial vector of time derivative volumetric ice water content (-)
-                   mLayerMatricHeadPrime,                     & ! intent(inout): trial vector of time derivative total water matric potential (m)
-                   mLayerMatricHeadLiqPrime,                  & ! intent(inout): trial vector of time derivative liquid water matric potential (m)
-                   ! output: error control
-                   err,cmessage)                                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! print the water content
-   if(globalPrintFlag)then
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracWatTrial = ', mLayerVolFracWatTrial(iJac1:min(iJac2,nSnow))
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial(iJac1:min(iJac2,nSnow))
-    if(iJac1<nSnow) write(*,'(a,10(f16.10,1x))') 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial(iJac1:min(iJac2,nSnow))
-   endif
-  
-   if(updateCp)then
-     ! *** compute volumetric heat capacity C_p
-    if(model_decisions(iLookDECISIONS%howHeatCap)%iDecision == enthalpyFD)then
-    ! compute H_T
-      call t2enthalpy_T(&
+
+    if(updateCp)then
+      ! *** compute volumetric heat capacity C_p
+      if(model_decisions(iLookDECISIONS%howHeatCap)%iDecision == enthalpyFD)then
+        ! compute H_T
+        call t2enthalpy_T(&
                         ! input: data structures
                         diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
                         mpar_data,                   & ! intent(in):  parameter data structure
@@ -522,350 +526,228 @@ module eval8summaSundials_module
                         mLayerEnthalpyTrial,         & ! intent(out):  enthalpy of each snow+soil layer (J m-3)
                         ! output: error control
                         err,cmessage)                  ! intent(out): error control
-      if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-  
-      ! *** compute volumetric heat capacity C_p = dH_T/dT
-      call computHeatCap(&
+        if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+
+        ! *** compute volumetric heat capacity C_p = dH_T/dT
+        call computHeatCap(&
+                            ! input: control variables
+                            nLayers,                 	 & ! intent(in): number of layers (soil+snow)
+                            computeVegFlux,         	 & ! intent(in): flag to denote if computing the vegetation flux
+                            canopyDepth,             	 & ! intent(in): canopy depth (m)
+                            ! input data structures
+                            mpar_data,               	 & ! intent(in): model parameters
+                            indx_data,               	 & ! intent(in): model layer indices
+                            diag_data,               	 & ! intent(in): model diagnostic variables for a local HRU
+                            ! input: state variables
+                            scalarCanopyIceTrial,      & ! intent(in): trial value for canopy ice content (kg m-2)
+                            scalarCanopyLiqTrial,      & ! intent(in): trial value for the liquid water on the vegetation canopy (kg m-2)
+                            scalarCanopyTempTrial,   	 & ! intent(in): trial value of canopy temperature (K)
+                            scalarCanopyTempPrev,    	 & ! intent(in): previous value of canopy temperature (K)
+                            scalarCanopyEnthalpyTrial, & ! intent(in): trial enthalpy of the vegetation canopy (J m-3)
+                            scalarCanopyEnthalpyPrev,  & ! intent(in): previous enthalpy of the vegetation canopy (J m-3)
+                            mLayerVolFracIceTrial,     & ! intent(in): volumetric fraction of ice at the start of the sub-step (-)
+                            mLayerVolFracLiqTrial,     & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
+                            mLayerTempTrial,           & ! intent(in): trial temperature
+                            mLayerTempPrev,            & ! intent(in): previous temperature
+                            mLayerEnthalpyTrial,       & ! intent(in): trial enthalpy for snow and soil
+                            mLayerEnthalpyPrev,        & ! intent(in): previous enthalpy for snow and soil
+                            ! output
+                            heatCapVegTrial,           & ! intent(out): volumetric heat capacity of vegetation canopy
+                            mLayerHeatCapTrial,        & ! intent(out): heat capacity for snow and soil
+                            ! output: error control
+                            err,cmessage)                    ! intent(out): error control
+          if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+        ! to conserve energy compute finite difference approximation of (theta_ice)'
+        if(dt_cur > 1e-14_rkind) then
+          scalarCanopyIcePrime = ( scalarCanopyIceTrial - scalarCanopyIcePrev ) / dt_cur
+          do concurrent (iLayer=1:nLayers)
+                mLayerVolFracIcePrime(iLayer) = ( mLayerVolFracIceTrial(iLayer) - mLayerVolFracIcePrev(iLayer) ) / dt_cur
+          end do
+        endif ! if dt_cur is not too samll
+      else ! if using closed formula of heat capacity
+        call computHeatCapAnalytic(&
                           ! input: control variables
-                          nLayers,                 	 & ! intent(in): number of layers (soil+snow)
-                          computeVegFlux,         	 & ! intent(in): flag to denote if computing the vegetation flux
-                          canopyDepth,             	 & ! intent(in): canopy depth (m)
-                          ! input data structures
-                          mpar_data,               	 & ! intent(in): model parameters
-                          indx_data,               	 & ! intent(in): model layer indices
-                          diag_data,               	 & ! intent(in): model diagnostic variables for a local HRU
+                          computeVegFlux,          		& ! intent(in):   flag to denote if computing the vegetation flux
+                          canopyDepth,             		& ! intent(in):   canopy depth (m)
                           ! input: state variables
-                          scalarCanopyIceTrial,      & ! intent(in): trial value for canopy ice content (kg m-2)
-                          scalarCanopyLiqTrial,      & ! intent(in): trial value for the liquid water on the vegetation canopy (kg m-2)
-                          scalarCanopyTempTrial,   	 & ! intent(in): trial value of canopy temperature (K)
-                          scalarCanopyTempPrev,    	 & ! intent(in): previous value of canopy temperature (K)
-                          scalarCanopyEnthalpyTrial, & ! intent(in): trial enthalpy of the vegetation canopy (J m-3)
-                          scalarCanopyEnthalpyPrev,  & ! intent(in): previous enthalpy of the vegetation canopy (J m-3)
-                          mLayerVolFracIceTrial,     & ! intent(in): volumetric fraction of ice at the start of the sub-step (-)
-                          mLayerVolFracLiqTrial,     & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
-                          mLayerTempTrial,           & ! intent(in): trial temperature
-                          mLayerTempPrev,            & ! intent(in): previous temperature
-                          mLayerEnthalpyTrial,       & ! intent(in): trial enthalpy for snow and soil
-                          mLayerEnthalpyPrev,        & ! intent(in): previous enthalpy for snow and soil
+                          scalarCanopyIceTrial,        & ! intent(in)
+                          scalarCanopyLiqTrial,      	& ! intent(in)
+                          mLayerVolFracIceTrial,      	& ! intent(in):   volumetric fraction of ice at the start of the sub-step (-)
+                          mLayerVolFracLiqTrial,      	& ! intent(in):   fraction of liquid water at the start of the sub-step (-)
+                          ! input data structures
+                          mpar_data,               		& ! intent(in):   model parameters
+                          indx_data,               		& ! intent(in):   model layer indices
                           ! output
-                          heatCapVegTrial,           & ! intent(out): volumetric heat capacity of vegetation canopy
-                          mLayerHeatCapTrial,        & ! intent(out): heat capacity for snow and soil
+                          heatCapVegTrial,             & ! intent(out):  volumetric heat capacity of vegetation canopy
+                          mLayerHeatCapTrial,          & ! intent(out):  volumetric heat capacity of soil and snow
                           ! output: error control
-                          err,cmessage)                    ! intent(out): error control
-        if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-      ! to conserve energy compute finite difference approximation of (theta_ice)'
-      if(dt_cur > 1e-14_rkind) then
-        scalarCanopyIcePrime = ( scalarCanopyIceTrial - scalarCanopyIcePrev ) / dt_cur
-        do concurrent (iLayer=1:nLayers)
-              mLayerVolFracIcePrime(iLayer) = ( mLayerVolFracIceTrial(iLayer) - mLayerVolFracIcePrev(iLayer) ) / dt_cur
-        end do
-      endif ! if dt_cur is not too samll
-    else ! if using closed formula of heat capacity
-       call computHeatCapAnalytic(&
-                         ! input: control variables
-                         computeVegFlux,          		& ! intent(in):   flag to denote if computing the vegetation flux
-                         canopyDepth,             		& ! intent(in):   canopy depth (m)
-                         ! input: state variables
-                         scalarCanopyIceTrial,        & ! intent(in)
-                         scalarCanopyLiqTrial,      	& ! intent(in)
-                         mLayerVolFracIceTrial,      	& ! intent(in):   volumetric fraction of ice at the start of the sub-step (-)
-                         mLayerVolFracLiqTrial,      	& ! intent(in):   fraction of liquid water at the start of the sub-step (-)
-                         ! input data structures
-                         mpar_data,               		& ! intent(in):   model parameters
-                         indx_data,               		& ! intent(in):   model layer indices
-                         ! output
-                         heatCapVegTrial,             & ! intent(out):  volumetric heat capacity of vegetation canopy
-                         mLayerHeatCapTrial,          & ! intent(out):  volumetric heat capacity of soil and snow
-                         ! output: error control
-                         err,cmessage)               		! intent(out):  error control
-    endif
-  
-     ! compute multiplier of state vector
-     call computStatMult(&
-                   ! input
-                   heatCapVegTrial,                  & ! intent(in):    volumetric heat capacity of vegetation canopy
-                   mLayerHeatCapTrial,               & ! intent(in):    volumetric heat capacity of soil and snow
-                   diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
-                   indx_data,                        & ! intent(in):    indices defining model states and layers
-                   ! output
-                   sMul,                             & ! intent(out):   multiplier for state vector (used in the residual calculations)
-                   err,cmessage)                       ! intent(out):   error control
-     if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-  
-     ! update thermal conductivity
-     call computThermConduct(&
-                         ! input: control variables
-                         computeVegFlux,               & ! intent(in): flag to denote if computing the vegetation flux
-                         canopyDepth,                  & ! intent(in): canopy depth (m)
-                         ! input: state variables
-                         scalarCanopyIceTrial,         & ! intent(in)
-                         scalarCanopyLiqTrial,         & ! intent(in)
-                         mLayerVolFracIceTrial,        & ! intent(in): volumetric fraction of ice at the start of the sub-step (-)
-                         mLayerVolFracLiqTrial,        & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
-                          ! input/output: data structures
-                         mpar_data,                    & ! intent(in):    model parameters
-                         indx_data,                    & ! intent(in):    model layer indices
-                         prog_data,                    & ! intent(in):    model prognostic variables for a local HRU
-                         diag_data,                    & ! intent(inout): model diagnostic variables for a local HRU
-                         err,cmessage)               ! intent(out): error control
-     if(err/=0)then; err=55; message=trim(message)//trim(cmessage); return; end if
-  
-   end if ! updateCp
-  
-  
-   if(needCm)then
-     ! compute C_m
-     call computCm(&
-                    ! input: control variables
-                    computeVegFlux,          	& ! intent(in): flag to denote if computing the vegetation flux
-                    ! input: state variables
-                    scalarCanopyTempTrial,    & ! intent(in)
-                    mLayerTempTrial,       	  & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
-                    mLayerMatricHeadTrial,    & ! intent(in)
-                    ! input data structures
-                    mpar_data,               	& ! intent(in):    model parameters
-                    indx_data,               	& ! intent(in):    model layer indices
+                          err,cmessage)               		! intent(out):  error control
+      endif
+
+      ! compute multiplier of state vector
+      call computStatMult(&
+                    ! input
+                    heatCapVegTrial,                  & ! intent(in):    volumetric heat capacity of vegetation canopy
+                    mLayerHeatCapTrial,               & ! intent(in):    volumetric heat capacity of soil and snow
+                    diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
+                    indx_data,                        & ! intent(in):    indices defining model states and layers
                     ! output
-                    scalarCanopyCmTrial,      & ! intent(out):   Cm for vegetation
-                    mLayerCmTrial,            & ! intent(out):   Cm for soil and snow
-                    err,cmessage)                ! intent(out): error control
-   else
-     scalarCanopyCmTrial = 0._qp
-     mLayerCmTrial = 0._qp
-   end if ! needCm
-  
-  
-   ! save the number of flux calls per time step
-   indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) = indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) + 1
-   ! compute the fluxes for a given state vector
-   call computFlux(&
-                   ! input-output: model control
-                   nSnow,                     & ! intent(in):    number of snow layers
-                   nSoil,                     & ! intent(in):    number of soil layers
-                   nLayers,                   & ! intent(in):    total number of layers
-                   firstSubStep,              & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   firstFluxCall,             & ! intent(inout): flag to denote the first flux call
-                   firstSplitOper,            & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
-                   computeVegFlux,            & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   scalarSolution,            & ! intent(in):    flag to indicate the scalar solution
-                   insideIDA,                 & ! intent(in):    logical flag if inside Sundials solver
-                   scalarSfcMeltPond/dt,      & ! intent(in):    drainage from the surface melt pond (kg m-2 s-1)
-                   ! input: state variables
-                   scalarCanairTempTrial,     & ! intent(in):    trial value for the temperature of the canopy air space (K)
-                   scalarCanopyTempTrial,     & ! intent(in):    trial value for the temperature of the vegetation canopy (K)
-                   mLayerTempTrial,           & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
-                   mLayerMatricHeadLiqTrial,  & ! intent(in):    trial value for the liquid water matric potential in each soil layer (m)
-                   mLayerMatricHeadTrial,     & ! intent(in):    trial vector of total water matric potential (m)
-                   scalarAquiferStorageTrial, & ! intent(in):    trial value of storage of water in the aquifer (m)
-                   ! input: diagnostic variables defining the liquid water and ice content
-                   scalarCanopyLiqTrial,      & ! intent(in):    trial value for the liquid water on the vegetation canopy (kg m-2)
-                   scalarCanopyIceTrial,      & ! intent(in):    trial value for the ice on the vegetation canopy (kg m-2)
-                   mLayerVolFracLiqTrial,     & ! intent(in):    trial value for the volumetric liquid water content in each snow and soil layer (-)
-                   mLayerVolFracIceTrial,     & ! intent(in):    trial value for the volumetric ice in each snow and soil layer (-)
-                   ! input: data structures
-                   model_decisions,           & ! intent(in):    model decisions
-                   type_data,                 & ! intent(in):    type of vegetation and soil
-                   attr_data,                 & ! intent(in):    spatial attributes
-                   mpar_data,                 & ! intent(in):    model parameters
-                   forc_data,                 & ! intent(in):    model forcing data
-                   bvar_data,                 & ! intent(in):    average model variables for the entire basin
-                   prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                 & ! intent(in):    index data
-                   ! input-output: data structures
-                   diag_data,                 & ! intent(inout): model diagnostic variables for a local HRU
-                   flux_data,                 & ! intent(inout): model fluxes for a local HRU
-                   deriv_data,                & ! intent(out):   derivatives in model fluxes w.r.t. relevant state variables
-                   ! input-output: flux vector and baseflow derivatives
-                   ixSaturation,              & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                   dBaseflow_dMatric,         & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1), we will use it later in computeJacobSundials
-                   fluxVec,                   & ! intent(out):   flux vector (mixed units)
-                   ! output: error control
-                   err,cmessage)                ! intent(out):   error code and error message
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   firstSplitOper = .true.
-  
-  
-   ! compute soil compressibility (-) and its derivative w.r.t. matric head (m)
-   ! NOTE: we already extracted trial matrix head and volumetric liquid water as part of the flux calculations
-   call soilCmpresSundials(&
-                   ! input:
-                   ixRichards,                             & ! intent(in): choice of option for Richards' equation
-                   ixBeg,ixEnd,                            & ! intent(in): start and end indices defining desired layers
-                   mLayerMatricHeadPrime(1:nSoil),      & ! intent(in): matric head at the start of the time step (m)
-                   mLayerVolFracLiqTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric liquid water content in each soil layer (-)
-                   mLayerVolFracIceTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric ice content in each soil layer (-)
-                   specificStorage,                        & ! intent(in): specific storage coefficient (m-1)
-                   theta_sat,                              & ! intent(in): soil porosity (-)
-                   ! output:
-                   mLayerCompress,                         & ! intent(inout): compressibility of the soil matrix (-)
-                   dCompress_dPsi,                         & ! intent(inout): derivative in compressibility w.r.t. matric head (m-1)
-                   err,cmessage)                             ! intent(out): error code and error message
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-  ! print *, 'dt = ', dt
-  ! print *, 'dt_cur = ', dt_cur
-  
-   ! compute the residual vector
-   call computResidSundials(&
-                    ! input: model control
+                    sMul,                             & ! intent(out):   multiplier for state vector (used in the residual calculations)
+                    err,cmessage)                       ! intent(out):   error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+
+      ! update thermal conductivity
+      call computThermConduct(&
+                          ! input: control variables
+                          computeVegFlux,               & ! intent(in): flag to denote if computing the vegetation flux
+                          canopyDepth,                  & ! intent(in): canopy depth (m)
+                          ! input: state variables
+                          scalarCanopyIceTrial,         & ! intent(in)
+                          scalarCanopyLiqTrial,         & ! intent(in)
+                          mLayerVolFracIceTrial,        & ! intent(in): volumetric fraction of ice at the start of the sub-step (-)
+                          mLayerVolFracLiqTrial,        & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
+                            ! input/output: data structures
+                          mpar_data,                    & ! intent(in):    model parameters
+                          indx_data,                    & ! intent(in):    model layer indices
+                          prog_data,                    & ! intent(in):    model prognostic variables for a local HRU
+                          diag_data,                    & ! intent(inout): model diagnostic variables for a local HRU
+                          err,cmessage)               ! intent(out): error control
+      if(err/=0)then; err=55; message=trim(message)//trim(cmessage); return; end if
+
+    end if ! updateCp
+
+
+    if(needCm)then
+      ! compute C_m
+      call computCm(&
+                      ! input: control variables
+                      computeVegFlux,          	& ! intent(in): flag to denote if computing the vegetation flux
+                      ! input: state variables
+                      scalarCanopyTempTrial,    & ! intent(in)
+                      mLayerTempTrial,       	  & ! intent(in): volumetric fraction of liquid water at the start of the sub-step (-)
+                      mLayerMatricHeadTrial,    & ! intent(in)
+                      ! input data structures
+                      mpar_data,               	& ! intent(in):    model parameters
+                      indx_data,               	& ! intent(in):    model layer indices
+                      ! output
+                      scalarCanopyCmTrial,      & ! intent(out):   Cm for vegetation
+                      mLayerCmTrial,            & ! intent(out):   Cm for soil and snow
+                      err,cmessage)                ! intent(out): error control
+    else
+      scalarCanopyCmTrial = 0._qp
+      mLayerCmTrial = 0._qp
+    end if ! needCm
+
+
+    ! save the number of flux calls per time step
+    indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) = indx_data%var(iLookINDEX%numberFluxCalc)%dat(1) + 1
+    ! compute the fluxes for a given state vector
+    call computFlux(&
+                    ! input-output: model control
                     nSnow,                     & ! intent(in):    number of snow layers
                     nSoil,                     & ! intent(in):    number of soil layers
                     nLayers,                   & ! intent(in):    total number of layers
-                    ! input: flux vectors
-                    sMul,                      & ! intent(in):    state vector multiplier (used in the residual calculations)
-                    fluxVec,                   & ! intent(in):    flux vector
-                    ! input: state variables (already disaggregated into scalars and vectors)
-                    scalarCanopyTempTrial,     & ! intent(in):
-                    mLayerTempTrial,           & ! intent(in)
-                    scalarCanairTempPrime,     & ! intent(in):    Prime value for the temperature of the canopy air space (K)
-                    scalarCanopyTempPrime,     & ! intent(in):    Prime value for the temperature of the vegetation canopy (K)
-                    scalarCanopyWatPrime,      &
-                    mLayerTempPrime,           & ! intent(in):    Prime value for the temperature of each snow and soil layer (K)
-                    scalarAquiferStoragePrime, & ! intent(in):    Prime value of storage of water in the aquifer (m)
-                    ! input: diagnostic variables defining the liquid water and ice content (function of state variables)
-                    scalarCanopyIcePrime,      & ! intent(in):    Prime value for the ice on the vegetation canopy (kg m-2)
-                    scalarCanopyLiqPrime,      & ! intent(in):
-                    mLayerVolFracIcePrime,     & ! intent(in):    Prime value for the volumetric ice in each snow and soil layer (-)
-                    mLayerVolFracWatPrime,     &
-                    mLayerVolFracLiqPrime,     &
-                    scalarCanopyCmTrial,       & ! intent(in) Cm of vegetation canopy
-                    mLayerCmTrial,             & ! intent(in) Cm of soil and snow
+                    firstSubStep,              & ! intent(in):    flag to indicate if we are processing the first sub-step
+                    firstFluxCall,             & ! intent(inout): flag to denote the first flux call
+                    firstSplitOper,            & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                    computeVegFlux,            & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                    scalarSolution,            & ! intent(in):    flag to indicate the scalar solution
+                    insideIDA,                 & ! intent(in): logical flag if inside Sundials solver
+                    scalarSfcMeltPond/dt,      & ! intent(in):    drainage from the surface melt pond (kg m-2 s-1)
+                    ! input: state variables
+                    scalarCanairTempTrial,     & ! intent(in):    trial value for the temperature of the canopy air space (K)
+                    scalarCanopyTempTrial,     & ! intent(in):    trial value for the temperature of the vegetation canopy (K)
+                    mLayerTempTrial,           & ! intent(in):    trial value for the temperature of each snow and soil layer (K)
+                    mLayerMatricHeadLiqTrial,  & ! intent(in):    trial value for the liquid water matric potential in each soil layer (m)
+                    mLayerMatricHeadTrial,     & ! intent(in):    trial vector of total water matric potential (m)
+                    scalarAquiferStorageTrial, & ! intent(in):    trial value of storage of water in the aquifer (m)
+                    ! input: diagnostic variables defining the liquid water and ice content
+                    scalarCanopyLiqTrial,      & ! intent(in):    trial value for the liquid water on the vegetation canopy (kg m-2)
+                    scalarCanopyIceTrial,      & ! intent(in):    trial value for the ice on the vegetation canopy (kg m-2)
+                    mLayerVolFracLiqTrial,     & ! intent(in):    trial value for the volumetric liquid water content in each snow and soil layer (-)
+                    mLayerVolFracIceTrial,     & ! intent(in):    trial value for the volumetric ice in each snow and soil layer (-)
                     ! input: data structures
+                    model_decisions,           & ! intent(in):    model decisions
+                    type_data,                 & ! intent(in):    type of vegetation and soil
+                    attr_data,                 & ! intent(in):    spatial attributes
+                    mpar_data,                 & ! intent(in):    model parameters
+                    forc_data,                 & ! intent(in):    model forcing data
+                    bvar_data,                 & ! intent(in):    average model variables for the entire basin
                     prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
-                    diag_data,                 & ! intent(in):    model diagnostic variables for a local HRU
-                    flux_data,                 & ! intent(in):    model fluxes for a local HRU
                     indx_data,                 & ! intent(in):    index data
-                    ! output
-                    resSink,                   & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                    resVec,                    & ! intent(out):   residual vector
-                    err,cmessage)                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   !print *, '====================================================================================='
-  
-   ! end association with the information in the data structures
-   end associate
-  
-   end subroutine eval8summaSundials
-  
-  
-    ! **********************************************************************************************************
-    ! public function eval8summa4IDA: compute the residual vector F(t,y,y') required for IDA solver
-    ! **********************************************************************************************************
-    ! Return values:
-    !    0 = success,
-    !    1 = recoverable error,
-    !   -1 = non-recoverable error
-    ! ----------------------------------------------------------------
-    integer(c_int) function eval8summa4IDA(tres, sunvec_y, sunvec_yp, sunvec_r, user_data) &
-         result(ierr) bind(C,name='eval8summa4IDA')
-  
-      !======= Inclusions ===========
-      use, intrinsic :: iso_c_binding
-      use fida_mod
-      use fsundials_nvector_mod
-      use fnvector_serial_mod
-      use nrtype
-      use type4IDA
-  
-      !======= Declarations =========
-      implicit none
-  
-      ! calling variables
-      real(rkind), value          :: tres      ! current time                 t
-      type(N_Vector)              :: sunvec_y  ! solution N_Vector    y
-      type(N_Vector)              :: sunvec_yp ! derivative N_Vector  y'
-      type(N_Vector)              :: sunvec_r  ! residual N_Vector    F(t,y,y')
-      type(c_ptr), value          :: user_data ! user-defined data
-  
-  
-      ! pointers to data in SUNDIALS vectors
-      type(eqnsData), pointer     :: eqns_data ! equations data
-      real(rkind), pointer        :: stateVec(:)
-      real(rkind), pointer        :: stateVecPrime(:)
-      real(rkind), pointer        :: rVec(:)
-      logical(lgt)                :: feasible
-      integer(i4b)                :: retval
-      real(c_double)              :: stepsize_next(1)
-      !======= Internals ============
-  
-      ! get equations data from user-defined data
-      call c_f_pointer(user_data, eqns_data)
-  
-      ! get data arrays from SUNDIALS vectors
-      stateVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_y)
-      stateVecPrime(1:eqns_data%nState) => FN_VGetArrayPointer(sunvec_yp)
-      rVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_r)
-  
-      retval = FIDAGetCurrentStep(eqns_data%ida_mem, stepsize_next)
-      if (retval /= 0) then
-        print *, 'Error in FIDAGetCurrentStep, retval = ', retval, '; halting'
-        stop 1
-      end if
-  
-      ! compute the flux and the residual vector for a given state vector
-      call eval8summaSundials(&
-                   ! input: model control
-                   stepsize_next(1),                  & ! intent(in):    current stepsize
-                   eqns_data%dt,                      & ! intent(in):    data step
-                   eqns_data%nSnow,                   & ! intent(in):    number of snow layers
-                   eqns_data%nSoil,                   & ! intent(in):    number of soil layers
-                   eqns_data%nLayers,                 & ! intent(in):    number of layers
-                   eqns_data%nState,                  & ! intent(in):    number of state variables in the current subset
-                   .true.,                            & ! intent(in):    inside Sundials solver
-                   eqns_data%firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   eqns_data%firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
-                   eqns_data%firstSplitOper,		    & ! intent(inout): flag to indicate if we are processing the first flux call in a splitting operation
-                   eqns_data%computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   eqns_data%scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                   ! input: state vectors
-                   stateVec,                          & ! intent(in):    model state vector
-                   stateVecPrime,                     & ! intent(in):    model state vector
-                   eqns_data%sMul,                    & ! intent(inout): state vector multiplier (used in the residual calculations)
-                   ! input: data structures
-                   model_decisions,                   & ! intent(in):    model decisions
-                   eqns_data%lookup_data,             & ! intent(in):    lookup data
-                   eqns_data%type_data,               & ! intent(in):    type of vegetation and soil
-                   eqns_data%attr_data,               & ! intent(in):    spatial attributes
-                   eqns_data%mpar_data,               & ! intent(in):    model parameters
-                   eqns_data%forc_data,               & ! intent(in):    model forcing data
-                   eqns_data%bvar_data,               & ! intent(in):    average model variables for the entire basin
-                   eqns_data%prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                   ! input-output: data structures
-                   eqns_data%indx_data,                & ! intent(inou):  index data
-                   eqns_data%diag_data,                & ! intent(inout): model diagnostic variables for a local HRU
-                   eqns_data%flux_data,                & ! intent(inout): model fluxes for a local HRU (initial flux structure)
-                   eqns_data%deriv_data,               & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! input-output: here we need to pass some extra variables that do not get updated in in the Sundials loops
-                   eqns_data%scalarCanopyTempTrial,    & ! intent(inout): trial value of canopy temperature (K)
-                   eqns_data%scalarCanopyIceTrial,	 & ! intent(inout): trial value for mass of ice on the vegetation canopy (kg m-2)
-                   eqns_data%scalarCanopyEnthalpyTrial,& ! intent(inout): trial value for enthalpy of the vegetation canopy (J m-3)
-                   eqns_data%mLayerTempTrial,          & ! intent(inout): trial vector of layer temperature (K)
-                   eqns_data%mLayerMatricHeadTrial,    & ! intent(inout): trial value for total water matric potential (m)
-                   eqns_data%mLayerMatricHeadLiqTrial, & ! intent(inout):   trial value for liquid water matric potential (m)
-                   eqns_data%mLayerVolFracWatTrial,    & ! intent(inout): trial vector of volumetric total water content (-)
-                   eqns_data%mLayerVolFracIceTrial,    & ! intent(inout): trial vector of volumetric ice water content (-)
-                   eqns_data%mLayerEnthalpyTrial,      & ! intent(inout): trial vector of enthalpy for snow+soil layers (J m-3)
-                   ! input-output: baseflow
-                   eqns_data%ixSaturation,             & ! intent(inout): index of the lowest saturated layer
-                   eqns_data%dBaseflow_dMatric,        & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
-                   ! output: flux and residual vectors
-                   feasible,                           & ! intent(out):   flag to denote the feasibility of the solution
-                   eqns_data%fluxVec,                  & ! intent(out):   flux vector
-                   eqns_data%resSink,                  & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                   rVec,                               & ! intent(out):   residual vector
-                   eqns_data%err,eqns_data%message)      ! intent(out):   error control
-  
-      if(eqns_data%err > 0)then; eqns_data%message=trim(eqns_data%message); ierr=-1; return; endif
-      if(eqns_data%err < 0)then; eqns_data%message=trim(eqns_data%message); ierr=1; return; endif
-      if(.not.feasible)then; eqns_data%message=trim(eqns_data%message)//'state vector not feasible'; ierr = 1; return; endif
-  
-      ! return success
-      ierr = 0
-      return
-  
-   end function eval8summa4IDA
-  
-  end module eval8summaSundials_module
-  
\ No newline at end of file
+                    ! input-output: data structures
+                    diag_data,                 & ! intent(inout): model diagnostic variables for a local HRU
+                    flux_data,                 & ! intent(inout): model fluxes for a local HRU
+                    deriv_data,                & ! intent(out):   derivatives in model fluxes w.r.t. relevant state variables
+                    ! input-output: flux vector and baseflow derivatives
+                    ixSaturation,              & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                    dBaseflow_dMatric,         & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1), we will use it later in computeJacobSundials
+                    fluxVec,                   & ! intent(out):   flux vector (mixed units)
+                    ! output: error control
+                    err,cmessage)                ! intent(out):   error code and error message
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+    firstSplitOper = .true.
+
+
+    ! compute soil compressibility (-) and its derivative w.r.t. matric head (m)
+    ! NOTE: we already extracted trial matrix head and volumetric liquid water as part of the flux calculations
+    call soilCmpresSundials(&
+                    ! input:
+                    ixRichards,                             & ! intent(in): choice of option for Richards' equation
+                    ixBeg,ixEnd,                            & ! intent(in): start and end indices defining desired layers
+                    mLayerMatricHeadPrime(1:nSoil),      & ! intent(in): matric head at the start of the time step (m)
+                    mLayerVolFracLiqTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric liquid water content in each soil layer (-)
+                    mLayerVolFracIceTrial(nSnow+1:nLayers), & ! intent(in): trial value for the volumetric ice content in each soil layer (-)
+                    specificStorage,                        & ! intent(in): specific storage coefficient (m-1)
+                    theta_sat,                              & ! intent(in): soil porosity (-)
+                    ! output:
+                    mLayerCompress,                         & ! intent(inout): compressibility of the soil matrix (-)
+                    dCompress_dPsi,                         & ! intent(inout): derivative in compressibility w.r.t. matric head (m-1)
+                    err,cmessage)                             ! intent(out): error code and error message
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+
+    ! compute the residual vector
+    call computResidSundials(&
+                      ! input: model control
+                      nSnow,                     & ! intent(in):    number of snow layers
+                      nSoil,                     & ! intent(in):    number of soil layers
+                      nLayers,                   & ! intent(in):    total number of layers
+                      ! input: flux vectors
+                      sMul,                      & ! intent(in):    state vector multiplier (used in the residual calculations)
+                      fluxVec,                   & ! intent(in):    flux vector
+                      ! input: state variables (already disaggregated into scalars and vectors)
+                      scalarCanopyTempTrial,     & ! intent(in):
+                      mLayerTempTrial,           & ! intent(in)
+                      scalarCanairTempPrime,     & ! intent(in):    Prime value for the temperature of the canopy air space (K)
+                      scalarCanopyTempPrime,     & ! intent(in):    Prime value for the temperature of the vegetation canopy (K)
+                      scalarCanopyWatPrime,      &
+                      mLayerTempPrime,           & ! intent(in):    Prime value for the temperature of each snow and soil layer (K)
+                      scalarAquiferStoragePrime, & ! intent(in):    Prime value of storage of water in the aquifer (m)
+                      ! input: diagnostic variables defining the liquid water and ice content (function of state variables)
+                      scalarCanopyIcePrime,      & ! intent(in):    Prime value for the ice on the vegetation canopy (kg m-2)
+                      scalarCanopyLiqPrime,      & ! intent(in):
+                      mLayerVolFracIcePrime,     & ! intent(in):    Prime value for the volumetric ice in each snow and soil layer (-)
+                      mLayerVolFracWatPrime,     &
+                      mLayerVolFracLiqPrime,     &
+                      scalarCanopyCmTrial,       & ! intent(in) Cm of vegetation canopy
+                      mLayerCmTrial,             & ! intent(in) Cm of soil and snow
+                      ! input: data structures
+                      prog_data,                 & ! intent(in):    model prognostic variables for a local HRU
+                      diag_data,                 & ! intent(in):    model diagnostic variables for a local HRU
+                      flux_data,                 & ! intent(in):    model fluxes for a local HRU
+                      indx_data,                 & ! intent(in):    index data
+                      ! output
+                      resSink,                   & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                      resVec,                    & ! intent(out):   residual vector
+                      err,cmessage)                ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+
+
+  ! end association with the information in the data structures
+  end associate
+
+end subroutine eval8summaSundials
+end module eval8summaSundials_module
diff --git a/build/source/engine/sundials/evalDAE4IDA.f90 b/build/source/engine/sundials/evalDAE4IDA.f90
new file mode 100644
index 0000000..0199be1
--- /dev/null
+++ b/build/source/engine/sundials/evalDAE4IDA.f90
@@ -0,0 +1,165 @@
+module evalDAE4IDA_module
+
+
+!======= Inclusions ===========
+use, intrinsic :: iso_c_binding
+use nrtype
+use type4IDA
+USE globalData,only:model_decisions        ! model decision structure
+USE globalData,only:flux_meta                        ! metadata on the model fluxes
+! 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_ilength,  & ! data vector with variable length dimension (i4b)
+                  var_dlength,  & ! data vector with variable length dimension (rkind)
+                  model_options   ! defines the model decisions
+USE multiconst,only:iden_water      ! intrinsic density of liquid water    (kg m-3)
+USE var_lookup,only:iLookDIAG
+USE var_lookup,only:iLookPROG
+USE var_lookup,only:iLookINDEX      ! named variables for structure elements
+USE var_lookup,only:iLookDERIV                   ! named variables for structure elements
+
+
+! privacy
+implicit none
+private
+public::evalDAE4IDA
+
+
+contains
+
+! **********************************************************************************************************
+! public function evalDAE4IDA: compute the residual vector F(t,y,y') required for IDA solver
+! **********************************************************************************************************
+! Return values:
+!    0 = success,
+!    1 = recoverable error,
+!   -1 = non-recoverable error
+! ----------------------------------------------------------------
+integer(c_int) function evalDAE4IDA(tres, sunvec_y, sunvec_yp, sunvec_r, user_data) &
+      result(ierr) bind(C,name='evalDAE4IDA')
+
+  !======= Inclusions ===========
+  use, intrinsic :: iso_c_binding
+  use fida_mod
+  use fsundials_nvector_mod
+  use fnvector_serial_mod
+  use nrtype
+  use type4IDA
+  use eval8summaSundials_module,only:eval8summaSundials
+
+  !======= Declarations =========
+  implicit none
+
+  ! calling variables
+  real(rkind), value          :: tres      ! current time                 t
+  type(N_Vector)              :: sunvec_y  ! solution N_Vector    y
+  type(N_Vector)              :: sunvec_yp ! derivative N_Vector  y'
+  type(N_Vector)              :: sunvec_r  ! residual N_Vector    F(t,y,y')
+  type(c_ptr), value          :: user_data ! user-defined data
+
+
+  ! pointers to data in SUNDIALS vectors
+  type(eqnsData), pointer     :: eqns_data ! equations data
+  real(rkind), pointer        :: stateVec(:)
+  real(rkind), pointer        :: stateVecPrime(:)
+  real(rkind), pointer        :: rVec(:)
+  logical(lgt)                :: feasible
+  integer(i4b)                :: retval
+  real(c_double)              :: stepsize_next(1)
+  !======= Internals ============
+
+  ! get equations data from user-defined data
+  call c_f_pointer(user_data, eqns_data)
+
+  ! get data arrays from SUNDIALS vectors
+  stateVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_y)
+  stateVecPrime(1:eqns_data%nState) => FN_VGetArrayPointer(sunvec_yp)
+  rVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_r)
+
+  retval = FIDAGetCurrentStep(eqns_data%ida_mem, stepsize_next)
+  if (retval /= 0) then
+    print *, 'Error in FIDAGetCurrentStep, retval = ', retval, '; halting'
+    stop 1
+  end if
+
+  ! compute the flux and the residual vector for a given state vector
+  call eval8summaSundials(&
+                ! input: model control
+                stepsize_next(1),                  & ! intent(in):    current stepsize
+                eqns_data%dt,                      & ! intent(in):    data step
+                eqns_data%nSnow,                   & ! intent(in):    number of snow layers
+                eqns_data%nSoil,                   & ! intent(in):    number of soil layers
+                eqns_data%nLayers,                 & ! intent(in):    number of layers
+                eqns_data%nState,                  & ! intent(in):    number of state variables in the current subset
+                .true.,                            & ! intent(in):    inside Sundials solver
+                eqns_data%firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                eqns_data%firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
+                eqns_data%firstSplitOper,		      & ! intent(inout): flag to indicate if we are processing the first flux call in a splitting operation
+                eqns_data%computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                eqns_data%scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                ! input: state vectors
+                stateVec,                          & ! intent(in):    model state vector
+                stateVecPrime,                     & ! intent(in):    model state vector
+                eqns_data%sMul,                    & ! intent(inout): state vector multiplier (used in the residual calculations)
+                ! input: data structures
+                model_decisions,                   & ! intent(in):    model decisions
+                eqns_data%lookup_data,             & ! intent(in):    lookup data
+                eqns_data%type_data,               & ! intent(in):    type of vegetation and soil
+                eqns_data%attr_data,               & ! intent(in):    spatial attributes
+                eqns_data%mpar_data,               & ! intent(in):    model parameters
+                eqns_data%forc_data,               & ! intent(in):    model forcing data
+                eqns_data%bvar_data,               & ! intent(in):    average model variables for the entire basin
+                eqns_data%prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                ! input-output: data structures
+                eqns_data%indx_data,               & ! intent(inou):  index data
+                eqns_data%diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                eqns_data%flux_data,               & ! intent(inout): model fluxes for a local HRU (initial flux structure)
+                eqns_data%deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                ! input-output: baseflow
+                eqns_data%dBaseflow_dMatric,       & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1), we will use it later for Jacobian
+                eqns_data%scalarCanopyTempTrial,   & ! intent(in):    trial value of canopy temperature (K)
+                eqns_data%scalarCanopyTempPrev,    & ! intent(in):    previous value of canopy temperature (K)
+                eqns_data%scalarCanopyIceTrial,    & ! intent(out):   trial value for mass of ice on the vegetation canopy (kg m-2)
+                eqns_data%scalarCanopyIcePrev,	    & ! intent(in):    value for mass of ice on the vegetation canopy (kg m-2)
+                eqns_data%scalarCanopyLiqTrial,    & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                eqns_data%scalarCanopyLiqPrev,	    & ! intent(in):    value of canopy liquid water (kg m-2)
+                eqns_data%scalarCanopyEnthalpyTrial,& ! intent(out):  trial value for enthalpy of the vegetation canopy (J m-3)
+                eqns_data%scalarCanopyEnthalpyPrev, & ! intent(in):   value for enthalpy of the vegetation canopy (J m-3)
+                eqns_data%mLayerTempTrial,         & ! intent(out):   trial vector of layer temperature (K)
+                eqns_data%mLayerTempPrev,          & ! intent(in):    vector of layer temperature (K)
+                eqns_data%mLayerMatricHeadLiqTrial,& ! intent(out):   trial value for liquid water matric potential (m)
+                eqns_data%mLayerMatricHeadTrial, 	& ! intent(out):   trial value for total water matric potential (m)
+                eqns_data%mLayerMatricHeadPrev, 	& ! intent(in):    value for total water matric potential (m)
+                eqns_data%mLayerVolFracWatTrial,   & ! intent(out):   trial vector of volumetric total water content (-)
+                eqns_data%mLayerVolFracWatPrev,    & ! intent(in):    vector of volumetric total water content (-)
+                eqns_data%mLayerVolFracIceTrial,   & ! intent(out):   trial vector of volumetric ice water content (-)
+                eqns_data%mLayerVolFracIcePrev,   	& ! intent(in):    vector of volumetric ice water content (-)
+                eqns_data%mLayerVolFracLiqTrial,   & ! intent(out):   trial vector of volumetric liquid water content (-)
+                eqns_data%mLayerVolFracLiqPrev,   	& ! intent(in):    vector of volumetric liquid water content (-)
+                eqns_data%scalarAquiferStorageTrial, & ! intent(out): trial value of storage of water in the aquifer (m)
+                eqns_data%scalarAquiferStoragePrev,  &  ! intent(in):  value of storage of water in the aquifer (m)
+                eqns_data%mLayerEnthalpyPrev,      & ! intent(in):    vector of enthalpy for snow+soil layers (J m-3)
+                eqns_data%mLayerEnthalpyTrial,     & ! intent(out):   trial vector of enthalpy for snow+soil layers (J m-3)
+                eqns_data%ixSaturation,			& ! intent(inout): index of the lowest saturated layer
+                ! output
+                feasible,                          & ! intent(out):   flag to denote the feasibility of the solution
+                eqns_data%fluxVec,                 & ! intent(out):   flux vector
+                eqns_data%resSink,                 & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                rVec,                              & ! intent(out):   residual vector
+                eqns_data%err,eqns_data%message)     ! intent(out):   error control
+
+  if(eqns_data%err > 0)then; eqns_data%message=trim(eqns_data%message); ierr=-1; return; endif
+  if(eqns_data%err < 0)then; eqns_data%message=trim(eqns_data%message); ierr=1; return; endif
+  if(.not.feasible)then; eqns_data%message=trim(eqns_data%message)//'state vector not feasible'; ierr = 1; return; endif
+
+  ! return success
+  ierr = 0
+  return
+
+end function evalDAE4IDA
+
+
+end module evalDAE4IDA_module
+    
\ No newline at end of file
diff --git a/build/source/engine/sundials/evalJac4IDA.f90 b/build/source/engine/sundials/evalJac4IDA.f90
new file mode 100644
index 0000000..97a877d
--- /dev/null
+++ b/build/source/engine/sundials/evalJac4IDA.f90
@@ -0,0 +1,132 @@
+module evalJac4IDA_module
+
+
+!======= Inclusions ===========
+use, intrinsic :: iso_c_binding
+use nrtype
+use type4IDA
+USE globalData,only:model_decisions        ! model decision structure
+! 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_ilength,  & ! data vector with variable length dimension (i4b)
+                  var_dlength,  & ! data vector with variable length dimension (rkind)
+                  model_options   ! defines the model decisions
+
+
+
+! privacy
+implicit none
+private
+public::evalJac4IDA
+
+
+contains
+
+! **********************************************************************************************************
+! public function evalJac4IDA: the interface to compute the Jacobian matrix dF/dy + c dF/dy' for IDA solver
+! **********************************************************************************************************
+! Return values:
+!    0 = success,
+!    1 = recoverable error,
+!   -1 = non-recoverable error
+! ----------------------------------------------------------------
+integer(c_int) function evalJac4IDA(t, cj, sunvec_y, sunvec_yp, sunvec_r, &
+                    sunmat_J, user_data, sunvec_temp1, sunvec_temp2, sunvec_temp3) &
+                    result(ierr) bind(C,name='evalJac4IDA')
+
+  !======= Inclusions ===========
+  use, intrinsic :: iso_c_binding
+  use fsundials_nvector_mod
+  use fsundials_matrix_mod
+  use fnvector_serial_mod
+  use fsunmatrix_band_mod
+  use fsunmatrix_dense_mod
+  use nrtype
+  use type4IDA
+  use eval8JacDAE_module,only:eval8JacDAE    ! compute Jacobian matrix
+  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
+  !======= Declarations =========
+  implicit none
+
+  ! calling variables
+  real(rkind), value            :: t              ! current time
+  real(rkind), value            :: cj             ! step size scaling factor
+  type(N_Vector)                :: sunvec_y       ! solution N_Vector
+  type(N_Vector)                :: sunvec_yp      ! derivative N_Vector
+  type(N_Vector)                :: sunvec_r       ! residual N_Vector
+  type(SUNMatrix)               :: sunmat_J       ! Jacobian SUNMatrix
+  type(c_ptr), value            :: user_data      ! user-defined data
+  type(N_Vector)                :: sunvec_temp1   ! temporary N_Vector
+  type(N_Vector)                :: sunvec_temp2   ! temporary N_Vector
+  type(N_Vector)                :: sunvec_temp3   ! temporary N_Vector
+
+  ! pointers to data in SUNDIALS vectors
+  real(rkind), pointer          :: stateVec(:)    ! state vector
+  real(rkind), pointer          :: stateVecPrime(:)! derivative of the state vector
+  real(rkind), pointer          :: rVec(:)        ! residual vector
+  real(rkind), pointer          :: Jac(:,:)       ! Jacobian matrix
+  type(eqnsData), pointer       :: eqns_data      ! equations data
+
+
+
+  !======= Internals ============
+
+  ! get equations data from user-defined data
+  call c_f_pointer(user_data, eqns_data)
+
+
+  ! get data arrays from SUNDIALS vectors
+  stateVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_y)
+  stateVecPrime(1:eqns_data%nState) => FN_VGetArrayPointer(sunvec_yp)
+  rVec(1:eqns_data%nState)  => FN_VGetArrayPointer(sunvec_r)
+  if (eqns_data%ixMatrix==ixBandMatrix) Jac(1:nBands, 1:eqns_data%nState) => FSUNBandMatrix_Data(sunmat_J)
+  if (eqns_data%ixMatrix==ixFullMatrix) Jac(1:eqns_data%nState, 1:eqns_data%nState) => FSUNDenseMatrix_Data(sunmat_J)
+
+  ! compute Jacobian matrix
+  call eval8JacDAE(&
+                ! input: model control
+                cj,                                & ! intent(in):    this scalar changes whenever the step size or method order changes
+                eqns_data%dt,                      & ! intent(in):    data step
+                eqns_data%nSnow,                   & ! intent(in):    number of snow layers
+                eqns_data%nSoil,                   & ! intent(in):    number of soil layers
+                eqns_data%nLayers,                 & ! intent(in):    number of layers
+                eqns_data%ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
+                eqns_data%computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                eqns_data%scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                ! input: state vectors
+                stateVec,                          & ! intent(in):    model state vector
+                stateVecPrime,                     & ! intent(in):    model state vector
+                eqns_data%sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
+                ! input: data structures
+                model_decisions,                   & ! intent(in):    model decisions
+                eqns_data%mpar_data,               & ! intent(in):    model parameters
+                eqns_data%prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                ! input-output: data structures
+                eqns_data%indx_data,               & ! intent(inou):  index data
+                eqns_data%diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                eqns_data%deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                ! input: baseflow
+                eqns_data%dBaseflow_dMatric,       & ! intent(in):    derivative in baseflow w.r.t. matric head (s-1)
+                ! output
+                eqns_data%dMat,                    & ! intetn(inout): diagonal of the Jacobian matrix
+                Jac,                               & ! intent(out):   Jacobian matrix
+                eqns_data%err,eqns_data%message)     ! intent(out):   error control
+
+  if(eqns_data%err > 0)then; eqns_data%message=trim(eqns_data%message); ierr=-1; return; endif
+  if(eqns_data%err < 0)then; eqns_data%message=trim(eqns_data%message); ierr=1; return; endif
+
+  ! return success
+  ierr = 0
+  return
+
+
+
+end function evalJac4IDA
+
+
+end module evalJac4IDA_module
+    
\ No newline at end of file
diff --git a/build/source/engine/sundials/getVectorzAddSundials.f90 b/build/source/engine/sundials/getVectorzAddSundials.f90
index e205e87..16cdb0a 100644
--- a/build/source/engine/sundials/getVectorzAddSundials.f90
+++ b/build/source/engine/sundials/getVectorzAddSundials.f90
@@ -1,256 +1,246 @@
+module getVectorzAddSundials_module
 
+! data types
+USE nrtype
 
-module getVectorzAddSundials_module
+! missing values
+USE globalData,only:integerMissing  ! missing integer
+USE globalData,only:realMissing     ! missing real number
+
+! access the global print flag
+USE globalData,only:globalPrintFlag
+
+! domain types
+USE globalData,only:iname_cas        ! named variables for canopy air space
+USE globalData,only:iname_veg        ! named variables for vegetation canopy
+USE globalData,only:iname_snow       ! named variables for snow
+USE globalData,only:iname_soil       ! named variables for soil
+
+! named variables to describe the state variable type
+USE globalData,only:iname_nrgCanair  ! named variable defining the energy of the canopy air space
+USE globalData,only:iname_nrgCanopy  ! named variable defining the energy of the vegetation canopy
+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
+
+! metadata for information in the data structures
+USE globalData,only:indx_meta       ! metadata for the variables in the index structure
+
+! constants
+USE multiconst,only:&
+                    gravity,      & ! acceleration of gravity              (m s-2)
+                    Tfreeze,      & ! temperature at freezing              (K)
+                    Cp_air,       & ! specific heat of air                 (J kg-1 K-1)
+                    LH_fus,       & ! latent heat of fusion                (J kg-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 the derived types to define the data structures
+USE data_types,only:&
+                    var_i,        & ! data vector (i4b)
+                    var_d,        & ! data vector (rkind)
+                    var_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength     ! data vector with variable length dimension (rkind)
+
+! provide access to indices that define elements of the data structures
+USE var_lookup,only:iLookDIAG             ! named variables for structure elements
+USE var_lookup,only:iLookPROG             ! named variables for structure elements
+USE var_lookup,only:iLookDERIV            ! 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
+
+! provide access to routines to update states
+USE updatState_module,only:updateSnow     ! update snow states
+USE updatState_module,only:updateSoil     ! update soil states
 
-  ! data types
-  USE nrtype
-  
-  ! missing values
-  USE globalData,only:integerMissing  ! missing integer
-  USE globalData,only:realMissing     ! missing real number
-  
-  ! access the global print flag
-  USE globalData,only:globalPrintFlag
-  
-  ! domain types
-  USE globalData,only:iname_cas        ! named variables for canopy air space
-  USE globalData,only:iname_veg        ! named variables for vegetation canopy
-  USE globalData,only:iname_snow       ! named variables for snow
-  USE globalData,only:iname_soil       ! named variables for soil
-  
-  ! named variables to describe the state variable type
-  USE globalData,only:iname_nrgCanair  ! named variable defining the energy of the canopy air space
-  USE globalData,only:iname_nrgCanopy  ! named variable defining the energy of the vegetation canopy
-  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
-  
-  ! metadata for information in the data structures
-  USE globalData,only:indx_meta       ! metadata for the variables in the index structure
-  
-  ! constants
-  USE multiconst,only:&
-                      gravity,      & ! acceleration of gravity              (m s-2)
-                      Tfreeze,      & ! temperature at freezing              (K)
-                      Cp_air,       & ! specific heat of air                 (J kg-1 K-1)
-                      LH_fus,       & ! latent heat of fusion                (J kg-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 the derived types to define the data structures
-  USE data_types,only:&
-                      var_i,        & ! data vector (i4b)
-                      var_d,        & ! data vector (rkind)
-                      var_ilength,  & ! data vector with variable length dimension (i4b)
-                      var_dlength     ! data vector with variable length dimension (rkind)
-  
-  ! provide access to indices that define elements of the data structures
-  USE var_lookup,only:iLookDIAG             ! named variables for structure elements
-  USE var_lookup,only:iLookPROG             ! named variables for structure elements
-  USE var_lookup,only:iLookDERIV            ! 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
-  
-  ! provide access to routines to update states
-  USE updatState_module,only:updateSnow     ! update snow states
-  USE updatState_module,only:updateSoil     ! update soil states
-  
-  ! provide access to functions for the constitutive functions and derivatives
-  USE snow_utils_module,only:fracliquid     ! compute the fraction of liquid water (snow)
-  USE snow_utils_module,only:dFracLiq_dTk   ! differentiate the freezing curve w.r.t. temperature (snow)
-  USE soil_utils_module,only:dTheta_dTk     ! differentiate the freezing curve w.r.t. temperature (soil)
-  USE soil_utils_module,only:dTheta_dPsi    ! derivative in the soil water characteristic (soil)
-  USE soil_utils_module,only:dPsi_dTheta    ! derivative in the soil water characteristic (soil)
-  USE soil_utils_module,only:matricHead     ! compute the matric head based on volumetric water content
-  USE soil_utils_module,only:volFracLiq     ! compute volumetric fraction of liquid water
-  USE soil_utils_module,only:crit_soilT     ! compute critical temperature below which ice exists
-  USE soil_utils_module,only:liquidHead     ! compute the liquid water matric potential
-  
+! provide access to functions for the constitutive functions and derivatives
+USE snow_utils_module,only:fracliquid     ! compute the fraction of liquid water (snow)
+USE snow_utils_module,only:dFracLiq_dTk   ! differentiate the freezing curve w.r.t. temperature (snow)
+USE soil_utils_module,only:dTheta_dTk     ! differentiate the freezing curve w.r.t. temperature (soil)
+USE soil_utils_module,only:dTheta_dPsi    ! derivative in the soil water characteristic (soil)
+USE soil_utils_module,only:dPsi_dTheta    ! derivative in the soil water characteristic (soil)
+USE soil_utils_module,only:matricHead     ! compute the matric head based on volumetric water content
+USE soil_utils_module,only:volFracLiq     ! compute volumetric fraction of liquid water
+USE soil_utils_module,only:crit_soilT     ! compute critical temperature below which ice exists
+USE soil_utils_module,only:liquidHead     ! compute the liquid water matric potential
+
+implicit none
+private
+public::residDiscontinuity
+public::countDiscontinuity
+contains
+
+
+
+! **********************************************************************************************************
+! public subroutine residDiscontinuity:
+! **********************************************************************************************************
+subroutine residDiscontinuity(&
+                      ! input
+                      stateVec,                                  & ! intent(in):    model state vector (mixed units)
+                      diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
+                      prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                      indx_data,                                 & ! intent(in):    indices defining model states and layers
+                      ! output
+                      resid,                                     & ! intent(out)
+                      err,message)                                 ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
   implicit none
-  private
-  public::varExtractSundials
-  
-  
-  contains
-  
-   ! **********************************************************************************************************
-   ! public subroutine varExtractSundials: extract state prime state variables from the state vector and compute diagnostic variables
-   !  This routine does not initialize any of the variables, needs to be done inside calling routine
-   ! **********************************************************************************************************
-   subroutine varExtractSundials(&
-                         ! input
-                         stateVec,                                  & ! intent(in):    model state vector (mixed units)
-                         stateVecPrime,                             & ! intent(in):    model state vector (mixed units)
-                         diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
-                         prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                         indx_data,                                 & ! intent(in):    indices defining model states and layers
-                         ! output: variables for the vegetation canopy
-                         scalarCanairTempTrial,                     & ! intent(inout):   trial value of canopy air temperature (K)
-                         scalarCanopyTempTrial,                     & ! intent(inout):   trial value of canopy temperature (K)
-                         scalarCanopyWatTrial,                      & ! intent(inout):   trial value of canopy total water (kg m-2)
-                         scalarCanopyLiqTrial,                      & ! intent(inout):   trial value of canopy liquid water (kg m-2)
-                         scalarCanairTempPrime,                     & ! intent(inout):   trial value of canopy air temperature (K)
-                         scalarCanopyTempPrime,                     & ! intent(inout):   trial value of canopy temperature (K)
-                         scalarCanopyWatPrime,                      & ! intent(inout):   trial value of canopy total water (kg m-2)
-                         scalarCanopyLiqPrime,                      & ! intent(inout):   trial value of canopy liquid water (kg m-2)
-                         ! output: variables for the snow-soil domain
-                         mLayerTempTrial,                           & ! intent(inout):   trial vector of layer temperature (K)
-                         mLayerVolFracWatTrial,                     & ! intent(inout):   trial vector of volumetric total water content (-)
-                         mLayerVolFracLiqTrial,                     & ! intent(inout):   trial vector of volumetric liquid water content (-)
-                         mLayerMatricHeadTrial,                     & ! intent(inout):   trial vector of total water matric potential (m)
-                         mLayerMatricHeadLiqTrial,                  & ! intent(inout):   trial vector of liquid water matric potential (m)
-                         mLayerTempPrime,                           & ! intent(inout):   trial vector of layer temperature (K)
-                         mLayerVolFracWatPrime,                     & ! intent(inout):   trial vector of volumetric total water content (-)
-                         mLayerVolFracLiqPrime,                     & ! intent(inout):   trial vector of volumetric liquid water content (-)
-                         mLayerMatricHeadPrime,                     & ! intent(inout):   trial vector of total water matric potential (m)
-                         mLayerMatricHeadLiqPrime,                  & ! intent(inout):   trial vector of liquid water matric potential (m)
-                         ! output: variables for the aquifer
-                         scalarAquiferStorageTrial,                 & ! intent(inout):   trial value of storage of water in the aquifer (m)
-                         scalarAquiferStoragePrime,                 & ! intent(inout):   trial value of storage of water in the aquifer (m)
-                         ! output: error control
-                         err,message)                                 ! intent(out):   error control
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   implicit none
-   ! input
-   real(rkind),intent(in)             :: stateVec(:)                ! model state vector (mixed units)
-   real(rkind),intent(in)             :: stateVecPrime(:)           ! model state vector (mixed units)
-   type(var_dlength),intent(in)       :: diag_data                  ! diagnostic variables for a local HRU
-   type(var_dlength),intent(in)       :: prog_data                  ! prognostic variables for a local HRU
-   type(var_ilength),intent(in)       :: indx_data                  ! indices defining model states and layers
-   ! output: variables for the vegetation canopy
-   real(rkind),intent(inout)          :: scalarCanairTempTrial      ! trial value of canopy air temperature (K)
-   real(rkind),intent(inout)          :: scalarCanopyTempTrial      ! trial value of canopy temperature (K)
-   real(rkind),intent(inout)          :: scalarCanopyWatTrial       ! trial value of canopy total water (kg m-2)
-   real(rkind),intent(inout)          :: scalarCanopyLiqTrial       ! trial value of canopy liquid water (kg m-2)
-   real(rkind),intent(inout)          :: scalarCanairTempPrime      ! trial value of canopy air temperature (K)
-   real(rkind),intent(inout)          :: scalarCanopyTempPrime      ! trial value of canopy temperature (K)
-   real(rkind),intent(inout)          :: scalarCanopyWatPrime       ! trial value of canopy total water (kg m-2)
-   real(rkind),intent(inout)          :: scalarCanopyLiqPrime       ! trial value of canopy liquid water (kg m-2)
-   ! output: variables for the snow-soil domain
-   real(rkind),intent(inout)          :: mLayerTempTrial(:)         ! trial vector of layer temperature (K)
-   real(rkind),intent(inout)          :: mLayerVolFracWatTrial(:)   ! trial vector of volumetric total water content (-)
-   real(rkind),intent(inout)          :: mLayerVolFracLiqTrial(:)   ! trial vector of volumetric liquid water content (-)
-   real(rkind),intent(inout)          :: mLayerMatricHeadTrial(:)   ! trial vector of total water matric potential (m)
-   real(rkind),intent(inout)          :: mLayerMatricHeadLiqTrial(:)! trial vector of liquid water matric potential (m)
-   real(rkind),intent(inout)          :: mLayerTempPrime(:)         ! trial vector of layer temperature (K)
-   real(rkind),intent(inout)          :: mLayerVolFracWatPrime(:)   ! trial vector of volumetric total water content (-)
-   real(rkind),intent(inout)          :: mLayerVolFracLiqPrime(:)   ! trial vector of volumetric liquid water content (-)
-   real(rkind),intent(inout)          :: mLayerMatricHeadPrime(:)   ! trial vector of total water matric potential (m)
-   real(rkind),intent(inout)          :: mLayerMatricHeadLiqPrime(:)! trial vector of liquid water matric potential (m)
-   ! output: variables for the aquifer
-   real(rkind),intent(inout)          :: scalarAquiferStorageTrial  ! trial value of storage of water in the aquifer (m)
-   real(rkind),intent(inout)          :: scalarAquiferStoragePrime  ! trial value of storage of water in the aquifer (m)
-   ! output: error control
-   integer(i4b),intent(out)           :: err                        ! error code
-   character(*),intent(out)           :: message                    ! error message
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! local variables
-   integer(i4b)                    :: iLayer                          ! index of layer within the snow+soil domain
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! make association with variables in the data structures
-   associate(&
-   ! number of model layers, and layer type
-   nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1)                 ,& ! intent(in):  [i4b]    total number of snow layers
-   nSoil                   => indx_data%var(iLookINDEX%nSoil)%dat(1)                 ,& ! intent(in):  [i4b]    total number of soil layers
-   nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1)               ,& ! intent(in):  [i4b]    total number of snow and soil layers
-   ! indices defining model states and layers
-   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)
-   ixAqWat                 => indx_data%var(iLookINDEX%ixAqWat)%dat(1)               ,& ! intent(in):  [i4b]    index of the squifer storage state variable
-   ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for energy states in the snow+soil subdomain
-   ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for hydrology states in the snow+soil subdomain
-   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 variables in the snow+soil domain
-   ! indices defining type of model state variables
-   ixStateType_subset      => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in):  [i4b(:)] [state subset] type of desired model state variables
-   ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                & ! intent(in):  [i4b(:)] index of the type of hydrology states in snow+soil domain
-  ) ! association with variables in the data structures
-  
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! --------------------------------------------------------------------------------------------------------------------------------
-  
-   ! initialize error control
-   err=0; message='varExtractSundials/'
-  
-  
-   ! check if computing the vegetation flux
-   if(ixCasNrg/=integerMissing .or. ixVegNrg/=integerMissing .or. ixVegHyd/=integerMissing)then
-  
-    ! extract temperature of the canopy air space
-    if(ixCasNrg/=integerMissing)then
-     scalarCanairTempTrial = stateVec(ixCasNrg)
-     scalarCanairTempPrime = stateVecPrime(ixCasNrg)
-    endif
-  
-    ! extract canopy temperature
-    if(ixVegNrg/=integerMissing) then
-     scalarCanopyTempTrial = stateVec(ixVegNrg)
-     scalarCanopyTempPrime = stateVecPrime(ixVegNrg)
+  ! input
+  real(rkind),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
+  type(var_dlength),intent(in)    :: diag_data                       ! diagnostic variables for a local HRU
+  type(var_dlength),intent(in)    :: prog_data                       ! prognostic variables for a local HRU
+  type(var_ilength),intent(in)    :: indx_data                       ! indices defining model states and layers
+  real(qp),intent(out)            :: resid(:)
+  ! output: error control
+  integer(i4b),intent(out)        :: err                             ! error code
+  character(*),intent(out)        :: message                         ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  integer(i4b)                    :: iLayer                          ! index of layer within the snow+soil domain
+  integer(i4b)                    :: iCount
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! make association with variables in the data structures
+  associate(&
+    ! number of model layers, and layer type
+    nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1)                 ,& ! intent(in):  [i4b]    total number of snow layers
+    nSoil                   => indx_data%var(iLookINDEX%nSoil)%dat(1)                 ,& ! intent(in):  [i4b]    total number of soil layers
+    nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1)               ,& ! intent(in):  [i4b]    total number of snow and soil layers
+    ! indices defining model states and layers
+    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)
+    ixAqWat                 => indx_data%var(iLookINDEX%ixAqWat)%dat(1)               ,& ! intent(in):  [i4b]    index of the squifer storage state variable
+    ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for energy states in the snow+soil subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for hydrology states in the snow+soil subdomain
+    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 variables in the snow+soil domain
+    ! indices defining type of model state variables
+    ixStateType_subset      => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in):  [i4b(:)] [state subset] type of desired model state variables
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                & ! intent(in):  [i4b(:)] index of the type of hydrology states in snow+soil domain
+    )! association with variables in the data structures
+
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! --------------------------------------------------------------------------------------------------------------------------------
+
+    ! initialize error control
+    err=0; message='residDiscontinuity/'
+
+    iCount = 1
+
+
+    ! check if computing the vegetation flux
+    if(ixCasNrg/=integerMissing .or. ixVegNrg/=integerMissing)then
+
+      ! temperature of the canopy air space
+      if(ixCasNrg/=integerMissing)then
+        resid(iCount) = stateVec(ixCasNrg) - Tfreeze    !  scalarCanairTempTrial - Tfreeze
+        iCount = iCount + 1
+      endif
+
+      ! canopy temperature
+      if(ixVegNrg/=integerMissing)then
+        resid(iCount) = stateVec(ixVegNrg) - Tfreeze    !  scalarCanopyTempTrial - Tfreeze
+        iCount = iCount + 1
+      endif
+
+    endif  ! not computing the vegetation flux
+
+    if(nSnowSoilNrg>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        resid( iCount ) = stateVec( ixSnowSoilNrg(iLayer) ) - Tfreeze          ! mLayerTempTrial(iLayer) - Tfreeze
+        iCount = iCount + 1
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
     endif
-  
-    ! extract intercepted water
-    if(ixVegHyd/=integerMissing)then
-     select case( ixStateType_subset(ixVegHyd) )
-      case(iname_liqCanopy)
-       scalarCanopyLiqTrial = stateVec(ixVegHyd)
-       scalarCanopyLiqPrime = stateVecPrime(ixVegHyd)
-      case(iname_watCanopy)
-       scalarCanopyWatTrial = stateVec(ixVegHyd)
-       scalarCanopyWatPrime = stateVecPrime(ixVegHyd)
-      case default; err=20; message=trim(message)//'case not found: expect iname_liqCanopy or iname_watCanopy'; return
-     end select
+
+  end associate
+end subroutine residDiscontinuity
+
+! **********************************************************************************************************
+! public subroutine countDiscontinuity:
+! **********************************************************************************************************
+subroutine countDiscontinuity(&
+                      ! input
+                      stateVec,                                  & ! intent(in):    model state vector (mixed units)
+                      diag_data,                                 & ! intent(in):    model diagnostic variables for a local HRU
+                      prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                      indx_data,                                 & ! intent(in):    indices defining model states and layers
+                      ! output
+                      countD,                                     & ! intent(out)
+                      err,message)                                 ! intent(out):   error control
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  implicit none
+  ! input
+  real(rkind),intent(in)             :: stateVec(:)                     ! model state vector (mixed units)
+  type(var_dlength),intent(in)    :: diag_data                       ! diagnostic variables for a local HRU
+  type(var_dlength),intent(in)    :: prog_data                       ! prognostic variables for a local HRU
+  type(var_ilength),intent(in)    :: indx_data                       ! indices defining model states and layers
+  integer(i4b),intent(out)        :: countD
+  ! output: error control
+  integer(i4b),intent(out)        :: err                             ! error code
+  character(*),intent(out)        :: message                         ! error message
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  integer(i4b)                    :: iLayer                          ! index of layer within the snow+soil domain
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! make association with variables in the data structures
+  associate(&
+    ! number of model layers, and layer type
+    nSnow                   => indx_data%var(iLookINDEX%nSnow)%dat(1)                 ,& ! intent(in):  [i4b]    total number of snow layers
+    nSoil                   => indx_data%var(iLookINDEX%nSoil)%dat(1)                 ,& ! intent(in):  [i4b]    total number of soil layers
+    nLayers                 => indx_data%var(iLookINDEX%nLayers)%dat(1)               ,& ! intent(in):  [i4b]    total number of snow and soil layers
+    ! indices defining model states and layers
+    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)
+    ixAqWat                 => indx_data%var(iLookINDEX%ixAqWat)%dat(1)               ,& ! intent(in):  [i4b]    index of the squifer storage state variable
+    ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for energy states in the snow+soil subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):  [i4b(:)] indices IN THE STATE SUBSET for hydrology states in the snow+soil subdomain
+    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 variables in the snow+soil domain
+    ! indices defining type of model state variables
+    ixStateType_subset      => indx_data%var(iLookINDEX%ixStateType_subset)%dat       ,& ! intent(in):  [i4b(:)] [state subset] type of desired model state variables
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                & ! intent(in):  [i4b(:)] index of the type of hydrology states in snow+soil domain
+    )! association with variables in the data structures
+
+    ! --------------------------------------------------------------------------------------------------------------------------------
+    ! --------------------------------------------------------------------------------------------------------------------------------
+
+    ! initialize error control
+    err=0; message='countDiscontinuity/'
+
+    ! *** extract state variables for the vegetation canopy
+
+    countD = 0
+    ! check if computing the vegetation flux
+    if(ixCasNrg/=integerMissing .or. ixVegNrg/=integerMissing)then
+
+      ! temperature of the canopy air space
+      if(ixCasNrg/=integerMissing)  countD = countD + 1
+
+      ! canopy temperature
+      if(ixVegNrg/=integerMissing)  countD = countD + 1
+
+
+    endif  ! not computing the vegetation flux
+
+    if(nSnowSoilNrg>0)then
+      do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
+        countD = countD + 1
+      end do  ! looping through non-missing energy state variables in the snow+soil domain
     endif
-  
-   endif  ! not computing the vegetation flux
-  
-  
-   ! overwrite with the energy values from the state vector
-   if(nSnowSoilNrg>0)then
-    do concurrent (iLayer=1:nLayers,ixSnowSoilNrg(iLayer)/=integerMissing)   ! (loop through non-missing energy state variables in the snow+soil domain)
-     mLayerTempTrial(iLayer) = stateVec( ixSnowSoilNrg(iLayer) )
-     mLayerTempPrime(iLayer) = stateVecPrime( ixSnowSoilNrg(iLayer) )
-    end do  ! looping through non-missing energy state variables in the snow+soil domain
-   endif
-  
-   ! overwrite with the hydrology values from the state vector
-   if(nSnowSoilHyd>0)then
-    do concurrent (iLayer=1:nLayers,ixSnowSoilHyd(iLayer)/=integerMissing)   ! (loop through non-missing hydrology state variables in the snow+soil domain)
-     select case( ixHydType(iLayer) )
-      case(iname_watLayer)
-       mLayerVolFracWatTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! total water state variable for snow+soil layers
-       mLayerVolFracWatPrime(iLayer)          = stateVecPrime( ixSnowSoilHyd(iLayer) ) ! total water state variable for snow+soil layers
-      case(iname_liqLayer)
-       mLayerVolFracLiqTrial(iLayer)          = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid water state variable for snow+soil layers
-       mLayerVolFracLiqPrime(iLayer)          = stateVecPrime( ixSnowSoilHyd(iLayer) ) ! liquid water state variable for snow+soil layers
-      case(iname_matLayer)
-       mLayerMatricHeadTrial(iLayer-nSnow)    = stateVec( ixSnowSoilHyd(iLayer) ) ! total water matric potential variable for soil layers
-       mLayerMatricHeadPrime(iLayer-nSnow)    = stateVecPrime( ixSnowSoilHyd(iLayer) ) ! total water matric potential variable for soil layers
-      case(iname_lmpLayer)
-       mLayerMatricHeadLiqTrial(iLayer-nSnow) = stateVec( ixSnowSoilHyd(iLayer) ) ! liquid matric potential state variable for soil layers
-       mLayerMatricHeadLiqPrime(iLayer-nSnow) = stateVecPrime( ixSnowSoilHyd(iLayer) ) ! liquid matric potential state variable for soil layers
-      case default ! do nothing
-     end select
-    end do  ! looping through non-missing energy state variables in the snow+soil domain
-   endif
-  
-   ! extract temperature of the canopy air space
-   if(ixAqWat/=integerMissing)then
-    scalarAquiferStorageTrial = stateVec(ixAqWat)
-    scalarAquiferStoragePrime = stateVecPrime(ixAqWat)
-   endif
-  
-   end associate
-  
-   end subroutine varExtractSundials
-  
-  
-  end module getVectorzAddSundials_module
+
+  end associate
+
+end subroutine countDiscontinuity
+
+end module getVectorzAddSundials_module
   
\ No newline at end of file
diff --git a/build/source/engine/sundials/summaSolveSundialsIDA.f90 b/build/source/engine/sundials/summaSolveSundialsIDA.f90
index 48cfe32..79b9dba 100644
--- a/build/source/engine/sundials/summaSolveSundialsIDA.f90
+++ b/build/source/engine/sundials/summaSolveSundialsIDA.f90
@@ -4,699 +4,729 @@
 module summaSolveSundialsIDA_module
 
 
+!======= Inclusions ===========
+USE, intrinsic :: iso_c_binding
+USE nrtype
+USE type4IDA
+
+! 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
+USE globalData,only: ku             ! number of super-diagonal bands
+USE globalData,only: kl             ! number of sub-diagonal bands
+
+! domain types
+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:model_decisions ! model decision structure
+
+! 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
+
+! constants
+USE multiconst,only:&
+                    LH_fus,       & ! latent heat of fusion                (J K-1)
+                    LH_sub,       & ! latent heat of sublimation           (J kg-1)
+                    Tfreeze,      & ! temperature at freezing              (K)
+                    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:iLookPROG       ! named variables for structure elements
+USE var_lookup,only:iLookDIAG       ! named variables for structure elements
+USE var_lookup,only:iLookDECISIONS  ! named variables for elements of the decision structure
+USE var_lookup,only:iLookDERIV     ! named variables for structure elements
+USE var_lookup,only:iLookFLUX       ! named variables for structure elements
+USE var_lookup,only:iLookPARAM      ! named variables for structure elements
+USE var_lookup,only:iLookINDEX      ! named variables for structure elements
+
+! 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_ilength,  & ! data vector with variable length dimension (i4b)
+                    var_dlength,  & ! data vector with variable length dimension (rkind)
+                    zLookup         ! data vector
+
+! look-up values for the choice of groundwater parameterization
+USE mDecisions_module,only:  qbaseTopmodel ! TOPMODEL-ish baseflow parameterization
+
+! privacy
+  implicit none
+  private::setInitialCondition
+  private::setSolverParams
+  public::summaSolveSundialsIDA
+
+contains
+
+!-------------------
+! * public subroutine summaSolveSundialsIDA: solve F(y,y') = 0 by IDA (y is the state vector)
+! ------------------
+subroutine summaSolveSundialsIDA(                         &
+                      dt,                      & ! intent(in):    data time step
+                      atol,                    & ! intent(in):    absolute telerance
+                      rtol,                    & ! intent(in):    relative tolerance
+                      nSnow,                   & ! intent(in):    number of snow layers
+                      nSoil,                   & ! intent(in):    number of soil layers
+                      nLayers,                 & ! intent(in):    total number of layers
+                      nStat,                   & ! intent(in):    total number of state variables
+                      ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
+                      firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                      computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                      scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                      ! input: state vectors
+                      stateVecInit,            & ! intent(in):    initial state vector
+                      sMul,                    & ! intent(inout): state vector multiplier (USEd in the residual calculations)
+                      dMat,                    & ! intent(inout): diagonal of the Jacobian matrix (excludes fluxes)
+                      ! input: data structures
+                      lookup_data,             & ! intent(in):    lookup tables
+                      type_data,               & ! intent(in):    type of vegetation and soil
+                      attr_data,               & ! intent(in):    spatial attributes
+                      mpar_data,               & ! intent(in):    model parameters
+                      forc_data,               & ! intent(in):    model forcing data
+                      bvar_data,               & ! intent(in):    average model variables for the entire basin
+                      prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                      ! input-output: data structures
+                      indx_data,               & ! intent(in):    index data
+                      diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                      flux_temp,               & ! intent(inout): model fluxes for a local HRU
+                      flux_data,               & ! intent(inout): model fluxes for a local HRU
+                      flux_sum,                & ! intent(inout): sum of fluxes model fluxes for a local HRU over a data step
+                      deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                      ! output
+                      ixSaturation,            & ! intent(inout) index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                      idaSucceeds,             & ! intent(out):   flag to indicate if ida successfully solved the problem in current data step
+                      tooMuchMelt,             & ! intent(inout):   flag to denote that there was too much melt
+                      mLayerCmpress_sum,       & ! intent(out):   sum of compression of the soil matrix
+                      dt_out,                  & ! intent(out):   time step
+                      stateVec,                & ! intent(out):   model state vector
+                      stateVecPrime,           & ! intent(out):   derivative of model state vector
+                      err,message              & ! intent(out):   error control
+                    )
+
   !======= Inclusions ===========
-  USE, intrinsic :: iso_c_binding
-  USE nrtype
-  USE type4IDA
-  
-  ! 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
-  USE globalData,only: ku             ! number of super-diagonal bands
-  USE globalData,only: kl             ! number of sub-diagonal bands
-  
-  ! domain types
-  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:model_decisions ! model decision structure
-  
-  ! 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
-  
-  ! constants
-  USE multiconst,only:&
-                      LH_fus,       & ! latent heat of fusion                (J K-1)
-                      LH_sub,       & ! latent heat of sublimation           (J kg-1)
-                      Tfreeze,      & ! temperature at freezing              (K)
-                      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:iLookPROG       ! named variables for structure elements
-  USE var_lookup,only:iLookDIAG       ! named variables for structure elements
-  USE var_lookup,only:iLookDECISIONS  ! named variables for elements of the decision structure
-  USE var_lookup,only:iLookDERIV     ! named variables for structure elements
-  USE var_lookup,only:iLookFLUX       ! named variables for structure elements
-  USE var_lookup,only:iLookPARAM      ! named variables for structure elements
-  USE var_lookup,only:iLookINDEX      ! named variables for structure elements
-  
-  ! 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_ilength,  & ! data vector with variable length dimension (i4b)
-                      var_dlength,  & ! data vector with variable length dimension (rkind)
-                      zLookup         ! data vector
-  
-  ! look-up values for the choice of groundwater parameterization
-  USE mDecisions_module,only:  qbaseTopmodel ! TOPMODEL-ish baseflow parameterization
-  
-  ! privacy
-   implicit none
-   private::setInitialCondition
-   private::setSolverParams
-   public::summaSolveSundialsIDA
-  
-  contains
-  
-   !-------------------
-   ! * public subroutine summaSolveSundialsIDA: solve F(y,y') = 0 by IDA (y is the state vector)
-   ! ------------------
-   subroutine summaSolveSundialsIDA(                         &
-                         dt,                      & ! intent(in):    data time step
-                         atol,                    & ! intent(in):    absolute telerance
-                         rtol,                    & ! intent(in):    relative tolerance
-                         nSnow,                   & ! intent(in):    number of snow layers
-                         nSoil,                   & ! intent(in):    number of soil layers
-                         nLayers,                 & ! intent(in):    total number of layers
-                         nStat,                   & ! intent(in):    total number of state variables
-                         ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
-                         firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                         computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                         scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                         ! input: state vectors
-                         stateVecInit,            & ! intent(in):    initial state vector
-                         sMul,                    & ! intent(inout): state vector multiplier (USEd in the residual calculations)
-                         dMat,                    & ! intent(inout): diagonal of the Jacobian matrix (excludes fluxes)
-                         ! input: data structures
-                         lookup_data,             & ! intent(in):    lookup tables
-                         type_data,               & ! intent(in):    type of vegetation and soil
-                         attr_data,               & ! intent(in):    spatial attributes
-                         mpar_data,               & ! intent(in):    model parameters
-                         forc_data,               & ! intent(in):    model forcing data
-                         bvar_data,               & ! intent(in):    average model variables for the entire basin
-                         prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                         ! input-output: data structures
-                         indx_data,               & ! intent(in):    index data
-                         diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
-                         flux_temp,               & ! intent(inout): model fluxes for a local HRU
-                         flux_data,               & ! intent(inout): model fluxes for a local HRU
-                         flux_sum,                & ! intent(inout): sum of fluxes model fluxes for a local HRU over a data step
-                         deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                         ! output
-                         ixSaturation,            & ! intent(inout) index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                         idaSucceeds,             & ! intent(out):   flag to indicate if ida successfully solved the problem in current data step
-                         tooMuchMelt,             & ! intent(inout):   flag to denote that there was too much melt
-                         mLayerCmpress_sum,       & ! intent(out):   sum of compression of the soil matrix
-                         dt_out,                  & ! intent(out):   time step
-                         stateVec,                & ! intent(out):   model state vector
-                         stateVecPrime,           & ! intent(out):   derivative of model state vector
-                         err,message              & ! intent(out):   error control
-                        )
-  
-   !======= Inclusions ===========
-   USE fida_mod                                    ! Fortran interface to IDA
-   USE fnvector_serial_mod                         ! Fortran interface to serial N_Vector
-   USE fsunmatrix_dense_mod                        ! Fortran interface to dense SUNMatrix
-   USE fsunlinsol_dense_mod                        ! Fortran interface to dense SUNLinearSolver
-   USE fsunmatrix_band_mod                         ! Fortran interface to banded SUNMatrix
-   USE fsunlinsol_band_mod                         ! Fortran interface to banded SUNLinearSolver
-   USE fsunnonlinsol_newton_mod                    ! Fortran interface to Newton SUNNonlinearSolver
-   USE fsundials_matrix_mod                        ! Fortran interface to generic SUNMatrix
-   USE fsundials_nvector_mod                       ! Fortran interface to generic N_Vector
-   USE fsundials_linearsolver_mod                  ! Fortran interface to generic SUNLinearSolver
-   USE fsundials_nonlinearsolver_mod               ! Fortran interface to generic SUNNonlinearSolver
-   USE allocspace4chm_module,only:allocLocal           ! allocate local data structures
-   USE eval8summaSundials_module,only:eval8summa4IDA         ! DAE/ODE functions
-   USE computJacobSundials_module,only:computJacob4IDA         ! system Jacobian
-   USE tol4IDA_module,only:computWeight4IDA        ! weight required for tolerances
-   USE eval8summaSundials_module,only:eval8summaSundials ! residual of DAE
-   USE var_derive_module,only:calcHeight           ! height at layer interfaces and layer mid-point
-  
-   !======= Declarations =========
-   implicit none
-  
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! calling variables
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! input: model control
-   real(qp),intent(in)             :: dt                     ! data time step
-   real(qp),intent(inout)          :: atol(:)                ! vector of absolute tolerances
-   real(qp),intent(inout)          :: rtol(:)                ! vector of relative tolerances
-   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)         :: nStat                  ! total number of state variables
-   integer(i4b),intent(in)         :: ixMatrix               ! form of matrix (dense or banded)
-   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 computing fluxes over vegetation
-   logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
-   ! input: state vectors
-   real(rkind),intent(in)          :: stateVecInit(:)        ! model state vector
-   real(qp),intent(in)             :: sMul(:)                ! state vector multiplier (used in the residual calculations)
-   real(rkind), intent(inout)      :: dMat(:)
-   ! input: data structures
-   type(zLookup),intent(in)        :: lookup_data            ! lookup tables
-   type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
-   type(var_d),        intent(in)  :: attr_data              ! spatial attributes
-   type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
-   type(var_d),        intent(in)  :: forc_data              ! model forcing data
-   type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
-   type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
-   type(var_ilength),  intent(in)  :: indx_data              ! indices defining model states and layers
-   ! input-output: data structures
-   type(var_dlength),intent(inout) :: diag_data              ! diagnostic variables for a local HRU
-   type(var_dlength),intent(inout) :: flux_temp              ! model fluxes for a local HRU
-   type(var_dlength),intent(inout) :: flux_data              ! model fluxes for a local HRU
-   type(var_dlength),intent(inout) :: flux_sum               ! sum of fluxes
-   type(var_dlength),intent(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
-   real(rkind),intent(inout)       :: mLayerCmpress_sum(:)   ! sum of soil compress
-   ! output: state vectors
-   integer(i4b),intent(inout)      :: ixSaturation           ! index of the lowest saturated layer
-   real(rkind),intent(inout)       :: stateVec(:)            ! model state vector (y)
-   real(rkind),intent(inout)       :: stateVecPrime(:)       ! model state vector (y')
-   logical(lgt),intent(out)        :: idaSucceeds            ! flag to indicate if IDA is successful
-   logical(lgt),intent(inout)      :: tooMuchMelt                   ! flag to denote that there was too much melt
-   real(qp),intent(out)            :: dt_out                 ! time step
-   ! output: error control
-   integer(i4b),intent(out)        :: err                    ! error code
-   character(*),intent(out)        :: message                ! error message
-  
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   ! local variables
-   ! --------------------------------------------------------------------------------------------------------------------------------
-   type(N_Vector),           pointer :: sunvec_y             ! sundials solution vector
-   type(N_Vector),           pointer :: sunvec_yp            ! sundials derivative vector
-   type(N_Vector),           pointer :: sunvec_av            ! sundials tolerance vector
-   type(SUNMatrix),          pointer :: sunmat_A             ! sundials matrix
-   type(SUNLinearSolver),    pointer :: sunlinsol_LS         ! sundials linear solver
-   type(SUNNonLinearSolver), pointer :: sunnonlin_NLS        ! sundials nonlinear solver
-   type(c_ptr)                       :: ida_mem              ! IDA memory
-   type(eqnsData),           target  :: eqns_data            ! IDA type
-   integer(i4b)                      :: retval, retvalr      ! return value
-   integer(i4b)                      :: rootsfound(3)        ! crossing direction of discontinuities
-   logical(lgt)                      :: feasible             ! feasibility flag
-   real(qp)                          :: t0                   ! staring time
-   real(qp)                          :: dt_last(1)           ! last time step
-   integer(kind = 8)                 :: mu, lu               ! in banded matrix mode
-   integer(i4b)                      :: iVar
-   logical(lgt)                      :: startQuadrature
-   real(rkind)                       :: mLayerMatricHeadLiqPrev(nSoil)
-   real(qp)                          :: h_init
-   integer(c_long)                   :: nState               ! total number of state variables
-   real(rkind)                       :: rVec(nStat)
-   real(qp)                          :: tret(1)
-   logical(lgt)                      :: mergedLayers
-   logical(lgt),parameter            :: offErrWarnMessage = .false.
-   real(rkind)                       :: superflousSub        ! superflous sublimation (kg m-2 s-1)
-   real(rkind)                       :: superflousNrg        ! superflous energy that cannot be used for sublimation (W m-2 [J m-2 s-1])
-   integer(i4b)                      :: i
-  
-   ! -----------------------------------------------------------------------------------------------------
-  
-   ! initialize error control
-   err=0; message="summaSolveSundialsIDA/"
-  
-   nState = nStat
-   idaSucceeds = .true.
-   ! fill eqns_data which will be required later to call eval8summaSundials
-   eqns_data%dt                      = dt
-   eqns_data%nSnow                   = nSnow
-   eqns_data%nSoil                   = nSoil
-   eqns_data%nLayers                 = nLayers
-   eqns_data%nState                  = nState
-   eqns_data%ixMatrix                = ixMatrix
-   eqns_data%firstSubStep            = firstSubStep
-   eqns_data%computeVegFlux          = computeVegFlux
-   eqns_data%scalarSolution          = scalarSolution
-  
-   allocate( eqns_data%atol(nState) )
-   eqns_data%atol = atol
-  
-   allocate( eqns_data%rtol(nState) )
-   eqns_data%rtol = rtol
-  
-   allocate( eqns_data%sMul(nState) )
-   eqns_data%sMul                    = sMul
-  
-   allocate( eqns_data%dMat(nState) )
-   eqns_data%dMat                   = dMat
-  
-   ! allocate space for the temporary prognostic variable structure
-   call allocLocal(prog_meta(:),eqns_data%prog_data,nSnow,nSoil,err,message)
-   if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
-   eqns_data%prog_data               = prog_data
-  
-   ! allocate space for the temporary diagnostic variable structure
-   call allocLocal(diag_meta(:),eqns_data%diag_data,nSnow,nSoil,err,message)
-   if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
-   eqns_data%diag_data               = diag_data
-  
-   ! allocate space for the temporary flux variable structure
-   call allocLocal(flux_meta(:),eqns_data%flux_data,nSnow,nSoil,err,message)
-   if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
-   eqns_data%flux_data               = flux_data
-  
-   ! allocate space for the derivative structure
-   call allocLocal(deriv_meta(:),eqns_data%deriv_data,nSnow,nSoil,err,message)
-   if(err/=0)then; err=20; message=trim(message)//trim(message); return; end if
-   eqns_data%deriv_data              = deriv_data
-  
-   eqns_data%lookup_data             = lookup_data
-   eqns_data%type_data               = type_data
-   eqns_data%attr_data               = attr_data
-   eqns_data%mpar_data               = mpar_data
-   eqns_data%forc_data               = forc_data
-   eqns_data%bvar_data               = bvar_data
-   eqns_data%indx_data               = indx_data
-  
-   ! allocate space
-   if(model_decisions(iLookDECISIONS%groundwatr)%iDecision==qbaseTopmodel)then
+  USE fida_mod                                    ! Fortran interface to IDA
+  USE fnvector_serial_mod                         ! Fortran interface to serial N_Vector
+  USE fsunmatrix_dense_mod                        ! Fortran interface to dense SUNMatrix
+  USE fsunlinsol_dense_mod                        ! Fortran interface to dense SUNLinearSolver
+  USE fsunmatrix_band_mod                         ! Fortran interface to banded SUNMatrix
+  USE fsunlinsol_band_mod                         ! Fortran interface to banded SUNLinearSolver
+  USE fsunnonlinsol_newton_mod                    ! Fortran interface to Newton SUNNonlinearSolver
+  USE fsundials_matrix_mod                        ! Fortran interface to generic SUNMatrix
+  USE fsundials_nvector_mod                       ! Fortran interface to generic N_Vector
+  USE fsundials_linearsolver_mod                  ! Fortran interface to generic SUNLinearSolver
+  USE fsundials_nonlinearsolver_mod               ! Fortran interface to generic SUNNonlinearSolver
+  USE allocspace_module,only:allocLocal           ! allocate local data structures
+  USE evalDAE4IDA_module,only:evalDAE4IDA         ! DAE/ODE functions
+  USE evalJac4IDA_module,only:evalJac4IDA         ! system Jacobian
+  USE tol4IDA_module,only:computWeight4IDA        ! weigth required for tolerances
+  USE eval8summaSundials_module,only:eval8summaSundials               ! residual of DAE
+  USE var_derive_module,only:calcHeight           ! height at layer interfaces and layer mid-point
+
+  !======= Declarations =========
+  implicit none
+
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! calling variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! input: model control
+  real(qp),intent(in)             :: dt                     ! data time step
+  real(qp),intent(inout)          :: atol(:)                ! vector of absolute tolerances
+  real(qp),intent(inout)          :: rtol(:)                ! vector of relative tolerances
+  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)         :: nStat                  ! total number of state variables
+  integer(i4b),intent(in)         :: ixMatrix               ! form of matrix (dense or banded)
+  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 computing fluxes over vegetation
+  logical(lgt),intent(in)         :: scalarSolution         ! flag to denote if implementing the scalar solution
+  ! input: state vectors
+  real(rkind),intent(in)          :: stateVecInit(:)        ! model state vector
+  real(qp),intent(in)             :: sMul(:)                ! state vector multiplier (used in the residual calculations)
+  real(rkind), intent(inout)      :: dMat(:)
+  ! input: data structures
+  type(zLookup),intent(in)        :: lookup_data            ! lookup tables
+  type(var_i),        intent(in)  :: type_data              ! type of vegetation and soil
+  type(var_d),        intent(in)  :: attr_data              ! spatial attributes
+  type(var_dlength),  intent(in)  :: mpar_data              ! model parameters
+  type(var_d),        intent(in)  :: forc_data              ! model forcing data
+  type(var_dlength),  intent(in)  :: bvar_data              ! model variables for the local basin
+  type(var_dlength),  intent(in)  :: prog_data              ! prognostic variables for a local HRU
+  type(var_ilength),  intent(in)  :: indx_data              ! indices defining model states and layers
+  ! input-output: data structures
+  type(var_dlength),intent(inout) :: diag_data              ! diagnostic variables for a local HRU
+  type(var_dlength),intent(inout) :: flux_temp              ! model fluxes for a local HRU
+  type(var_dlength),intent(inout) :: flux_data              ! model fluxes for a local HRU
+  type(var_dlength),intent(inout) :: flux_sum               ! sum of fluxes
+  type(var_dlength),intent(inout) :: deriv_data             ! derivatives in model fluxes w.r.t. relevant state variables
+  real(rkind),intent(inout)       :: mLayerCmpress_sum(:)   ! sum of soil compress
+  ! output: state vectors
+  integer(i4b),intent(inout)      :: ixSaturation           ! index of the lowest saturated layer
+  real(rkind),intent(inout)       :: stateVec(:)            ! model state vector (y)
+  real(rkind),intent(inout)       :: stateVecPrime(:)       ! model state vector (y')
+  logical(lgt),intent(out)        :: idaSucceeds            ! flag to indicate if IDA is successful
+  logical(lgt),intent(inout)      :: tooMuchMelt                   ! flag to denote that there was too much melt
+  real(qp),intent(out)            :: dt_out                 ! time step
+  ! output: error control
+  integer(i4b),intent(out)        :: err                    ! error code
+  character(*),intent(out)        :: message                ! error message
+
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  ! local variables
+  ! --------------------------------------------------------------------------------------------------------------------------------
+  type(N_Vector),           pointer :: sunvec_y             ! sundials solution vector
+  type(N_Vector),           pointer :: sunvec_yp            ! sundials derivative vector
+  type(N_Vector),           pointer :: sunvec_av            ! sundials tolerance vector
+  type(SUNMatrix),          pointer :: sunmat_A             ! sundials matrix
+  type(SUNLinearSolver),    pointer :: sunlinsol_LS         ! sundials linear solver
+  type(SUNNonLinearSolver), pointer :: sunnonlin_NLS        ! sundials nonlinear solver
+  type(c_ptr)                       :: ida_mem              ! IDA memory
+  type(eqnsData),           target  :: eqns_data            ! IDA type
+  integer(i4b)                      :: retval, retvalr      ! return value
+  integer(i4b)                      :: rootsfound(3)        ! crossing direction of discontinuities
+  logical(lgt)                      :: feasible             ! feasibility flag
+  real(qp)                          :: t0                   ! staring time
+  real(qp)                          :: dt_last(1)           ! last time step
+  integer(kind = 8)                 :: mu, lu               ! in banded matrix mode
+  integer(i4b)                      :: iVar
+  logical(lgt)                      :: startQuadrature
+  real(rkind)                       :: mLayerMatricHeadLiqPrev(nSoil)
+  real(qp)                          :: h_init
+  integer(c_long)                   :: nState               ! total number of state variables
+  real(rkind)                       :: rVec(nStat)
+  real(qp)                          :: tret(1)
+  logical(lgt)                      :: mergedLayers
+  logical(lgt),parameter            :: offErrWarnMessage = .false.
+  real(rkind)                       :: superflousSub        ! superflous sublimation (kg m-2 s-1)
+  real(rkind)                       :: superflousNrg        ! superflous energy that cannot be used for sublimation (W m-2 [J m-2 s-1])
+  integer(i4b)                      :: i
+
+  ! -----------------------------------------------------------------------------------------------------
+
+  ! initialize error control
+  err=0; message="summaSolveSundialsIDA/"
+
+  nState = nStat
+  idaSucceeds = .true.
+  ! fill eqns_data which will be required later to call eval8summaSundials
+  eqns_data%dt                      = dt
+  eqns_data%nSnow                   = nSnow
+  eqns_data%nSoil                   = nSoil
+  eqns_data%nLayers                 = nLayers
+  eqns_data%nState                  = nState
+  eqns_data%ixMatrix                = ixMatrix
+  eqns_data%firstSubStep            = firstSubStep
+  eqns_data%computeVegFlux          = computeVegFlux
+  eqns_data%scalarSolution          = scalarSolution
+
+  allocate( eqns_data%atol(nState) )
+  eqns_data%atol = atol
+
+  allocate( eqns_data%rtol(nState) )
+  eqns_data%rtol = rtol
+
+  allocate( eqns_data%sMul(nState) )
+  eqns_data%sMul                    = sMul
+
+  allocate( eqns_data%dMat(nState) )
+  eqns_data%dMat                   = dMat
+
+  ! allocate space for the temporary prognostic variable structure
+  call allocLocal(prog_meta(:),eqns_data%prog_data,nSnow,nSoil,err,message)
+  if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
+  eqns_data%prog_data               = prog_data
+
+  ! allocate space for the temporary diagnostic variable structure
+  call allocLocal(diag_meta(:),eqns_data%diag_data,nSnow,nSoil,err,message)
+  if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
+  eqns_data%diag_data               = diag_data
+
+  ! allocate space for the temporary flux variable structure
+  call allocLocal(flux_meta(:),eqns_data%flux_data,nSnow,nSoil,err,message)
+  if(err/=0)then; err=20; message=trim(message)//trim(message); return; endif
+  eqns_data%flux_data               = flux_data
+
+  ! allocate space for the derivative structure
+  call allocLocal(deriv_meta(:),eqns_data%deriv_data,nSnow,nSoil,err,message)
+  if(err/=0)then; err=20; message=trim(message)//trim(message); return; end if
+  eqns_data%deriv_data              = deriv_data
+
+  eqns_data%lookup_data             = lookup_data
+  eqns_data%type_data               = type_data
+  eqns_data%attr_data               = attr_data
+  eqns_data%mpar_data               = mpar_data
+  eqns_data%forc_data               = forc_data
+  eqns_data%bvar_data               = bvar_data
+  eqns_data%indx_data               = indx_data
+
+  ! allocate space
+  if(model_decisions(iLookDECISIONS%groundwatr)%iDecision==qbaseTopmodel)then
     allocate(eqns_data%dBaseflow_dMatric(nSoil,nSoil),stat=err)
-   else
+  else
     allocate(eqns_data%dBaseflow_dMatric(0,0),stat=err)
-   end if
-   allocate( eqns_data%mLayerTempTrial(nLayers) )
-   allocate( eqns_data%mLayerMatricHeadLiqTrial(nSoil) )
-   allocate( eqns_data%mLayerMatricHeadTrial(nSoil) )
-   allocate( eqns_data%mLayerVolFracWatTrial(nLayers) )
-   allocate( eqns_data%mLayerVolFracIceTrial(nLayers) )
-   allocate( eqns_data%mLayerEnthalpyTrial(nLayers) )
-   allocate( eqns_data%fluxVec(nState) )
-   allocate( eqns_data%resSink(nState) )
-  
-   startQuadrature = .true.
-  
-   ! create serial vectors
-   sunvec_y => FN_VMake_Serial(nState, stateVec)
-   if (.not. associated(sunvec_y)) then; err=20; message='summaSolveSundialsIDA: sunvec = NULL'; return; endif
-  
-   sunvec_yp => FN_VMake_Serial(nState, stateVecPrime)
-   if (.not. associated(sunvec_yp)) then; err=20; message='summaSolveSundialsIDA: sunvec = NULL'; return; endif
-  
-   ! Initialize solution vectors
-   call setInitialCondition(nState, stateVecInit, sunvec_y, sunvec_yp)
-  
-   ! Create memory
-   ida_mem = FIDACreate()
-   if (.not. c_associated(ida_mem)) then; err=20; message='summaSolveSundialsIDA: ida_mem = NULL'; return; endif
-  
-   ! Attach user data to memory
-   eqns_data%ida_mem = ida_mem
-   retval = FIDASetUserData(ida_mem, c_loc(eqns_data))
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetUserData'; return; endif
-  
-   ! Initialize memory
-   t0 = 0._rkind
-   retval = FIDAInit(ida_mem, c_funloc(eval8summa4IDA), t0, sunvec_y, sunvec_yp)
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDAInit'; return; endif
-  
-   ! set tolerances
-   retval = FIDAWFtolerances(ida_mem, c_funloc(computWeight4IDA))
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDAWFtolerances'; return; endif
-  
-   ! define the form of the matrix
-   select case(ixMatrix)
+  end if
+  allocate( eqns_data%mLayerMatricHeadLiqTrial(nSoil) )
+  allocate( eqns_data%mLayerMatricHeadTrial(nSoil) )
+  allocate( eqns_data%mLayerMatricHeadPrev(nSoil) )
+  allocate( eqns_data%mLayerVolFracWatTrial(nLayers) )
+  allocate( eqns_data%mLayerVolFracWatPrev(nLayers) )
+  allocate( eqns_data%mLayerTempTrial(nLayers) )
+  allocate( eqns_data%mLayerTempPrev(nLayers) )
+  allocate( eqns_data%mLayerVolFracIceTrial(nLayers) )
+  allocate( eqns_data%mLayerVolFracIcePrev(nLayers) )
+  allocate( eqns_data%mLayerVolFracLiqTrial(nLayers) )
+  allocate( eqns_data%mLayerVolFracLiqPrev(nLayers) )
+  allocate( eqns_data%mLayerEnthalpyTrial(nLayers) )
+  allocate( eqns_data%mLayerEnthalpyPrev(nLayers) )
+  allocate( eqns_data%fluxVec(nState) )
+  allocate( eqns_data%resSink(nState) )
+
+  startQuadrature = .true.
+
+  ! create serial vectors
+  sunvec_y => FN_VMake_Serial(nState, stateVec)
+  if (.not. associated(sunvec_y)) then; err=20; message='summaSolveSundialsIDA: sunvec = NULL'; return; endif
+
+  sunvec_yp => FN_VMake_Serial(nState, stateVecPrime)
+  if (.not. associated(sunvec_yp)) then; err=20; message='summaSolveSundialsIDA: sunvec = NULL'; return; endif
+
+  ! Initialize solution vectors
+  call setInitialCondition(nState, stateVecInit, sunvec_y, sunvec_yp)
+
+  ! Create memory
+  ida_mem = FIDACreate()
+  if (.not. c_associated(ida_mem)) then; err=20; message='summaSolveSundialsIDA: ida_mem = NULL'; return; endif
+
+  ! Attach user data to memory
+  eqns_data%ida_mem = ida_mem
+  retval = FIDASetUserData(ida_mem, c_loc(eqns_data))
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetUserData'; return; endif
+
+  ! Initialize memory
+  t0 = 0._rkind
+  retval = FIDAInit(ida_mem, c_funloc(evalDAE4IDA), t0, sunvec_y, sunvec_yp)
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDAInit'; return; endif
+
+  ! set tolerances
+  retval = FIDAWFtolerances(ida_mem, c_funloc(computWeight4IDA))
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDAWFtolerances'; return; endif
+
+  ! define the form of the matrix
+  select case(ixMatrix)
     case(ixBandMatrix)
-     mu = ku; lu = kl;
-     ! Create banded SUNMatrix for use in linear solves
-     sunmat_A => FSUNBandMatrix(nState, mu, lu)
-     if (.not. associated(sunmat_A)) then; err=20; message='summaSolveSundialsIDA: sunmat = NULL'; return; endif
-  
-     ! Create banded SUNLinearSolver object
-     sunlinsol_LS => FSUNLinSol_Band(sunvec_y, sunmat_A)
-     if (.not. associated(sunlinsol_LS)) then; err=20; message='summaSolveSundialsIDA: sunlinsol = NULL'; return; endif
-  
+      mu = ku; lu = kl;
+      ! Create banded SUNMatrix for use in linear solves
+      sunmat_A => FSUNBandMatrix(nState, mu, lu)
+      if (.not. associated(sunmat_A)) then; err=20; message='summaSolveSundialsIDA: sunmat = NULL'; return; endif
+
+      ! Create banded SUNLinearSolver object
+      sunlinsol_LS => FSUNLinSol_Band(sunvec_y, sunmat_A)
+      if (.not. associated(sunlinsol_LS)) then; err=20; message='summaSolveSundialsIDA: sunlinsol = NULL'; return; endif
+
     case(ixFullMatrix)
-     ! Create dense SUNMatrix for use in linear solves
-     sunmat_A => FSUNDenseMatrix(nState, nState)
-     if (.not. associated(sunmat_A)) then; err=20; message='summaSolveSundialsIDA: sunmat = NULL'; return; endif
-  
-     ! Create dense SUNLinearSolver object
-     sunlinsol_LS => FSUNDenseLinearSolver(sunvec_y, sunmat_A)
-     if (.not. associated(sunlinsol_LS)) then; err=20; message='summaSolveSundialsIDA: sunlinsol = NULL'; return; endif
-  
-   ! check
+      ! Create dense SUNMatrix for use in linear solves
+      sunmat_A => FSUNDenseMatrix(nState, nState)
+      if (.not. associated(sunmat_A)) then; err=20; message='summaSolveSundialsIDA: sunmat = NULL'; return; endif
+
+      ! Create dense SUNLinearSolver object
+      sunlinsol_LS => FSUNDenseLinearSolver(sunvec_y, sunmat_A)
+      if (.not. associated(sunlinsol_LS)) then; err=20; message='summaSolveSundialsIDA: sunlinsol = NULL'; return; endif
+
+      ! check
     case default;  err=20; message='summaSolveSundialsIDA: error in type of matrix'; return
-  
-   end select  ! form of matrix
-  
-   ! Attach the matrix and linear solver
-   retval = FIDASetLinearSolver(ida_mem, sunlinsol_LS, sunmat_A);
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetLinearSolver'; return; endif
-  
-   if(ixMatrix == ixFullMatrix)then
-    ! Set the user-supplied Jacobian routine
-    !comment this line out to use FD Jacobian
-    retval = FIDASetJacFn(ida_mem, c_funloc(computJacob4IDA))
-    if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetJacFn'; return; endif
-   endif
-  
-   ! Create Newton SUNNonlinearSolver object
-   sunnonlin_NLS => FSUNNonlinSol_Newton(sunvec_y)
-   if (.not. associated(sunnonlin_NLS)) then; err=20; message='summaSolveSundialsIDA: sunnonlinsol = NULL'; return; endif
-  
-   ! Attach the nonlinear solver
-   retval = FIDASetNonlinearSolver(ida_mem, sunnonlin_NLS)
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetNonlinearSolver'; return; endif
-  
-   ! Enforce the solver to stop at end of the time step
-   retval = FIDASetStopTime(ida_mem, dt)
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetStopTime'; return; endif
-  
-   ! Set solver parameters such as maximum order, number of iterations, ...
-   call setSolverParams(dt, ida_mem, retval)
-   if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in setSolverParams'; return; endif
-  
-   ! Disable error messages and warnings
-   if(offErrWarnMessage) then
-     retval = FIDASetErrFile(ida_mem, c_null_ptr)
-     retval = FIDASetNoInactiveRootWarn(ida_mem)
-   endif
-  
-   ! need the following values for the first substep
-   eqns_data%scalarCanopyTempTrial      = prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)
-   eqns_data%scalarCanopyIceTrial       = prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)
-   eqns_data%scalarCanopyEnthalpyTrial  = diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)
-   eqns_data%mLayerTempTrial(:)         = prog_data%var(iLookPROG%mLayerTemp)%dat(:)
-   eqns_data%mLayerMatricHeadLiqTrial(:)= diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat(:)
-   eqns_data%mLayerMatricHeadTrial(:)   = prog_data%var(iLookPROG%mLayerMatricHead)%dat(:)
-   eqns_data%mLayerVolFracWatTrial(:)   = prog_data%var(iLookPROG%mLayerVolFracWat)%dat(:)
-   eqns_data%mLayerVolFracIceTrial(:)   = prog_data%var(iLookPROG%mLayerVolFracIce)%dat(:)
-   eqns_data%mLayerEnthalpyTrial(:)     = diag_data%var(iLookDIAG%mLayerEnthalpy)%dat(:)
-   eqns_data%ixSaturation               = ixSaturation
-  
-   !**********************************************************************************
-   !****************************** Main Solver ***************************************
-   !************************* loop on one_step mode **********************************
-   !**********************************************************************************
-  
-   tret(1) = t0           ! intial time
-   do while(tret(1) < dt)
+
+  end select  ! form of matrix
+
+  ! Attach the matrix and linear solver
+  retval = FIDASetLinearSolver(ida_mem, sunlinsol_LS, sunmat_A);
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetLinearSolver'; return; endif
+
+  ! Set the user-supplied Jacobian routine
+  !comment this line out to use FD Jacobian
+  retval = FIDASetJacFn(ida_mem, c_funloc(evalJac4IDA))
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetJacFn'; return; endif
+
+  ! Create Newton SUNNonlinearSolver object
+  sunnonlin_NLS => FSUNNonlinSol_Newton(sunvec_y)
+  if (.not. associated(sunnonlin_NLS)) then; err=20; message='summaSolveSundialsIDA: sunnonlinsol = NULL'; return; endif
+
+  ! Attach the nonlinear solver
+  retval = FIDASetNonlinearSolver(ida_mem, sunnonlin_NLS)
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetNonlinearSolver'; return; endif
+
+  ! Enforce the solver to stop at end of the time step
+  retval = FIDASetStopTime(ida_mem, dt)
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in FIDASetStopTime'; return; endif
+
+  ! Set solver parameters such as maximum order, number of iterations, ...
+  call setSolverParams(dt, ida_mem, retval)
+  if (retval /= 0) then; err=20; message='summaSolveSundialsIDA: error in setSolverParams'; return; endif
+
+  ! Disable error messages and warnings
+  if(offErrWarnMessage) then
+    retval = FIDASetErrFile(ida_mem, c_null_ptr)
+    retval = FIDASetNoInactiveRootWarn(ida_mem)
+  endif
+
+  ! need the following values for the first substep
+  eqns_data%scalarCanopyTempPrev     = prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)
+  eqns_data%scalarCanopyIcePrev      = prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)
+  eqns_data%scalarCanopyLiqPrev      = prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)
+  eqns_data%mLayerVolFracWatPrev(:)  = prog_data%var(iLookPROG%mLayerVolFracWat)%dat(:)
+  eqns_data%mLayerTempPrev(:)        = prog_data%var(iLookPROG%mLayerTemp)%dat(:)
+  eqns_data%mLayerVolFracIcePrev(:)  = prog_data%var(iLookPROG%mLayerVolFracIce)%dat(:)
+  eqns_data%mLayerVolFracLiqPrev(:)  = prog_data%var(iLookPROG%mLayerVolFracLiq)%dat(:)
+  eqns_data%mLayerMatricHeadPrev(:)  = prog_data%var(iLookPROG%mLayerMatricHead)%dat(:)
+  eqns_data%scalarAquiferStoragePrev = prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)
+  eqns_data%mLayerEnthalpyPrev(:)    = diag_data%var(iLookDIAG%mLayerEnthalpy)%dat(:)
+  eqns_data%scalarCanopyEnthalpyPrev = diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)
+  mLayerMatricHeadLiqPrev(:)         = diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat(:)
+  eqns_data%ixSaturation             = ixSaturation
+
+  !**********************************************************************************
+  !****************************** Main Solver ***************************************
+  !************************* loop on one_step mode **********************************
+  !**********************************************************************************
+
+  tret(1) = t0           ! intial time
+  do while(tret(1) < dt)
     eqns_data%firstFluxCall = .false.
     eqns_data%firstSplitOper = .true.
     ! call IDASolve, advance solver just one internal step
     retvalr = FIDASolve(ida_mem, dt, tret, sunvec_y, sunvec_yp, IDA_ONE_STEP)
     if( retvalr < 0 )then
-     idaSucceeds = .false.
-     exit
+      idaSucceeds = .false.
+      exit
     endif
-  
+
     tooMuchMelt = .false.
     feasible = .true.
     ! loop through non-missing energy state variables in the snow domain to see if need to merge
     do concurrent (i=1:nSnow,indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat(i)/=integerMissing)
-     if (stateVec(indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat(i)) > Tfreeze) tooMuchMelt = .true. !need to merge
+      if (stateVec(indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat(i)) > Tfreeze) tooMuchMelt = .true. !need to merge
     enddo
     if(tooMuchMelt)exit
-  
+
     ! get the last stepsize
     retval = FIDAGetLastStep(ida_mem, dt_last)
-  
-    ! save previous step
-    mLayerMatricHeadLiqPrev(:)         = eqns_data%mLayerMatricHeadLiqTrial(:)
-  
+
     ! compute the flux and the residual vector for a given state vector
     call eval8summaSundials(&
-                   ! input: model control
-                   dt_last(1),                         & ! intent(in):    current stepsize
-                   eqns_data%dt,                       & ! intent(in):    total data step
-                   eqns_data%nSnow,                    & ! intent(in):    number of snow layers
-                   eqns_data%nSoil,                    & ! intent(in):    number of soil layers
-                   eqns_data%nLayers,                  & ! intent(in):    number of layers
-                   eqns_data%nState,                   & ! intent(in):    number of state variables in the current subset
-                   .false.,                            & ! intent(in):    outside Sundials solverå
-                   eqns_data%firstSubStep,             & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   eqns_data%firstFluxCall,            & ! intent(inout): flag to indicate if we are processing the first flux call
-                   eqns_data%firstSplitOper,           & ! intent(inout): flag to indicate if we are processing the first flux call in a splitting operation
-                   eqns_data%computeVegFlux,           & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   eqns_data%scalarSolution,           & ! intent(in):    flag to indicate the scalar solution
-                   ! input: state vectors
-                   stateVec,                           & ! intent(in):    model state vector
-                   stateVecPrime,                      & ! intent(in):    model state vector
-                   eqns_data%sMul,                     & ! intent(inout): state vector multiplier (used in the residual calculations)
-                   ! input: data structures
-                   model_decisions,                    & ! intent(in):    model decisions
-                   eqns_data%lookup_data,              & ! intent(in):    lookup data
-                   eqns_data%type_data,                & ! intent(in):    type of vegetation and soil
-                   eqns_data%attr_data,                & ! intent(in):    spatial attributes
-                   eqns_data%mpar_data,                & ! intent(in):    model parameters
-                   eqns_data%forc_data,                & ! intent(in):    model forcing data
-                   eqns_data%bvar_data,                & ! intent(in):    average model variables for the entire basin
-                   eqns_data%prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                   ! input-output: data structures
-                   eqns_data%indx_data,                & ! intent(inout): index data
-                   eqns_data%diag_data,                & ! intent(inout): model diagnostic variables for a local HRU
-                   eqns_data%flux_data,                & ! intent(inout): model fluxes for a local HRU (initial flux structure)
-                   eqns_data%deriv_data,               & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! input-output: here we need to pass some extra variables that do not get updated in in the Sundials loops
-                   eqns_data%scalarCanopyTempTrial,    & ! intent(inout): trial value of canopy temperature (K)
-                   eqns_data%scalarCanopyIceTrial,	 & ! intent(inout): trial value for mass of ice on the vegetation canopy (kg m-2)
-                   eqns_data%scalarCanopyEnthalpyTrial,& ! intent(inout): trial value for enthalpy of the vegetation canopy (J m-3)
-                   eqns_data%mLayerTempTrial,          & ! intent(inout): trial vector of layer temperature (K)
-                   eqns_data%mLayerMatricHeadTrial,    & ! intent(inout): trial value for total water matric potential (m)
-                   eqns_data%mLayerMatricHeadLiqTrial, & ! intent(inout):   trial value for liquid water matric potential (m)
-                   eqns_data%mLayerVolFracWatTrial,    & ! intent(inout): trial vector of volumetric total water content (-)
-                   eqns_data%mLayerVolFracIceTrial,    & ! intent(inout): trial vector of volumetric ice water content (-)
-                   eqns_data%mLayerEnthalpyTrial,      & ! intent(inout): trial vector of enthalpy for snow+soil layers (J m-3)
-                   ! input-output: baseflow
-                   eqns_data%ixSaturation,             & ! intent(inout): index of the lowest saturated layer
-                   eqns_data%dBaseflow_dMatric,        & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
-                   ! output: flux and residual vectors
-                   feasible,                           & ! intent(out):   flag to denote the feasibility of the solution
-                   eqns_data%fluxVec,                  & ! intent(out):   flux vector
-                   eqns_data%resSink,                  & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                   rVec,                               & ! intent(out):   residual vector
-                   eqns_data%err,eqns_data%message)      ! intent(out):   error control
-  
+                  ! input: model control
+                  dt_last(1),                         & ! intent(in):    current stepsize
+                  eqns_data%dt,                       & ! intent(in):    total data step
+                  eqns_data%nSnow,                    & ! intent(in):    number of snow layers
+                  eqns_data%nSoil,                    & ! intent(in):    number of soil layers
+                  eqns_data%nLayers,                  & ! intent(in):    number of layers
+                  eqns_data%nState,                   & ! intent(in):    number of state variables in the current subset
+                  .false.,                            & ! intent(in):    check for feasibility once outside Sundials loop
+                  eqns_data%firstSubStep,             & ! intent(in):    flag to indicate if we are processing the first sub-step
+                  eqns_data%firstFluxCall,            & ! intent(inout): flag to indicate if we are processing the first flux call
+                  eqns_data%firstSplitOper,           & ! intent(inout): flag to indicate if we are processing the first flux call in a splitting operation
+                  eqns_data%computeVegFlux,           & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                  eqns_data%scalarSolution,           & ! intent(in):    flag to indicate the scalar solution
+                  ! input: state vectors
+                  stateVec,                           & ! intent(in):    model state vector
+                  stateVecPrime,                      & ! intent(in):    model state vector
+                  eqns_data%sMul,                     & ! intent(inout): state vector multiplier (used in the residual calculations)
+                  ! input: data structures
+                  model_decisions,                    & ! intent(in):    model decisions
+                  eqns_data%lookup_data,              & ! intent(in):    lookup data
+                  eqns_data%type_data,                & ! intent(in):    type of vegetation and soil
+                  eqns_data%attr_data,                & ! intent(in):    spatial attributes
+                  eqns_data%mpar_data,                & ! intent(in):    model parameters
+                  eqns_data%forc_data,                & ! intent(in):    model forcing data
+                  eqns_data%bvar_data,                & ! intent(in):    average model variables for the entire basin
+                  eqns_data%prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                  ! input-output: data structures
+                  eqns_data%indx_data,                & ! intent(inout): index data
+                  eqns_data%diag_data,                & ! intent(inout): model diagnostic variables for a local HRU
+                  eqns_data%flux_data,                & ! intent(inout): model fluxes for a local HRU (initial flux structure)
+                  eqns_data%deriv_data,               & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                  ! input-output
+                  eqns_data%dBaseflow_dMatric,        & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1), we will use it later for Jacobian
+                  eqns_data%scalarCanopyTempTrial,    & ! intent(in):    trial value of canopy temperature (K)
+                  eqns_data%scalarCanopyTempPrev,     & ! intent(in):    previous value of canopy temperature (K)
+                  eqns_data%scalarCanopyIceTrial,     & ! intent(out):   trial value for mass of ice on the vegetation canopy (kg m-2)
+                  eqns_data%scalarCanopyIcePrev,      & ! intent(in):    value for mass of ice on the vegetation canopy (kg m-2)
+                  eqns_data%scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                  eqns_data%scalarCanopyLiqPrev,      & ! intent(in):    value of canopy liquid water (kg m-2)
+                  eqns_data%scalarCanopyEnthalpyTrial,& ! intent(out):  trial value for enthalpy of the vegetation canopy (J m-3)
+                  eqns_data%scalarCanopyEnthalpyPrev, & ! intent(in):   value for enthalpy of the vegetation canopy (J m-3)
+                  eqns_data%mLayerTempTrial,          & ! intent(out):  trial vector of layer temperature (K)
+                  eqns_data%mLayerTempPrev,           & ! intent(in):   vector of layer temperature (K)
+                  eqns_data%mLayerMatricHeadLiqTrial, & ! intent(out):  trial value for liquid water matric potential (m)
+                  eqns_data%mLayerMatricHeadTrial,    & ! intent(out):  trial value for total water matric potential (m)
+                  eqns_data%mLayerMatricHeadPrev,     & ! intent(in):   value for total water matric potential (m)
+                  eqns_data%mLayerVolFracWatTrial,    & ! intent(out):  trial vector of volumetric total water content (-)
+                  eqns_data%mLayerVolFracWatPrev,     & ! intent(in):   vector of volumetric total water content (-)
+                  eqns_data%mLayerVolFracIceTrial,    & ! intent(out):  trial vector of volumetric ice water content (-)
+                  eqns_data%mLayerVolFracIcePrev,     & ! intent(in):   vector of volumetric ice water content (-)
+                  eqns_data%mLayerVolFracLiqTrial,    & ! intent(out):  trial vector of volumetric liquid water content (-)
+                  eqns_data%mLayerVolFracLiqPrev,     & ! intent(in):   vector of volumetric liquid water content (-)
+                  eqns_data%scalarAquiferStorageTrial,& ! intent(out): trial value of storage of water in the aquifer (m)
+                  eqns_data%scalarAquiferStoragePrev, & ! intent(in):   value of storage of water in the aquifer (m)
+                  eqns_data%mLayerEnthalpyPrev,       & ! intent(in):   vector of enthalpy for snow+soil layers (J m-3)
+                  eqns_data%mLayerEnthalpyTrial,      & ! intent(out):  trial vector of enthalpy for snow+soil layers (J m-3)
+                  eqns_data%ixSaturation,             & ! intent(inout): index of the lowest saturated layer
+                  ! output
+                  feasible,                           & ! intent(out):   flag to denote the feasibility of the solution
+                  eqns_data%fluxVec,                  & ! intent(out):   flux vector
+                  eqns_data%resSink,                  & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                  rVec,                               & ! intent(out):   residual vector
+                  eqns_data%err,eqns_data%message)      ! intent(out):   error control
+
     ! sum of fluxes
     do iVar=1,size(flux_meta)
-     flux_sum%var(iVar)%dat(:) = flux_sum%var(iVar)%dat(:) + eqns_data%flux_data%var(iVar)%dat(:) *  dt_last(1)
+      flux_sum%var(iVar)%dat(:) = flux_sum%var(iVar)%dat(:) + eqns_data%flux_data%var(iVar)%dat(:) *  dt_last(1)
     end do
-  
-    ! do iVar=1,size(flux_meta)
-    !  flux_data%var(iVar)%dat(:) = ( flux_sum%var(iVar)%dat(:) ) /  tret(1)
-    ! end do
-  
+
     ! sum of mLayerCmpress
     mLayerCmpress_sum(:) = mLayerCmpress_sum(:) + eqns_data%deriv_data%var(iLookDERIV%dCompress_dPsi)%dat(:) &
-                                     * ( eqns_data%mLayerMatricHeadLiqTrial(:) - mLayerMatricHeadLiqPrev(:) )
-  
-   enddo ! while loop on one_step mode until time dt
-  
-   !****************************** End of Main Solver ***************************************
-  
-   err               = eqns_data%err
-   message           = eqns_data%message
-   if( .not. feasible) idaSucceeds = .false.
-  
-   if(idaSucceeds)then
+                                    * ( eqns_data%mLayerMatricHeadLiqTrial(:) - mLayerMatricHeadLiqPrev(:) )
+
+    ! save required quantities for next step
+    eqns_data%scalarCanopyTempPrev     = eqns_data%scalarCanopyTempTrial
+    eqns_data%scalarCanopyIcePrev      = eqns_data%scalarCanopyIceTrial
+    eqns_data%scalarCanopyLiqPrev      = eqns_data%scalarCanopyLiqTrial
+    eqns_data%mLayerTempPrev(:)        = eqns_data%mLayerTempTrial(:)
+    mLayerMatricHeadLiqPrev(:)         = eqns_data%mLayerMatricHeadLiqTrial(:)
+    eqns_data%mLayerMatricHeadPrev(:)  = eqns_data%mLayerMatricHeadTrial(:)
+    eqns_data%mLayerVolFracWatPrev(:)  = eqns_data%mLayerVolFracWatTrial(:)
+    eqns_data%mLayerVolFracIcePrev(:)  = eqns_data%mLayerVolFracIceTrial(:)
+    eqns_data%mLayerVolFracLiqPrev(:)  = eqns_data%mLayerVolFracLiqTrial(:)
+    eqns_data%scalarAquiferStoragePrev = eqns_data%scalarAquiferStorageTrial
+    eqns_data%mLayerEnthalpyPrev(:)    = eqns_data%mLayerEnthalpyTrial(:)
+    eqns_data%scalarCanopyEnthalpyPrev = eqns_data%scalarCanopyEnthalpyTrial
+
+  enddo ! while loop on one_step mode until time dt
+
+  !****************************** End of Main Solver ***************************************
+
+  err               = eqns_data%err
+  message           = eqns_data%message
+  if( .not. feasible) idaSucceeds = .false.
+
+  if(idaSucceeds)then
     ! copy to output data
     diag_data     = eqns_data%diag_data
     flux_data     = eqns_data%flux_data
     deriv_data    = eqns_data%deriv_data
     ixSaturation  = eqns_data%ixSaturation
     dt_out        = tret(1)
-   endif
-  
-   ! free memory
-   deallocate( eqns_data%sMul )
-   deallocate( eqns_data%dMat )
-   deallocate( eqns_data%dBaseflow_dMatric )
-   deallocate( eqns_data%mLayerTempTrial )
-   deallocate( eqns_data%mLayerMatricHeadLiqTrial )
-   deallocate( eqns_data%mLayerMatricHeadTrial )
-   deallocate( eqns_data%mLayerVolFracWatTrial )
-   deallocate( eqns_data%mLayerVolFracIceTrial )
-   deallocate( eqns_data%mLayerEnthalpyTrial )
-   deallocate( eqns_data%fluxVec )
-   deallocate( eqns_data%resSink )
-  
-   call FIDAFree(ida_mem)
-   retval = FSUNNonlinSolFree(sunnonlin_NLS)
-   retval = FSUNLinSolFree(sunlinsol_LS)
-   call FSUNMatDestroy(sunmat_A)
-   call FN_VDestroy(sunvec_y)
-   call FN_VDestroy(sunvec_yp)
-  
-   end subroutine summaSolveSundialsIDA
-  
-  ! ----------------------------------------------------------------
-  ! SetInitialCondition: routine to initialize u and up vectors.
-  ! ----------------------------------------------------------------
-   subroutine setInitialCondition(neq, y, sunvec_u, sunvec_up)
-  
-   !======= Inclusions ===========
-   USE, intrinsic :: iso_c_binding
-   USE fsundials_nvector_mod
-   USE fnvector_serial_mod
-  
-   !======= Declarations =========
-   implicit none
-  
-   ! calling variables
-   type(N_Vector)  :: sunvec_u  ! solution N_Vector
-   type(N_Vector)  :: sunvec_up ! derivative N_Vector
-   integer(c_long) :: neq
-   real(rkind)        :: y(neq)
-  
-   ! pointers to data in SUNDIALS vectors
-   real(c_double), pointer :: uu(:)
-   real(c_double), pointer :: up(:)
-  
-   ! get data arrays from SUNDIALS vectors
-   uu(1:neq) => FN_VGetArrayPointer(sunvec_u)
-   up(1:neq) => FN_VGetArrayPointer(sunvec_up)
-  
-   uu = y
-   up = 0._rkind
-  
-   end subroutine setInitialCondition
-  
-  ! ----------------------------------------------------------------
-  ! setSolverParams: private routine to set parameters in ida solver
-  ! ----------------------------------------------------------------
-   subroutine setSolverParams(dt,ida_mem,retval)
-  
-   !======= Inclusions ===========
-   USE, intrinsic :: iso_c_binding
-   USE fida_mod   ! Fortran interface to IDA
-  
-   !======= Declarations =========
-   implicit none
-  
-   ! calling variables
-   real(rkind),intent(in)      :: dt                 ! time step
-   type(c_ptr),intent(inout)   :: ida_mem            ! IDA memory
-   integer(i4b),intent(out)    :: retval             ! return value
-  
-   !======= Internals ============
-   real(qp),parameter          :: coef_nonlin = 0.33 ! Coeff. in the nonlinear convergence test, default = 0.33
-   integer,parameter           :: max_order = 1      ! maximum BDF order,  default = 5
-   integer,parameter           :: nonlin_iter = 100  ! maximun number of nonliear iterations, default = 4
-   integer,parameter           :: acurtest_fail = 50 ! maximum number of error test failures, default = 10
-   integer,parameter           :: convtest_fail = 50 ! maximum number of convergence test failures, default = 10
-   integer(kind = 8),parameter :: max_step = 999999  ! maximum number of steps,  dafault = 500
-   real(qp),parameter          :: h_init = 0         ! initial stepsize
-   real(qp)                    :: h_max              ! maximum stepsize,  dafault = infinity
-  
-   ! Set the maximum BDF order
-   retval = FIDASetMaxOrd(ida_mem, max_order)
-   if (retval /= 0) return
-  
-   ! Set Coeff. in the nonlinear convergence test
-   retval = FIDASetNonlinConvCoef(ida_mem, coef_nonlin)
-   if (retval /= 0) return
-  
-   ! Set maximun number of nonliear iterations
-   retval = FIDASetMaxNonlinIters(ida_mem, nonlin_iter)
-   if (retval /= 0) return
-  
-   !  Set maximum number of convergence test failures
-   retval = FIDASetMaxConvFails(ida_mem, convtest_fail)
-   if (retval /= 0) return
-  
-   !  Set maximum number of error test failures
-   retval = FIDASetMaxErrTestFails(ida_mem, acurtest_fail)
-   if (retval /= 0) return
-  
-   ! Set maximum number of steps
-   retval = FIDASetMaxNumSteps(ida_mem, max_step)
-   if (retval /= 0) return
-  
-   ! Set maximum stepsize
-   h_max = dt
-   retval = FIDASetMaxStep(ida_mem, h_max)
-   if (retval /= 0) return
-  
-   ! Set initial stepsize
-   retval = FIDASetInitStep(ida_mem, h_init)
-   if (retval /= 0) return
-  
-   ! scaling on 1 and off 0
-   ! retval = FIDASetLinearSolutionScaling(ida_mem, 0)
-   ! if (retval /= 0) return
-  
-   end subroutine setSolverParams
-  
-   ! *********************************************************************************************************
-   ! private subroutine implctMelt: compute melt of the "snow without a layer"
-   ! *********************************************************************************************************
-   subroutine implctMelt(&
-                         ! input/output: integrated snowpack properties
-                         scalarSWE,         & ! intent(inout): snow water equivalent (kg m-2)
-                         scalarSnowDepth,   & ! intent(inout): snow depth (m)
-                         scalarSfcMeltPond, & ! intent(inout): surface melt pond (kg m-2)
-                         ! input/output: properties of the upper-most soil layer
-                         soilTemp,          & ! intent(inout): surface layer temperature (K)
-                         soilDepth,         & ! intent(inout): surface layer depth (m)
-                         soilHeatcap,       & ! intent(inout): surface layer volumetric heat capacity (J m-3 K-1)
-                         ! output: error control
-                         err,message        ) ! intent(out): error control
-   implicit none
-   ! input/output: integrated snowpack properties
-   real(rkind),intent(inout)    :: scalarSWE          ! snow water equivalent (kg m-2)
-   real(rkind),intent(inout)    :: scalarSnowDepth    ! snow depth (m)
-   real(rkind),intent(inout)    :: scalarSfcMeltPond  ! surface melt pond (kg m-2)
-   ! input/output: properties of the upper-most soil layer
-   real(rkind),intent(inout)    :: soilTemp           ! surface layer temperature (K)
-   real(rkind),intent(inout)    :: soilDepth          ! surface layer depth (m)
-   real(rkind),intent(inout)    :: soilHeatcap        ! surface layer volumetric heat capacity (J m-3 K-1)
-   ! output: error control
-   integer(i4b),intent(out)  :: err                ! error code
-   character(*),intent(out)  :: message            ! error message
-   ! local variables
-   real(rkind)                  :: nrgRequired        ! energy required to melt all the snow (J m-2)
-   real(rkind)                  :: nrgAvailable       ! energy available to melt the snow (J m-2)
-   real(rkind)                  :: snwDensity         ! snow density (kg m-3)
-   ! initialize error control
-   err=0; message='implctMelt/'
-  
-   if(scalarSWE > 0._rkind)then
+  endif
+
+  ! free memory
+  deallocate( eqns_data%sMul )
+  deallocate( eqns_data%dMat )
+  deallocate( eqns_data%dBaseflow_dMatric )
+  deallocate( eqns_data%mLayerMatricHeadLiqTrial )
+  deallocate( eqns_data%mLayerMatricHeadTrial )
+  deallocate( eqns_data%mLayerMatricHeadPrev )
+  deallocate( eqns_data%fluxVec )
+  deallocate( eqns_data%resSink )
+  deallocate( eqns_data%mLayerVolFracWatTrial )
+  deallocate( eqns_data%mLayerVolFracWatPrev )
+  deallocate( eqns_data%mLayerVolFracIceTrial )
+  deallocate( eqns_data%mLayerTempPrev )
+  deallocate( eqns_data%mLayerTempTrial )
+  deallocate( eqns_data%mLayerVolFracIcePrev )
+  deallocate( eqns_data%mLayerVolFracLiqPrev )
+  deallocate( eqns_data%mLayerEnthalpyTrial )
+  deallocate( eqns_data%mLayerEnthalpyPrev )
+
+  call FIDAFree(ida_mem)
+  retval = FSUNNonlinSolFree(sunnonlin_NLS)
+  retval = FSUNLinSolFree(sunlinsol_LS)
+  call FSUNMatDestroy(sunmat_A)
+  call FN_VDestroy(sunvec_y)
+  call FN_VDestroy(sunvec_yp)
+
+end subroutine summaSolveSundialsIDA
+
+! ----------------------------------------------------------------
+! SetInitialCondition: routine to initialize u and up vectors.
+! ----------------------------------------------------------------
+subroutine setInitialCondition(neq, y, sunvec_u, sunvec_up)
+
+  !======= Inclusions ===========
+  USE, intrinsic :: iso_c_binding
+  USE fsundials_nvector_mod
+  USE fnvector_serial_mod
+
+  !======= Declarations =========
+  implicit none
+
+  ! calling variables
+  type(N_Vector)  :: sunvec_u  ! solution N_Vector
+  type(N_Vector)  :: sunvec_up ! derivative N_Vector
+  integer(c_long) :: neq
+  real(rkind)        :: y(neq)
+
+  ! pointers to data in SUNDIALS vectors
+  real(c_double), pointer :: uu(:)
+  real(c_double), pointer :: up(:)
+
+  ! get data arrays from SUNDIALS vectors
+  uu(1:neq) => FN_VGetArrayPointer(sunvec_u)
+  up(1:neq) => FN_VGetArrayPointer(sunvec_up)
+
+  uu = y
+  up = 0._rkind
+
+end subroutine setInitialCondition
+
+! ----------------------------------------------------------------
+! setSolverParams: private routine to set parameters in ida solver
+! ----------------------------------------------------------------
+subroutine setSolverParams(dt,ida_mem,retval)
+
+  !======= Inclusions ===========
+  USE, intrinsic :: iso_c_binding
+  USE fida_mod   ! Fortran interface to IDA
+
+  !======= Declarations =========
+  implicit none
+
+  ! calling variables
+  real(rkind),intent(in)      :: dt                 ! time step
+  type(c_ptr),intent(inout)   :: ida_mem            ! IDA memory
+  integer(i4b),intent(out)    :: retval             ! return value
+
+  !======= Internals ============
+  real(qp),parameter          :: coef_nonlin = 0.33 ! Coeff. in the nonlinear convergence test, default = 0.33
+  integer,parameter           :: max_order = 1      ! maximum BDF order,  default = 5
+  integer,parameter           :: nonlin_iter = 100  ! maximun number of nonliear iterations, default = 4
+  integer,parameter           :: acurtest_fail = 50 ! maximum number of error test failures, default = 10
+  integer,parameter           :: convtest_fail = 50 ! maximum number of convergence test failures, default = 10
+  integer(kind = 8),parameter :: max_step = 999999  ! maximum number of steps,  dafault = 500
+  real(qp),parameter          :: h_init = 0         ! initial stepsize
+  real(qp)                    :: h_max              ! maximum stepsize,  dafault = infinity
+
+  ! Set the maximum BDF order
+  retval = FIDASetMaxOrd(ida_mem, max_order)
+  if (retval /= 0) return
+
+  ! Set Coeff. in the nonlinear convergence test
+  retval = FIDASetNonlinConvCoef(ida_mem, coef_nonlin)
+  if (retval /= 0) return
+
+  ! Set maximun number of nonliear iterations
+  retval = FIDASetMaxNonlinIters(ida_mem, nonlin_iter)
+  if (retval /= 0) return
+
+  !  Set maximum number of convergence test failures
+  retval = FIDASetMaxConvFails(ida_mem, convtest_fail)
+  if (retval /= 0) return
+
+  !  Set maximum number of error test failures
+  retval = FIDASetMaxErrTestFails(ida_mem, acurtest_fail)
+  if (retval /= 0) return
+
+  ! Set maximum number of steps
+  retval = FIDASetMaxNumSteps(ida_mem, max_step)
+  if (retval /= 0) return
+
+  ! Set maximum stepsize
+  h_max = dt
+  retval = FIDASetMaxStep(ida_mem, h_max)
+  if (retval /= 0) return
+
+  ! Set initial stepsize
+  retval = FIDASetInitStep(ida_mem, h_init)
+  if (retval /= 0) return
+
+end subroutine setSolverParams
+
+! *********************************************************************************************************
+! private subroutine implctMelt: compute melt of the "snow without a layer"
+! *********************************************************************************************************
+subroutine implctMelt(&
+                      ! input/output: integrated snowpack properties
+                      scalarSWE,         & ! intent(inout): snow water equivalent (kg m-2)
+                      scalarSnowDepth,   & ! intent(inout): snow depth (m)
+                      scalarSfcMeltPond, & ! intent(inout): surface melt pond (kg m-2)
+                      ! input/output: properties of the upper-most soil layer
+                      soilTemp,          & ! intent(inout): surface layer temperature (K)
+                      soilDepth,         & ! intent(inout): surface layer depth (m)
+                      soilHeatcap,       & ! intent(inout): surface layer volumetric heat capacity (J m-3 K-1)
+                      ! output: error control
+                      err,message        ) ! intent(out): error control
+  implicit none
+  ! input/output: integrated snowpack properties
+  real(rkind),intent(inout)    :: scalarSWE          ! snow water equivalent (kg m-2)
+  real(rkind),intent(inout)    :: scalarSnowDepth    ! snow depth (m)
+  real(rkind),intent(inout)    :: scalarSfcMeltPond  ! surface melt pond (kg m-2)
+  ! input/output: properties of the upper-most soil layer
+  real(rkind),intent(inout)    :: soilTemp           ! surface layer temperature (K)
+  real(rkind),intent(inout)    :: soilDepth          ! surface layer depth (m)
+  real(rkind),intent(inout)    :: soilHeatcap        ! surface layer volumetric heat capacity (J m-3 K-1)
+  ! output: error control
+  integer(i4b),intent(out)  :: err                ! error code
+  character(*),intent(out)  :: message            ! error message
+  ! local variables
+  real(rkind)                  :: nrgRequired        ! energy required to melt all the snow (J m-2)
+  real(rkind)                  :: nrgAvailable       ! energy available to melt the snow (J m-2)
+  real(rkind)                  :: snwDensity         ! snow density (kg m-3)
+  ! initialize error control
+  err=0; message='implctMelt/'
+
+  if(scalarSWE > 0._rkind)then
     ! only melt if temperature of the top soil layer is greater than Tfreeze
     if(soilTemp > Tfreeze)then
-     ! compute the energy required to melt all the snow (J m-2)
-     nrgRequired     = scalarSWE*LH_fus
-     ! compute the energy available to melt the snow (J m-2)
-     nrgAvailable    = soilHeatcap*(soilTemp - Tfreeze)*soilDepth
-     ! compute the snow density (not saved)
-     snwDensity      = scalarSWE/scalarSnowDepth
-     ! compute the amount of melt, and update SWE (kg m-2)
-     if(nrgAvailable > nrgRequired)then
-      scalarSfcMeltPond  = scalarSWE
-      scalarSWE          = 0._rkind
-     else
-      scalarSfcMeltPond  = nrgAvailable/LH_fus
-      scalarSWE          = scalarSWE - scalarSfcMeltPond
-     end if
-     ! update depth
-     scalarSnowDepth = scalarSWE/snwDensity
-     ! update temperature of the top soil layer (K)
-     soilTemp =  soilTemp - (LH_fus*scalarSfcMeltPond/soilDepth)/soilHeatcap
+      ! compute the energy required to melt all the snow (J m-2)
+      nrgRequired     = scalarSWE*LH_fus
+      ! compute the energy available to melt the snow (J m-2)
+      nrgAvailable    = soilHeatcap*(soilTemp - Tfreeze)*soilDepth
+      ! compute the snow density (not saved)
+      snwDensity      = scalarSWE/scalarSnowDepth
+      ! compute the amount of melt, and update SWE (kg m-2)
+      if(nrgAvailable > nrgRequired)then
+        scalarSfcMeltPond  = scalarSWE
+        scalarSWE          = 0._rkind
+      else
+        scalarSfcMeltPond  = nrgAvailable/LH_fus
+        scalarSWE          = scalarSWE - scalarSfcMeltPond
+      end if
+      ! update depth
+      scalarSnowDepth = scalarSWE/snwDensity
+      ! update temperature of the top soil layer (K)
+      soilTemp =  soilTemp - (LH_fus*scalarSfcMeltPond/soilDepth)/soilHeatcap
     else  ! melt is zero if the temperature of the top soil layer is less than Tfreeze
-     scalarSfcMeltPond = 0._rkind  ! kg m-2
+      scalarSfcMeltPond = 0._rkind  ! kg m-2
     end if ! (if the temperature of the top soil layer is greater than Tfreeze)
-   else  ! melt is zero if the "snow without a layer" does not exist
+  else  ! melt is zero if the "snow without a layer" does not exist
     scalarSfcMeltPond = 0._rkind  ! kg m-2
-   end if ! (if the "snow without a layer" exists)
-  
-   end subroutine implctMelt
-  
-  end module summaSolveSundialsIDA_module
+  end if ! (if the "snow without a layer" exists)
+
+end subroutine implctMelt
+
+end module summaSolveSundialsIDA_module
   
\ No newline at end of file
diff --git a/build/source/engine/sundials/systemSolvSundials.f90 b/build/source/engine/sundials/systemSolvSundials.f90
index 308f741..100cc56 100644
--- a/build/source/engine/sundials/systemSolvSundials.f90
+++ b/build/source/engine/sundials/systemSolvSundials.f90
@@ -2,561 +2,537 @@
 
 module systemSolvSundials_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_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
-  
-  ! global metadata
-  USE globalData,only:flux_meta                        ! metadata on the model fluxes
-  
-  ! constants
-  USE multiconst,only:&
-                      LH_fus,       & ! latent heat of fusion                (J K-1)
-                      Tfreeze,      & ! temperature at freezing              (K)
-                      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: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
-  USE var_lookup,only:iLookDERIV      ! named variables for structure elements
-  
-  ! 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_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
-  
-  
-  ! 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_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
+
+! global metadata
+USE globalData,only:flux_meta                        ! metadata on the model fluxes
+
+! constants
+USE multiconst,only:&
+                    LH_fus,       & ! latent heat of fusion                (J K-1)
+                    Tfreeze,      & ! temperature at freezing              (K)
+                    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: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
+USE var_lookup,only:iLookDERIV      ! named variables for structure elements
+
+! 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_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
+
+
+! safety: set private unless specified otherwise
+implicit none
+private
+public::systemSolvSundials
+
+! 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 systemSolvSundials: run the coupled energy-mass model for one timestep
+! **********************************************************************************************************
+subroutine systemSolvSundials(&
+                      ! input: model control
+                      dt,                & ! intent(in):    time step (s)
+                      nState,            & ! intent(in):    total number of state variables
+                      firstSubStep,      & ! intent(in):    flag to denote first sub-step
+                      firstFluxCall,     & ! intent(inout): flag to indicate if we are processing the first flux call
+                      firstSplitOper,    & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                      computeVegFlux,    & ! intent(in):    flag to denote if computing energy flux over vegetation
+                      scalarSolution,    & ! intent(in):    flag to denote if implementing the scalar solution
+                      ! input/output: data structures
+                      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_temp,         & ! intent(inout): model fluxes for a local HRU
+                      bvar_data,         & ! intent(in):    model variables for the local basin
+                      model_decisions,   & ! intent(in):    model decisions
+                      stateVecInit,      & ! intent(in):    initial state vector
+                      ! output
+                      deriv_data,        & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                      ixSaturation,      & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                      stateVecTrial,     & ! intent(out):   updated state vector
+                      stateVecPrime,     & ! intent(out):   updated state vector
+                      reduceCoupledStep, & ! intent(out):   flag to reduce the length of the coupled step
+                      tooMuchMelt,       & ! intent(out):   flag to denote that there was too much melt
+                      dt_out,			  & ! intent(out)
+                      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 eval8summa_module,only:eval8summa               ! simulation of fluxes and residuals given a trial state vector
+  USE eval8summaSundials_module,only:eval8summaSundials
+  USE getVectorz_module,only:getScaling                ! get the scaling vectors
+  USE convE2Temp_module,only:temp2ethpy                ! convert temperature to enthalpy
+  USE tol4IDA_module,only:popTol4IDA                   ! pop tolerances
+  USE summaSolveSundialsIDA_module,only:summaSolveSundialsIDA                ! solve DAE by IDA
+  USE t2enthalpy_module, only:t2enthalpy_T             ! compute enthalpy
+  use, intrinsic :: iso_c_binding
   implicit none
-  private
-  public::systemSolvSundials
-  
-  ! 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 systemSolvSundials: run the coupled energy-mass model for one timestep
-   ! **********************************************************************************************************
-   subroutine systemSolvSundials(&
-                         ! input: model control
-                         dt,                & ! intent(in):    time step (s)
-                         nState,            & ! intent(in):    total number of state variables
-                         firstSubStep,      & ! intent(in):    flag to denote first sub-step
-                         firstFluxCall,     & ! intent(inout): flag to indicate if we are processing the first flux call
-                         firstSplitOper,    & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
-                         computeVegFlux,    & ! intent(in):    flag to denote if computing energy flux over vegetation
-                         scalarSolution,    & ! intent(in):    flag to denote if implementing the scalar solution
-                         ! input/output: data structures
-                         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_temp,         & ! intent(inout): model fluxes for a local HRU
-                         bvar_data,         & ! intent(in):    model variables for the local basin
-                         model_decisions,   & ! intent(in):    model decisions
-                         stateVecInit,      & ! intent(in):    initial state vector
-                         ! output
-                         deriv_data,        & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                         ixSaturation,      & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                         stateVecTrial,     & ! intent(out):   updated state vector
-                         stateVecPrime,     & ! intent(out):   updated state vector
-                         reduceCoupledStep, & ! intent(out):   flag to reduce the length of the coupled step
-                         tooMuchMelt,       & ! intent(out):   flag to denote that there was too much melt
-                         dt_out,			  & ! intent(out)
-                         err,message)         ! intent(out):   error code and error message
-   ! ---------------------------------------------------------------------------------------
-   ! structure allocations
-   USE allocspace4chm_module,only:allocLocal                ! allocate local data structures
-   ! simulation of fluxes and residuals given a trial state vector
-   USE eval8summaSundials_module,only:eval8summaSundials ! simulation of fluxes and residuals given a trial state vector
-   USE getVectorz_module,only:getScaling                ! get the scaling vectors
-   USE convE2Temp_module,only:temp2ethpy                ! convert temperature to enthalpy
-   USE tol4IDA_module,only:popTol4IDA                   ! pop tolerances
-   USE summaSolveSundialsIDA_module,only:summaSolveSundialsIDA                ! solve DAE by IDA
-   USE t2enthalpy_module, only:t2enthalpy_T             ! compute enthalpy
-   use, intrinsic :: iso_c_binding
-   implicit none
-   ! ---------------------------------------------------------------------------------------
-   ! * dummy variables
-   ! ---------------------------------------------------------------------------------------
-   ! input: model control
-   real(rkind),intent(in)          :: dt                            ! time step (seconds)
-   integer(i4b),intent(in)         :: nState                        ! total number of state variables
-   logical(lgt),intent(in)         :: firstSubStep                  ! flag to indicate if we are processing the first sub-step
-   logical(lgt),intent(inout)      :: firstFluxCall                 ! flag to define the first flux call
-   logical(lgt),intent(inout)      :: firstSplitOper                ! flag to indicate if we are processing the first flux call in a splitting operation
-   logical(lgt),intent(in)         :: computeVegFlux                ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
-   logical(lgt),intent(in)         :: scalarSolution                ! flag to denote if implementing the scalar solution
-   ! input/output: data structures
-   type(zLookup),intent(in)        :: lookup_data                   ! lookup tables
-   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_temp                     ! model fluxes for a local HRU
-   type(var_dlength),intent(in)    :: bvar_data                     ! model variables for the local basin
-   type(model_options),intent(in)  :: model_decisions(:)            ! model decisions
-   real(rkind),intent(in)          :: stateVecInit(:)               ! initial state vector (mixed units)
-   ! output: model control
-   type(var_dlength),intent(inout) :: deriv_data                    ! derivatives in model fluxes w.r.t. relevant state variables
-   integer(i4b),intent(inout)      :: ixSaturation                  ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
-   real(rkind),intent(out)         :: stateVecTrial(:)              ! trial state vector (mixed units)
-   real(rkind),intent(out)         :: stateVecPrime(:)              ! trial state vector (mixed units)
-   logical(lgt),intent(out)        :: reduceCoupledStep             ! flag to reduce the length of the coupled step
-   logical(lgt),intent(out)        :: tooMuchMelt                   ! flag to denote that there was too much melt
-   real(qp),intent(out)  			 :: dt_out                        ! time step
-   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)                    :: iVar                          ! index of variable
-   integer(i4b)                    :: local_ixGroundwater           ! local index for groundwater representation
-   real(rkind)                     :: bulkDensity                   ! bulk density of a given layer (kg m-3)
-   real(rkind)                     :: volEnthalpy                   ! volumetric enthalpy of a given layer (J m-3)
-   real(rkind),parameter           :: tempAccelerate=0.00_rkind        ! factor to force initial canopy temperatures to be close to air temperature
-   real(rkind),parameter           :: xMinCanopyWater=0.0001_rkind     ! minimum value to initialize canopy water (kg m-2)
-   real(rkind),parameter           :: tinyStep=0.000001_rkind          ! stupidly small time step (s)
-   ! ------------------------------------------------------------------------------------------------------
-   ! * model solver
-   ! ------------------------------------------------------------------------------------------------------
-   logical(lgt),parameter          :: forceFullMatrix=.true.        ! flag to force the use of the full Jacobian matrix
-   integer(i4b)                    :: ixMatrix                      ! form of matrix (band diagonal or full matrix)
-   type(var_dlength)               :: flux_init                     ! model fluxes at the start of the time step
-   real(rkind),allocatable         :: dBaseflow_dMatric(:,:)        ! derivative in baseflow w.r.t. matric head (s-1)  ! NOTE: allocatable, since not always needed
-   real(rkind)                     :: stateVecNew(nState)           ! new state vector (mixed units)
-   real(rkind)                     :: fluxVec0(nState)              ! flux vector (mixed units)
-   real(rkind)                     :: fScale(nState)                ! characteristic scale of the function evaluations (mixed units)
-   real(rkind)                     :: xScale(nState)                ! characteristic scale of the state vector (mixed units)
-   real(rkind)                     :: dMat(nState)                  ! diagonal matrix (excludes flux derivatives)
-   real(qp)                        :: sMul(nState)    ! NOTE: qp    ! multiplier for state vector for the residual calculations
-   real(qp)                        :: rVec(nState)    ! NOTE: qp    ! residual vector
-   real(rkind)                     :: rAdd(nState)                  ! additional terms in the residual vector
-   logical(lgt)                    :: feasible                      ! feasibility flag
-   real(rkind)                     :: atol(nState)     		 	  ! absolute telerance
-   real(rkind)                     :: rtol(nState)     		      ! relative tolerance
-   integer(i4b)                    :: iLayer                        ! index of model layer in the snow+soil domain
-   real(rkind)                     :: xMin,xMax                     ! minimum and maximum values for water content
-   real(rkind),parameter           :: canopyTempMax=500._rkind      ! expected maximum value for the canopy temperature (K)
-   type(var_dlength)               :: flux_sum	   	              ! sum of fluxes model fluxes for a local HRU over a data step
-   integer(i4b) 					 :: tol_iter			          ! iteration index
-   real(rkind), allocatable        :: mLayerCmpress_sum(:)		  ! sum of compression of the soil matrix
-   logical(lgt)					 :: idaSucceeds		   		      ! flag to indicate if ida successfully solved the problem in current data step
-  
-   ! ---------------------------------------------------------------------------------------
-   ! 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)
-    ! enthalpy
-   scalarCanairEnthalpy    => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the canopy air space (J m-3)
-   scalarCanopyEnthalpy    => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the vegetation canopy (J m-3)
-   mLayerEnthalpy          => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(out): [dp(:)] enthalpy of the snow+soil layers (J m-3)
-   ! soil parameters
-   theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
-   theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
-   ! model state variables
-   scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in): [dp]     temperature of the canopy air space (K)
-   scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in): [dp]     temperature of the vegetation canopy (K)
-   scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(in): [dp]     mass of ice on the vegetation canopy (kg m-2)
-   scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in): [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(in): [dp(:)]  temperature of each snow/soil layer (K)
-   mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of ice (-)
-   mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of liquid water (-)
-   mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of total water (-)
-   mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat       ,& ! intent(in): [dp(:)]  liquid water matric potential (m)
-   mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
-   ! check the need to merge snow layers
-   mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
-   snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,& ! intent(in):    [dp]     scaling parameter for the snow freezing curve (K-1)
-   ! accelerate solution for temperature
-   airtemp                 => forc_data%var(iLookFORCE%airtemp)                      ,& ! intent(in):    [dp]     temperature of the upper boundary of the snow and soil domains (K)
-   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)
-   ! vector of energy and hydrology indices for the snow and soil domains
-   ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,& ! intent(in):    [i4b(:)] indices for energy states in the snow subdomain
-   ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):    [i4b(:)] indices for hydrology states in the snow+soil subdomain
-   ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):    [i4b(:)] indices for energy states in the snow+soil subdomain
-   ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,& ! intent(in):    [i4b(:)] index of the type of hydrology states in snow+soil domain
-   layerType               => indx_data%var(iLookINDEX%layerType)%dat                ,& ! intent(in):    [i4b(:)] layer type (iname_soil or iname_snow)
-   ! layer geometry
-   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
-   )
-   ! ---------------------------------------------------------------------------------------
-   ! initialize error control
-   err=0; message="systemSolvSundials/"
-  
-   ! *****
-   ! (0) PRELIMINARIES...
-   ! ********************
-  
-   ! -----
-   ! * initialize...
-   ! ---------------
-  
-   ! check
-   if(dt < tinyStep)then
-    message=trim(message)//'dt is tiny'
-    err=20; return
-   endif
-  
-   ! initialize the flags
-   tooMuchMelt        = .false.   ! too much melt
-   reduceCoupledStep  = .false.   ! need to reduce the length of the coupled step
-  
-   ! modify the groundwater representation for this single-column implementation
-   select case(ixSpatialGroundwater)
-    case(singleBasin); local_ixGroundwater = noExplicit    ! force no explicit representation of groundwater at the local scale
-    case(localColumn); local_ixGroundwater = ixGroundwater ! go with the specified decision
-    case default; err=20; message=trim(message)//'unable to identify spatial representation of groundwater'; return
-   end select ! (modify the groundwater representation for this single-column implementation)
-  
-   ! allocate space for the model fluxes at the start of the time step
-   call allocLocal(flux_meta(:),flux_init,nSnow,nSoil,err,cmessage)
-   if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-   ! allocate space for the baseflow derivatives
-   ! NOTE: needs allocation because only used when baseflow sinks are active
-   if(ixGroundwater==qbaseTopmodel)then
-    allocate(dBaseflow_dMatric(nSoil,nSoil),stat=err)  ! baseflow depends on total storage in the soil column, hence on matric head in every soil layer
-   else
-    allocate(dBaseflow_dMatric(0,0),stat=err)          ! allocate zero-length dimnensions to avoid passing around an unallocated matrix
-   end if
-   if(err/=0)then; err=20; message=trim(message)//'unable to allocate space for the baseflow derivatives'; return; end if
-  
-  
-   ! identify the matrix solution method
-   ! (the type of matrix used to solve the linear system A.X=B)
-   if(local_ixGroundwater==qbaseTopmodel .or. scalarSolution .or. forceFullMatrix)then
-    ixMatrix=ixFullMatrix   ! named variable to denote the full Jacobian matrix
-   else
-    ixMatrix=ixBandMatrix   ! named variable to denote the band-diagonal matrix
-   endif
-  
-   ! initialize the model fluxes (some model fluxes are not computed in the iterations)
-   do iVar=1,size(flux_temp%var)
-    flux_init%var(iVar)%dat(:) = flux_temp%var(iVar)%dat(:)
-   end do
-  
-   ! -----
-   ! * get scaling vectors...
-   ! ------------------------
-  
-   ! initialize state vectors
-   call getScaling(&
-                   ! input
-                   diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
-                   indx_data,                        & ! intent(in):    indices defining model states and layers
-                   ! output
-                   fScale,                           & ! intent(out):   function scaling vector (mixed units)
-                   xScale,                           & ! intent(out):   variable scaling vector (mixed units)
-                   sMul,                             & ! intent(out):   multiplier for state vector (used in the residual calculations)
-                   dMat,                             & ! intent(out):   diagonal of the Jacobian matrix (excludes fluxes)
-                   err,cmessage)                       ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-  
-   ! initialize the trial state vectors
-   stateVecTrial = stateVecInit
-  
-   ! need to intialize canopy water at a positive value
-   if(ixVegHyd/=integerMissing)then
-    if(stateVecTrial(ixVegHyd) < xMinCanopyWater) stateVecTrial(ixVegHyd) = stateVecTrial(ixVegHyd) + xMinCanopyWater
-   endif
-  
-   ! try to accelerate solution for energy
-   if(ixCasNrg/=integerMissing) stateVecTrial(ixCasNrg) = stateVecInit(ixCasNrg) + (airtemp - stateVecInit(ixCasNrg))*tempAccelerate
-   if(ixVegNrg/=integerMissing) stateVecTrial(ixVegNrg) = stateVecInit(ixVegNrg) + (airtemp - stateVecInit(ixVegNrg))*tempAccelerate
-  
-   ! compute H_T at the beginning of the data step
-   call t2enthalpy_T(&
-                  ! input: data structures
-                  diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
-                  mpar_data,                   & ! intent(in):  parameter data structure
-                  indx_data,                   & ! intent(in):  model indices
-                  lookup_data,                 & ! intent(in):  lookup table data structure
-                  ! input: state variables for the vegetation canopy
-                  scalarCanairTemp,            & ! intent(in):  value of canopy air temperature (K)
-                  scalarCanopyTemp,            & ! intent(in):  value of canopy temperature (K)
-                  scalarCanopyWat,             & ! intent(in):  value of canopy total water (kg m-2)
-                  scalarCanopyIce,             & ! intent(in):  value for canopy ice content (kg m-2)
-                  ! input: variables for the snow-soil domain
-                  mLayerTemp,                  & ! intent(in):  vector of layer temperature (K)
-                  mLayerVolFracWat,            & ! intent(in):  vector of volumetric total water content (-)
-                  mLayerMatricHead,            & ! intent(in):  vector of total water matric potential (m)
-                  mLayerVolFracIce,            & ! intent(in):  vector of volumetric fraction of ice (-)
-                  ! output: enthalpy
-                  scalarCanairEnthalpy,        & ! intent(out): temperature component of enthalpy of the canopy air space (J m-3)
-                  scalarCanopyEnthalpy,        & ! intent(out): temperature component of enthalpy of the vegetation canopy (J m-3)
-                  mLayerEnthalpy,              & ! intent(out): temperature component of enthalpy of each snow+soil layer (J m-3)
-                  ! output: error control
-                  err,cmessage)                  ! intent(out): error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
-  
-   ! compute the flux and the residual vector for a given state vector
-   ! NOTE 1: The derivatives computed in eval8summaSundials are used to calculate the Jacobian matrix for the first iteration
-   ! NOTE 2: The Jacobian matrix together with the residual vector is used to calculate the first iteration increment
-   call eval8summaSundials(&
-                   ! input: model control
-                   dt,                      & ! intent(in):    current stepsize
-                   dt,                      & ! intent(in):    length of the time step (seconds)
-                   nSnow,                   & ! intent(in):    number of snow layers
-                   nSoil,                   & ! intent(in):    number of soil layers
-                   nLayers,                 & ! intent(in):    number of layers
-                   nState,                  & ! intent(in):    number of state variables in the current subset
-                   .false.,                 & ! intent(in):    outside Sundials solver loop
-                   firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
-                   firstSplitOper,          & ! intent(inout): flag to indicate if we are processing the first flux call in a splitting operation
-                   computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                   ! input: state vectors
-                   stateVecTrial,           & ! intent(in):    model state vector
-                   fScale,                  & ! intent(in):    function scaling vector
-                   sMul,                    & ! intent(inout): state vector multiplier (used in the residual calculations)
-                   ! input: 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
-                   mpar_data,               & ! intent(in):    model parameters
-                   forc_data,               & ! intent(in):    model forcing data
-                   bvar_data,               & ! intent(in):    average model variables for the entire basin
-                   prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                   ! input-output: data structures
-                   indx_data,               & ! intent(inout): index data
-                   diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
-                   flux_init,               & ! intent(inout): model fluxes for a local HRU (initial flux structure)
-                   deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! input-output: here we need to pass some extra variables that do not get updated in in the Sundials loops
-                   scalarCanopyTemp,        & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyIce,	      & ! intent(inout): trial value for mass of ice on the vegetation canopy (kg m-2)
-                   scalarCanopyEnthalpy,    & ! intent(inout): trial value for enthalpy of the vegetation canopy (J m-3)
-                   mLayerTemp,              & ! intent(inout): trial vector of layer temperature (K)
-                   mLayerMatricHead,        & ! intent(inout): trial value for total water matric potential (m)
-                   mLayerMatricHeadLiq,     & ! intent(inout):   trial value for liquid water matric potential (m)
-                   mLayerVolFracWat,        & ! intent(inout): trial vector of volumetric total water content (-)
-                   mLayerVolFracIce,        & ! intent(inout): trial vector of volumetric ice water content (-)
-                   mLayerEnthalpy,          & ! intent(inout): trial vector of enthalpy for snow+soil layers (J m-3)
-                   ! input-output: baseflow
-                   ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                   dBaseflow_dMatric,       & ! intent(out):    derivative in baseflow w.r.t. matric head (s-1)
-                   ! output: flux and residual vectors
-                   feasible,                & ! intent(out):   flag to denote the feasibility of the solution
-                   fluxVec0,                & ! intent(out):   flux vector
-                   rAdd,                    & ! intent(out):   additional (sink) terms on the RHS of the state equation
-                   rVec,                    & ! intent(out):   residual vector
-                   err,cmessage)              ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-   if(.not.feasible)then; message=trim(message)//'state vector not feasible'; err=20; return; endif
-  
-   ! copy over the initial flux structure since some model fluxes are not computed in the iterations
-   do concurrent ( iVar=1:size(flux_meta) )
-    flux_temp%var(iVar)%dat(:) = flux_init%var(iVar)%dat(:)
-   end do
-  
-   ! allocate space for the temporary flux_sum structure
-   call allocLocal(flux_meta(:),flux_sum,nSnow,nSoil,err,cmessage)
-   if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-   ! allocate space for mLayerCmpress_sum
-   allocate( mLayerCmpress_sum(nSoil) )
-  
-   ! check the need to merge snow layers
-   if(nSnow>0)then
-    ! compute the energy required to melt the top snow layer (J m-2)
-    bulkDensity = mLayerVolFracIce(1)*iden_ice + mLayerVolFracLiq(1)*iden_water
-    volEnthalpy = temp2ethpy(mLayerTemp(1),bulkDensity,snowfrz_scale)
-    ! set flag and error codes for too much melt
-    if(-volEnthalpy < flux_init%var(iLookFLUX%mLayerNrgFlux)%dat(1)*dt)then
-     tooMuchMelt=.true.
-     message=trim(message)//'net flux in the top snow layer can melt all the snow in the top layer'
-     err=-20; return ! negative error code to denote a warning
+  ! ---------------------------------------------------------------------------------------
+  ! * dummy variables
+  ! ---------------------------------------------------------------------------------------
+  ! input: model control
+  real(rkind),intent(in)          :: dt                            ! time step (seconds)
+  integer(i4b),intent(in)         :: nState                        ! total number of state variables
+  logical(lgt),intent(in)         :: firstSubStep                  ! flag to indicate if we are processing the first sub-step
+  logical(lgt),intent(inout)      :: firstFluxCall                 ! flag to define the first flux call
+  logical(lgt),intent(in)         :: firstSplitOper                ! flag to indicate if we are processing the first flux call in a splitting operation
+  logical(lgt),intent(in)         :: computeVegFlux                ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
+  logical(lgt),intent(in)         :: scalarSolution                ! flag to denote if implementing the scalar solution
+  ! input/output: data structures
+  type(zLookup),intent(in)        :: lookup_data                   ! lookup tables
+  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_temp                     ! model fluxes for a local HRU
+  type(var_dlength),intent(in)    :: bvar_data                     ! model variables for the local basin
+  type(model_options),intent(in)  :: model_decisions(:)            ! model decisions
+  real(rkind),intent(in)          :: stateVecInit(:)               ! initial state vector (mixed units)
+  ! output: model control
+  type(var_dlength),intent(inout) :: deriv_data                    ! derivatives in model fluxes w.r.t. relevant state variables
+  integer(i4b),intent(inout)      :: ixSaturation                  ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
+  real(rkind),intent(out)         :: stateVecTrial(:)              ! trial state vector (mixed units)
+  real(rkind),intent(out)         :: stateVecPrime(:)              ! trial state vector (mixed units)
+  logical(lgt),intent(out)        :: reduceCoupledStep             ! flag to reduce the length of the coupled step
+  logical(lgt),intent(out)        :: tooMuchMelt                   ! flag to denote that there was too much melt
+  real(qp),intent(out)  			 :: dt_out                        ! time step
+  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)                    :: iVar                          ! index of variable
+  integer(i4b)                    :: local_ixGroundwater           ! local index for groundwater representation
+  real(rkind)                     :: bulkDensity                   ! bulk density of a given layer (kg m-3)
+  real(rkind)                     :: volEnthalpy                   ! volumetric enthalpy of a given layer (J m-3)
+  real(rkind),parameter           :: tempAccelerate=0.00_rkind        ! factor to force initial canopy temperatures to be close to air temperature
+  real(rkind),parameter           :: xMinCanopyWater=0.0001_rkind     ! minimum value to initialize canopy water (kg m-2)
+  real(rkind),parameter           :: tinyStep=0.000001_rkind          ! stupidly small time step (s)
+
+  ! ------------------------------------------------------------------------------------------------------
+  ! * model solver
+  ! ------------------------------------------------------------------------------------------------------
+  logical(lgt),parameter          :: forceFullMatrix=.true.        ! flag to force the use of the full Jacobian matrix
+  integer(i4b)                    :: ixMatrix                      ! form of matrix (band diagonal or full matrix)
+  type(var_dlength)               :: flux_init                     ! model fluxes at the start of the time step
+  real(rkind),allocatable         :: dBaseflow_dMatric(:,:)        ! derivative in baseflow w.r.t. matric head (s-1)  ! NOTE: allocatable, since not always needed
+  real(rkind)                     :: stateVecNew(nState)           ! new state vector (mixed units)
+  real(rkind)                     :: fluxVec0(nState)              ! flux vector (mixed units)
+  real(rkind)                     :: fScale(nState)                ! characteristic scale of the function evaluations (mixed units)
+  real(rkind)                     :: xScale(nState)                ! characteristic scale of the state vector (mixed units)
+  real(rkind)                     :: dMat(nState)                  ! diagonal matrix (excludes flux derivatives)
+  real(qp)                        :: sMul(nState)    ! NOTE: qp    ! multiplier for state vector for the residual calculations
+  real(qp)                        :: rVec(nState)    ! NOTE: qp    ! residual vector
+  real(rkind)                     :: rAdd(nState)                  ! additional terms in the residual vector
+  real(rkind)                     :: fOld                          ! function values (-); NOTE: dimensionless because scaled
+  logical(lgt)                    :: feasible                      ! feasibility flag
+  real(rkind)                     :: atol(nState)     		 	  ! absolute telerance
+  real(rkind)                     :: rtol(nState)     		      ! relative tolerance
+  integer(i4b)                    :: iLayer                        ! index of model layer in the snow+soil domain
+  real(rkind)                     :: xMin,xMax                     ! minimum and maximum values for water content
+  real(rkind),parameter           :: canopyTempMax=500._rkind      ! expected maximum value for the canopy temperature (K)
+  type(var_dlength)               :: flux_sum	   	              ! sum of fluxes model fluxes for a local HRU over a data step
+  integer(i4b) 					          :: tol_iter			          ! iteration index
+  real(rkind), allocatable        :: mLayerCmpress_sum(:)		  ! sum of compression of the soil matrix
+  logical(lgt)					          :: idaSucceeds		   		      ! flag to indicate if ida successfully solved the problem in current data step
+
+
+  ! ---------------------------------------------------------------------------------------
+  ! 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)
+      ! enthalpy
+    scalarCanairEnthalpy    => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the canopy air space (J m-3)
+    scalarCanopyEnthalpy    => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(out): [dp]    enthalpy of the vegetation canopy (J m-3)
+    mLayerEnthalpy          => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(out): [dp(:)] enthalpy of the snow+soil layers (J m-3)
+    ! soil parameters
+    theta_sat               => mpar_data%var(iLookPARAM%theta_sat)%dat                ,&  ! intent(in):  [dp(:)] soil porosity (-)
+    theta_res               => mpar_data%var(iLookPARAM%theta_res)%dat                ,&  ! intent(in):  [dp(:)] residual volumetric water content (-)
+    ! model state variables
+    scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(in): [dp]     temperature of the canopy air space (K)
+    scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(in): [dp]     temperature of the vegetation canopy (K)
+    scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(in): [dp]     mass of ice on the vegetation canopy (kg m-2)
+    scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(in): [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(in): [dp(:)]  temperature of each snow/soil layer (K)
+    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of ice (-)
+    mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of liquid water (-)
+    mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(in): [dp(:)]  volumetric fraction of total water (-)
+    mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
+    mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
+    snowfrz_scale           => mpar_data%var(iLookPARAM%snowfrz_scale)%dat(1)         ,& ! intent(in):    [dp]     scaling parameter for the snow freezing curve (K-1)
+    airtemp                 => forc_data%var(iLookFORCE%airtemp)                      ,& ! intent(in):    [dp]     temperature of the upper boundary of the snow and soil domains (K)
+    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
+    ixSnowOnlyNrg           => indx_data%var(iLookINDEX%ixSnowOnlyNrg)%dat            ,& ! intent(in):    [i4b(:)] indices for energy states in the snow subdomain
+    ixSnowSoilHyd           => indx_data%var(iLookINDEX%ixSnowSoilHyd)%dat            ,& ! intent(in):    [i4b(:)] indices for hydrology states in the snow+soil subdomain
+    ixSnowSoilNrg           => indx_data%var(iLookINDEX%ixSnowSoilNrg)%dat            ,& ! intent(in):    [i4b(:)] indices for energy states in the snow+soil subdomain
+    ixHydType               => indx_data%var(iLookINDEX%ixHydType)%dat                ,& ! intent(in):    [i4b(:)] index of the type of hydrology states in snow+soil domain
+    layerType               => indx_data%var(iLookINDEX%layerType)%dat                ,& ! intent(in):    [i4b(:)] layer type (iname_soil or iname_snow)
+    ixVegHyd                => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)              ,& ! intent(in):    [i4b]    index of canopy hydrology state variable (mass)
+    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
+    )
+    ! ---------------------------------------------------------------------------------------
+    ! initialize error control
+    err=0; message="systemSolvSundials/"
+
+    ! *****
+    ! (0) PRELIMINARIES...
+    ! ********************
+
+    ! -----
+    ! * initialize...
+    ! ---------------
+
+    ! check
+    if(dt < tinyStep)then
+      message=trim(message)//'dt is tiny'
+      err=20; return
+    endif
+
+    ! initialize the flags
+    tooMuchMelt        = .false.   ! too much melt
+    reduceCoupledStep  = .false.   ! need to reduce the length of the coupled step
+
+
+    ! modify the groundwater representation for this single-column implementation
+    select case(ixSpatialGroundwater)
+      case(singleBasin); local_ixGroundwater = noExplicit    ! force no explicit representation of groundwater at the local scale
+      case(localColumn); local_ixGroundwater = ixGroundwater ! go with the specified decision
+      case default; err=20; message=trim(message)//'unable to identify spatial representation of groundwater'; return
+    end select ! (modify the groundwater representation for this single-column implementation)
+
+    ! allocate space for the model fluxes at the start of the time step
+    call allocLocal(flux_meta(:),flux_init,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for the baseflow derivatives
+    ! NOTE: needs allocation because only used when baseflow sinks are active
+    if(ixGroundwater==qbaseTopmodel)then
+      allocate(dBaseflow_dMatric(nSoil,nSoil),stat=err)  ! baseflow depends on total storage in the soil column, hence on matric head in every soil layer
+    else
+      allocate(dBaseflow_dMatric(0,0),stat=err)          ! allocate zero-length dimnensions to avoid passing around an unallocated matrix
+    end if
+    if(err/=0)then; err=20; message=trim(message)//'unable to allocate space for the baseflow derivatives'; return; end if
+
+
+    ! identify the matrix solution method
+    ! (the type of matrix used to solve the linear system A.X=B)
+    if(local_ixGroundwater==qbaseTopmodel .or. scalarSolution .or. forceFullMatrix)then
+      ixMatrix=ixFullMatrix   ! named variable to denote the full Jacobian matrix
+    else
+      ixMatrix=ixBandMatrix   ! named variable to denote the band-diagonal matrix
     endif
-   endif
-  
-   ! get tolerance vectors
-   call popTol4IDA(&
+
+    ! initialize the model fluxes (some model fluxes are not computed in the iterations)
+    do iVar=1,size(flux_temp%var)
+      flux_init%var(iVar)%dat(:) = flux_temp%var(iVar)%dat(:)
+    end do
+
+    ! -----
+    ! * get scaling vectors...
+    ! ------------------------
+
+    ! initialize state vectors
+    call getScaling(&
                     ! input
-                    nState,                           & ! intent(in):    number of desired state variables
-                    prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
                     diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
                     indx_data,                        & ! intent(in):    indices defining model states and layers
-                    mpar_data,                        & ! intent(in):	  model parameters
                     ! output
-                    atol,                             & ! intent(out):   absolute tolerances vector (mixed units)
-                    rtol,                             & ! intent(out):	  relative tolerances vector (mixed units)
+                    fScale,                           & ! intent(out):   function scaling vector (mixed units)
+                    xScale,                           & ! intent(out):   variable scaling vector (mixed units)
+                    sMul,                             & ! intent(out):   multiplier for state vector (used in the residual calculations)
+                    dMat,                             & ! intent(out):   diagonal of the Jacobian matrix (excludes fluxes)
                     err,cmessage)                       ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-  
-   !-------------------
-   ! * solving F(y,y') = 0 by IDA. Here, y is the state vector
-   ! ------------------
-  
-   !do tol_iter=1,3
-  
-     ! initialize flux_sum
-      do concurrent ( iVar=1:size(flux_meta) )
-        flux_sum%var(iVar)%dat(:) = 0._rkind
-      end do
-  
-      ! initialize sum of compression of the soil matrix
-      mLayerCmpress_sum(:) = 0._rkind
-  
-     call summaSolveSundialsIDA(&
-                   dt,                      & ! intent (in) 	 data time step
-                   atol,                    & ! intent (in) 	 absolute telerance
-                   rtol,                    & ! intent (in) 	 relative tolerance
-                   nSnow,                   & ! intent(in):    number of snow layers
-                   nSoil,                   & ! intent(in):    number of soil layers
-                   nLayers,                 & ! intent(in):    number of snow+soil layers
-                   nState,                  & ! intent(in):    number of state variables in the current subset
-                   ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
-                   firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
-                   computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
-                   scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
-                   ! input: state vector
-                   stateVecTrial,           & ! intent(in):    model state vector at the beginning of the data time step
-                   sMul,                    & ! intent(inout): state vector multiplier (used in the residual calculations)
-                   dMat,                    & ! intent(inout)  diagonal of the Jacobian matrix (excludes fluxes)
-                   ! input: data structures
-                   lookup_data,             & ! intent(in):    lookup tables
-                   type_data,               & ! intent(in):    type of vegetation and soil
-                   attr_data,               & ! intent(in):    spatial attributes
-                   mpar_data,               & ! intent(in):    model parameters
-                   forc_data,               & ! intent(in):    model forcing data
-                   bvar_data,               & ! intent(in):    average model variables for the entire basin
-                   prog_data,               & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,               & ! intent(in):    index data
-                   ! input-output: data structures
-                   diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
-                   flux_init,               & ! intent(inout): model fluxes for a local HRU (initial flux structure)
-                   flux_temp,               & ! intent(inout): model fluxes for a local HRU
-                   flux_sum,                & ! intent(inout): sum of fluxes model fluxes for a local HRU over a data step
-                   deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! output
-                   ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                   idaSucceeds,			  & ! intent(out):   flag to indicate if ida successfully solved the problem in current data step
-                   tooMuchMelt,		      & ! intent(inout):   flag to denote that there was too much melt
-                   mLayerCmpress_sum,       & ! intent(out):	 sum of compression of the soil matrix
-                   dt_out,				          & ! intent(out):   time step
-                   stateVecNew,             & ! intent(out):   model state vector (y) at the end of the data time step
-                   stateVecPrime,           & ! intent(out):   derivative of model state vector (y') at the end of the data time step
-                   err,cmessage)              ! intent(out):   error control
-  
-   !if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-   !  if (idaSucceeds)then
-   !     exit
-   !  else
-   !     atol = atol * 0.1
-   !     rtol = rtol * 0.1
-   !  endif
-   !  if( .not.idaSucceeds .and. tol_iter==3) message=trim(message)//'IDA did not succeed after reducing tolerance by 2 magnitudes'
-  
-   !end do  ! iteration over tolerances
-  
-    ! check if IDA is successful
-   if( .not.idaSucceeds )then
-    err = 20
-    message=trim(message)//trim(cmessage)
-  ! reduceCoupledStep  = .true.
-    return
-   else
-    if (tooMuchMelt) return !exit to start same step over after merge
-   endif
-  
-   ! compute average flux
-   do iVar=1,size(flux_meta)
-    flux_temp%var(iVar)%dat(:) = ( flux_sum%var(iVar)%dat(:) ) /  dt_out
-   end do
-  
-   ! compute the total change in storage associated with compression of the soil matrix (kg m-2)
-   diag_data%var(iLookDIAG%mLayerCompress)%dat(:) = mLayerCmpress_sum(:)
-   diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sum(diag_data%var(iLookDIAG%mLayerCompress)%dat(1:nSoil)*mLayerDepth(nSnow+1:nLayers))*iden_water
-  
-   ! save the computed solution
-   stateVecTrial = stateVecNew
-  
-   ! free memory
-   deallocate(mLayerCmpress_sum)
-   deallocate(dBaseflow_dMatric)
-  
-   ! end associate statements
-   end associate globalVars
-  
-   end subroutine systemSolvSundials
-  
-  end module systemSolvSundials_module
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+
+    ! initialize the trial state vectors
+    stateVecTrial = stateVecInit
+
+    ! need to intialize canopy water at a positive value
+    if(ixVegHyd/=integerMissing)then
+      if(stateVecTrial(ixVegHyd) < xMinCanopyWater) stateVecTrial(ixVegHyd) = stateVecTrial(ixVegHyd) + xMinCanopyWater
+    endif
+
+    ! try to accelerate solution for energy
+    if(ixCasNrg/=integerMissing) stateVecTrial(ixCasNrg) = stateVecInit(ixCasNrg) + (airtemp - stateVecInit(ixCasNrg))*tempAccelerate
+    if(ixVegNrg/=integerMissing) stateVecTrial(ixVegNrg) = stateVecInit(ixVegNrg) + (airtemp - stateVecInit(ixVegNrg))*tempAccelerate
+
+    ! compute H_T at the beginning of the data step
+    call t2enthalpy_T(&
+                    ! input: data structures
+                    diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
+                    mpar_data,                   & ! intent(in):  parameter data structure
+                    indx_data,                   & ! intent(in):  model indices
+                    lookup_data,                 & ! intent(in):  lookup table data structure
+                    ! input: state variables for the vegetation canopy
+                    scalarCanairTemp,            & ! intent(in):  value of canopy air temperature (K)
+                    scalarCanopyTemp,            & ! intent(in):  value of canopy temperature (K)
+                    scalarCanopyWat,             & ! intent(in):  value of canopy total water (kg m-2)
+                    scalarCanopyIce,             & ! intent(in):  value for canopy ice content (kg m-2)
+                    ! input: variables for the snow-soil domain
+                    mLayerTemp,                  & ! intent(in):  vector of layer temperature (K)
+                    mLayerVolFracWat,            & ! intent(in):  vector of volumetric total water content (-)
+                    mLayerMatricHead,            & ! intent(in):  vector of total water matric potential (m)
+                    mLayerVolFracIce,            & ! intent(in):  vector of volumetric fraction of ice (-)
+                    ! output: enthalpy
+                    scalarCanairEnthalpy,        & ! intent(out): temperature component of enthalpy of the canopy air space (J m-3)
+                    scalarCanopyEnthalpy,        & ! intent(out): temperature component of enthalpy of the vegetation canopy (J m-3)
+                    mLayerEnthalpy,              & ! intent(out): temperature component of enthalpy of each snow+soil layer (J m-3)
+                    ! output: error control
+                    err,cmessage)                  ! intent(out): error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
+
+    ! compute the flux and the residual vector for a given state vector
+    ! NOTE 1: The derivatives computed in eval8summa are used to calculate the Jacobian matrix for the first iteration
+    ! NOTE 2: The Jacobian matrix together with the residual vector is used to calculate the first iteration increment
+
+    call eval8summa(&
+                    ! input: model control
+                    dt,                      & ! intent(in):    length of the time step (seconds)
+                    nSnow,                   & ! intent(in):    number of snow layers
+                    nSoil,                   & ! intent(in):    number of soil layers
+                    nLayers,                 & ! intent(in):    number of layers
+                    nState,                  & ! intent(in):    number of state variables in the current subset
+                    firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                    firstFluxCall,           & ! intent(inout): flag to indicate if we are processing the first flux call
+                    firstSplitOper,          & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                    computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                    scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                    ! input: state vectors
+                    stateVecTrial,           & ! intent(in):    model state vector
+                    fScale,                  & ! intent(in):    function scaling vector
+                    sMul,                    & ! intent(in):    state vector multiplier (used in the residual calculations)
+                    ! input: 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
+                    mpar_data,               & ! intent(in):    model parameters
+                    forc_data,               & ! intent(in):    model forcing data
+                    bvar_data,               & ! intent(in):    average model variables for the entire basin
+                    prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,               & ! intent(in):    index data
+                    ! input-output: data structures
+                    diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                    flux_init,               & ! intent(inout): model fluxes for a local HRU (initial flux structure)
+                    deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                    ! input-output: baseflow
+                    ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                    dBaseflow_dMatric,       & ! intent(out):   derivative in baseflow w.r.t. matric head (s-1)
+                    ! output
+                    feasible,                & ! intent(out):   flag to denote the feasibility of the solution
+                    fluxVec0,                & ! intent(out):   flux vector
+                    rAdd,                    & ! intent(out):   additional (sink) terms on the RHS of the state equation
+                    rVec,                    & ! intent(out):   residual vector
+                    fOld,                    & ! intent(out):   function evaluation
+                    err,cmessage)              ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+    if(.not.feasible)then; message=trim(message)//'state vector not feasible'; err=20; return; endif
+
+    ! copy over the initial flux structure since some model fluxes are not computed in the iterations
+    do concurrent ( iVar=1:size(flux_meta) )
+      flux_temp%var(iVar)%dat(:) = flux_init%var(iVar)%dat(:)
+    end do
+
+    ! allocate space for the temporary flux_sum structure
+    call allocLocal(flux_meta(:),flux_sum,nSnow,nSoil,err,cmessage)
+    if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+
+    ! allocate space for mLayerCmpress_sum
+    allocate( mLayerCmpress_sum(nSoil) )
+
+    ! check the need to merge snow layers
+    if(nSnow>0)then
+      ! compute the energy required to melt the top snow layer (J m-2)
+      bulkDensity = mLayerVolFracIce(1)*iden_ice + mLayerVolFracLiq(1)*iden_water
+      volEnthalpy = temp2ethpy(mLayerTemp(1),bulkDensity,snowfrz_scale)
+      ! set flag and error codes for too much melt
+      if(-volEnthalpy < flux_init%var(iLookFLUX%mLayerNrgFlux)%dat(1)*dt)then
+        tooMuchMelt=.true.
+        message=trim(message)//'net flux in the top snow layer can melt all the snow in the top layer'
+        err=-20; return ! negative error code to denote a warning
+      endif
+    endif
+
+    ! get tolerance vectors
+    call popTol4IDA(&
+                      ! input
+                      nState,                           & ! intent(in):    number of desired state variables
+                      prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
+                      diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
+                      indx_data,                        & ! intent(in):    indices defining model states and layers
+                      mpar_data,                        & ! intent(in):	  model parameters
+                      ! output
+                      atol,                             & ! intent(out):   absolute tolerances vector (mixed units)
+                      rtol,                             & ! intent(out):	  relative tolerances vector (mixed units)
+                      err,cmessage)                       ! intent(out):   error control
+    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+
+    !-------------------
+    ! * solving F(y,y') = 0 by IDA. Here, y is the state vector
+    ! ------------------
+    ! initialize flux_sum
+    do concurrent ( iVar=1:size(flux_meta) )
+      flux_sum%var(iVar)%dat(:) = 0._rkind
+    end do
+
+    ! initialize sum of compression of the soil matrix
+    mLayerCmpress_sum(:) = 0._rkind
+
+    call summaSolveSundialsIDA(&
+                  dt,                      & ! intent (in) 	 data time step
+                  atol,                    & ! intent (in) 	 absolute telerance
+                  rtol,                    & ! intent (in) 	 relative tolerance
+                  nSnow,                   & ! intent(in):    number of snow layers
+                  nSoil,                   & ! intent(in):    number of soil layers
+                  nLayers,                 & ! intent(in):    number of snow+soil layers
+                  nState,                  & ! intent(in):    number of state variables in the current subset
+                  ixMatrix,                & ! intent(in):    type of matrix (dense or banded)
+                  firstSubStep,            & ! intent(in):    flag to indicate if we are processing the first sub-step
+                  computeVegFlux,          & ! intent(in):    flag to indicate if we need to compute fluxes over vegetation
+                  scalarSolution,          & ! intent(in):    flag to indicate the scalar solution
+                  ! input: state vector
+                  stateVecTrial,           & ! intent(in):    model state vector at the beginning of the data time step
+                  sMul,                    & ! intent(inout): state vector multiplier (used in the residual calculations)
+                  dMat,                    & ! intent(inout)  diagonal of the Jacobian matrix (excludes fluxes)
+                  ! input: data structures
+                  lookup_data,             & ! intent(in):    lookup tables
+                  type_data,               & ! intent(in):    type of vegetation and soil
+                  attr_data,               & ! intent(in):    spatial attributes
+                  mpar_data,               & ! intent(in):    model parameters
+                  forc_data,               & ! intent(in):    model forcing data
+                  bvar_data,               & ! intent(in):    average model variables for the entire basin
+                  prog_data,               & ! intent(in):    model prognostic variables for a local HRU
+                  indx_data,               & ! intent(in):    index data
+                  ! input-output: data structures
+                  diag_data,               & ! intent(inout): model diagnostic variables for a local HRU
+                  flux_init,               & ! intent(inout): model fluxes for a local HRU (initial flux structure)
+                  flux_temp,               & ! intent(inout): model fluxes for a local HRU
+                  flux_sum,                & ! intent(inout): sum of fluxes model fluxes for a local HRU over a data step
+                  deriv_data,              & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                  ! output
+                  ixSaturation,            & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                  idaSucceeds,			  & ! intent(out):   flag to indicate if ida successfully solved the problem in current data step
+                  tooMuchMelt,		      & ! intent(inout):   flag to denote that there was too much melt
+                  mLayerCmpress_sum,       & ! intent(out):	 sum of compression of the soil matrix
+                  dt_out,				          & ! intent(out):   time step
+                  stateVecNew,             & ! intent(out):   model state vector (y) at the end of the data time step
+                  stateVecPrime,           & ! intent(out):   derivative of model state vector (y') at the end of the data time step
+                  err,cmessage)              ! intent(out):   error control
+
+      ! check if IDA is successful
+    if( .not.idaSucceeds )then
+      err = 20
+      message=trim(message)//trim(cmessage)
+    ! reduceCoupledStep  = .true.
+      return
+    else
+      if (tooMuchMelt) return !exit to start same step over after merge
+    endif
+
+    ! compute average flux
+    do iVar=1,size(flux_meta)
+      flux_temp%var(iVar)%dat(:) = ( flux_sum%var(iVar)%dat(:) ) /  dt_out
+    end do
+
+    diag_data%var(iLookDIAG%mLayerCompress)%dat(:) = mLayerCmpress_sum(:)
+
+    ! compute the total change in storage associated with compression of the soil matrix (kg m-2)
+    diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sum(diag_data%var(iLookDIAG%mLayerCompress)%dat(1:nSoil)*mLayerDepth(nSnow+1:nLayers))*iden_water
+
+    ! save the computed solution
+    stateVecTrial = stateVecNew
+
+    ! free memory
+    deallocate(mLayerCmpress_sum)
+    deallocate(dBaseflow_dMatric)
+
+  ! end associate statements
+  end associate globalVars
+
+end subroutine systemSolvSundials
+
+end module systemSolvSundials_module
   
\ No newline at end of file
diff --git a/build/source/engine/sundials/varSubstepSundials.f90 b/build/source/engine/sundials/varSubstepSundials.f90
index 3da718e..93921b0 100644
--- a/build/source/engine/sundials/varSubstepSundials.f90
+++ b/build/source/engine/sundials/varSubstepSundials.f90
@@ -84,723 +84,712 @@ module varSubstepSundials_module
   contains
   
   
-   ! **********************************************************************************************************
-   ! public subroutine varSubstepSundials: run the model for a collection of substeps for a given state subset
-   ! **********************************************************************************************************
-   subroutine 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)
-                         nState,            & ! intent(in)    : total number of state variables
-                         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
-                         scalarSolution,    & ! intent(in)    : flag to denote implementing the scalar solution
-                         iStateSplit,       & ! intent(in)    : index of the state in the splitting operation
-                         fluxMask,          & ! intent(in)    : mask for the fluxes used in this given state subset
-                         fluxCount,         & ! intent(inout) : number of times that fluxes are updated (should equal nSubsteps)
-                         ! 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: model 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 to denote success of substepping for a given split
-                         reduceCoupledStep, & ! intent(out)   : flag to denote need 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,message)         ! intent(out)   : error code and error message
-   ! ---------------------------------------------------------------------------------------
-   ! structure allocations
-   USE allocspace4chm_module,only:allocLocal               ! allocate local data structures
-   ! simulation of fluxes and residuals given a trial state vector
-   USE systemSolv_module,only:systemSolv                 ! solve the system of equations for one time step
-   USE getVectorz_module,only:popStateVec                ! populate the state vector
-   USE updateVarsSundials_module,only:updateVarsSundials ! update prognostic variables
-   USE getVectorzAddSundials_module,only:varExtractSundials
-   ! identify name of variable type (for error message)
-   USE get_ixName_module,only:get_varTypeName           ! to access type strings for error messages
-   USE systemSolvSundials_module,only:systemSolvSundials
-   implicit none
-   ! ---------------------------------------------------------------------------------------
-   ! * dummy variables
-   ! ---------------------------------------------------------------------------------------
-   ! input: model control
-   real(rkind),intent(in)             :: dt                            ! time step (seconds)
-   real(rkind),intent(in)             :: dtInit                        ! initial time step (seconds)
-   real(rkind),intent(in)             :: dt_min                        ! minimum time step (seconds)
-   integer(i4b),intent(in)         :: nState                        ! total number of state variables
-   logical(lgt),intent(in)         :: doAdjustTemp                  ! flag to indicate if we adjust the temperature
-   logical(lgt),intent(in)         :: firstSubStep                  ! flag to indicate if we are processing the first sub-step
-   logical(lgt),intent(inout)      :: firstFluxCall                 ! flag to define the first flux call
-   logical(lgt),intent(in)         :: computeVegFlux                ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
-   logical(lgt),intent(in)         :: scalarSolution                ! flag to denote implementing the scalar solution
-   integer(i4b),intent(in)         :: iStateSplit                   ! index of the state in the splitting operation
-   type(var_flagVec),intent(in)    :: fluxMask                      ! flags to denote if the flux is calculated in the given state subset
-   type(var_ilength),intent(inout) :: fluxCount                     ! number of times that the flux is updated (should equal nSubsteps)
-   ! input/output: data structures
-   type(model_options),intent(in)  :: model_decisions(:)            ! model decisions
-   type(zLookup),intent(in)        :: lookup_data                   ! lookup tables
-   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(inout) :: deriv_data                    ! derivatives in model fluxes w.r.t. relevant state variables
-   type(var_dlength),intent(in)    :: bvar_data                     ! model variables for the local basin
-   ! output: model control
-   integer(i4b),intent(inout)      :: ixSaturation                  ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
-   real(rkind),intent(out)            :: dtMultiplier                  ! substep multiplier (-)
-   integer(i4b),intent(out)        :: nSubsteps                     ! number of substeps taken for a given split
-   logical(lgt),intent(out)        :: failedMinimumStep             ! flag to denote success of substepping for a given split
-   logical(lgt),intent(out)        :: reduceCoupledStep             ! flag to denote need to reduce the length of the coupled step
-   logical(lgt),intent(out)        :: tooMuchMelt                   ! flag to denote that ice is insufficient to support melt
-   real(qp),intent(out)   		 :: dt_out
-   integer(i4b),intent(out)        :: err                           ! error code
-   character(*),intent(out)        :: message                       ! error message
-   ! ---------------------------------------------------------------------------------------
-   ! * general local variables
-   ! ---------------------------------------------------------------------------------------
-   ! error control
-   character(LEN=256)              :: cmessage                      ! error message of downwind routine
-   ! general local variables
-   integer(i4b)                    :: iVar                          ! index of variables in data structures
-   integer(i4b)                    :: iSoil                         ! index of soil layers
-   integer(i4b)                    :: ixLayer                       ! index in a given domain
-   integer(i4b), dimension(1)      :: ixMin,ixMax                   ! bounds of a given flux vector
-   ! time stepping
-   real(rkind)                        :: dtSum                         ! sum of time from successful steps (seconds)
-   real(rkind)                        :: dt_wght                       ! weight given to a given flux calculation
-   real(rkind)                        :: dtSubstep                     ! length of a substep (s)
-   ! adaptive sub-stepping for the explicit solution
-   logical(lgt)                    :: failedSubstep                 ! flag to denote success of substepping for a given split
-   real(rkind),parameter              :: safety=0.85_rkind                ! safety factor in adaptive sub-stepping
-   real(rkind),parameter              :: reduceMin=0.1_rkind              ! mimimum factor that time step is reduced
-   real(rkind),parameter              :: increaseMax=4.0_rkind            ! maximum factor that time step is increased
-   ! adaptive sub-stepping for the implicit solution
-   integer(i4b),parameter          :: n_inc=5                       ! minimum number of iterations to increase time step
-   integer(i4b),parameter          :: n_dec=15                      ! maximum number of iterations to decrease time step
-   real(rkind),parameter              :: F_inc = 1.25_rkind               ! factor used to increase time step
-   real(rkind),parameter              :: F_dec = 0.90_rkind               ! factor used to decrease time step
-   ! state and flux vectors
-   real(rkind)                        :: untappedMelt(nState)          ! un-tapped melt energy (J m-3 s-1)
-   real(rkind)                        :: stateVecInit(nState)          ! initial state vector (mixed units)
-   real(rkind)                        :: stateVecTrial(nState)         ! trial state vector (mixed units)
-   real(rkind)                        :: stateVecPrime(nState)         ! trial state vector (mixed units)
-   type(var_dlength)               :: flux_temp                     ! temporary model fluxes
-   ! flags
-   logical(lgt)                    :: firstSplitOper                ! flag to indicate if we are processing the first flux call in a splitting operation
-   logical(lgt)                    :: checkMassBalance              ! flag to check the mass balance
-   logical(lgt)                    :: checkNrgBalance
-   logical(lgt)                    :: waterBalanceError             ! flag to denote that there is a water balance error
-   logical(lgt)                    :: nrgFluxModified               ! flag to denote that the energy fluxes were modified
-   ! energy fluxes
-   real(rkind)                        :: sumCanopyEvaporation          ! sum of canopy evaporation/condensation (kg m-2 s-1)
-   real(rkind)                        :: sumLatHeatCanopyEvap          ! sum of latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   real(rkind)                        :: sumSenHeatCanopy              ! sum of sensible heat flux from the canopy to the canopy air space (W m-2)
-   real(rkind)                        :: sumSoilCompress
-   real(rkind),allocatable            :: sumLayerCompress(:)
-   ! ---------------------------------------------------------------------------------------
-   ! point to variables in the data structures
-   ! ---------------------------------------------------------------------------------------
-   globalVars: associate(&
-   ! 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
-   nSoilOnlyHyd            => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology variables in the soil domain
-   mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
-   ! mapping between state vectors and control volumes
-   ixLayerActive           => indx_data%var(iLookINDEX%ixLayerActive)%dat            ,& ! intent(in):    [i4b(:)] list of indices for all active layers (inactive=integerMissing)
-   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)
-   ! model state variables (vegetation canopy)
-   scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the canopy air space (K)
-   scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the vegetation canopy (K)
-   scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(inout): [dp]     mass of ice on the vegetation canopy (kg m-2)
-   scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(inout): [dp]     mass of liquid water on the vegetation canopy (kg m-2)
-   scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(inout): [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(inout): [dp(:)]  temperature of each snow/soil layer (K)
-   mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of ice (-)
-   mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of liquid water (-)
-   mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of total water (-)
-   mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
-   mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(inout): [dp(:)]  matric potential of liquid water (m)
-   )  ! end association with variables in the data structures
-   ! *********************************************************************************************************************************************************
-   ! *********************************************************************************************************************************************************
-   ! Procedure starts here
-  
-   ! initialize error control
-   err=0; message='varSubstepSundials/'
-  
-   ! initialize flag for the success of the substepping
-   failedMinimumStep=.false.
-  
-   ! initialize the length of the substep
-   dtSubstep = dtInit
-  
-   ! allocate space for the temporary model flux structure
-   call allocLocal(flux_meta(:),flux_temp,nSnow,nSoil,err,cmessage)
-   if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
-  
-   ! initialize the model fluxes (some model fluxes are not computed in the iterations)
-   do iVar=1,size(flux_data%var)
-    flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
-   end do
-  
-   ! initialize the total energy fluxes (modified in updateProgSundials)
-   sumCanopyEvaporation = 0._rkind  ! canopy evaporation/condensation (kg m-2 s-1)
-   sumLatHeatCanopyEvap = 0._rkind  ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   sumSenHeatCanopy     = 0._rkind  ! sensible heat flux from the canopy to the canopy air space (W m-2)
-   sumSoilCompress      = 0._rkind  ! total soil compression
-   allocate(sumLayerCompress(nSoil)); sumLayerCompress = 0._rkind ! soil compression by layer
-  
-   ! define the first flux call in a splitting operation
-   firstSplitOper = (.not.scalarSolution .or. iStateSplit==1)
-  
-   ! initialize subStep
-   dtSum     = 0._rkind  ! keep track of the portion of the time step that is completed
-   nSubsteps = 0
-  
-   ! loop through substeps
-   ! NOTE: continuous do statement with exit clause
-   substeps: do
-  
-    ! initialize error control
-    err=0; message='varSubstepSundials/'
-  
-    !write(*,'(a,1x,3(f13.2,1x))') '***** new subStep: dtSubstep, dtSum, dt = ', dtSubstep, dtSum, dt
-    !print*, 'scalarCanopyIce  = ', prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)
-    !print*, 'scalarCanopyTemp = ', prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)
-  
-    ! -----
-    ! * populate state vectors...
-    ! ---------------------------
-  
-    ! initialize state vectors
-    call popStateVec(&
-                     ! input
-                     nState,                           & ! intent(in):    number of desired state variables
-                     prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
-                     diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
-                     indx_data,                        & ! intent(in):    indices defining model states and layers
-                     ! output
-                     stateVecInit,                     & ! intent(out):   initial model state vector (mixed units)
-                     err,cmessage)                       ! intent(out):   error control
-    if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
-  
-    ! -----
-    ! * iterative solution...
-    ! -----------------------
-    ! solve the system of equations for a given state subset
-    call systemSolvSundials(&
-                    ! input: model control
-                    dtSubstep,         & ! intent(in):    time step (s)
-                    nState,            & ! intent(in):    total number of state variables
-                    firstSubStep,      & ! intent(in):    flag to denote first sub-step
-                    firstFluxCall,     & ! intent(inout): flag to indicate if we are processing the first flux call
-                    firstSplitOper,    & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
-                    computeVegFlux,    & ! intent(in):    flag to denote if computing energy flux over vegetation
-                    scalarSolution,    & ! intent(in):    flag to denote if implementing the scalar solution
-                    ! input/output: data structures
-                    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_temp,         & ! intent(inout): model fluxes for a local HRU
-                    bvar_data,         & ! intent(in):    model variables for the local basin
-                    model_decisions,   & ! intent(in):    model decisions
-                    stateVecInit,      & ! intent(in):    initial state vector
-                    ! output: model control
-                    deriv_data,        & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                    ixSaturation,      & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
-                    stateVecTrial,     & ! intent(out):   updated state vector
-                    stateVecPrime,     & ! intent(out):   updated state vector
-                    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):   time step (s)
-                    err,cmessage)        ! intent(out):   error code and error message
-  
-    if(err/=0)then
-     message=trim(message)//trim(cmessage)
-     if(err>0) return
-    endif
-  
-    ! set untapped melt energy to zero
-    untappedMelt(:) = 0._rkind
-  
-    ! if too much melt or need to reduce length of 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) return
-  
-    ! identify failure
-    failedSubstep = (err<0)
+  ! **********************************************************************************************************
+  ! public subroutine varSubstepSundials: run the model for a collection of substeps for a given state subset
+  ! **********************************************************************************************************
+  subroutine 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)
+                        nState,            & ! intent(in)    : total number of state variables
+                        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
+                        scalarSolution,    & ! intent(in)    : flag to denote implementing the scalar solution
+                        iStateSplit,       & ! intent(in)    : index of the state in the splitting operation
+                        fluxMask,          & ! intent(in)    : mask for the fluxes used in this given state subset
+                        fluxCount,         & ! intent(inout) : number of times that fluxes are updated (should equal nSubsteps)
+                        ! 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: model 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 to denote success of substepping for a given split
+                        reduceCoupledStep, & ! intent(out)   : flag to denote need 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,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 systemSolv_module,only:systemSolv                 ! solve the system of equations for one time step
+    USE getVectorz_module,only:popStateVec                ! populate the state vector
+    USE getVectorz_module,only:varExtract                 ! extract variables from the state vector
+    USE updateVarsSundials_module,only:updateVarsSundials ! update prognostic variables
+    ! identify name of variable type (for error message)
+    USE get_ixName_module,only:get_varTypeName           ! to access type strings for error messages
+    USE systemSolvSundials_module,only:systemSolvSundials
+    implicit none
+    ! ---------------------------------------------------------------------------------------
+    ! * dummy variables
+    ! ---------------------------------------------------------------------------------------
+    ! input: model control
+    real(rkind),intent(in)             :: dt                            ! time step (seconds)
+    real(rkind),intent(in)             :: dtInit                        ! initial time step (seconds)
+    real(rkind),intent(in)             :: dt_min                        ! minimum time step (seconds)
+    integer(i4b),intent(in)            :: nState                        ! total number of state variables
+    logical(lgt),intent(in)            :: doAdjustTemp                  ! flag to indicate if we adjust the temperature
+    logical(lgt),intent(in)            :: firstSubStep                  ! flag to indicate if we are processing the first sub-step
+    logical(lgt),intent(inout)         :: firstFluxCall                 ! flag to define the first flux call
+    logical(lgt),intent(in)            :: computeVegFlux                ! flag to indicate if we are computing fluxes over vegetation (.false. means veg is buried with snow)
+    logical(lgt),intent(in)            :: scalarSolution                ! flag to denote implementing the scalar solution
+    integer(i4b),intent(in)            :: iStateSplit                   ! index of the state in the splitting operation
+    type(var_flagVec),intent(in)       :: fluxMask                      ! flags to denote if the flux is calculated in the given state subset
+    type(var_ilength),intent(inout)    :: fluxCount                     ! number of times that the flux is updated (should equal nSubsteps)
+    ! input/output: data structures
+    type(model_options),intent(in)     :: model_decisions(:)            ! model decisions
+    type(zLookup),intent(in)           :: lookup_data                   ! lookup tables
+    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(inout)    :: deriv_data                    ! derivatives in model fluxes w.r.t. relevant state variables
+    type(var_dlength),intent(in)       :: bvar_data                     ! model variables for the local basin
+    ! output: model control
+    integer(i4b),intent(inout)         :: ixSaturation                  ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
+    real(rkind),intent(out)            :: dtMultiplier                  ! substep multiplier (-)
+    integer(i4b),intent(out)           :: nSubsteps                     ! number of substeps taken for a given split
+    logical(lgt),intent(out)           :: failedMinimumStep             ! flag to denote success of substepping for a given split
+    logical(lgt),intent(out)           :: reduceCoupledStep             ! flag to denote need to reduce the length of the coupled step
+    logical(lgt),intent(out)           :: tooMuchMelt                   ! flag to denote that ice is insufficient to support melt
+    real(qp),intent(out)   		         :: dt_out
+    integer(i4b),intent(out)           :: err                           ! error code
+    character(*),intent(out)           :: message                       ! error message
+    ! ---------------------------------------------------------------------------------------
+    ! * general local variables
+    ! ---------------------------------------------------------------------------------------
+    ! error control
+    character(LEN=256)                 :: cmessage                      ! error message of downwind routine
+    ! general local variables
+    integer(i4b)                       :: iVar                          ! index of variables in data structures
+    integer(i4b)                       :: iSoil                         ! index of soil layers
+    integer(i4b)                       :: ixLayer                       ! index in a given domain
+    integer(i4b), dimension(1)         :: ixMin,ixMax                   ! bounds of a given flux vector
+    ! time stepping
+    real(rkind)                        :: dtSum                         ! sum of time from successful steps (seconds)
+    real(rkind)                        :: dt_wght                       ! weight given to a given flux calculation
+    real(rkind)                        :: dtSubstep                     ! length of a substep (s)
+    ! adaptive sub-stepping for the explicit solution
+    logical(lgt)                       :: failedSubstep                 ! flag to denote success of substepping for a given split
+    real(rkind),parameter              :: safety=0.85_rkind             ! safety factor in adaptive sub-stepping
+    real(rkind),parameter              :: reduceMin=0.1_rkind           ! mimimum factor that time step is reduced
+    real(rkind),parameter              :: increaseMax=4.0_rkind         ! maximum factor that time step is increased
+    ! adaptive sub-stepping for the implicit solution
+    integer(i4b),parameter             :: n_inc=5                       ! minimum number of iterations to increase time step
+    integer(i4b),parameter             :: n_dec=15                      ! maximum number of iterations to decrease time step
+    real(rkind),parameter              :: F_inc = 1.25_rkind            ! factor used to increase time step
+    real(rkind),parameter              :: F_dec = 0.90_rkind            ! factor used to decrease time step
+    ! state and flux vectors
+    real(rkind)                        :: untappedMelt(nState)          ! un-tapped melt energy (J m-3 s-1)
+    real(rkind)                        :: stateVecInit(nState)          ! initial state vector (mixed units)
+    real(rkind)                        :: stateVecTrial(nState)         ! trial state vector (mixed units)
+    real(rkind)                        :: stateVecPrime(nState)         ! trial state vector (mixed units)
+    type(var_dlength)                  :: flux_temp                     ! temporary model fluxes
+    ! flags
+    logical(lgt)                       :: firstSplitOper                ! flag to indicate if we are processing the first flux call in a splitting operation
+    logical(lgt)                       :: checkMassBalance              ! flag to check the mass balance
+    logical(lgt)                       :: checkNrgBalance
+    logical(lgt)                       :: waterBalanceError             ! flag to denote that there is a water balance error
+    logical(lgt)                       :: nrgFluxModified               ! flag to denote that the energy fluxes were modified
+    ! energy fluxes
+    real(rkind)                        :: sumCanopyEvaporation          ! sum of canopy evaporation/condensation (kg m-2 s-1)
+    real(rkind)                        :: sumLatHeatCanopyEvap          ! sum of latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+    real(rkind)                        :: sumSenHeatCanopy              ! sum of sensible heat flux from the canopy to the canopy air space (W m-2)
+    real(rkind)                        :: sumSoilCompress
+    real(rkind),allocatable            :: sumLayerCompress(:)
+    ! ---------------------------------------------------------------------------------------
+    ! point to variables in the data structures
+    ! ---------------------------------------------------------------------------------------
+    globalVars: associate(&
+      ! 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
+      nSoilOnlyHyd            => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology variables in the soil domain
+      mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
+      ! mapping between state vectors and control volumes
+      ixLayerActive           => indx_data%var(iLookINDEX%ixLayerActive)%dat            ,& ! intent(in):    [i4b(:)] list of indices for all active layers (inactive=integerMissing)
+      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)
+      ! model state variables (vegetation canopy)
+      scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the canopy air space (K)
+      scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the vegetation canopy (K)
+      scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(inout): [dp]     mass of ice on the vegetation canopy (kg m-2)
+      scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(inout): [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+      scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(inout): [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(inout): [dp(:)]  temperature of each snow/soil layer (K)
+      mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of ice (-)
+      mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of liquid water (-)
+      mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of total water (-)
+      mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
+      mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(inout): [dp(:)]  matric potential of liquid water (m)
+      )  ! end association with variables in the data structures
+      ! *********************************************************************************************************************************************************
+      ! *********************************************************************************************************************************************************
+      ! Procedure starts here
+  
+      ! initialize error control
+      err=0; message='varSubstepSundials/'
+  
+      ! initialize flag for the success of the substepping
+      failedMinimumStep=.false.
+  
+      ! initialize the length of the substep
+      dtSubstep = dtInit
+  
+      ! initalize flag for checking if energy fluxes had been modified
+      nrgFluxModified = .false.
   
-    ! reduce step based on failure
-    if(failedSubstep)then
-      err=0; message='varSubstepSundials/'  ! recover from failed convergence
-      dtMultiplier  = 0.5_rkind        ! system failure: step halving
-    else
+      ! allocate space for the temporary model flux structure
+      call allocLocal(flux_meta(:),flux_temp,nSnow,nSoil,err,cmessage)
+      if(err/=0)then; err=20; message=trim(message)//trim(cmessage); return; endif
+  
+      ! initialize the model fluxes (some model fluxes are not computed in the iterations)
+      do iVar=1,size(flux_data%var)
+        flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
+      end do
+  
+      ! initialize the total energy fluxes (modified in updateProgSundials)
+      sumCanopyEvaporation = 0._rkind  ! canopy evaporation/condensation (kg m-2 s-1)
+      sumLatHeatCanopyEvap = 0._rkind  ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+      sumSenHeatCanopy     = 0._rkind  ! sensible heat flux from the canopy to the canopy air space (W m-2)
+      sumSoilCompress      = 0._rkind  ! total soil compression
+      allocate(sumLayerCompress(nSoil)); sumLayerCompress = 0._rkind ! soil compression by layer
+  
+      ! define the first flux call in a splitting operation
+      firstSplitOper = (.not.scalarSolution .or. iStateSplit==1)
+  
+      ! initialize subStep
+      dtSum     = 0._rkind  ! keep track of the portion of the time step that is completed
+      nSubsteps = 0
+  
+      ! loop through substeps
+      ! NOTE: continuous do statement with exit clause
+      substeps: do
+  
+        ! initialize error control
+        err=0; message='varSubstepSundials/'
+  
+        ! -----
+        ! * populate state vectors...
+        ! ---------------------------
+  
+        ! initialize state vectors
+        call popStateVec(&
+                        ! input
+                        nState,                           & ! intent(in):    number of desired state variables
+                        prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
+                        diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
+                        indx_data,                        & ! intent(in):    indices defining model states and layers
+                        ! output
+                        stateVecInit,                     & ! intent(out):   initial model state vector (mixed units)
+                        err,cmessage)                       ! intent(out):   error control
+        if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
+  
+        ! -----
+        ! * iterative solution...
+        ! -----------------------
+        ! solve the system of equations for a given state subset
+        call systemSolvSundials(&
+                        ! input: model control
+                        dtSubstep,         & ! intent(in):    time step (s)
+                        nState,            & ! intent(in):    total number of state variables
+                        firstSubStep,      & ! intent(in):    flag to denote first sub-step
+                        firstFluxCall,     & ! intent(inout): flag to indicate if we are processing the first flux call
+                        firstSplitOper,    & ! intent(in):    flag to indicate if we are processing the first flux call in a splitting operation
+                        computeVegFlux,    & ! intent(in):    flag to denote if computing energy flux over vegetation
+                        scalarSolution,    & ! intent(in):    flag to denote if implementing the scalar solution
+                        ! input/output: data structures
+                        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_temp,         & ! intent(inout): model fluxes for a local HRU
+                        bvar_data,         & ! intent(in):    model variables for the local basin
+                        model_decisions,   & ! intent(in):    model decisions
+                        stateVecInit,      & ! intent(in):    initial state vector
+                        ! output: model control
+                        deriv_data,        & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                        ixSaturation,      & ! intent(inout): index of the lowest saturated layer (NOTE: only computed on the first iteration)
+                        stateVecTrial,     & ! intent(out):   updated state vector
+                        stateVecPrime,     & ! intent(out):   updated state vector
+                        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):   time step (s)
+                        err,cmessage)        ! intent(out):   error code and error message
+  
+        if(err/=0)then
+          message=trim(message)//trim(cmessage)
+          if(err>0) return
+        endif
   
-    endif  ! switch between failure and success
+        ! set untapped melt energy to zero
+        untappedMelt(:) = 0._rkind
   
-    ! check if we failed the substep
-    if(failedSubstep)then
+        ! if too much melt or need to reduce length of 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) return
   
-     ! check that the substep is greater than the minimum step
-     if(dtSubstep*dtMultiplier<dt_min)then
-      ! --> exit, and either (1) try another solution method; or (2) reduce coupled step
-      failedMinimumStep=.true.
-      exit subSteps
+        ! identify failure
+        failedSubstep = (err<0)
   
-     else ! step is still OK
-      dtSubstep = dtSubstep*dtMultiplier
-      cycle subSteps
-     endif  ! if step is less than the minimum
+        ! reduce step based on failure
+        if(failedSubstep)then
+          err=0; message='varSubstepSundials/'  ! recover from failed convergence
+          dtMultiplier  = 0.5_rkind        ! system failure: step halving
+        else
   
-    endif  ! if failed the substep
+        endif  ! switch between failure and success
   
-    ! -----
-    ! * update model fluxes...
-    ! ------------------------
+        ! check if we failed the substep
+        if(failedSubstep)then
   
-    ! NOTE: if we get to here then we are accepting the step
+          ! check that the substep is greater than the minimum step
+          if(dtSubstep*dtMultiplier<dt_min)then
+            ! --> exit, and either (1) try another solution method; or (2) reduce coupled step
+            failedMinimumStep=.true.
+            exit subSteps
   
-    ! NOTE: we get to here if iterations are successful
-    if(err/=0)then
-     message=trim(message)//'expect err=0 if updating fluxes'
-     return
-    endif
+          else ! step is still OK
+            dtSubstep = dtSubstep*dtMultiplier
+            cycle subSteps
+          endif  ! if step is less than the minimum
   
-    ! identify the need to check the mass balance
-    checkMassBalance = .true. ! (.not.scalarSolution)
-    checkNrgBalance = .true.
-  
-    ! update prognostic variables
-    call updateProgSundials(dt_out,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,stateVecPrime,checkMassBalance, checkNrgBalance, & ! input: model control
-                    lookup_data,mpar_data,indx_data,flux_temp,prog_data,diag_data,deriv_data,                               & ! input-output: data structures
-                    waterBalanceError,nrgFluxModified,err,cmessage)                                                           ! output: flags and error control
-    if(err/=0)then
-     message=trim(message)//trim(cmessage)
-     if(err>0) return
-    endif
+        endif  ! if failed the substep
   
-    ! if water balance error then reduce the length of the coupled step
-    if(waterBalanceError)then
-     message=trim(message)//'water balance error'
-     reduceCoupledStep=.true.
-     err=-20; return
-    endif
+        ! -----
+        ! * update model fluxes...
+        ! ------------------------
   
-    if(globalPrintFlag)&
-    print*, trim(cmessage)//': dt = ', dtSubstep
-  
-    ! recover from errors in prognostic update
-    if(err<0)then
-  
-     ! modify step
-     err=0  ! error recovery
-     dtSubstep = dtSubstep/2._rkind
-  
-     ! check minimum: fail minimum step if there is an error in the update
-     if(dtSubstep<dt_min)then
-      failedMinimumStep=.true.
-      exit subSteps
-     ! minimum OK -- try again
-     else
-      cycle substeps
-     endif
-  
-    endif  ! if errors in prognostic update
-  
-    ! get the total energy fluxes (modified in updateProgSundials)
-    if(nrgFluxModified .or. indx_data%var(iLookINDEX%ixVegNrg)%dat(1)/=integerMissing)then
-     sumCanopyEvaporation = sumCanopyEvaporation + dt_out*flux_temp%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
-     sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dt_out*flux_temp%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-     sumSenHeatCanopy     = sumSenHeatCanopy     + dt_out*flux_temp%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
-    else
-     sumCanopyEvaporation = sumCanopyEvaporation + dt_out*flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
-     sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dt_out*flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-     sumSenHeatCanopy     = sumSenHeatCanopy     + dt_out*flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
-    endif  ! if energy fluxes were modified
-  
-    ! get the total soil compression
-    if (count(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat/=integerMissing)>0) then
-     ! scalar compression
-     if(.not.scalarSolution .or. iStateSplit==nSoil)&
-     sumSoilCompress = sumSoilCompress + diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) ! total soil compression
-     ! vector compression
-     do iSoil=1,nSoil
-      if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
-      sumLayerCompress(iSoil) = sumLayerCompress(iSoil) + diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) ! soil compression in layers
-     end do
-    endif
+        ! NOTE: if we get to here then we are accepting the step
   
-    ! print progress
-    if(globalPrintFlag)&
-    write(*,'(a,1x,3(f13.2,1x))') 'updating: dtSubstep, dtSum, dt = ', dtSubstep, dtSum, dt
-  
-    ! increment fluxes
-    dt_wght = 1._qp !dt_out/dt ! (define weight applied to each splitting operation)
-    do iVar=1,size(flux_meta)
-     if(count(fluxMask%var(iVar)%dat)>0) then
-  
-      !print*, flux_meta(iVar)%varname, fluxMask%var(iVar)%dat
-  
-      ! ** no domain splitting
-      if(count(ixLayerActive/=integerMissing)==nLayers)then
-       flux_data%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:) + flux_temp%var(iVar)%dat(:)*dt_wght
-       fluxCount%var(iVar)%dat(:) = fluxCount%var(iVar)%dat(:) + 1
-  
-      ! ** domain splitting
-      else
-       ixMin=lbound(flux_data%var(iVar)%dat)
-       ixMax=ubound(flux_data%var(iVar)%dat)
-       do ixLayer=ixMin(1),ixMax(1)
-        if(fluxMask%var(iVar)%dat(ixLayer)) then
-         flux_data%var(iVar)%dat(ixLayer) = flux_data%var(iVar)%dat(ixLayer) + flux_temp%var(iVar)%dat(ixLayer)*dt_wght
-         fluxCount%var(iVar)%dat(ixLayer) = fluxCount%var(iVar)%dat(ixLayer) + 1
+        ! NOTE: we get to here if iterations are successful
+        if(err/=0)then
+          message=trim(message)//'expect err=0 if updating fluxes'
+          return
         endif
-       end do
-      endif  ! (domain splitting)
-  
-     endif   ! (if the flux is desired)
-    end do  ! (loop through fluxes)
-  
-    ! ------------------------------------------------------
-    ! ------------------------------------------------------
   
-    ! increment the number of substeps
-    nSubsteps = nSubsteps+1
-  
-    ! increment the sub-step legth
-    dtSum = dtSum + dtSubstep
-    !print*, 'dtSum, dtSubstep, dt, nSubsteps = ', dtSum, dtSubstep, dt, nSubsteps
+        ! identify the need to check the mass balance
+        checkMassBalance = .true. ! (.not.scalarSolution)
+        checkNrgBalance = .true.
+  
+        ! update prognostic variables
+        call updateProgSundials(dt_out,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,stateVecPrime,checkMassBalance, checkNrgBalance, & ! input: model control
+                        lookup_data,mpar_data,indx_data,flux_temp,prog_data,diag_data,deriv_data,                               & ! input-output: data structures
+                        waterBalanceError,nrgFluxModified,err,cmessage)                                                           ! output: flags and error control
+        if(err/=0)then
+          message=trim(message)//trim(cmessage)
+          if(err>0) return
+        endif
   
-    ! check that we have completed the sub-step
-    if(dtSum >= dt-verySmall)then
-     failedMinimumStep=.false.
-     exit subSteps
-    endif
+        ! if water balance error then reduce the length of the coupled step
+        if(waterBalanceError)then
+          message=trim(message)//'water balance error'
+          reduceCoupledStep=.true.
+          err=-20; return
+        endif
   
-    ! adjust length of the sub-step (make sure that we don't exceed the step)
-    dtSubstep = min(dt - dtSum, max(dtSubstep*dtMultiplier, dt_min) )
+        if(globalPrintFlag)&
+        print*, trim(cmessage)//': dt = ', dtSubstep
+  
+        ! recover from errors in prognostic update
+        if(err<0)then
+  
+          ! modify step
+          err=0  ! error recovery
+          dtSubstep = dtSubstep/2._rkind
+  
+          ! check minimum: fail minimum step if there is an error in the update
+          if(dtSubstep<dt_min)then
+            failedMinimumStep=.true.
+            exit subSteps
+          ! minimum OK -- try again
+          else
+            cycle substeps
+          endif
+  
+        endif  ! if errors in prognostic update
+  
+        ! get the total energy fluxes (modified in updateProgSundials)
+        if(nrgFluxModified .or. indx_data%var(iLookINDEX%ixVegNrg)%dat(1)/=integerMissing)then
+          sumCanopyEvaporation = sumCanopyEvaporation + dt_out*flux_temp%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
+          sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dt_out*flux_temp%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+          sumSenHeatCanopy     = sumSenHeatCanopy     + dt_out*flux_temp%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
+        else
+          sumCanopyEvaporation = sumCanopyEvaporation + dt_out*flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
+          sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dt_out*flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+          sumSenHeatCanopy     = sumSenHeatCanopy     + dt_out*flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
+        endif  ! if energy fluxes were modified
+  
+        ! get the total soil compression
+        if (count(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat/=integerMissing)>0) then
+          ! scalar compression
+          if(.not.scalarSolution .or. iStateSplit==nSoil)&
+          sumSoilCompress = sumSoilCompress + diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) ! total soil compression
+          ! vector compression
+          do iSoil=1,nSoil
+            if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
+            sumLayerCompress(iSoil) = sumLayerCompress(iSoil) + diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) ! soil compression in layers
+          end do
+        endif
   
-   end do substeps  ! time steps for variable-dependent sub-stepping
+        ! print progress
+        if(globalPrintFlag)&
+        write(*,'(a,1x,3(f13.2,1x))') 'updating: dtSubstep, dtSum, dt = ', dtSubstep, dtSum, dt
+  
+        ! increment fluxes
+        dt_wght = 1._qp !dt_out/dt ! (define weight applied to each splitting operation)
+        do iVar=1,size(flux_meta)
+          if(count(fluxMask%var(iVar)%dat)>0) then
+  
+            ! ** no domain splitting
+            if(count(ixLayerActive/=integerMissing)==nLayers)then
+              flux_data%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:) + flux_temp%var(iVar)%dat(:)*dt_wght
+              fluxCount%var(iVar)%dat(:) = fluxCount%var(iVar)%dat(:) + 1
+  
+            ! ** domain splitting
+            else
+              ixMin=lbound(flux_data%var(iVar)%dat)
+              ixMax=ubound(flux_data%var(iVar)%dat)
+              do ixLayer=ixMin(1),ixMax(1)
+                if(fluxMask%var(iVar)%dat(ixLayer)) then
+                  flux_data%var(iVar)%dat(ixLayer) = flux_data%var(iVar)%dat(ixLayer) + flux_temp%var(iVar)%dat(ixLayer)*dt_wght
+                  fluxCount%var(iVar)%dat(ixLayer) = fluxCount%var(iVar)%dat(ixLayer) + 1
+                endif
+              end do
+            endif  ! (domain splitting)
+  
+          endif   ! (if the flux is desired)
+        end do  ! (loop through fluxes)
+  
+        ! increment the number of substeps
+        nSubsteps = nSubsteps+1
+  
+        ! increment the sub-step legth
+        dtSum = dtSum + dtSubstep
+  
+        ! check that we have completed the sub-step
+        if(dtSum >= dt-verySmall)then
+          failedMinimumStep=.false.
+          exit subSteps
+        endif
   
-   ! save the energy fluxes
-   flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) = sumCanopyEvaporation /dt_out      ! canopy evaporation/condensation (kg m-2 s-1)
-   flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) = sumLatHeatCanopyEvap /dt_out      ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     = sumSenHeatCanopy     /dt_out      ! sensible heat flux from the canopy to the canopy air space (W m-2)
+        ! adjust length of the sub-step (make sure that we don't exceed the step)
+        dtSubstep = min(dt - dtSum, max(dtSubstep*dtMultiplier, dt_min) )
   
-   ! save the soil compression diagnostics
-   diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sumSoilCompress
-   do iSoil=1,nSoil
-    if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
-    diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) = sumLayerCompress(iSoil)
-   end do
-   deallocate(sumLayerCompress)
+      end do substeps  ! time steps for variable-dependent sub-stepping
   
-   ! end associate statements
-   end associate globalVars
+      ! save the energy fluxes
+      flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) = sumCanopyEvaporation /dt_out      ! canopy evaporation/condensation (kg m-2 s-1)
+      flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) = sumLatHeatCanopyEvap /dt_out      ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+      flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     = sumSenHeatCanopy     /dt_out      ! sensible heat flux from the canopy to the canopy air space (W m-2)
   
-   ! update error codes
-   if(failedMinimumStep)then
-    err=-20 ! negative = recoverable error
-    message=trim(message)//'failed minimum step'
-   endif
+      ! save the soil compression diagnostics
+      diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sumSoilCompress
+      do iSoil=1,nSoil
+        if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
+        diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) = sumLayerCompress(iSoil)
+      end do
+      deallocate(sumLayerCompress)
   
+    ! end associate statements
+    end associate globalVars
   
-   end subroutine varSubstepSundials
+    ! update error codes
+    if(failedMinimumStep)then
+      err=-20 ! negative = recoverable error
+      message=trim(message)//'failed minimum step'
+    endif
+  end subroutine varSubstepSundials
   
   
-   ! **********************************************************************************************************
-   ! private subroutine updateProgSundials: update prognostic variables
-   ! **********************************************************************************************************
-   subroutine updateProgSundials(dt,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,stateVecPrime,checkMassBalance, checkNrgBalance, & ! input: model control
+  ! **********************************************************************************************************
+  ! private subroutine updateProgSundials: update prognostic variables
+  ! **********************************************************************************************************
+  subroutine updateProgSundials(dt,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,stateVecPrime,checkMassBalance, checkNrgBalance, & ! input: model control
                          lookup_data,mpar_data,indx_data,flux_data,prog_data,diag_data,deriv_data,                                   & ! input-output: data structures
                          waterBalanceError,nrgFluxModified,err,message)                                                    ! output: flags and error control
-   USE getVectorz_module,only:varExtract                             ! extract variables from the state vector
-   USE updateVarsSundials_module,only:updateVarsSundials             ! update prognostic variables
-   USE getVectorzAddSundials_module, only:varExtractSundials
-   USE computEnthalpy_module,only:computEnthalpy
-   USE t2enthalpy_module, only:t2enthalpy           ! compute enthalpy
-   implicit none
-   ! model control
-   real(rkind)      ,intent(in)    :: dt                             ! time step (s)
-   integer(i4b)     ,intent(in)    :: nSnow                          ! number of snow layers
-   integer(i4b)     ,intent(in)    :: nSoil                          ! number of soil layers
-   integer(i4b)     ,intent(in)    :: nLayers                        ! total number of layers
-   logical(lgt)     ,intent(in)    :: doAdjustTemp                   ! flag to indicate if we adjust the temperature
-   logical(lgt)     ,intent(in)    :: computeVegFlux                 ! flag to compute the vegetation flux
-   real(rkind)      ,intent(in)    :: untappedMelt(:)                ! un-tapped melt energy (J m-3 s-1)
-   real(rkind)      ,intent(in)    :: stateVecTrial(:)               ! trial state vector (mixed units)
-   real(rkind)      ,intent(in)    :: stateVecPrime(:)               ! trial state vector (mixed units)
-   logical(lgt)     ,intent(in)    :: checkMassBalance               ! flag to check the mass balance
-   logical(lgt)     ,intent(in)    :: checkNrgBalance                ! flag to check the energy balance
-   ! data structures
-   type(zLookup),intent(in)        :: lookup_data                   ! lookup tables
-   type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
-   type(var_ilength),intent(in)    :: indx_data                      ! indices for a local HRU
-   type(var_dlength),intent(inout) :: flux_data                      ! model fluxes 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) :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
-   ! flags and error control
-   logical(lgt)     ,intent(out)   :: waterBalanceError              ! flag to denote that there is a water balance error
-   logical(lgt)     ,intent(out)   :: nrgFluxModified                ! flag to denote that the energy fluxes were modified
-   integer(i4b)     ,intent(out)   :: err                            ! error code
-   character(*)     ,intent(out)   :: message                        ! error message
-   ! ==================================================================================================================
-   ! general
-   integer(i4b)                    :: iState                         ! index of model state variable
-   integer(i4b)                    :: ixSubset                       ! index within the state subset
-   integer(i4b)                    :: ixFullVector                   ! index within full state vector
-   integer(i4b)                    :: ixControlIndex                 ! index within a given domain
-   real(rkind)                        :: volMelt                        ! volumetric melt (kg m-3)
-   real(rkind),parameter              :: verySmall=epsilon(1._rkind)*2._rkind ! a very small number (deal with precision issues)
-   ! mass balance
-   real(rkind)                        :: canopyBalance0,canopyBalance1  ! canopy storage at start/end of time step
-   real(rkind)                        :: soilBalance0,soilBalance1      ! soil storage at start/end of time step
-   real(rkind)                        :: vertFlux                       ! change in storage due to vertical fluxes
-   real(rkind)                        :: tranSink,baseSink,compSink     ! change in storage due to sink terms
-   real(rkind)                        :: liqError                       ! water balance error
-   real(rkind)                        :: fluxNet                        ! net water fluxes (kg m-2 s-1)
-   real(rkind)                        :: superflousWat                  ! superflous water used for evaporation (kg m-2 s-1)
-   real(rkind)                        :: superflousNrg                  ! superflous energy that cannot be used for evaporation (W m-2 [J m-2 s-1])
-   character(LEN=256)              :: cmessage                       ! error message of downwind routine
-   ! trial state variables
-   real(rkind)                        :: scalarCanairTempTrial          ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempTrial          ! trial value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatTrial           ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempTrial                ! trial vector for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial          ! trial vector for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial          ! trial vector for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial       ! trial vector for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStorageTrial      ! trial value for storage of water in the aquifer (m)
-   ! diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqTrial           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIceTrial           ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial          ! trial vector for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial          ! trial vector for volumetric fraction of ice (-)
-   real(rkind)                        :: scalarCanairEnthalpyTrial      ! enthalpy of the canopy air space (J m-3)
-   real(rkind)                        :: scalarCanopyEnthalpyTrial      ! enthalpy of the vegetation canopy (J m-3)
-   real(rkind),dimension(nLayers)     :: mLayerEnthalpyTrial            ! enthalpy of snow + soil (J m-3)
-   ! derivative of state variables
-   real(rkind)                        :: scalarCanairTempPrime          ! trial value for temperature of the canopy air space (K)
-   real(rkind)                        :: scalarCanopyTempPrime          ! trial value for temperature of the vegetation canopy (K)
-   real(rkind)                        :: scalarCanopyWatPrime           ! trial value for liquid water storage in the canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerTempPrime                ! trial vector for temperature of layers in the snow and soil domains (K)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracWatPrime          ! trial vector for volumetric fraction of total water (-)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadPrime          ! trial vector for total water matric potential (m)
-   real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqPrime       ! trial vector for liquid water matric potential (m)
-   real(rkind)                        :: scalarAquiferStoragePrime      ! trial value for storage of water in the aquifer (m)
-   ! derivative of diagnostic variables
-   real(rkind)                        :: scalarCanopyLiqPrime           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
-   real(rkind)                        :: scalarCanopyIcePrime           ! trial value for mass of ice on the vegetation canopy (kg m-2)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracLiqPrime          ! trial vector for volumetric fraction of liquid water (-)
-   real(rkind),dimension(nLayers)     :: mLayerVolFracIcePrime          ! trial vector for volumetric fraction of ice (-)
-   ! -------------------------------------------------------------------------------------------------------------------
-  
-   ! -------------------------------------------------------------------------------------------------------------------
-   ! point to flux variables in the data structure
-   associate(&
-   ! get indices for mass balance
-   ixVegHyd                  => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)                  ,& ! intent(in)    : [i4b]    index of canopy hydrology state variable (mass)
-   ixSoilOnlyHyd             => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                ,& ! intent(in)    : [i4b(:)] index in the state subset for hydrology state variables in the soil domain
-   ! get indices for the un-tapped melt
-   ixNrgOnly                 => indx_data%var(iLookINDEX%ixNrgOnly)%dat                    ,& ! intent(in)    : [i4b(:)] list of indices for all energy states
-   ixDomainType              => indx_data%var(iLookINDEX%ixDomainType)%dat                 ,& ! intent(in)    : [i4b(:)] indices defining the domain of the state (iname_veg, iname_snow, iname_soil)
-   ixControlVolume           => indx_data%var(iLookINDEX%ixControlVolume)%dat              ,& ! intent(in)    : [i4b(:)] index of the control volume for different domains (veg, snow, soil)
-   ixMapSubset2Full          => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat             ,& ! intent(in)    : [i4b(:)] [state subset] list of indices of the full state vector in the state subset
-   ! water fluxes
-   scalarRainfall            => flux_data%var(iLookFLUX%scalarRainfall)%dat(1)             ,& ! intent(in)    : [dp]     rainfall rate (kg m-2 s-1)
-   scalarThroughfallRain     => flux_data%var(iLookFLUX%scalarThroughfallRain)%dat(1)      ,& ! intent(in)    : [dp]     rain reaches ground without touching the canopy (kg m-2 s-1)
-   scalarCanopyEvaporation   => flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1)    ,& ! intent(in)    : [dp]     canopy evaporation/condensation (kg m-2 s-1)
-   scalarCanopyTranspiration => flux_data%var(iLookFLUX%scalarCanopyTranspiration)%dat(1)  ,& ! intent(in)    : [dp]     canopy transpiration (kg m-2 s-1)
-   scalarCanopyLiqDrainage   => flux_data%var(iLookFLUX%scalarCanopyLiqDrainage)%dat(1)    ,& ! intent(in)    : [dp]     drainage liquid water from vegetation canopy (kg m-2 s-1)
-   iLayerLiqFluxSoil         => flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat             ,& ! intent(in)    : [dp(0:)] vertical liquid water flux at soil layer interfaces (-)
-   iLayerNrgFlux             => flux_data%var(iLookFLUX%iLayerNrgFlux)%dat                 ,& ! intent(in)    :
-   mLayerNrgFlux             => flux_data%var(iLookFLUX%mLayerNrgFlux)%dat                      ,&  ! intent(out): [dp] net energy flux for each layer within the snow+soil domain (J m-3 s-1)
-   mLayerTranspire           => flux_data%var(iLookFLUX%mLayerTranspire)%dat               ,& ! intent(in)    : [dp(:)]  transpiration loss from each soil layer (m s-1)
-   mLayerBaseflow            => flux_data%var(iLookFLUX%mLayerBaseflow)%dat                ,& ! intent(in)    : [dp(:)]  baseflow from each soil layer (m s-1)
-   mLayerCompress            => diag_data%var(iLookDIAG%mLayerCompress)%dat                ,& ! intent(in)    : [dp(:)]  change in storage associated with compression of the soil matrix (-)
-   scalarCanopySublimation   => flux_data%var(iLookFLUX%scalarCanopySublimation)%dat(1)    ,& ! intent(in)    : [dp]     sublimation of ice from the vegetation canopy (kg m-2 s-1)
-   scalarSnowSublimation     => flux_data%var(iLookFLUX%scalarSnowSublimation)%dat(1)      ,& ! intent(in)    : [dp]     sublimation of ice from the snow surface (kg m-2 s-1)
-   ! energy fluxes
-   scalarLatHeatCanopyEvap   => flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1)    ,& ! intent(in)    : [dp]     latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   scalarSenHeatCanopy       => flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)        ,& ! intent(in)    : [dp]     sensible heat flux from the canopy to the canopy air space (W m-2)
-   ! domain depth
-   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)
-   ! model state variables (vegetation canopy)
-   scalarCanairTemp          => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the canopy air space (K)
-   scalarCanopyTemp          => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the vegetation canopy (K)
-   scalarCanopyIce           => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)            ,& ! intent(inout) : [dp]     mass of ice on the vegetation canopy (kg m-2)
-   scalarCanopyLiq           => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)            ,& ! intent(inout) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
-   scalarCanopyWat           => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)            ,& ! intent(inout) : [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(inout) : [dp(:)]  temperature of each snow/soil layer (K)
-   mLayerVolFracIce          => prog_data%var(iLookPROG%mLayerVolFracIce)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of ice (-)
-   mLayerVolFracLiq          => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of liquid water (-)
-   mLayerVolFracWat          => prog_data%var(iLookPROG%mLayerVolFracWat)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of total water (-)
-   mLayerMatricHead          => prog_data%var(iLookPROG%mLayerMatricHead)%dat              ,& ! intent(inout) : [dp(:)]  matric head (m)
-   mLayerMatricHeadLiq       => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat           ,& ! intent(inout) : [dp(:)]  matric potential of liquid water (m)
-  ! enthalpy
-   scalarCanairEnthalpy    => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(inout): [dp]    enthalpy of the canopy air space (J m-3)
-   scalarCanopyEnthalpy    => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(inout): [dp]    enthalpy of the vegetation canopy (J m-3)
-   mLayerEnthalpy          => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(inout): [dp(:)] enthalpy of the snow+soil layers (J m-3)
-   ! model state variables (aquifer)
-   scalarAquiferStorage      => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)       ,& ! intent(inout) : [dp(:)]  storage of water in the aquifer (m)
-   ! error tolerance
-   absConvTol_liquid         => mpar_data%var(iLookPARAM%absConvTol_liquid)%dat(1)          & ! intent(in)    : [dp]     absolute convergence tolerance for vol frac liq water (-)
-   ) ! associating flux variables in the data structure
-   ! -------------------------------------------------------------------------------------------------------------------
-   ! initialize error control
-   err=0; message='updateProgSundials/'
-  
-   ! initialize water balancmLayerVolFracWatTriale error
-   waterBalanceError=.false.
-  
-   ! get storage at the start of the step
-   canopyBalance0 = merge(scalarCanopyWat, realMissing, computeVegFlux)
-   soilBalance0   = sum( (mLayerVolFracLiq(nSnow+1:nLayers)  + mLayerVolFracIce(nSnow+1:nLayers)  )*mLayerDepth(nSnow+1:nLayers) )
-  
-   ! -----
-   ! * update states...
-   ! ------------------
-   ! these will need to be initialized as they do not have updated prognostic structures in Sundials
-   ! should all be set to previous values if splits, but for now operator splitting is not hooked up
-   scalarCanairTempPrime    = realMissing
-   scalarCanopyTempPrime    = realMissing
-   scalarCanopyWatPrime     = realMissing
-   scalarCanopyLiqPrime     = realMissing
-   scalarCanopyIcePrime     = realMissing
-   mLayerTempPrime          = realMissing
-   mLayerVolFracWatPrime    = realMissing
-   mLayerVolFracLiqPrime    = realMissing
-   mLayerVolFracIcePrime    = realMissing
-   mLayerMatricHeadPrime    = realMissing
-   mLayerMatricHeadLiqPrime = realMissing
-   scalarAquiferStoragePrime= realMissing
-   ! set to previous value from prognostic structure, correct because outside Sundials
-   scalarCanairTempTrial    = scalarCanairTemp
-   scalarCanopyTempTrial    = scalarCanopyTemp
-   scalarCanopyWatTrial     = scalarCanopyWat
-   scalarCanopyLiqTrial     = scalarCanopyLiq
-   scalarCanopyIceTrial     = scalarCanopyIce
-   mLayerTempTrial          = mLayerTemp
-   mLayerVolFracWatTrial    = mLayerVolFracWat
-   mLayerVolFracLiqTrial    = mLayerVolFracLiq
-   mLayerVolFracIceTrial    = mLayerVolFracIce
-   mLayerMatricHeadTrial    = mLayerMatricHead
-   mLayerMatricHeadLiqTrial = mLayerMatricHeadLiq
-   scalarAquiferStorageTrial= scalarAquiferStorage
-  
-   ! extract variables from the model state vector
-   call varExtractSundials(&
-                   ! input
-                   stateVecTrial,                 & ! intent(in):    model state vector (mixed units)
-                   stateVecPrime,            & ! intent(in):    model state vector (mixed units)
-                   diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
-                   prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                   indx_data,                & ! intent(in):    indices defining model states and layers
-                   ! output: variables for the vegetation canopy
-                   scalarCanairTempTrial,    & ! intent(inout):   trial value of canopy air temperature (K)
-                   scalarCanopyTempTrial,    & ! intent(inout):   trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,     & ! intent(inout):   trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,     & ! intent(inout):   trial value of canopy liquid water (kg m-2)
-                   scalarCanairTempPrime,    & ! intent(inout):   derivative of canopy air temperature (K)
-                   scalarCanopyTempPrime,    & ! intent(inout):   derivative of canopy temperature (K)
-                   scalarCanopyWatPrime,     & ! intent(inout):   derivative of canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,     & ! intent(inout):   derivative of canopy liquid water (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,          & ! intent(inout):   trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,    & ! intent(inout):   trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,    & ! intent(inout):   trial vector of volumetric liquid water content (-)
-                   mLayerMatricHeadTrial,    & ! intent(inout):   trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial, & ! intent(inout):   trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,          & ! intent(inout):   derivative of layer temperature (K)
-                   mLayerVolFracWatPrime,    & ! intent(inout):   derivative of volumetric total water content (-)
-                   mLayerVolFracLiqPrime,    & ! intent(inout):   derivative of volumetric liquid water content (-)
-                   mLayerMatricHeadPrime,    & ! intent(inout):   derivative of total water matric potential (m)
-                   mLayerMatricHeadLiqPrime, & ! intent(inout):   derivative of liquid water matric potential (m)
-                   ! output: variables for the aquifer
-                   scalarAquiferStorageTrial,& ! intent(inout):   trial value of storage of water in the aquifer (m)
-                   scalarAquiferStoragePrime,& ! intent(inout):   derivative of storage of water in the aquifer (m)
-                   ! output: error control
-                   err,cmessage)               ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-  
-    ! update diagnostic variables
-   call updateVarsSundials(&
-                   ! input
-                   dt,                                        &
-                   .false.,                                   & ! intent(in):    logical flag if computing Jacobian for Sundials solver
-                   doAdjustTemp,                              & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
-                   mpar_data,                                 & ! intent(in):    model parameters for a local HRU
-                   indx_data,                                 & ! intent(in):    indices defining model states and layers
-                   prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
-                   mLayerVolFracWatTrial,                     & ! intent(in):    use current vector for prev vector of volumetric total water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(in):    use current vector for prev vector of total water matric potential (m)
-                   diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
-                   deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                   ! output: variables for the vegetation canopy
-                   scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
-                   scalarCanopyTempPrime,                     & ! intent(inout): trial value of canopy temperature (K)
-                   scalarCanopyWatPrime,                      & ! intent(inout): trial value of canopy total water (kg m-2)
-                   scalarCanopyLiqPrime,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                   scalarCanopyIcePrime,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
-                   ! output: variables for the snow-soil domain
-                   mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
-                   mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
-                   mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
-                   mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
-                   mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
-                   mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
-                   mLayerTempPrime,                           & !
-                   mLayerVolFracWatPrime,                     & ! intent(inout): Prime vector of volumetric total water content (-)
-                   mLayerVolFracLiqPrime,                     & ! intent(inout): Prime vector of volumetric liquid water content (-)
-                   mLayerVolFracIcePrime,                     & !
-                   mLayerMatricHeadPrime,                     & ! intent(inout): Prime vector of total water matric potential (m)
-                   mLayerMatricHeadLiqPrime,                  & ! intent(inout): Prime vector of liquid water matric potential (m)
-                   ! output: error control
-                   err,cmessage)                                ! intent(out):   error control
-   if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-  
-   ! ----
-   ! * check energy balance
-   !------------------------
-   ! NOTE: for now, we just compute enthalpy
-   if(checkNrgBalance)then
+    USE getVectorz_module,only:varExtract                             ! extract variables from the state vector
+    USE updateVarsSundials_module,only:updateVarsSundials             ! update prognostic variables
+    USE computEnthalpy_module,only:computEnthalpy
+    USE t2enthalpy_module, only:t2enthalpy           ! compute enthalpy
+    implicit none
+    ! model control
+    real(rkind)      ,intent(in)    :: dt                             ! time step (s)
+    integer(i4b)     ,intent(in)    :: nSnow                          ! number of snow layers
+    integer(i4b)     ,intent(in)    :: nSoil                          ! number of soil layers
+    integer(i4b)     ,intent(in)    :: nLayers                        ! total number of layers
+    logical(lgt)     ,intent(in)    :: doAdjustTemp                   ! flag to indicate if we adjust the temperature
+    logical(lgt)     ,intent(in)    :: computeVegFlux                 ! flag to compute the vegetation flux
+    real(rkind)      ,intent(in)    :: untappedMelt(:)                ! un-tapped melt energy (J m-3 s-1)
+    real(rkind)      ,intent(in)    :: stateVecTrial(:)               ! trial state vector (mixed units)
+    real(rkind)      ,intent(in)    :: stateVecPrime(:)               ! trial state vector (mixed units)
+    logical(lgt)     ,intent(in)    :: checkMassBalance               ! flag to check the mass balance
+    logical(lgt)     ,intent(in)    :: checkNrgBalance                ! flag to check the energy balance
+    ! data structures
+    type(zLookup),intent(in)        :: lookup_data                   ! lookup tables
+    type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
+    type(var_ilength),intent(in)    :: indx_data                      ! indices for a local HRU
+    type(var_dlength),intent(inout) :: flux_data                      ! model fluxes 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) :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
+    ! flags and error control
+    logical(lgt)     ,intent(out)   :: waterBalanceError              ! flag to denote that there is a water balance error
+    logical(lgt)     ,intent(out)   :: nrgFluxModified                ! flag to denote that the energy fluxes were modified
+    integer(i4b)     ,intent(out)   :: err                            ! error code
+    character(*)     ,intent(out)   :: message                        ! error message
+    ! ==================================================================================================================
+    ! general
+    integer(i4b)                    :: iState                         ! index of model state variable
+    integer(i4b)                    :: ixSubset                       ! index within the state subset
+    integer(i4b)                    :: ixFullVector                   ! index within full state vector
+    integer(i4b)                    :: ixControlIndex                 ! index within a given domain
+    real(rkind)                     :: volMelt                        ! volumetric melt (kg m-3)
+    real(rkind),parameter           :: verySmall=epsilon(1._rkind)*2._rkind ! a very small number (deal with precision issues)
+    ! mass balance
+    real(rkind)                     :: canopyBalance0,canopyBalance1  ! canopy storage at start/end of time step
+    real(rkind)                     :: soilBalance0,soilBalance1      ! soil storage at start/end of time step
+    real(rkind)                     :: vertFlux                       ! change in storage due to vertical fluxes
+    real(rkind)                     :: tranSink,baseSink,compSink     ! change in storage due to sink terms
+    real(rkind)                     :: liqError                       ! water balance error
+    real(rkind)                     :: fluxNet                        ! net water fluxes (kg m-2 s-1)
+    real(rkind)                     :: superflousWat                  ! superflous water used for evaporation (kg m-2 s-1)
+    real(rkind)                     :: superflousNrg                  ! superflous energy that cannot be used for evaporation (W m-2 [J m-2 s-1])
+    character(LEN=256)              :: cmessage                       ! error message of downwind routine
+    ! trial state variables
+    real(rkind)                     :: scalarCanairTempTrial          ! trial value for temperature of the canopy air space (K)
+    real(rkind)                     :: scalarCanopyTempTrial          ! trial value for temperature of the vegetation canopy (K)
+    real(rkind)                     :: scalarCanopyWatTrial           ! trial value for liquid water storage in the canopy (kg m-2)
+    real(rkind),dimension(nLayers)  :: mLayerTempTrial                ! trial vector for temperature of layers in the snow and soil domains (K)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracWatTrial          ! trial vector for volumetric fraction of total water (-)
+    real(rkind),dimension(nSoil)    :: mLayerMatricHeadTrial          ! trial vector for total water matric potential (m)
+    real(rkind),dimension(nSoil)    :: mLayerMatricHeadLiqTrial       ! trial vector for liquid water matric potential (m)
+    real(rkind)                     :: scalarAquiferStorageTrial      ! trial value for storage of water in the aquifer (m)
+    ! diagnostic variables
+    real(rkind)                     :: scalarCanopyLiqTrial           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
+    real(rkind)                     :: scalarCanopyIceTrial           ! trial value for mass of ice on the vegetation canopy (kg m-2)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracLiqTrial          ! trial vector for volumetric fraction of liquid water (-)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracIceTrial          ! trial vector for volumetric fraction of ice (-)
+      ! derivative of state variables
+    real(rkind)                     :: scalarCanairTempPrime          ! trial value for temperature of the canopy air space (K)
+    real(rkind)                     :: scalarCanopyTempPrime          ! trial value for temperature of the vegetation canopy (K)
+    real(rkind)                     :: scalarCanopyWatPrime           ! trial value for liquid water storage in the canopy (kg m-2)
+    real(rkind),dimension(nLayers)  :: mLayerTempPrime                ! trial vector for temperature of layers in the snow and soil domains (K)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracWatPrime          ! trial vector for volumetric fraction of total water (-)
+    real(rkind),dimension(nSoil)    :: mLayerMatricHeadPrime          ! trial vector for total water matric potential (m)
+    real(rkind),dimension(nSoil)    :: mLayerMatricHeadLiqPrime       ! trial vector for liquid water matric potential (m)
+    real(rkind)                     :: scalarAquiferStoragePrime      ! trial value for storage of water in the aquifer (m)
+    ! diagnostic variables
+    real(rkind)                     :: scalarCanopyLiqPrime           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
+    real(rkind)                     :: scalarCanopyIcePrime           ! trial value for mass of ice on the vegetation canopy (kg m-2)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracLiqPrime          ! trial vector for volumetric fraction of liquid water (-)
+    real(rkind),dimension(nLayers)  :: mLayerVolFracIcePrime          ! trial vector for volumetric fraction of ice (-)
+    real(rkind)                     :: scalarCanairEnthalpyTrial      ! enthalpy of the canopy air space (J m-3)
+    real(rkind)                     :: scalarCanopyEnthalpyTrial      ! enthalpy of the vegetation canopy (J m-3)
+    real(rkind),dimension(nLayers)  :: mLayerEnthalpyTrial            ! enthalpy of snow + soil (J m-3)
+    ! -------------------------------------------------------------------------------------------------------------------
+  
+    ! -------------------------------------------------------------------------------------------------------------------
+    ! point to flux variables in the data structure
+    associate(&
+      ! get indices for mass balance
+      ixVegHyd                  => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)                  ,& ! intent(in)    : [i4b]    index of canopy hydrology state variable (mass)
+      ixSoilOnlyHyd             => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                ,& ! intent(in)    : [i4b(:)] index in the state subset for hydrology state variables in the soil domain
+      ! get indices for the un-tapped melt
+      ixNrgOnly                 => indx_data%var(iLookINDEX%ixNrgOnly)%dat                    ,& ! intent(in)    : [i4b(:)] list of indices for all energy states
+      ixDomainType              => indx_data%var(iLookINDEX%ixDomainType)%dat                 ,& ! intent(in)    : [i4b(:)] indices defining the domain of the state (iname_veg, iname_snow, iname_soil)
+      ixControlVolume           => indx_data%var(iLookINDEX%ixControlVolume)%dat              ,& ! intent(in)    : [i4b(:)] index of the control volume for different domains (veg, snow, soil)
+      ixMapSubset2Full          => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat             ,& ! intent(in)    : [i4b(:)] [state subset] list of indices of the full state vector in the state subset
+      ! water fluxes
+      scalarRainfall            => flux_data%var(iLookFLUX%scalarRainfall)%dat(1)             ,& ! intent(in)    : [dp]     rainfall rate (kg m-2 s-1)
+      scalarThroughfallRain     => flux_data%var(iLookFLUX%scalarThroughfallRain)%dat(1)      ,& ! intent(in)    : [dp]     rain reaches ground without touching the canopy (kg m-2 s-1)
+      scalarCanopyEvaporation   => flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1)    ,& ! intent(in)    : [dp]     canopy evaporation/condensation (kg m-2 s-1)
+      scalarCanopyTranspiration => flux_data%var(iLookFLUX%scalarCanopyTranspiration)%dat(1)  ,& ! intent(in)    : [dp]     canopy transpiration (kg m-2 s-1)
+      scalarCanopyLiqDrainage   => flux_data%var(iLookFLUX%scalarCanopyLiqDrainage)%dat(1)    ,& ! intent(in)    : [dp]     drainage liquid water from vegetation canopy (kg m-2 s-1)
+      iLayerLiqFluxSoil         => flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat             ,& ! intent(in)    : [dp(0:)] vertical liquid water flux at soil layer interfaces (-)
+      iLayerNrgFlux             => flux_data%var(iLookFLUX%iLayerNrgFlux)%dat                 ,& ! intent(in)    :
+      mLayerNrgFlux             => flux_data%var(iLookFLUX%mLayerNrgFlux)%dat                      ,&  ! intent(out): [dp] net energy flux for each layer within the snow+soil domain (J m-3 s-1)
+      mLayerTranspire           => flux_data%var(iLookFLUX%mLayerTranspire)%dat               ,& ! intent(in)    : [dp(:)]  transpiration loss from each soil layer (m s-1)
+      mLayerBaseflow            => flux_data%var(iLookFLUX%mLayerBaseflow)%dat                ,& ! intent(in)    : [dp(:)]  baseflow from each soil layer (m s-1)
+      mLayerCompress            => diag_data%var(iLookDIAG%mLayerCompress)%dat                ,& ! intent(in)    : [dp(:)]  change in storage associated with compression of the soil matrix (-)
+      scalarCanopySublimation   => flux_data%var(iLookFLUX%scalarCanopySublimation)%dat(1)    ,& ! intent(in)    : [dp]     sublimation of ice from the vegetation canopy (kg m-2 s-1)
+      scalarSnowSublimation     => flux_data%var(iLookFLUX%scalarSnowSublimation)%dat(1)      ,& ! intent(in)    : [dp]     sublimation of ice from the snow surface (kg m-2 s-1)
+      ! energy fluxes
+      scalarLatHeatCanopyEvap   => flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1)    ,& ! intent(in)    : [dp]     latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+      scalarSenHeatCanopy       => flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)        ,& ! intent(in)    : [dp]     sensible heat flux from the canopy to the canopy air space (W m-2)
+      ! domain depth
+      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)
+      ! model state variables (vegetation canopy)
+      scalarCanairTemp          => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the canopy air space (K)
+      scalarCanopyTemp          => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the vegetation canopy (K)
+      scalarCanopyIce           => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)            ,& ! intent(inout) : [dp]     mass of ice on the vegetation canopy (kg m-2)
+      scalarCanopyLiq           => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)            ,& ! intent(inout) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+      scalarCanopyWat           => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)            ,& ! intent(inout) : [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(inout) : [dp(:)]  temperature of each snow/soil layer (K)
+      mLayerVolFracIce          => prog_data%var(iLookPROG%mLayerVolFracIce)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of ice (-)
+      mLayerVolFracLiq          => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of liquid water (-)
+      mLayerVolFracWat          => prog_data%var(iLookPROG%mLayerVolFracWat)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of total water (-)
+      mLayerMatricHead          => prog_data%var(iLookPROG%mLayerMatricHead)%dat              ,& ! intent(inout) : [dp(:)]  matric head (m)
+      mLayerMatricHeadLiq       => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat           ,& ! intent(inout) : [dp(:)]  matric potential of liquid water (m)
+      ! enthalpy
+      scalarCanairEnthalpy      => diag_data%var(iLookDIAG%scalarCanairEnthalpy)%dat(1)   ,&  ! intent(inout): [dp]    enthalpy of the canopy air space (J m-3)
+      scalarCanopyEnthalpy      => diag_data%var(iLookDIAG%scalarCanopyEnthalpy)%dat(1)   ,&  ! intent(inout): [dp]    enthalpy of the vegetation canopy (J m-3)
+      mLayerEnthalpy            => diag_data%var(iLookDIAG%mLayerEnthalpy)%dat            ,&  ! intent(inout): [dp(:)] enthalpy of the snow+soil layers (J m-3)
+      ! model state variables (aquifer)
+      scalarAquiferStorage      => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)       ,& ! intent(inout) : [dp(:)]  storage of water in the aquifer (m)
+      ! error tolerance
+      absConvTol_liquid         => mpar_data%var(iLookPARAM%absConvTol_liquid)%dat(1)          & ! intent(in)    : [dp]     absolute convergence tolerance for vol frac liq water (-)
+      ) ! associating flux variables in the data structure
+      ! -------------------------------------------------------------------------------------------------------------------
+      ! initialize error control
+      err=0; message='updateProgSundials/'
+  
+      ! initialize water balancmLayerVolFracWatTriale error
+      waterBalanceError=.false.
+  
+      ! get storage at the start of the step
+      canopyBalance0 = merge(scalarCanopyWat, realMissing, computeVegFlux)
+      soilBalance0   = sum( (mLayerVolFracLiq(nSnow+1:nLayers)  + mLayerVolFracIce(nSnow+1:nLayers)  )*mLayerDepth(nSnow+1:nLayers) )
+  
+      ! -----
+      ! * update states...
+      ! ------------------
+  
+      ! initialize to state variable from the last update
+      scalarCanairTempTrial = scalarCanairTemp
+      scalarCanopyTempTrial = scalarCanopyTemp
+      scalarCanopyWatTrial  = scalarCanopyWat
+      scalarCanopyLiqTrial  = scalarCanopyLiq
+      scalarCanopyIceTrial  = scalarCanopyIce
+      mLayerTempTrial           = mLayerTemp
+      mLayerVolFracWatTrial     = mLayerVolFracWat
+      mLayerVolFracLiqTrial     = mLayerVolFracLiq
+      mLayerVolFracIceTrial     = mLayerVolFracIce
+      mLayerMatricHeadTrial     = mLayerMatricHead      ! total water matric potential
+      mLayerMatricHeadLiqTrial  = mLayerMatricHeadLiq   ! liquid water matric potential
+      scalarAquiferStorageTrial = scalarAquiferStorage
+  
+      ! extract states from the state vector
+      call varExtract(&
+                      ! input
+                      stateVecTrial,            & ! intent(in):    model state vector (mixed units)
+                      diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                      prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                      indx_data,                & ! intent(in):    indices defining model states and layers
+                      ! output: variables for the vegetation canopy
+                      scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
+                      scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
+                      scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
+                      scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                      ! output: variables for the snow-soil domain
+                      mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
+                      mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
+                      mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
+                      mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
+                      mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
+                      ! output: variables for the aquifer
+                      scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                      ! output: error control
+                      err,cmessage)               ! intent(out):   error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+  
+      call varExtract(&
+                    ! input
+                    stateVecPrime,            & ! intent(in):    derivative of model state vector (mixed units)
+                    diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                    prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                    indx_data,                & ! intent(in):    indices defining model states and layers
+                    ! output: variables for the vegetation canopy
+                    scalarCanairTempPrime,    & ! intent(out):   derivative of canopy air temperature (K)
+                    scalarCanopyTempPrime,    & ! intent(out):   derivative of canopy temperature (K)
+                    scalarCanopyWatPrime,     & ! intent(out):   derivative of canopy total water (kg m-2)
+                    scalarCanopyLiqPrime,     & ! intent(out):   derivative of canopy liquid water (kg m-2)
+                    ! output: variables for the snow-soil domain
+                    mLayerTempPrime,          & ! intent(out):   derivative of layer temperature (K)
+                    mLayerVolFracWatPrime,    & ! intent(out):   derivative of volumetric total water content (-)
+                    mLayerVolFracLiqPrime,    & ! intent(out):   derivative of volumetric liquid water content (-)
+                    mLayerMatricHeadPrime,    & ! intent(out):   derivative of total water matric potential (m)
+                    mLayerMatricHeadLiqPrime, & ! intent(out):   derivative of liquid water matric potential (m)
+                    ! output: variables for the aquifer
+                    scalarAquiferStoragePrime,& ! intent(out):   derivative of storage of water in the aquifer (m)
+                    ! output: error control
+                    err,cmessage)               ! intent(out):   error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+  
+  
+      ! update diagnostic variables
+      call updateVarsSundials(&
+                      ! input
+                      dt,                                        &
+                      .false.,                                   & ! intent(in):    logical flag if computing Jacobian for Sundials solver
+                      doAdjustTemp,                              & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
+                      mpar_data,                                 & ! intent(in):    model parameters for a local HRU
+                      indx_data,                                 & ! intent(in):    indices defining model states and layers
+                      prog_data,                                 & ! intent(in):    model prognostic variables for a local HRU
+                      mLayerVolFracWatTrial,                     & ! intent(in):    use current vector for prev vector of volumetric total water content (-)
+                      mLayerMatricHeadTrial,                     & ! intent(in):    use current vector for prev vector of total water matric potential (m)
+                      diag_data,                                 & ! intent(inout): model diagnostic variables for a local HRU
+                      deriv_data,                                & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                      ! output: variables for the vegetation canopy
+                      scalarCanopyTempTrial,                     & ! intent(inout): trial value of canopy temperature (K)
+                      scalarCanopyWatTrial,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                      scalarCanopyLiqTrial,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                      scalarCanopyIceTrial,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                      scalarCanopyTempPrime,                     & ! intent(inout): trial value of canopy temperature (K)
+                      scalarCanopyWatPrime,                      & ! intent(inout): trial value of canopy total water (kg m-2)
+                      scalarCanopyLiqPrime,                      & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                      scalarCanopyIcePrime,                      & ! intent(inout): trial value of canopy ice content (kg m-2)
+                      ! output: variables for the snow-soil domain
+                      mLayerTempTrial,                           & ! intent(inout): trial vector of layer temperature (K)
+                      mLayerVolFracWatTrial,                     & ! intent(inout): trial vector of volumetric total water content (-)
+                      mLayerVolFracLiqTrial,                     & ! intent(inout): trial vector of volumetric liquid water content (-)
+                      mLayerVolFracIceTrial,                     & ! intent(inout): trial vector of volumetric ice water content (-)
+                      mLayerMatricHeadTrial,                     & ! intent(inout): trial vector of total water matric potential (m)
+                      mLayerMatricHeadLiqTrial,                  & ! intent(inout): trial vector of liquid water matric potential (m)
+                      mLayerTempPrime,                           & !
+                      mLayerVolFracWatPrime,                     & ! intent(inout): Prime vector of volumetric total water content (-)
+                      mLayerVolFracLiqPrime,                     & ! intent(inout): Prime vector of volumetric liquid water content (-)
+                      mLayerVolFracIcePrime,                     & !
+                      mLayerMatricHeadPrime,                     & ! intent(inout): Prime vector of total water matric potential (m)
+                      mLayerMatricHeadLiqPrime,                  & ! intent(inout): Prime vector of liquid water matric potential (m)
+                      ! output: error control
+                      err,cmessage)                                ! intent(out):   error control
+      if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+  
+      ! ----
+      ! * check energy balance
+      !------------------------
+      ! NOTE: for now, we just compute enthalpy
+      if(checkNrgBalance)then
         ! compute enthalpy at t_{n+1}
-         call t2enthalpy(&
+        call t2enthalpy(&
                     ! input: data structures
                     diag_data,                   & ! intent(in):  model diagnostic variables for a local HRU
                     mpar_data,                   & ! intent(in):  parameter data structure
@@ -824,281 +813,279 @@ module varSubstepSundials_module
                     err,cmessage)                  ! intent(out): error control
         if(err/=0)then; message=trim(message)//trim(cmessage); return; endif
   
-   endif
-  
-   ! -----
-   ! * check mass balance...
-   ! -----------------------
-  
-   ! NOTE: should not need to do this, since mass balance is checked in the solver
-   if(checkMassBalance)then
-  
-    ! check mass balance for the canopy
-    if(ixVegHyd/=integerMissing)then
-  
-     ! handle cases where fluxes empty the canopy
-     fluxNet = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
-     if(-fluxNet*dt > canopyBalance0)then
-  
-      ! --> first add water
-      canopyBalance1 = canopyBalance0 + (scalarRainfall - scalarThroughfallRain)*dt
-  
-      ! --> next, remove canopy evaporation -- put the unsatisfied evap into sensible heat
-      canopyBalance1 = canopyBalance1 + scalarCanopyEvaporation*dt
-      if(canopyBalance1 < 0._rkind)then
-       ! * get superfluous water and energy
-       superflousWat = -canopyBalance1/dt     ! kg m-2 s-1
-       superflousNrg = superflousWat*LH_vap   ! W m-2 (J m-2 s-1)
-       ! * update fluxes and states
-       canopyBalance1          = 0._rkind
-       scalarCanopyEvaporation = scalarCanopyEvaporation + superflousWat
-       scalarLatHeatCanopyEvap = scalarLatHeatCanopyEvap + superflousNrg
-       scalarSenHeatCanopy     = scalarSenHeatCanopy - superflousNrg
-      endif
-  
-      ! --> next, remove canopy drainage
-      canopyBalance1 = canopyBalance1 - scalarCanopyLiqDrainage*dt
-      if(canopyBalance1 < 0._rkind)then
-       superflousWat            = -canopyBalance1/dt     ! kg m-2 s-1
-       canopyBalance1          = 0._rkind
-       scalarCanopyLiqDrainage = scalarCanopyLiqDrainage + superflousWat
       endif
   
-      ! update the trial state
-      scalarCanopyWatTrial = canopyBalance1
-  
-      ! set the modification flag
-      nrgFluxModified = .true.
-  
-     else
-      canopyBalance1  = canopyBalance0 + fluxNet*dt
-      nrgFluxModified = .false.
-     endif  ! cases where fluxes empty the canopy
-  
-     ! check the mass balance
-     fluxNet  = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
-     liqError = (canopyBalance0 + fluxNet*dt) - scalarCanopyWatTrial
-     if(abs(liqError) > absConvTol_liquid*10._rkind*iden_water)then  ! *10 because of precision issues
-      !write(*,'(a,1x,f20.10)') 'dt = ', dt
-      !write(*,'(a,1x,f20.10)') 'scalarCanopyWatTrial       = ', scalarCanopyWatTrial
-      !write(*,'(a,1x,f20.10)') 'canopyBalance0             = ', canopyBalance0
-      !write(*,'(a,1x,f20.10)') 'canopyBalance1             = ', canopyBalance1
-      !write(*,'(a,1x,f20.10)') 'scalarRainfall*dt          = ', scalarRainfall*dt
-      !write(*,'(a,1x,f20.10)') 'scalarCanopyLiqDrainage*dt = ', scalarCanopyLiqDrainage*dt
-      !write(*,'(a,1x,f20.10)') 'scalarCanopyEvaporation*dt = ', scalarCanopyEvaporation*dt
-      !write(*,'(a,1x,f20.10)') 'scalarThroughfallRain*dt   = ', scalarThroughfallRain*dt
-      !write(*,'(a,1x,f20.10)') 'liqError                   = ', liqError
-      waterBalanceError = .true.
-      return
-     endif  ! if there is a water balance error
-    endif  ! if veg canopy
-  
-    ! check mass balance for soil
-    ! NOTE: fatal errors, though possible to recover using negative error codes
-   if(count(ixSoilOnlyHyd/=integerMissing)==nSoil)then
-     soilBalance1 = sum( (mLayerVolFracLiqTrial(nSnow+1:nLayers) + mLayerVolFracIceTrial(nSnow+1:nLayers) )*mLayerDepth(nSnow+1:nLayers) )
-     vertFlux     = -(iLayerLiqFluxSoil(nSoil) - iLayerLiqFluxSoil(0))*dt  ! m s-1 --> m
-     tranSink     = sum(mLayerTranspire)*dt                                ! m s-1 --> m
-     baseSink     = sum(mLayerBaseflow)*dt                                 ! m s-1 --> m
-     compSink     = sum(mLayerCompress(1:nSoil) * mLayerDepth(nSnow+1:nLayers) ) ! dimensionless --> m
-     liqError     = soilBalance1 - (soilBalance0 + vertFlux + tranSink - baseSink - compSink)
-     if(abs(liqError) > absConvTol_liquid*10._rkind)then   ! *10 because of precision issues
-      !write(*,'(a,1x,f20.10)') 'dt = ', dt
-      !write(*,'(a,1x,f20.10)') 'soilBalance0      = ', soilBalance0
-      !write(*,'(a,1x,f20.10)') 'soilBalance1      = ', soilBalance1
-      !write(*,'(a,1x,f20.10)') 'vertFlux          = ', vertFlux
-      !write(*,'(a,1x,f20.10)') 'tranSink          = ', tranSink
-      !write(*,'(a,1x,f20.10)') 'baseSink          = ', baseSink
-      !write(*,'(a,1x,f20.10)') 'compSink          = ', compSink
-      !write(*,'(a,1x,f20.10)') 'liqError          = ', liqError
-      !write(*,'(a,1x,f20.10)') 'absConvTol_liquid = ', absConvTol_liquid
-      waterBalanceError = .true.
-      return
-    endif  ! if there is a water balance error
-   endif  ! if hydrology states exist in the soil domain
-  
-  endif  ! if checking the mass balance
-  
-   ! -----
-   ! * remove untapped melt energy...
-   ! --------------------------------
-  
-   ! only work with energy state variables
-   if(size(ixNrgOnly)>0)then  ! energy state variables exist
-  
-    ! loop through energy state variables
-    do iState=1,size(ixNrgOnly)
-  
-     ! get index of the control volume within the domain
-     ixSubset       = ixNrgOnly(iState)             ! index within the state subset
-     ixFullVector   = ixMapSubset2Full(ixSubset)    ! index within full state vector
-     ixControlIndex = ixControlVolume(ixFullVector) ! index within a given domain
-  
-     ! compute volumetric melt (kg m-3)
-     volMelt = dt*untappedMelt(ixSubset)/LH_fus  ! (kg m-3)
-  
-     ! update ice content
-     select case( ixDomainType(ixFullVector) )
-      case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
-      case(iname_veg);  scalarCanopyIceTrial                        = scalarCanopyIceTrial                        - volMelt*canopyDepth  ! (kg m-2)
-      case(iname_snow); mLayerVolFracIceTrial(ixControlIndex)       = mLayerVolFracIceTrial(ixControlIndex)       - volMelt/iden_ice     ! (-)
-      case(iname_soil); mLayerVolFracIceTrial(ixControlIndex+nSnow) = mLayerVolFracIceTrial(ixControlIndex+nSnow) - volMelt/iden_water   ! (-)
-      case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
-     end select
-  
-     ! update liquid water content
-     select case( ixDomainType(ixFullVector) )
-      case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
-      case(iname_veg);  scalarCanopyLiqTrial                        = scalarCanopyLiqTrial                        + volMelt*canopyDepth  ! (kg m-2)
-      case(iname_snow); mLayerVolFracLiqTrial(ixControlIndex)       = mLayerVolFracLiqTrial(ixControlIndex)       + volMelt/iden_water   ! (-)
-      case(iname_soil); mLayerVolFracLiqTrial(ixControlIndex+nSnow) = mLayerVolFracLiqTrial(ixControlIndex+nSnow) + volMelt/iden_water   ! (-)
-      case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
-     end select
-  
-    end do  ! looping through energy variables
-  
-    ! ========================================================================================================
-  
-    ! *** ice
-  
-    ! --> check if we removed too much water
-    if(scalarCanopyIceTrial < 0._rkind  .or. any(mLayerVolFracIceTrial < 0._rkind) )then
-  
-     ! **
-     ! canopy within numerical precision
-     if(scalarCanopyIceTrial < 0._rkind)then
-  
-      if(scalarCanopyIceTrial > -verySmall)then
-       scalarCanopyLiqTrial = scalarCanopyLiqTrial - scalarCanopyIceTrial
-       scalarCanopyIceTrial = 0._rkind
-  
-      ! encountered an inconsistency: spit the dummy
-      else
-       print*, 'dt = ', dt
-       print*, 'untappedMelt          = ', untappedMelt
-       print*, 'untappedMelt*dt       = ', untappedMelt*dt
-       print*, 'scalarCanopyiceTrial  = ', scalarCanopyIceTrial
-       message=trim(message)//'melted more than the available water'
-       err=20; return
-      endif  ! (inconsistency)
-  
-     endif  ! if checking the canopy
-     ! **
-     ! snow+soil within numerical precision
-     do iState=1,size(mLayerVolFracIceTrial)
-  
-      ! snow layer within numerical precision
-      if(mLayerVolFracIceTrial(iState) < 0._rkind)then
-  
-       if(mLayerVolFracIceTrial(iState) > -verySmall)then
-        mLayerVolFracLiqTrial(iState) = mLayerVolFracLiqTrial(iState) - mLayerVolFracIceTrial(iState)
-        mLayerVolFracIceTrial(iState) = 0._rkind
-  
-       ! encountered an inconsistency: spit the dummy
-       else
-        print*, 'dt = ', dt
-        print*, 'untappedMelt          = ', untappedMelt
-        print*, 'untappedMelt*dt       = ', untappedMelt*dt
-        print*, 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial
-        message=trim(message)//'melted more than the available water'
-        err=20; return
-       endif  ! (inconsistency)
-  
-      endif  ! if checking a snow layer
-  
-     end do ! (looping through state variables)
-  
-    endif  ! (if we removed too much water)
-  
-    ! ========================================================================================================
-  
-    ! *** liquid water
-  
-    ! --> check if we removed too much water
-    if(scalarCanopyLiqTrial < 0._rkind  .or. any(mLayerVolFracLiqTrial < 0._rkind) )then
-  
-     ! **
-     ! canopy within numerical precision
-     if(scalarCanopyLiqTrial < 0._rkind)then
-  
-      if(scalarCanopyLiqTrial > -verySmall)then
-       scalarCanopyIceTrial = scalarCanopyIceTrial - scalarCanopyLiqTrial
-       scalarCanopyLiqTrial = 0._rkind
-  
-  
-      ! encountered an inconsistency: spit the dummy
-      else
-       print*, 'dt = ', dt
-       print*, 'untappedMelt          = ', untappedMelt
-       print*, 'untappedMelt*dt       = ', untappedMelt*dt
-       print*, 'scalarCanopyLiqTrial  = ', scalarCanopyLiqTrial
-       message=trim(message)//'frozen more than the available water'
-       err=20; return
-      endif  ! (inconsistency)
-  
-     endif  ! checking the canopy
-  
-     ! **
-     ! snow+soil within numerical precision
-     do iState=1,size(mLayerVolFracLiqTrial)
-  
-      ! snow layer within numerical precision
-      if(mLayerVolFracLiqTrial(iState) < 0._rkind)then
-  
-       if(mLayerVolFracLiqTrial(iState) > -verySmall)then
-        mLayerVolFracIceTrial(iState) = mLayerVolFracIceTrial(iState) - mLayerVolFracLiqTrial(iState)
-        mLayerVolFracLiqTrial(iState) = 0._rkind
-  
-       ! encountered an inconsistency: spit the dummy
-       else
-        print*, 'dt = ', dt
-        print*, 'untappedMelt          = ', untappedMelt
-        print*, 'untappedMelt*dt       = ', untappedMelt*dt
-        print*, 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial
-        message=trim(message)//'frozen more than the available water'
-        err=20; return
-       endif  ! (inconsistency)
-  
-      endif  ! checking a snow layer
-  
-     end do ! (looping through state variables)
-  
-    endif  ! (if we removed too much water)
-  
-   endif  ! (if energy state variables exist)
-  
-   ! -----
-   ! * update enthalpy as a diagnostic variable...
-   ! --------------------------------
-   scalarCanairEnthalpy = scalarCanairEnthalpyTrial
-   scalarCanopyEnthalpy = scalarCanopyEnthalpyTrial
-   mLayerEnthalpy = mLayerEnthalpyTrial
-  
-   ! -----
-   ! * update prognostic variables...
-   ! --------------------------------
-    ! update state variables for the vegetation canopy
-   scalarCanairTemp    = scalarCanairTempTrial    ! trial value of canopy air temperature (K)
-   scalarCanopyTemp    = scalarCanopyTempTrial    ! trial value of canopy temperature (K)
-   scalarCanopyWat     = scalarCanopyWatTrial     ! trial value of canopy total water (kg m-2)
-   scalarCanopyLiq     = scalarCanopyLiqTrial     ! trial value of canopy liquid water (kg m-2)
-   scalarCanopyIce     = scalarCanopyIceTrial     ! trial value of canopy ice content (kg m-2)
-  
-   ! update state variables for the snow+soil domain
-   mLayerTemp          = mLayerTempTrial          ! trial vector of layer temperature (K)
-   mLayerVolFracWat    = mLayerVolFracWatTrial    ! trial vector of volumetric total water content (-)
-   mLayerVolFracLiq    = mLayerVolFracLiqTrial    ! trial vector of volumetric liquid water content (-)
-   mLayerVolFracIce    = mLayerVolFracIceTrial    ! trial vector of volumetric ice water content (-)
-   mLayerMatricHead    = mLayerMatricHeadTrial    ! trial vector of matric head (m)
-   mLayerMatricHeadLiq = mLayerMatricHeadLiqTrial ! trial vector of matric head (m)
-  
-   ! update state variables for the aquifer
-   scalarAquiferStorage = scalarAquiferStorageTrial
-  
-   ! end associations to info in the data structures
-   end associate
-  
-   end subroutine updateProgSundials
+      ! -----
+      ! * check mass balance...
+      ! -----------------------
+  
+      ! NOTE: should not need to do this, since mass balance is checked in the solver
+      if(checkMassBalance)then
+  
+        ! check mass balance for the canopy
+        if(ixVegHyd/=integerMissing)then
+  
+          ! handle cases where fluxes empty the canopy
+          fluxNet = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
+          if(-fluxNet*dt > canopyBalance0)then
+  
+            ! --> first add water
+            canopyBalance1 = canopyBalance0 + (scalarRainfall - scalarThroughfallRain)*dt
+  
+            ! --> next, remove canopy evaporation -- put the unsatisfied evap into sensible heat
+            canopyBalance1 = canopyBalance1 + scalarCanopyEvaporation*dt
+            if(canopyBalance1 < 0._rkind)then
+              ! * get superfluous water and energy
+              superflousWat = -canopyBalance1/dt     ! kg m-2 s-1
+              superflousNrg = superflousWat*LH_vap   ! W m-2 (J m-2 s-1)
+              ! * update fluxes and states
+              canopyBalance1          = 0._rkind
+              scalarCanopyEvaporation = scalarCanopyEvaporation + superflousWat
+              scalarLatHeatCanopyEvap = scalarLatHeatCanopyEvap + superflousNrg
+              scalarSenHeatCanopy     = scalarSenHeatCanopy - superflousNrg
+            endif
+  
+            ! --> next, remove canopy drainage
+            canopyBalance1 = canopyBalance1 - scalarCanopyLiqDrainage*dt
+            if(canopyBalance1 < 0._rkind)then
+              superflousWat            = -canopyBalance1/dt     ! kg m-2 s-1
+              canopyBalance1          = 0._rkind
+              scalarCanopyLiqDrainage = scalarCanopyLiqDrainage + superflousWat
+            endif
+  
+            ! update the trial state
+            scalarCanopyWatTrial = canopyBalance1
+  
+            ! set the modification flag
+            nrgFluxModified = .true.
+  
+          else
+            canopyBalance1  = canopyBalance0 + fluxNet*dt
+            nrgFluxModified = .false.
+          endif  ! cases where fluxes empty the canopy
+  
+          ! check the mass balance
+          fluxNet  = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
+          liqError = (canopyBalance0 + fluxNet*dt) - scalarCanopyWatTrial
+          if(abs(liqError) > absConvTol_liquid*10._rkind*iden_water)then  ! *10 because of precision issues
+            write(*,'(a,1x,f20.10)') 'dt = ', dt
+            write(*,'(a,1x,f20.10)') 'scalarCanopyWatTrial       = ', scalarCanopyWatTrial
+            write(*,'(a,1x,f20.10)') 'canopyBalance0             = ', canopyBalance0
+            write(*,'(a,1x,f20.10)') 'canopyBalance1             = ', canopyBalance1
+            write(*,'(a,1x,f20.10)') 'scalarRainfall*dt          = ', scalarRainfall*dt
+            write(*,'(a,1x,f20.10)') 'scalarCanopyLiqDrainage*dt = ', scalarCanopyLiqDrainage*dt
+            write(*,'(a,1x,f20.10)') 'scalarCanopyEvaporation*dt = ', scalarCanopyEvaporation*dt
+            write(*,'(a,1x,f20.10)') 'scalarThroughfallRain*dt   = ', scalarThroughfallRain*dt
+            write(*,'(a,1x,f20.10)') 'liqError                   = ', liqError
+            waterBalanceError = .true.
+            return
+          endif  ! if there is a water balance error
+        endif  ! if veg canopy
+  
+        ! check mass balance for soil
+        ! NOTE: fatal errors, though possible to recover using negative error codes
+        if(count(ixSoilOnlyHyd/=integerMissing)==nSoil)then
+          soilBalance1 = sum( (mLayerVolFracLiqTrial(nSnow+1:nLayers) + mLayerVolFracIceTrial(nSnow+1:nLayers) )*mLayerDepth(nSnow+1:nLayers) )
+          vertFlux     = -(iLayerLiqFluxSoil(nSoil) - iLayerLiqFluxSoil(0))*dt  ! m s-1 --> m
+          tranSink     = sum(mLayerTranspire)*dt                                ! m s-1 --> m
+          baseSink     = sum(mLayerBaseflow)*dt                                 ! m s-1 --> m
+          compSink     = sum(mLayerCompress(1:nSoil) * mLayerDepth(nSnow+1:nLayers) ) ! dimensionless --> m
+          liqError     = soilBalance1 - (soilBalance0 + vertFlux + tranSink - baseSink - compSink)
+          if(abs(liqError) > absConvTol_liquid*10._rkind)then   ! *10 because of precision issues
+            write(*,'(a,1x,f20.10)') 'dt = ', dt
+            write(*,'(a,1x,f20.10)') 'soilBalance0      = ', soilBalance0
+            write(*,'(a,1x,f20.10)') 'soilBalance1      = ', soilBalance1
+            write(*,'(a,1x,f20.10)') 'vertFlux          = ', vertFlux
+            write(*,'(a,1x,f20.10)') 'tranSink          = ', tranSink
+            write(*,'(a,1x,f20.10)') 'baseSink          = ', baseSink
+            write(*,'(a,1x,f20.10)') 'compSink          = ', compSink
+            write(*,'(a,1x,f20.10)') 'liqError          = ', liqError
+            write(*,'(a,1x,f20.10)') 'absConvTol_liquid = ', absConvTol_liquid
+            waterBalanceError = .true.
+            return
+          endif  ! if there is a water balance error
+        endif  ! if hydrology states exist in the soil domain
+      endif  ! if checking the mass balance
+  
+      ! -----
+      ! * remove untapped melt energy...
+      ! --------------------------------
+  
+      ! only work with energy state variables
+      if(size(ixNrgOnly)>0)then  ! energy state variables exist
+  
+        ! loop through energy state variables
+        do iState=1,size(ixNrgOnly)
+  
+          ! get index of the control volume within the domain
+          ixSubset       = ixNrgOnly(iState)             ! index within the state subset
+          ixFullVector   = ixMapSubset2Full(ixSubset)    ! index within full state vector
+          ixControlIndex = ixControlVolume(ixFullVector) ! index within a given domain
+  
+          ! compute volumetric melt (kg m-3)
+          volMelt = dt*untappedMelt(ixSubset)/LH_fus  ! (kg m-3)
+  
+          ! update ice content
+          select case( ixDomainType(ixFullVector) )
+            case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
+            case(iname_veg);  scalarCanopyIceTrial                        = scalarCanopyIceTrial                        - volMelt*canopyDepth  ! (kg m-2)
+            case(iname_snow); mLayerVolFracIceTrial(ixControlIndex)       = mLayerVolFracIceTrial(ixControlIndex)       - volMelt/iden_ice     ! (-)
+            case(iname_soil); mLayerVolFracIceTrial(ixControlIndex+nSnow) = mLayerVolFracIceTrial(ixControlIndex+nSnow) - volMelt/iden_water   ! (-)
+            case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
+          end select
+  
+          ! update liquid water content
+          select case( ixDomainType(ixFullVector) )
+            case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
+            case(iname_veg);  scalarCanopyLiqTrial                        = scalarCanopyLiqTrial                        + volMelt*canopyDepth  ! (kg m-2)
+            case(iname_snow); mLayerVolFracLiqTrial(ixControlIndex)       = mLayerVolFracLiqTrial(ixControlIndex)       + volMelt/iden_water   ! (-)
+            case(iname_soil); mLayerVolFracLiqTrial(ixControlIndex+nSnow) = mLayerVolFracLiqTrial(ixControlIndex+nSnow) + volMelt/iden_water   ! (-)
+            case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
+          end select
+  
+        end do  ! looping through energy variables
+  
+        ! ========================================================================================================
+  
+        ! *** ice
+  
+        ! --> check if we removed too much water
+        if(scalarCanopyIceTrial < 0._rkind  .or. any(mLayerVolFracIceTrial < 0._rkind) )then
+  
+          ! **
+          ! canopy within numerical precision
+          if(scalarCanopyIceTrial < 0._rkind)then
+  
+            if(scalarCanopyIceTrial > -verySmall)then
+              scalarCanopyLiqTrial = scalarCanopyLiqTrial - scalarCanopyIceTrial
+              scalarCanopyIceTrial = 0._rkind
+  
+            ! encountered an inconsistency: spit the dummy
+            else
+              print*, 'dt = ', dt
+              print*, 'untappedMelt          = ', untappedMelt
+              print*, 'untappedMelt*dt       = ', untappedMelt*dt
+              print*, 'scalarCanopyiceTrial  = ', scalarCanopyIceTrial
+              message=trim(message)//'melted more than the available water'
+              err=20; return
+            endif  ! (inconsistency)
+  
+          endif  ! if checking the canopy
+          ! **
+          ! snow+soil within numerical precision
+          do iState=1,size(mLayerVolFracIceTrial)
+  
+            ! snow layer within numerical precision
+            if(mLayerVolFracIceTrial(iState) < 0._rkind)then
+  
+              if(mLayerVolFracIceTrial(iState) > -verySmall)then
+                mLayerVolFracLiqTrial(iState) = mLayerVolFracLiqTrial(iState) - mLayerVolFracIceTrial(iState)
+                mLayerVolFracIceTrial(iState) = 0._rkind
+  
+              ! encountered an inconsistency: spit the dummy
+              else
+                print*, 'dt = ', dt
+                print*, 'untappedMelt          = ', untappedMelt
+                print*, 'untappedMelt*dt       = ', untappedMelt*dt
+                print*, 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial
+                message=trim(message)//'melted more than the available water'
+                err=20; return
+              endif  ! (inconsistency)
+  
+            endif  ! if checking a snow layer
+  
+          end do ! (looping through state variables)
+  
+        endif  ! (if we removed too much water)
+  
+        ! ========================================================================================================
+  
+        ! *** liquid water
+  
+        ! --> check if we removed too much water
+        if(scalarCanopyLiqTrial < 0._rkind  .or. any(mLayerVolFracLiqTrial < 0._rkind) )then
+  
+          ! **
+          ! canopy within numerical precision
+          if(scalarCanopyLiqTrial < 0._rkind)then
+  
+            if(scalarCanopyLiqTrial > -verySmall)then
+              scalarCanopyIceTrial = scalarCanopyIceTrial - scalarCanopyLiqTrial
+              scalarCanopyLiqTrial = 0._rkind
+  
+  
+            ! encountered an inconsistency: spit the dummy
+            else
+              print*, 'dt = ', dt
+              print*, 'untappedMelt          = ', untappedMelt
+              print*, 'untappedMelt*dt       = ', untappedMelt*dt
+              print*, 'scalarCanopyLiqTrial  = ', scalarCanopyLiqTrial
+              message=trim(message)//'frozen more than the available water'
+              err=20; return
+            endif  ! (inconsistency)
+          endif  ! checking the canopy
+  
+          ! **
+          ! snow+soil within numerical precision
+          do iState=1,size(mLayerVolFracLiqTrial)
+  
+            ! snow layer within numerical precision
+            if(mLayerVolFracLiqTrial(iState) < 0._rkind)then
+  
+              if(mLayerVolFracLiqTrial(iState) > -verySmall)then
+                mLayerVolFracIceTrial(iState) = mLayerVolFracIceTrial(iState) - mLayerVolFracLiqTrial(iState)
+                mLayerVolFracLiqTrial(iState) = 0._rkind
+  
+              ! encountered an inconsistency: spit the dummy
+              else
+                print*, 'dt = ', dt
+                print*, 'untappedMelt          = ', untappedMelt
+                print*, 'untappedMelt*dt       = ', untappedMelt*dt
+                print*, 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial
+                message=trim(message)//'frozen more than the available water'
+                err=20; return
+              endif  ! (inconsistency)
+  
+            endif  ! checking a snow layer
+  
+          end do ! (looping through state variables)
+  
+        endif  ! (if we removed too much water)
+  
+      endif  ! (if energy state variables exist)
+  
+      ! -----
+      ! * update enthalpy as a diagnostic variable...
+      ! --------------------------------
+      scalarCanairEnthalpy = scalarCanairEnthalpyTrial
+      scalarCanopyEnthalpy = scalarCanopyEnthalpyTrial
+      mLayerEnthalpy = mLayerEnthalpyTrial
+  
+      ! -----
+      ! * update prognostic variables...
+      ! --------------------------------
+      ! update state variables for the vegetation canopy
+      scalarCanairTemp    = scalarCanairTempTrial    ! trial value of canopy air temperature (K)
+      scalarCanopyTemp    = scalarCanopyTempTrial    ! trial value of canopy temperature (K)
+      scalarCanopyWat     = scalarCanopyWatTrial     ! trial value of canopy total water (kg m-2)
+      scalarCanopyLiq     = scalarCanopyLiqTrial     ! trial value of canopy liquid water (kg m-2)
+      scalarCanopyIce     = scalarCanopyIceTrial     ! trial value of canopy ice content (kg m-2)
+  
+      ! update state variables for the snow+soil domain
+      mLayerTemp          = mLayerTempTrial          ! trial vector of layer temperature (K)
+      mLayerVolFracWat    = mLayerVolFracWatTrial    ! trial vector of volumetric total water content (-)
+      mLayerVolFracLiq    = mLayerVolFracLiqTrial    ! trial vector of volumetric liquid water content (-)
+      mLayerVolFracIce    = mLayerVolFracIceTrial    ! trial vector of volumetric ice water content (-)
+      mLayerMatricHead    = mLayerMatricHeadTrial    ! trial vector of matric head (m)
+      mLayerMatricHeadLiq = mLayerMatricHeadLiqTrial ! trial vector of matric head (m)
+  
+      ! update state variables for the aquifer
+      scalarAquiferStorage = scalarAquiferStorageTrial
+  
+      ! end associations to info in the data structures
+    end associate
+  
+  end subroutine updateProgSundials
   
   end module varSubstepSundials_module
   
\ No newline at end of file
diff --git a/build/source/engine/systemSolv.f90 b/build/source/engine/systemSolv.f90
index cf83051..9c59345 100755
--- a/build/source/engine/systemSolv.f90
+++ b/build/source/engine/systemSolv.f90
@@ -143,7 +143,7 @@ contains
                        err,message)         ! intent(out):   error code and error message
  ! ---------------------------------------------------------------------------------------
  ! structure allocations
- USE allocspace4chm_module,only:allocLocal                ! allocate local data structures
+ USE allocspace_module,only:allocLocal                ! allocate local data structures
  ! simulation of fluxes and residuals given a trial state vector
  USE eval8summa_module,only:eval8summa                ! simulation of fluxes and residuals given a trial state vector
  USE summaSolve_module,only:summaSolve                ! calculate the iteration increment, evaluate the new state, and refine if necessary
diff --git a/build/source/engine/varSubstep.f90 b/build/source/engine/varSubstep.f90
index d5dd079..3936068 100755
--- a/build/source/engine/varSubstep.f90
+++ b/build/source/engine/varSubstep.f90
@@ -1,5 +1,5 @@
 ! SUMMA - Structure for Unifying Multiple Modeling Alternatives
-! Copyright (C) 2014-2020 NCAR/RAL; University of Saskatchewan; University of Washington
+! Copyright (C) 2014-2015 NCAR/RAL
 !
 ! This file is part of SUMMA
 !
@@ -43,11 +43,11 @@ USE globalData,only:flux_meta       ! metadata on the model fluxes
 ! derived types to define the data structures
 USE data_types,only:&
                     var_i,        & ! data vector (i4b)
-                    var_d,        & ! data vector (dp)
+                    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 (dp)
-                    zLookup,      &
+                    var_dlength,  & ! data vector with variable length dimension (rkind)
+                    zLookup,      & ! data vector with variable length dimension (rkind)
                     model_options   ! defines the model decisions
 
 ! provide access to indices that define elements of the data structures
@@ -74,52 +74,52 @@ private
 public::varSubstep
 
 ! algorithmic parameters
-real(dp),parameter     :: verySmall=1.e-6_dp   ! used as an additive constant to check if substantial difference among real numbers
+real(rkind),parameter     :: verySmall=1.e-6_rkind   ! used as an additive constant to check if substantial difference among real numbers
 
 contains
 
 
-! **********************************************************************************************************
-! public subroutine varSubstep: run the model for a collection of substeps for a given state subset
-! **********************************************************************************************************
-subroutine 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)
-                       nState,            & ! intent(in)    : total number of state variables
-                       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
-                       scalarSolution,    & ! intent(in)    : flag to denote implementing the scalar solution
-                       iStateSplit,       & ! intent(in)    : index of the state in the splitting operation
-                       fluxMask,          & ! intent(in)    : mask for the fluxes used in this given state subset
-                       fluxCount,         & ! intent(inout) : number of times that fluxes are updated (should equal nSubsteps)
-                       ! 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: model 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 to denote success of substepping for a given split
-                       reduceCoupledStep, & ! intent(out)   : flag to denote need to reduce the length of the coupled step
-                       tooMuchMelt,       & ! intent(out)   : flag to denote that ice is insufficient to support melt
-                       err,message)         ! intent(out)   : error code and error message
+  ! **********************************************************************************************************
+  ! public subroutine varSubstep: run the model for a collection of substeps for a given state subset
+  ! **********************************************************************************************************
+  subroutine 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)
+                        nState,            & ! intent(in)    : total number of state variables
+                        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
+                        scalarSolution,    & ! intent(in)    : flag to denote implementing the scalar solution
+                        iStateSplit,       & ! intent(in)    : index of the state in the splitting operation
+                        fluxMask,          & ! intent(in)    : mask for the fluxes used in this given state subset
+                        fluxCount,         & ! intent(inout) : number of times that fluxes are updated (should equal nSubsteps)
+                        ! 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: model 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 to denote success of substepping for a given split
+                        reduceCoupledStep, & ! intent(out)   : flag to denote need to reduce the length of the coupled step
+                        tooMuchMelt,       & ! intent(out)   : flag to denote that ice is insufficient to support melt
+                        err,message)         ! intent(out)   : error code and error message
   ! ---------------------------------------------------------------------------------------
   ! structure allocations
-  USE allocspace4chm_module,only:allocLocal                ! allocate local data structures
+  USE allocspace_module,only:allocLocal                ! allocate local data structures
   ! simulation of fluxes and residuals given a trial state vector
   USE systemSolv_module,only:systemSolv                ! solve the system of equations for one time step
   USE getVectorz_module,only:popStateVec               ! populate the state vector
@@ -132,9 +132,9 @@ subroutine varSubstep(&
   ! * dummy variables
   ! ---------------------------------------------------------------------------------------
   ! input: model control
-  real(dp),intent(in)             :: dt                            ! time step (seconds)
-  real(dp),intent(in)             :: dtInit                        ! initial time step (seconds)
-  real(dp),intent(in)             :: dt_min                        ! minimum time step (seconds)
+  real(rkind),intent(in)             :: dt                            ! time step (seconds)
+  real(rkind),intent(in)             :: dtInit                        ! initial time step (seconds)
+  real(rkind),intent(in)             :: dt_min                        ! minimum time step (seconds)
   integer(i4b),intent(in)         :: nState                        ! total number of state variables
   logical(lgt),intent(in)         :: doAdjustTemp                  ! flag to indicate if we adjust the temperature
   logical(lgt),intent(in)         :: firstSubStep                  ! flag to indicate if we are processing the first sub-step
@@ -159,7 +159,7 @@ subroutine varSubstep(&
   type(var_dlength),intent(in)    :: bvar_data                     ! model variables for the local basin
   ! output: model control
   integer(i4b),intent(inout)      :: ixSaturation                  ! index of the lowest saturated layer (NOTE: only computed on the first iteration)
-  real(dp),intent(out)            :: dtMultiplier                  ! substep multiplier (-)
+  real(rkind),intent(out)            :: dtMultiplier                  ! substep multiplier (-)
   integer(i4b),intent(out)        :: nSubsteps                     ! number of substeps taken for a given split
   logical(lgt),intent(out)        :: failedMinimumStep             ! flag to denote success of substepping for a given split
   logical(lgt),intent(out)        :: reduceCoupledStep             ! flag to denote need to reduce the length of the coupled step
@@ -177,24 +177,24 @@ subroutine varSubstep(&
   integer(i4b)                    :: ixLayer                       ! index in a given domain
   integer(i4b), dimension(1)      :: ixMin,ixMax                   ! bounds of a given flux vector
   ! time stepping
-  real(dp)                        :: dtSum                         ! sum of time from successful steps (seconds)
-  real(dp)                        :: dt_wght                       ! weight given to a given flux calculation
-  real(dp)                        :: dtSubstep                     ! length of a substep (s)
+  real(rkind)                        :: dtSum                         ! sum of time from successful steps (seconds)
+  real(rkind)                        :: dt_wght                       ! weight given to a given flux calculation
+  real(rkind)                        :: dtSubstep                     ! length of a substep (s)
   ! adaptive sub-stepping for the explicit solution
   logical(lgt)                    :: failedSubstep                 ! flag to denote success of substepping for a given split
-  real(dp),parameter              :: safety=0.85_dp                ! safety factor in adaptive sub-stepping
-  real(dp),parameter              :: reduceMin=0.1_dp              ! mimimum factor that time step is reduced
-  real(dp),parameter              :: increaseMax=4.0_dp            ! maximum factor that time step is increased
+  real(rkind),parameter              :: safety=0.85_rkind                ! safety factor in adaptive sub-stepping
+  real(rkind),parameter              :: reduceMin=0.1_rkind              ! mimimum factor that time step is reduced
+  real(rkind),parameter              :: increaseMax=4.0_rkind            ! maximum factor that time step is increased
   ! adaptive sub-stepping for the implicit solution
   integer(i4b)                    :: niter                         ! number of iterations taken
   integer(i4b),parameter          :: n_inc=5                       ! minimum number of iterations to increase time step
   integer(i4b),parameter          :: n_dec=15                      ! maximum number of iterations to decrease time step
-  real(dp),parameter              :: F_inc = 1.25_dp               ! factor used to increase time step
-  real(dp),parameter              :: F_dec = 0.90_dp               ! factor used to decrease time step
+  real(rkind),parameter              :: F_inc = 1.25_rkind               ! factor used to increase time step
+  real(rkind),parameter              :: F_dec = 0.90_rkind               ! factor used to decrease time step
   ! state and flux vectors
-  real(dp)                        :: untappedMelt(nState)          ! un-tapped melt energy (J m-3 s-1)
-  real(dp)                        :: stateVecInit(nState)          ! initial state vector (mixed units)
-  real(dp)                        :: stateVecTrial(nState)         ! trial state vector (mixed units)
+  real(rkind)                        :: untappedMelt(nState)          ! un-tapped melt energy (J m-3 s-1)
+  real(rkind)                        :: stateVecInit(nState)          ! initial state vector (mixed units)
+  real(rkind)                        :: stateVecTrial(nState)         ! trial state vector (mixed units)
   type(var_dlength)               :: flux_temp                     ! temporary model fluxes
   ! flags
   logical(lgt)                    :: firstSplitOper                ! flag to indicate if we are processing the first flux call in a splitting operation
@@ -202,38 +202,38 @@ subroutine varSubstep(&
   logical(lgt)                    :: waterBalanceError             ! flag to denote that there is a water balance error
   logical(lgt)                    :: nrgFluxModified               ! flag to denote that the energy fluxes were modified
   ! energy fluxes
-  real(dp)                        :: sumCanopyEvaporation          ! sum of canopy evaporation/condensation (kg m-2 s-1)
-  real(dp)                        :: sumLatHeatCanopyEvap          ! sum of latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-  real(dp)                        :: sumSenHeatCanopy              ! sum of sensible heat flux from the canopy to the canopy air space (W m-2)
-  real(dp)                        :: sumSoilCompress
-  real(dp),allocatable            :: sumLayerCompress(:)
+  real(rkind)                        :: sumCanopyEvaporation          ! sum of canopy evaporation/condensation (kg m-2 s-1)
+  real(rkind)                        :: sumLatHeatCanopyEvap          ! sum of latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+  real(rkind)                        :: sumSenHeatCanopy              ! sum of sensible heat flux from the canopy to the canopy air space (W m-2)
+  real(rkind)                        :: sumSoilCompress
+  real(rkind),allocatable            :: sumLayerCompress(:)
   ! ---------------------------------------------------------------------------------------
   ! point to variables in the data structures
   ! ---------------------------------------------------------------------------------------
   globalVars: associate(&
-    ! 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
-    nSoilOnlyHyd            => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology variables in the soil domain
-    mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
-    ! mapping between state vectors and control volumes
-    ixLayerActive           => indx_data%var(iLookINDEX%ixLayerActive)%dat            ,& ! intent(in):    [i4b(:)] list of indices for all active layers (inactive=integerMissing)
-    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)
-    ! model state variables (vegetation canopy)
-    scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the canopy air space (K)
-    scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the vegetation canopy (K)
-    scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(inout): [dp]     mass of ice on the vegetation canopy (kg m-2)
-    scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(inout): [dp]     mass of liquid water on the vegetation canopy (kg m-2)
-    scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(inout): [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(inout): [dp(:)]  temperature of each snow/soil layer (K)
-    mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of ice (-)
-    mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of liquid water (-)
-    mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of total water (-)
-    mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
-    mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(inout): [dp(:)]  matric potential of liquid water (m)
+  ! 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
+  nSoilOnlyHyd            => indx_data%var(iLookINDEX%nSoilOnlyHyd )%dat(1)         ,& ! intent(in):    [i4b]    number of hydrology variables in the soil domain
+  mLayerDepth             => prog_data%var(iLookPROG%mLayerDepth)%dat               ,& ! intent(in):    [dp(:)]  depth of each layer in the snow-soil sub-domain (m)
+  ! mapping between state vectors and control volumes
+  ixLayerActive           => indx_data%var(iLookINDEX%ixLayerActive)%dat            ,& ! intent(in):    [i4b(:)] list of indices for all active layers (inactive=integerMissing)
+  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)
+  ! model state variables (vegetation canopy)
+  scalarCanairTemp        => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the canopy air space (K)
+  scalarCanopyTemp        => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)       ,& ! intent(inout): [dp]     temperature of the vegetation canopy (K)
+  scalarCanopyIce         => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)        ,& ! intent(inout): [dp]     mass of ice on the vegetation canopy (kg m-2)
+  scalarCanopyLiq         => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)        ,& ! intent(inout): [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+  scalarCanopyWat         => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)        ,& ! intent(inout): [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(inout): [dp(:)]  temperature of each snow/soil layer (K)
+  mLayerVolFracIce        => prog_data%var(iLookPROG%mLayerVolFracIce)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of ice (-)
+  mLayerVolFracLiq        => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of liquid water (-)
+  mLayerVolFracWat        => prog_data%var(iLookPROG%mLayerVolFracWat)%dat          ,& ! intent(inout): [dp(:)]  volumetric fraction of total water (-)
+  mLayerMatricHead        => prog_data%var(iLookPROG%mLayerMatricHead)%dat          ,& ! intent(inout): [dp(:)]  matric head (m)
+  mLayerMatricHeadLiq     => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat        & ! intent(inout): [dp(:)]  matric potential of liquid water (m)
   )  ! end association with variables in the data structures
   ! *********************************************************************************************************************************************************
   ! *********************************************************************************************************************************************************
@@ -254,22 +254,21 @@ subroutine varSubstep(&
 
   ! initialize the model fluxes (some model fluxes are not computed in the iterations)
   do iVar=1,size(flux_data%var)
-    flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
+  flux_temp%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:)
   end do
 
   ! initialize the total energy fluxes (modified in updateProg)
-  sumCanopyEvaporation = 0._dp  ! canopy evaporation/condensation (kg m-2 s-1)
-  sumLatHeatCanopyEvap = 0._dp  ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-  sumSenHeatCanopy     = 0._dp  ! sensible heat flux from the canopy to the canopy air space (W m-2)
-  sumSoilCompress      = 0._dp  ! total soil compression
-
-  allocate(sumLayerCompress(nSoil)); sumLayerCompress = 0._dp ! soil compression by layer
+  sumCanopyEvaporation = 0._rkind  ! canopy evaporation/condensation (kg m-2 s-1)
+  sumLatHeatCanopyEvap = 0._rkind  ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+  sumSenHeatCanopy     = 0._rkind  ! sensible heat flux from the canopy to the canopy air space (W m-2)
+  sumSoilCompress      = 0._rkind  ! total soil compression
+  allocate(sumLayerCompress(nSoil)); sumLayerCompress = 0._rkind ! soil compression by layer
 
   ! define the first flux call in a splitting operation
   firstSplitOper = (.not.scalarSolution .or. iStateSplit==1)
 
   ! initialize subStep
-  dtSum     = 0._dp  ! keep track of the portion of the time step that is completed
+  dtSum     = 0._rkind  ! keep track of the portion of the time step that is completed
   nSubsteps = 0
 
   ! loop through substeps
@@ -289,14 +288,14 @@ subroutine varSubstep(&
 
   ! initialize state vectors
   call popStateVec(&
-                   ! input
-                   nState,                           & ! intent(in):    number of desired state variables
-                   prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
-                   diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
-                   indx_data,                        & ! intent(in):    indices defining model states and layers
-                   ! output
-                   stateVecInit,                     & ! intent(out):   initial model state vector (mixed units)
-                   err,cmessage)                       ! intent(out):   error control
+                    ! input
+                    nState,                           & ! intent(in):    number of desired state variables
+                    prog_data,                        & ! intent(in):    model prognostic variables for a local HRU
+                    diag_data,                        & ! intent(in):    model diagnostic variables for a local HRU
+                    indx_data,                        & ! intent(in):    indices defining model states and layers
+                    ! output
+                    stateVecInit,                     & ! intent(out):   initial model state vector (mixed units)
+                    err,cmessage)                       ! intent(out):   error control
   if(err/=0)then; message=trim(message)//trim(cmessage); return; endif  ! (check for errors)
 
   ! -----
@@ -336,8 +335,8 @@ subroutine varSubstep(&
                   niter,             & ! intent(out):   number of iterations taken
                   err,cmessage)        ! intent(out):   error code and error message
   if(err/=0)then
-   message=trim(message)//trim(cmessage)
-   if(err>0) return
+    message=trim(message)//trim(cmessage)
+    if(err>0) return
   endif
 
   ! if too much melt or need to reduce length of the coupled step then return
@@ -349,23 +348,23 @@ subroutine varSubstep(&
 
   ! check
   if(globalPrintFlag)then
-   print*, 'niter, failedSubstep, dtSubstep = ', niter, failedSubstep, dtSubstep
-   print*, trim(cmessage)
+    print*, 'niter, failedSubstep, dtSubstep = ', niter, failedSubstep, dtSubstep
+    print*, trim(cmessage)
   endif
 
   ! reduce step based on failure
   if(failedSubstep)then
     err=0; message='varSubstep/'  ! recover from failed convergence
-    dtMultiplier  = 0.5_dp        ! system failure: step halving
+    dtMultiplier  = 0.5_rkind        ! system failure: step halving
   else
 
-   ! ** implicit Euler: adjust step length based on iteration count
+    ! ** implicit Euler: adjust step length based on iteration count
     if(niter<n_inc)then
-     dtMultiplier = F_inc
+      dtMultiplier = F_inc
     elseif(niter>n_dec)then
-     dtMultiplier = F_dec
+      dtMultiplier = F_dec
     else
-     dtMultiplier = 1._dp
+      dtMultiplier = 1._rkind
     endif
 
   endif  ! switch between failure and success
@@ -373,16 +372,16 @@ subroutine varSubstep(&
   ! check if we failed the substep
   if(failedSubstep)then
 
-   ! check that the substep is greater than the minimum step
-   if(dtSubstep*dtMultiplier<dt_min)then
+    ! check that the substep is greater than the minimum step
+    if(dtSubstep*dtMultiplier<dt_min)then
     ! --> exit, and either (1) try another solution method; or (2) reduce coupled step
     failedMinimumStep=.true.
     exit subSteps
 
-   else ! step is still OK
+    else ! step is still OK
     dtSubstep = dtSubstep*dtMultiplier
     cycle subSteps
-   endif  ! if step is less than the minimum
+    endif  ! if step is less than the minimum
 
   endif  ! if failed the substep
 
@@ -394,8 +393,8 @@ subroutine varSubstep(&
 
   ! NOTE: we get to here if iterations are successful
   if(err/=0)then
-   message=trim(message)//'expect err=0 if updating fluxes'
-   return
+    message=trim(message)//'expect err=0 if updating fluxes'
+    return
   endif
 
   ! identify the need to check the mass balance
@@ -404,17 +403,17 @@ subroutine varSubstep(&
   ! update prognostic variables
   call updateProg(dtSubstep,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,checkMassBalance, & ! input: model control
                   lookup_data,mpar_data,indx_data,flux_temp,prog_data,diag_data,deriv_data,                              & ! input-output: data structures
-                  waterBalanceError,nrgFluxModified,tooMuchMelt,err,cmessage)                                              ! output: flags and error control
+                  waterBalanceError,nrgFluxModified,err,cmessage)                                                           ! output: flags and error control
   if(err/=0)then
-   message=trim(message)//trim(cmessage)
-   if(err>0) return
+    message=trim(message)//trim(cmessage)
+    if(err>0) return
   endif
 
   ! if water balance error then reduce the length of the coupled step
-  if(waterBalanceError .or. tooMuchMelt)then
-   message=trim(message)//'water balance error'
-   reduceCoupledStep=.true.
-   err=-20; return
+  if(waterBalanceError)then
+    message=trim(message)//'water balance error'
+    reduceCoupledStep=.true.
+    err=-20; return
   endif
 
   if(globalPrintFlag)&
@@ -423,42 +422,42 @@ subroutine varSubstep(&
   ! recover from errors in prognostic update
   if(err<0)then
 
-   ! modify step
-   err=0  ! error recovery
-   dtSubstep = dtSubstep/2._dp
+    ! modify step
+    err=0  ! error recovery
+    dtSubstep = dtSubstep/2._rkind
 
-   ! check minimum: fail minimum step if there is an error in the update
-   if(dtSubstep<dt_min)then
+    ! check minimum: fail minimum step if there is an error in the update
+    if(dtSubstep<dt_min)then
     failedMinimumStep=.true.
     exit subSteps
-   ! minimum OK -- try again
-   else
+    ! minimum OK -- try again
+    else
     cycle substeps
-   endif
+    endif
 
   endif  ! if errors in prognostic update
 
   ! get the total energy fluxes (modified in updateProg)
   if(nrgFluxModified .or. indx_data%var(iLookINDEX%ixVegNrg)%dat(1)/=integerMissing)then
-   sumCanopyEvaporation = sumCanopyEvaporation + dtSubstep*flux_temp%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
-   sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dtSubstep*flux_temp%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   sumSenHeatCanopy     = sumSenHeatCanopy     + dtSubstep*flux_temp%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
+    sumCanopyEvaporation = sumCanopyEvaporation + dtSubstep*flux_temp%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
+    sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dtSubstep*flux_temp%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+    sumSenHeatCanopy     = sumSenHeatCanopy     + dtSubstep*flux_temp%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
   else
-   sumCanopyEvaporation = sumCanopyEvaporation + dtSubstep*flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
-   sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dtSubstep*flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
-   sumSenHeatCanopy     = sumSenHeatCanopy     + dtSubstep*flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
+    sumCanopyEvaporation = sumCanopyEvaporation + dtSubstep*flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) ! canopy evaporation/condensation (kg m-2 s-1)
+    sumLatHeatCanopyEvap = sumLatHeatCanopyEvap + dtSubstep*flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+    sumSenHeatCanopy     = sumSenHeatCanopy     + dtSubstep*flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     ! sensible heat flux from the canopy to the canopy air space (W m-2)
   endif  ! if energy fluxes were modified
 
   ! get the total soil compression
   if (count(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat/=integerMissing)>0) then
-   ! scalar compression
-   if(.not.scalarSolution .or. iStateSplit==nSoil)&
-   sumSoilCompress = sumSoilCompress + diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) ! total soil compression
-   ! vector compression
-   do iSoil=1,nSoil
+    ! scalar compression
+    if(.not.scalarSolution .or. iStateSplit==nSoil)&
+    sumSoilCompress = sumSoilCompress + diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) ! total soil compression
+    ! vector compression
+    do iSoil=1,nSoil
     if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
     sumLayerCompress(iSoil) = sumLayerCompress(iSoil) + diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) ! soil compression in layers
-   end do
+    end do
   endif
 
   ! print progress
@@ -468,37 +467,28 @@ subroutine varSubstep(&
   ! increment fluxes
   dt_wght = dtSubstep/dt ! (define weight applied to each splitting operation)
   do iVar=1,size(flux_meta)
-   if(count(fluxMask%var(iVar)%dat)>0) then
+    if(count(fluxMask%var(iVar)%dat)>0) then
 
     !print*, flux_meta(iVar)%varname, fluxMask%var(iVar)%dat
 
     ! ** no domain splitting
     if(count(ixLayerActive/=integerMissing)==nLayers)then
-     flux_data%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:) + flux_temp%var(iVar)%dat(:)*dt_wght
-     fluxCount%var(iVar)%dat(:) = fluxCount%var(iVar)%dat(:) + 1
+      flux_data%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:) + flux_temp%var(iVar)%dat(:)*dt_wght
+      fluxCount%var(iVar)%dat(:) = fluxCount%var(iVar)%dat(:) + 1
 
     ! ** domain splitting
     else
-     ixMin=lbound(flux_data%var(iVar)%dat)
-     ixMax=ubound(flux_data%var(iVar)%dat)
-     do ixLayer=ixMin(1),ixMax(1)
+      ixMin=lbound(flux_data%var(iVar)%dat)
+      ixMax=ubound(flux_data%var(iVar)%dat)
+      do ixLayer=ixMin(1),ixMax(1)
       if(fluxMask%var(iVar)%dat(ixLayer)) then
-
-       ! special case of the transpiration sink from soil layers: only computed for the top soil layer
-       if(iVar==iLookFlux%mLayerTranspire)then
-         if(ixLayer==1)  flux_data%var(iVar)%dat(:) = flux_data%var(iVar)%dat(:) + flux_temp%var(iVar)%dat(:)*dt_wght
-
-       ! standard case
-       else
         flux_data%var(iVar)%dat(ixLayer) = flux_data%var(iVar)%dat(ixLayer) + flux_temp%var(iVar)%dat(ixLayer)*dt_wght
-       endif
-       fluxCount%var(iVar)%dat(ixLayer) = fluxCount%var(iVar)%dat(ixLayer) + 1
-
+        fluxCount%var(iVar)%dat(ixLayer) = fluxCount%var(iVar)%dat(ixLayer) + 1
       endif
-     end do
+      end do
     endif  ! (domain splitting)
 
-   endif   ! (if the flux is desired)
+    endif   ! (if the flux is desired)
   end do  ! (loop through fluxes)
 
   ! ------------------------------------------------------
@@ -513,274 +503,278 @@ subroutine varSubstep(&
 
   ! check that we have completed the sub-step
   if(dtSum >= dt-verySmall)then
-   failedMinimumStep=.false.
-   exit subSteps
+    failedMinimumStep=.false.
+    exit subSteps
   endif
 
   ! adjust length of the sub-step (make sure that we don't exceed the step)
   dtSubstep = min(dt - dtSum, max(dtSubstep*dtMultiplier, dt_min) )
 
- end do substeps  ! time steps for variable-dependent sub-stepping
+  end do substeps  ! time steps for variable-dependent sub-stepping
 
- ! save the energy fluxes
- flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) = sumCanopyEvaporation /dt      ! canopy evaporation/condensation (kg m-2 s-1)
- flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) = sumLatHeatCanopyEvap /dt      ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
- flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     = sumSenHeatCanopy     /dt      ! sensible heat flux from the canopy to the canopy air space (W m-2)
+  ! save the energy fluxes
+  flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1) = sumCanopyEvaporation /dt      ! canopy evaporation/condensation (kg m-2 s-1)
+  flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1) = sumLatHeatCanopyEvap /dt      ! latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+  flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)     = sumSenHeatCanopy     /dt      ! sensible heat flux from the canopy to the canopy air space (W m-2)
 
- ! save the soil compression diagnostics
- diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sumSoilCompress
- do iSoil=1,nSoil
+  ! save the soil compression diagnostics
+  diag_data%var(iLookDIAG%scalarSoilCompress)%dat(1) = sumSoilCompress
+  do iSoil=1,nSoil
   if(indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat(iSoil)/=integerMissing)&
   diag_data%var(iLookDIAG%mLayerCompress)%dat(iSoil) = sumLayerCompress(iSoil)
- end do
- deallocate(sumLayerCompress)
+  end do
+  deallocate(sumLayerCompress)
 
- ! end associate statements
- end associate globalVars
+  ! end associate statements
+  end associate globalVars
 
- ! update error codes
- if(failedMinimumStep)then
+  ! update error codes
+  if(failedMinimumStep)then
   err=-20 ! negative = recoverable error
   message=trim(message)//'failed minimum step'
- endif
-
- end subroutine varSubstep
-
-
- ! **********************************************************************************************************
- ! private subroutine updateProg: update prognostic variables
- ! **********************************************************************************************************
- subroutine updateProg(dt,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,checkMassBalance, & ! input: model control
-                      lookup_data,mpar_data,indx_data,flux_data,prog_data,diag_data,deriv_data,                       & ! input-output: data structures
-                       waterBalanceError,nrgFluxModified,tooMuchMelt,err,message)                                        ! output: flags and error control
- USE getVectorz_module,only:varExtract                             ! extract variables from the state vector
- USE updateVars_module,only:updateVars                             ! update prognostic variables
- implicit none
- ! model control
- real(dp)         ,intent(in)    :: dt                             ! time step (s)
- integer(i4b)     ,intent(in)    :: nSnow                          ! number of snow layers
- integer(i4b)     ,intent(in)    :: nSoil                          ! number of soil layers
- integer(i4b)     ,intent(in)    :: nLayers                        ! total number of layers
- logical(lgt)     ,intent(in)    :: doAdjustTemp                   ! flag to indicate if we adjust the temperature
- logical(lgt)     ,intent(in)    :: computeVegFlux                 ! flag to compute the vegetation flux
- real(dp)         ,intent(in)    :: untappedMelt(:)                ! un-tapped melt energy (J m-3 s-1)
- real(dp)         ,intent(in)    :: stateVecTrial(:)               ! trial state vector (mixed units)
- logical(lgt)     ,intent(in)    :: checkMassBalance               ! flag to check the mass balance
- ! data structures
- type(zLookup),    intent(in)    :: lookup_data                    ! lookup tables
- type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
- type(var_ilength),intent(in)    :: indx_data                      ! indices for a local HRU
- type(var_dlength),intent(inout) :: flux_data                      ! model fluxes 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) :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
- ! flags and error control
- logical(lgt)     ,intent(out)   :: waterBalanceError              ! flag to denote that there is a water balance error
- logical(lgt)     ,intent(out)   :: nrgFluxModified                ! flag to denote that the energy fluxes were modified
- logical(lgt)     ,intent(out)   :: tooMuchMelt                    ! flag to denote that the energy fluxes were modified
- integer(i4b)     ,intent(out)   :: err                            ! error code
- character(*)     ,intent(out)   :: message                        ! error message
- ! ==================================================================================================================
- ! general
- integer(i4b)                    :: iState                         ! index of model state variable
- integer(i4b)                    :: ixSubset                       ! index within the state subset
- integer(i4b)                    :: ixFullVector                   ! index within full state vector
- integer(i4b)                    :: ixControlIndex                 ! index within a given domain
- real(dp)                        :: volMelt                        ! volumetric melt (kg m-3)
- real(dp),parameter              :: verySmall=epsilon(1._dp)*2._dp ! a very small number (deal with precision issues)
- ! mass balance
- real(dp)                        :: canopyBalance0,canopyBalance1  ! canopy storage at start/end of time step
- real(dp)                        :: soilBalance0,soilBalance1      ! soil storage at start/end of time step
- real(dp)                        :: vertFlux                       ! change in storage due to vertical fluxes
- real(dp)                        :: tranSink,baseSink,compSink     ! change in storage due to sink terms
- real(dp)                        :: liqError                       ! water balance error
- real(dp)                        :: fluxNet                        ! net water fluxes (kg m-2 s-1)
- real(dp)                        :: superflousWat                  ! superflous water used for evaporation (kg m-2 s-1)
- real(dp)                        :: superflousNrg                  ! superflous energy that cannot be used for evaporation (W m-2 [J m-2 s-1])
- character(LEN=256)              :: cmessage                       ! error message of downwind routine
- ! trial state variables
- real(dp)                        :: scalarCanairTempTrial          ! trial value for temperature of the canopy air space (K)
- real(dp)                        :: scalarCanopyTempTrial          ! trial value for temperature of the vegetation canopy (K)
- real(dp)                        :: scalarCanopyWatTrial           ! trial value for liquid water storage in the canopy (kg m-2)
- real(dp),dimension(nLayers)     :: mLayerTempTrial                ! trial vector for temperature of layers in the snow and soil domains (K)
- real(dp),dimension(nLayers)     :: mLayerVolFracWatTrial          ! trial vector for volumetric fraction of total water (-)
- real(dp),dimension(nSoil)       :: mLayerMatricHeadTrial          ! trial vector for total water matric potential (m)
- real(dp),dimension(nSoil)       :: mLayerMatricHeadLiqTrial       ! trial vector for liquid water matric potential (m)
- real(dp)                        :: scalarAquiferStorageTrial      ! trial value for storage of water in the aquifer (m)
- ! diagnostic variables
- real(dp)                        :: scalarCanopyLiqTrial           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
- real(dp)                        :: scalarCanopyIceTrial           ! trial value for mass of ice on the vegetation canopy (kg m-2)
- real(dp),dimension(nLayers)     :: mLayerVolFracLiqTrial          ! trial vector for volumetric fraction of liquid water (-)
- real(dp),dimension(nLayers)     :: mLayerVolFracIceTrial          ! trial vector for volumetric fraction of ice (-)
- ! -------------------------------------------------------------------------------------------------------------------
-
- ! -------------------------------------------------------------------------------------------------------------------
- ! point to flux variables in the data structure
- associate(&
- ! get indices for mass balance
- ixVegHyd                  => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)                  ,& ! intent(in)    : [i4b]    index of canopy hydrology state variable (mass)
- ixSoilOnlyHyd             => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                ,& ! intent(in)    : [i4b(:)] index in the state subset for hydrology state variables in the soil domain
- ! get indices for the un-tapped melt
- ixNrgOnly                 => indx_data%var(iLookINDEX%ixNrgOnly)%dat                    ,& ! intent(in)    : [i4b(:)] list of indices for all energy states
- ixDomainType              => indx_data%var(iLookINDEX%ixDomainType)%dat                 ,& ! intent(in)    : [i4b(:)] indices defining the domain of the state (iname_veg, iname_snow, iname_soil)
- ixControlVolume           => indx_data%var(iLookINDEX%ixControlVolume)%dat              ,& ! intent(in)    : [i4b(:)] index of the control volume for different domains (veg, snow, soil)
- ixMapSubset2Full          => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat             ,& ! intent(in)    : [i4b(:)] [state subset] list of indices of the full state vector in the state subset
- ! water fluxes
- scalarRainfall            => flux_data%var(iLookFLUX%scalarRainfall)%dat(1)             ,& ! intent(in)    : [dp]     rainfall rate (kg m-2 s-1)
- scalarThroughfallRain     => flux_data%var(iLookFLUX%scalarThroughfallRain)%dat(1)      ,& ! intent(in)    : [dp]     rain reaches ground without touching the canopy (kg m-2 s-1)
- scalarCanopyEvaporation   => flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1)    ,& ! intent(in)    : [dp]     canopy evaporation/condensation (kg m-2 s-1)
- scalarCanopyTranspiration => flux_data%var(iLookFLUX%scalarCanopyTranspiration)%dat(1)  ,& ! intent(in)    : [dp]     canopy transpiration (kg m-2 s-1)
- scalarCanopyLiqDrainage   => flux_data%var(iLookFLUX%scalarCanopyLiqDrainage)%dat(1)    ,& ! intent(in)    : [dp]     drainage liquid water from vegetation canopy (kg m-2 s-1)
- iLayerLiqFluxSoil         => flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat             ,& ! intent(in)    : [dp(0:)] vertical liquid water flux at soil layer interfaces (-)
- mLayerTranspire           => flux_data%var(iLookFLUX%mLayerTranspire)%dat               ,& ! intent(in)    : [dp(:)]  transpiration loss from each soil layer (m s-1)
- mLayerBaseflow            => flux_data%var(iLookFLUX%mLayerBaseflow)%dat                ,& ! intent(in)    : [dp(:)]  baseflow from each soil layer (m s-1)
- mLayerCompress            => diag_data%var(iLookDIAG%mLayerCompress)%dat                ,& ! intent(in)    : [dp(:)]  change in storage associated with compression of the soil matrix (-)
- scalarCanopySublimation   => flux_data%var(iLookFLUX%scalarCanopySublimation)%dat(1)    ,& ! intent(in)    : [dp]     sublimation of ice from the vegetation canopy (kg m-2 s-1)
- scalarSnowSublimation     => flux_data%var(iLookFLUX%scalarSnowSublimation)%dat(1)      ,& ! intent(in)    : [dp]     sublimation of ice from the snow surface (kg m-2 s-1)
- ! energy fluxes
- scalarLatHeatCanopyEvap   => flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1)    ,& ! intent(in)    : [dp]     latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
- scalarSenHeatCanopy       => flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)        ,& ! intent(in)    : [dp]     sensible heat flux from the canopy to the canopy air space (W m-2)
- ! domain depth
- 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)
- ! model state variables (vegetation canopy)
- scalarCanairTemp          => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the canopy air space (K)
- scalarCanopyTemp          => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the vegetation canopy (K)
- scalarCanopyIce           => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)            ,& ! intent(inout) : [dp]     mass of ice on the vegetation canopy (kg m-2)
- scalarCanopyLiq           => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)            ,& ! intent(inout) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
- scalarCanopyWat           => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)            ,& ! intent(inout) : [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(inout) : [dp(:)]  temperature of each snow/soil layer (K)
- mLayerVolFracIce          => prog_data%var(iLookPROG%mLayerVolFracIce)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of ice (-)
- mLayerVolFracLiq          => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of liquid water (-)
- mLayerVolFracWat          => prog_data%var(iLookPROG%mLayerVolFracWat)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of total water (-)
- mLayerMatricHead          => prog_data%var(iLookPROG%mLayerMatricHead)%dat              ,& ! intent(inout) : [dp(:)]  matric head (m)
- mLayerMatricHeadLiq       => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat           ,& ! intent(inout) : [dp(:)]  matric potential of liquid water (m)
- ! model state variables (aquifer)
- scalarAquiferStorage      => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)       ,& ! intent(inout) : [dp(:)]  storage of water in the aquifer (m)
- ! error tolerance
- absConvTol_liquid         => mpar_data%var(iLookPARAM%absConvTol_liquid)%dat(1)          & ! intent(in)    : [dp]     absolute convergence tolerance for vol frac liq water (-)
- ) ! associating flux variables in the data structure
- ! -------------------------------------------------------------------------------------------------------------------
- ! initialize error control
- err=0; message='updateProg/'
-
- ! initialize water balance error
- waterBalanceError=.false.
-
- ! get storage at the start of the step
- canopyBalance0 = merge(scalarCanopyWat, realMissing, computeVegFlux)
- soilBalance0   = sum( (mLayerVolFracLiq(nSnow+1:nLayers)  + mLayerVolFracIce(nSnow+1:nLayers)  )*mLayerDepth(nSnow+1:nLayers) )
-
- ! -----
- ! * update states...
- ! ------------------
-
- ! extract states from the state vector
- call varExtract(&
-                 ! input
-                 stateVecTrial,            & ! intent(in):    model state vector (mixed units)
-                 diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
-                 prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                 indx_data,                & ! intent(in):    indices defining model states and layers
-                 ! output: variables for the vegetation canopy
-                 scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
-                 scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
-                 scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
-                 scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
-                 scalarCanopyIceTrial,     & ! intent(out):   trial value of canopy ice content (kg m-2)
-                 ! output: variables for the snow-soil domain
-                 mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
-                 mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
-                 mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
-                 mLayerVolFracIceTrial,    & ! intent(out):   trial vector of volumetric ice water content (-)
-                 mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
-                 mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
-                 ! output: variables for the aquifer
-                 scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
-                 ! output: error control
-                 err,cmessage)               ! intent(out):   error control
- if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
-
- !print*, 'after varExtract: scalarCanopyTempTrial =', scalarCanopyTempTrial   ! trial value of canopy temperature (K)
- !print*, 'after varExtract: scalarCanopyWatTrial  =', scalarCanopyWatTrial    ! trial value of canopy total water (kg m-2)
- !print*, 'after varExtract: scalarCanopyLiqTrial  =', scalarCanopyLiqTrial    ! trial value of canopy liquid water (kg m-2)
- !print*, 'after varExtract: scalarCanopyIceTrial  =', scalarCanopyIceTrial    ! trial value of canopy ice content (kg m-2)
-
- ! check if there was too much melt
- if(nSnow>0) tooMuchMelt = (mLayerTempTrial(1)>Tfreeze)
-
- ! update diagnostic variables
- call updateVars(&
-                 ! input
-                 doAdjustTemp,             & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
-                 lookup_data,              & ! intent(in):    lookup tables for a local HRU
-                 mpar_data,                & ! intent(in):    model parameters for a local HRU
-                 indx_data,                & ! intent(in):    indices defining model states and layers
-                 prog_data,                & ! intent(in):    model prognostic variables for a local HRU
-                 diag_data,                & ! intent(inout): model diagnostic variables for a local HRU
-                 deriv_data,               & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
-                 ! output: variables for the vegetation canopy
-                 scalarCanopyTempTrial,    & ! intent(inout): trial value of canopy temperature (K)
-                 scalarCanopyWatTrial,     & ! intent(inout): trial value of canopy total water (kg m-2)
-                 scalarCanopyLiqTrial,     & ! intent(inout): trial value of canopy liquid water (kg m-2)
-                 scalarCanopyIceTrial,     & ! intent(inout): trial value of canopy ice content (kg m-2)
-                 ! output: variables for the snow-soil domain
-                 mLayerTempTrial,          & ! intent(inout): trial vector of layer temperature (K)
-                 mLayerVolFracWatTrial,    & ! intent(inout): trial vector of volumetric total water content (-)
-                 mLayerVolFracLiqTrial,    & ! intent(inout): trial vector of volumetric liquid water content (-)
-                 mLayerVolFracIceTrial,    & ! intent(inout): trial vector of volumetric ice water content (-)
-                 mLayerMatricHeadTrial,    & ! intent(inout): trial vector of total water matric potential (m)
-                 mLayerMatricHeadLiqTrial, & ! intent(inout): trial vector of liquid water matric potential (m)
-                 ! output: error control
-                 err,cmessage)               ! intent(out):   error control
-  if(err/=0)then
-    message=trim(message)//trim(cmessage)
-    print*, message
-    return
-  end if  ! (check for errors)
+  endif
+
+  end subroutine varSubstep
 
- !print*, 'after updateVars: scalarCanopyTempTrial =', scalarCanopyTempTrial   ! trial value of canopy temperature (K)
- !print*, 'after updateVars: scalarCanopyWatTrial  =', scalarCanopyWatTrial    ! trial value of canopy total water (kg m-2)
- !print*, 'after updateVars: scalarCanopyLiqTrial  =', scalarCanopyLiqTrial    ! trial value of canopy liquid water (kg m-2)
- !print*, 'after updateVars: scalarCanopyIceTrial  =', scalarCanopyIceTrial    ! trial value of canopy ice content (kg m-2)
 
- ! -----
- ! * check mass balance...
- ! -----------------------
+  ! **********************************************************************************************************
+  ! private subroutine updateProg: update prognostic variables
+  ! **********************************************************************************************************
+  subroutine updateProg(dt,nSnow,nSoil,nLayers,doAdjustTemp,computeVegFlux,untappedMelt,stateVecTrial,checkMassBalance, & ! input: model control
+                        lookup_data,mpar_data,indx_data,flux_data,prog_data,diag_data,deriv_data,                       & ! input-output: data structures
+                        waterBalanceError,nrgFluxModified,err,message)                                                    ! output: flags and error control
+  USE getVectorz_module,only:varExtract                             ! extract variables from the state vector
+  USE updateVars_module,only:updateVars                             ! update prognostic variables
+  implicit none
+  ! model control
+  real(rkind)         ,intent(in)    :: dt                             ! time step (s)
+  integer(i4b)     ,intent(in)    :: nSnow                          ! number of snow layers
+  integer(i4b)     ,intent(in)    :: nSoil                          ! number of soil layers
+  integer(i4b)     ,intent(in)    :: nLayers                        ! total number of layers
+  logical(lgt)     ,intent(in)    :: doAdjustTemp                   ! flag to indicate if we adjust the temperature
+  logical(lgt)     ,intent(in)    :: computeVegFlux                 ! flag to compute the vegetation flux
+  real(rkind)         ,intent(in)    :: untappedMelt(:)                ! un-tapped melt energy (J m-3 s-1)
+  real(rkind)         ,intent(in)    :: stateVecTrial(:)               ! trial state vector (mixed units)
+  logical(lgt)     ,intent(in)    :: checkMassBalance               ! flag to check the mass balance
+  ! data structures
+  type(zLookup),    intent(in)    :: lookup_data                    ! lookup tables
+  type(var_dlength),intent(in)    :: mpar_data                      ! model parameters
+  type(var_ilength),intent(in)    :: indx_data                      ! indices for a local HRU
+  type(var_dlength),intent(inout) :: flux_data                      ! model fluxes 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) :: deriv_data                     ! derivatives in model fluxes w.r.t. relevant state variables
+  ! flags and error control
+  logical(lgt)     ,intent(out)   :: waterBalanceError              ! flag to denote that there is a water balance error
+  logical(lgt)     ,intent(out)   :: nrgFluxModified                ! flag to denote that the energy fluxes were modified
+  integer(i4b)     ,intent(out)   :: err                            ! error code
+  character(*)     ,intent(out)   :: message                        ! error message
+  ! ==================================================================================================================
+  ! general
+  integer(i4b)                    :: iState                         ! index of model state variable
+  integer(i4b)                    :: ixSubset                       ! index within the state subset
+  integer(i4b)                    :: ixFullVector                   ! index within full state vector
+  integer(i4b)                    :: ixControlIndex                 ! index within a given domain
+  real(rkind)                        :: volMelt                        ! volumetric melt (kg m-3)
+  real(rkind),parameter              :: verySmall=epsilon(1._rkind)*2._rkind ! a very small number (deal with precision issues)
+  ! mass balance
+  real(rkind)                        :: canopyBalance0,canopyBalance1  ! canopy storage at start/end of time step
+  real(rkind)                        :: soilBalance0,soilBalance1      ! soil storage at start/end of time step
+  real(rkind)                        :: vertFlux                       ! change in storage due to vertical fluxes
+  real(rkind)                        :: tranSink,baseSink,compSink     ! change in storage due to sink terms
+  real(rkind)                        :: liqError                       ! water balance error
+  real(rkind)                        :: fluxNet                        ! net water fluxes (kg m-2 s-1)
+  real(rkind)                        :: superflousWat                  ! superflous water used for evaporation (kg m-2 s-1)
+  real(rkind)                        :: superflousNrg                  ! superflous energy that cannot be used for evaporation (W m-2 [J m-2 s-1])
+  character(LEN=256)              :: cmessage                       ! error message of downwind routine
+  ! trial state variables
+  real(rkind)                        :: scalarCanairTempTrial          ! trial value for temperature of the canopy air space (K)
+  real(rkind)                        :: scalarCanopyTempTrial          ! trial value for temperature of the vegetation canopy (K)
+  real(rkind)                        :: scalarCanopyWatTrial           ! trial value for liquid water storage in the canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerTempTrial                ! trial vector for temperature of layers in the snow and soil domains (K)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracWatTrial          ! trial vector for volumetric fraction of total water (-)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadTrial          ! trial vector for total water matric potential (m)
+  real(rkind),dimension(nSoil)       :: mLayerMatricHeadLiqTrial       ! trial vector for liquid water matric potential (m)
+  real(rkind)                        :: scalarAquiferStorageTrial      ! trial value for storage of water in the aquifer (m)
+  ! diagnostic variables
+  real(rkind)                        :: scalarCanopyLiqTrial           ! trial value for mass of liquid water on the vegetation canopy (kg m-2)
+  real(rkind)                        :: scalarCanopyIceTrial           ! trial value for mass of ice on the vegetation canopy (kg m-2)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracLiqTrial          ! trial vector for volumetric fraction of liquid water (-)
+  real(rkind),dimension(nLayers)     :: mLayerVolFracIceTrial          ! trial vector for volumetric fraction of ice (-)
+  ! -------------------------------------------------------------------------------------------------------------------
+
+  ! -------------------------------------------------------------------------------------------------------------------
+  ! point to flux variables in the data structure
+  associate(&
+  ! get indices for mass balance
+  ixVegHyd                  => indx_data%var(iLookINDEX%ixVegHyd)%dat(1)                  ,& ! intent(in)    : [i4b]    index of canopy hydrology state variable (mass)
+  ixSoilOnlyHyd             => indx_data%var(iLookINDEX%ixSoilOnlyHyd)%dat                ,& ! intent(in)    : [i4b(:)] index in the state subset for hydrology state variables in the soil domain
+  ! get indices for the un-tapped melt
+  ixNrgOnly                 => indx_data%var(iLookINDEX%ixNrgOnly)%dat                    ,& ! intent(in)    : [i4b(:)] list of indices for all energy states
+  ixDomainType              => indx_data%var(iLookINDEX%ixDomainType)%dat                 ,& ! intent(in)    : [i4b(:)] indices defining the domain of the state (iname_veg, iname_snow, iname_soil)
+  ixControlVolume           => indx_data%var(iLookINDEX%ixControlVolume)%dat              ,& ! intent(in)    : [i4b(:)] index of the control volume for different domains (veg, snow, soil)
+  ixMapSubset2Full          => indx_data%var(iLookINDEX%ixMapSubset2Full)%dat             ,& ! intent(in)    : [i4b(:)] [state subset] list of indices of the full state vector in the state subset
+  ! water fluxes
+  scalarRainfall            => flux_data%var(iLookFLUX%scalarRainfall)%dat(1)             ,& ! intent(in)    : [dp]     rainfall rate (kg m-2 s-1)
+  scalarThroughfallRain     => flux_data%var(iLookFLUX%scalarThroughfallRain)%dat(1)      ,& ! intent(in)    : [dp]     rain reaches ground without touching the canopy (kg m-2 s-1)
+  scalarCanopyEvaporation   => flux_data%var(iLookFLUX%scalarCanopyEvaporation)%dat(1)    ,& ! intent(in)    : [dp]     canopy evaporation/condensation (kg m-2 s-1)
+  scalarCanopyTranspiration => flux_data%var(iLookFLUX%scalarCanopyTranspiration)%dat(1)  ,& ! intent(in)    : [dp]     canopy transpiration (kg m-2 s-1)
+  scalarCanopyLiqDrainage   => flux_data%var(iLookFLUX%scalarCanopyLiqDrainage)%dat(1)    ,& ! intent(in)    : [dp]     drainage liquid water from vegetation canopy (kg m-2 s-1)
+  iLayerLiqFluxSoil         => flux_data%var(iLookFLUX%iLayerLiqFluxSoil)%dat             ,& ! intent(in)    : [dp(0:)] vertical liquid water flux at soil layer interfaces (-)
+  mLayerTranspire           => flux_data%var(iLookFLUX%mLayerTranspire)%dat               ,& ! intent(in)    : [dp(:)]  transpiration loss from each soil layer (m s-1)
+  mLayerBaseflow            => flux_data%var(iLookFLUX%mLayerBaseflow)%dat                ,& ! intent(in)    : [dp(:)]  baseflow from each soil layer (m s-1)
+  mLayerCompress            => diag_data%var(iLookDIAG%mLayerCompress)%dat                ,& ! intent(in)    : [dp(:)]  change in storage associated with compression of the soil matrix (-)
+  scalarCanopySublimation   => flux_data%var(iLookFLUX%scalarCanopySublimation)%dat(1)    ,& ! intent(in)    : [dp]     sublimation of ice from the vegetation canopy (kg m-2 s-1)
+  scalarSnowSublimation     => flux_data%var(iLookFLUX%scalarSnowSublimation)%dat(1)      ,& ! intent(in)    : [dp]     sublimation of ice from the snow surface (kg m-2 s-1)
+  ! energy fluxes
+  scalarLatHeatCanopyEvap   => flux_data%var(iLookFLUX%scalarLatHeatCanopyEvap)%dat(1)    ,& ! intent(in)    : [dp]     latent heat flux for evaporation from the canopy to the canopy air space (W m-2)
+  scalarSenHeatCanopy       => flux_data%var(iLookFLUX%scalarSenHeatCanopy)%dat(1)        ,& ! intent(in)    : [dp]     sensible heat flux from the canopy to the canopy air space (W m-2)
+  ! domain depth
+  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)
+  ! model state variables (vegetation canopy)
+  scalarCanairTemp          => prog_data%var(iLookPROG%scalarCanairTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the canopy air space (K)
+  scalarCanopyTemp          => prog_data%var(iLookPROG%scalarCanopyTemp)%dat(1)           ,& ! intent(inout) : [dp]     temperature of the vegetation canopy (K)
+  scalarCanopyIce           => prog_data%var(iLookPROG%scalarCanopyIce)%dat(1)            ,& ! intent(inout) : [dp]     mass of ice on the vegetation canopy (kg m-2)
+  scalarCanopyLiq           => prog_data%var(iLookPROG%scalarCanopyLiq)%dat(1)            ,& ! intent(inout) : [dp]     mass of liquid water on the vegetation canopy (kg m-2)
+  scalarCanopyWat           => prog_data%var(iLookPROG%scalarCanopyWat)%dat(1)            ,& ! intent(inout) : [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(inout) : [dp(:)]  temperature of each snow/soil layer (K)
+  mLayerVolFracIce          => prog_data%var(iLookPROG%mLayerVolFracIce)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of ice (-)
+  mLayerVolFracLiq          => prog_data%var(iLookPROG%mLayerVolFracLiq)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of liquid water (-)
+  mLayerVolFracWat          => prog_data%var(iLookPROG%mLayerVolFracWat)%dat              ,& ! intent(inout) : [dp(:)]  volumetric fraction of total water (-)
+  mLayerMatricHead          => prog_data%var(iLookPROG%mLayerMatricHead)%dat              ,& ! intent(inout) : [dp(:)]  matric head (m)
+  mLayerMatricHeadLiq       => diag_data%var(iLookDIAG%mLayerMatricHeadLiq)%dat           ,& ! intent(inout) : [dp(:)]  matric potential of liquid water (m)
+  ! model state variables (aquifer)
+  scalarAquiferStorage      => prog_data%var(iLookPROG%scalarAquiferStorage)%dat(1)       ,& ! intent(inout) : [dp(:)]  storage of water in the aquifer (m)
+  ! error tolerance
+  absConvTol_liquid         => mpar_data%var(iLookPARAM%absConvTol_liquid)%dat(1)          & ! intent(in)    : [dp]     absolute convergence tolerance for vol frac liq water (-)
+  ) ! associating flux variables in the data structure
+  ! -------------------------------------------------------------------------------------------------------------------
+  ! initialize error control
+  err=0; message='updateProg/'
 
- ! NOTE: should not need to do this, since mass balance is checked in the solver
- if(checkMassBalance)then
+  ! initialize water balance error
+  waterBalanceError=.false.
+
+  ! get storage at the start of the step
+  canopyBalance0 = merge(scalarCanopyWat, realMissing, computeVegFlux)
+  soilBalance0   = sum( (mLayerVolFracLiq(nSnow+1:nLayers)  + mLayerVolFracIce(nSnow+1:nLayers)  )*mLayerDepth(nSnow+1:nLayers) )
+
+  ! -----
+  ! * update states...
+  ! ------------------
+
+  ! initialize to state variable from the last update
+  scalarCanairTempTrial = scalarCanairTemp
+  scalarCanopyTempTrial = scalarCanopyTemp
+  scalarCanopyWatTrial  = scalarCanopyWat
+  scalarCanopyLiqTrial  = scalarCanopyLiq
+  scalarCanopyIceTrial  = scalarCanopyIce
+  mLayerTempTrial           = mLayerTemp
+  mLayerVolFracWatTrial     = mLayerVolFracWat
+  mLayerVolFracLiqTrial     = mLayerVolFracLiq
+  mLayerVolFracIceTrial     = mLayerVolFracIce
+  mLayerMatricHeadTrial     = mLayerMatricHead      ! total water matric potential
+  mLayerMatricHeadLiqTrial  = mLayerMatricHeadLiq   ! liquid water matric potential
+  scalarAquiferStorageTrial = scalarAquiferStorage
+
+  ! extract states from the state vector
+  call varExtract(&
+                  ! input
+                  stateVecTrial,            & ! intent(in):    model state vector (mixed units)
+                  diag_data,                & ! intent(in):    model diagnostic variables for a local HRU
+                  prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                  indx_data,                & ! intent(in):    indices defining model states and layers
+                  ! output: variables for the vegetation canopy
+                  scalarCanairTempTrial,    & ! intent(out):   trial value of canopy air temperature (K)
+                  scalarCanopyTempTrial,    & ! intent(out):   trial value of canopy temperature (K)
+                  scalarCanopyWatTrial,     & ! intent(out):   trial value of canopy total water (kg m-2)
+                  scalarCanopyLiqTrial,     & ! intent(out):   trial value of canopy liquid water (kg m-2)
+                  ! output: variables for the snow-soil domain
+                  mLayerTempTrial,          & ! intent(out):   trial vector of layer temperature (K)
+                  mLayerVolFracWatTrial,    & ! intent(out):   trial vector of volumetric total water content (-)
+                  mLayerVolFracLiqTrial,    & ! intent(out):   trial vector of volumetric liquid water content (-)
+                  mLayerMatricHeadTrial,    & ! intent(out):   trial vector of total water matric potential (m)
+                  mLayerMatricHeadLiqTrial, & ! intent(out):   trial vector of liquid water matric potential (m)
+                  ! output: variables for the aquifer
+                  scalarAquiferStorageTrial,& ! intent(out):   trial value of storage of water in the aquifer (m)
+                  ! output: error control
+                  err,cmessage)               ! intent(out):   error control
+  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+  !print*, 'after varExtract: scalarCanopyTempTrial =', scalarCanopyTempTrial   ! trial value of canopy temperature (K)
+  !print*, 'after varExtract: scalarCanopyWatTrial  =', scalarCanopyWatTrial    ! trial value of canopy total water (kg m-2)
+  !print*, 'after varExtract: scalarCanopyLiqTrial  =', scalarCanopyLiqTrial    ! trial value of canopy liquid water (kg m-2)
+  !print*, 'after varExtract: scalarCanopyIceTrial  =', scalarCanopyIceTrial    ! trial value of canopy ice content (kg m-2)
+
+  ! update diagnostic variables
+  call updateVars(&
+                  ! input
+                  doAdjustTemp,             & ! intent(in):    logical flag to adjust temperature to account for the energy used in melt+freeze
+                  lookup_data,              & ! intent(in):    lookup tables for a local HRU
+                  mpar_data,                & ! intent(in):    model parameters for a local HRU
+                  indx_data,                & ! intent(in):    indices defining model states and layers
+                  prog_data,                & ! intent(in):    model prognostic variables for a local HRU
+                  diag_data,                & ! intent(inout): model diagnostic variables for a local HRU
+                  deriv_data,               & ! intent(inout): derivatives in model fluxes w.r.t. relevant state variables
+                  ! output: variables for the vegetation canopy
+                  scalarCanopyTempTrial,    & ! intent(inout): trial value of canopy temperature (K)
+                  scalarCanopyWatTrial,     & ! intent(inout): trial value of canopy total water (kg m-2)
+                  scalarCanopyLiqTrial,     & ! intent(inout): trial value of canopy liquid water (kg m-2)
+                  scalarCanopyIceTrial,     & ! intent(inout): trial value of canopy ice content (kg m-2)
+                  ! output: variables for the snow-soil domain
+                  mLayerTempTrial,          & ! intent(inout): trial vector of layer temperature (K)
+                  mLayerVolFracWatTrial,    & ! intent(inout): trial vector of volumetric total water content (-)
+                  mLayerVolFracLiqTrial,    & ! intent(inout): trial vector of volumetric liquid water content (-)
+                  mLayerVolFracIceTrial,    & ! intent(inout): trial vector of volumetric ice water content (-)
+                  mLayerMatricHeadTrial,    & ! intent(inout): trial vector of total water matric potential (m)
+                  mLayerMatricHeadLiqTrial, & ! intent(inout): trial vector of liquid water matric potential (m)
+                  ! output: error control
+                  err,cmessage)               ! intent(out):   error control
+  if(err/=0)then; message=trim(message)//trim(cmessage); return; end if  ! (check for errors)
+
+  !print*, 'after updateVars: scalarCanopyTempTrial =', scalarCanopyTempTrial   ! trial value of canopy temperature (K)
+  !print*, 'after updateVars: scalarCanopyWatTrial  =', scalarCanopyWatTrial    ! trial value of canopy total water (kg m-2)
+  !print*, 'after updateVars: scalarCanopyLiqTrial  =', scalarCanopyLiqTrial    ! trial value of canopy liquid water (kg m-2)
+  !print*, 'after updateVars: scalarCanopyIceTrial  =', scalarCanopyIceTrial    ! trial value of canopy ice content (kg m-2)
+
+  ! -----
+  ! * check mass balance...
+  ! -----------------------
+
+  ! NOTE: should not need to do this, since mass balance is checked in the solver
+  if(checkMassBalance)then
 
   ! check mass balance for the canopy
   if(ixVegHyd/=integerMissing)then
 
-   ! handle cases where fluxes empty the canopy
-   fluxNet = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
-   if(-fluxNet*dt > canopyBalance0)then
+    ! handle cases where fluxes empty the canopy
+    fluxNet = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
+    if(-fluxNet*dt > canopyBalance0)then
 
     ! --> first add water
     canopyBalance1 = canopyBalance0 + (scalarRainfall - scalarThroughfallRain)*dt
 
     ! --> next, remove canopy evaporation -- put the unsatisfied evap into sensible heat
     canopyBalance1 = canopyBalance1 + scalarCanopyEvaporation*dt
-    if(canopyBalance1 < 0._dp)then
-     ! * get superfluous water and energy
-     superflousWat = -canopyBalance1/dt     ! kg m-2 s-1
-     superflousNrg = superflousWat*LH_vap   ! W m-2 (J m-2 s-1)
-     ! * update fluxes and states
-     canopyBalance1          = 0._dp
-     scalarCanopyEvaporation = scalarCanopyEvaporation + superflousWat
-     scalarLatHeatCanopyEvap = scalarLatHeatCanopyEvap + superflousNrg
-     scalarSenHeatCanopy     = scalarSenHeatCanopy - superflousNrg
+    if(canopyBalance1 < 0._rkind)then
+      ! * get superfluous water and energy
+      superflousWat = -canopyBalance1/dt     ! kg m-2 s-1
+      superflousNrg = superflousWat*LH_vap   ! W m-2 (J m-2 s-1)
+      ! * update fluxes and states
+      canopyBalance1          = 0._rkind
+      scalarCanopyEvaporation = scalarCanopyEvaporation + superflousWat
+      scalarLatHeatCanopyEvap = scalarLatHeatCanopyEvap + superflousNrg
+      scalarSenHeatCanopy     = scalarSenHeatCanopy - superflousNrg
     endif
 
     ! --> next, remove canopy drainage
     canopyBalance1 = canopyBalance1 - scalarCanopyLiqDrainage*dt
-    if(canopyBalance1 < 0._dp)then
-     superflousWat            = -canopyBalance1/dt     ! kg m-2 s-1
-     canopyBalance1          = 0._dp
-     scalarCanopyLiqDrainage = scalarCanopyLiqDrainage + superflousWat
+    if(canopyBalance1 < 0._rkind)then
+      superflousWat            = -canopyBalance1/dt     ! kg m-2 s-1
+      canopyBalance1          = 0._rkind
+      scalarCanopyLiqDrainage = scalarCanopyLiqDrainage + superflousWat
     endif
 
     ! update the trial state
@@ -789,43 +783,43 @@ subroutine varSubstep(&
     ! set the modification flag
     nrgFluxModified = .true.
 
-   else
+    else
     canopyBalance1  = canopyBalance0 + fluxNet*dt
     nrgFluxModified = .false.
-   endif  ! cases where fluxes empty the canopy
-
-   ! check the mass balance
-   fluxNet  = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
-   liqError = (canopyBalance0 + fluxNet*dt) - scalarCanopyWatTrial
-   !write(*,'(a,1x,f20.10)') 'dt = ', dt
-   !write(*,'(a,1x,f20.10)') 'scalarCanopyWatTrial       = ', scalarCanopyWatTrial
-   !write(*,'(a,1x,f20.10)') 'canopyBalance0             = ', canopyBalance0
-   !write(*,'(a,1x,f20.10)') 'canopyBalance1             = ', canopyBalance1
-   !write(*,'(a,1x,f20.10)') 'scalarRainfall*dt          = ', scalarRainfall*dt
-   !write(*,'(a,1x,f20.10)') 'scalarCanopyLiqDrainage*dt = ', scalarCanopyLiqDrainage*dt
-   !write(*,'(a,1x,f20.10)') 'scalarCanopyEvaporation*dt = ', scalarCanopyEvaporation*dt
-   !write(*,'(a,1x,f20.10)') 'scalarThroughfallRain*dt   = ', scalarThroughfallRain*dt
-   !write(*,'(a,1x,f20.10)') 'liqError                   = ', liqError
-   if(abs(liqError) > absConvTol_liquid*10._dp)then  ! *10 because of precision issues
+    endif  ! cases where fluxes empty the canopy
+
+    ! check the mass balance
+    fluxNet  = scalarRainfall + scalarCanopyEvaporation - scalarThroughfallRain - scalarCanopyLiqDrainage
+    liqError = (canopyBalance0 + fluxNet*dt) - scalarCanopyWatTrial
+    !write(*,'(a,1x,f20.10)') 'dt = ', dt
+    !write(*,'(a,1x,f20.10)') 'scalarCanopyWatTrial       = ', scalarCanopyWatTrial
+    !write(*,'(a,1x,f20.10)') 'canopyBalance0             = ', canopyBalance0
+    !write(*,'(a,1x,f20.10)') 'canopyBalance1             = ', canopyBalance1
+    !write(*,'(a,1x,f20.10)') 'scalarRainfall*dt          = ', scalarRainfall*dt
+    !write(*,'(a,1x,f20.10)') 'scalarCanopyLiqDrainage*dt = ', scalarCanopyLiqDrainage*dt
+    !write(*,'(a,1x,f20.10)') 'scalarCanopyEvaporation*dt = ', scalarCanopyEvaporation*dt
+    !write(*,'(a,1x,f20.10)') 'scalarThroughfallRain*dt   = ', scalarThroughfallRain*dt
+    !write(*,'(a,1x,f20.10)') 'liqError                   = ', liqError
+    if(abs(liqError) > absConvTol_liquid*10._rkind)then  ! *10 because of precision issues
     waterBalanceError = .true.
     return
-   endif  ! if there is a water balance error
+    endif  ! if there is a water balance error
   endif  ! if veg canopy
 
   ! check mass balance for soil
   ! NOTE: fatal errors, though possible to recover using negative error codes
   if(count(ixSoilOnlyHyd/=integerMissing)==nSoil)then
-   soilBalance1 = sum( (mLayerVolFracLiqTrial(nSnow+1:nLayers) + mLayerVolFracIceTrial(nSnow+1:nLayers) )*mLayerDepth(nSnow+1:nLayers) )
-   vertFlux     = -(iLayerLiqFluxSoil(nSoil) - iLayerLiqFluxSoil(0))*dt  ! m s-1 --> m
-   tranSink     = sum(mLayerTranspire)*dt                                ! m s-1 --> m
-   baseSink     = sum(mLayerBaseflow)*dt                                 ! m s-1 --> m
-   compSink     = sum(mLayerCompress(1:nSoil) * mLayerDepth(nSnow+1:nLayers) ) ! dimensionless --> m
-   liqError     = soilBalance1 - (soilBalance0 + vertFlux + tranSink - baseSink - compSink)
-   if(abs(liqError) > absConvTol_liquid*10._dp)then   ! *10 because of precision issues
+    soilBalance1 = sum( (mLayerVolFracLiqTrial(nSnow+1:nLayers) + mLayerVolFracIceTrial(nSnow+1:nLayers) )*mLayerDepth(nSnow+1:nLayers) )
+    vertFlux     = -(iLayerLiqFluxSoil(nSoil) - iLayerLiqFluxSoil(0))*dt  ! m s-1 --> m
+    tranSink     = sum(mLayerTranspire)*dt                                ! m s-1 --> m
+    baseSink     = sum(mLayerBaseflow)*dt                                 ! m s-1 --> m
+    compSink     = sum(mLayerCompress(1:nSoil) * mLayerDepth(nSnow+1:nLayers) ) ! dimensionless --> m
+    liqError     = soilBalance1 - (soilBalance0 + vertFlux + tranSink - baseSink - compSink)
+    if(abs(liqError) > absConvTol_liquid*10._rkind)then   ! *10 because of precision issues
     !write(*,'(a,1x,f20.10)') 'dt = ', dt
     !write(*,'(a,1x,f20.10)') 'soilBalance0      = ', soilBalance0
     !write(*,'(a,1x,f20.10)') 'soilBalance1      = ', soilBalance1
-    ! write(*,'(a,1x,f20.10)') 'vertFlux          = ', vertFlux
+    !write(*,'(a,1x,f20.10)') 'vertFlux          = ', vertFlux
     !write(*,'(a,1x,f20.10)') 'tranSink          = ', tranSink
     !write(*,'(a,1x,f20.10)') 'baseSink          = ', baseSink
     !write(*,'(a,1x,f20.10)') 'compSink          = ', compSink
@@ -833,46 +827,46 @@ subroutine varSubstep(&
     !write(*,'(a,1x,f20.10)') 'absConvTol_liquid = ', absConvTol_liquid
     waterBalanceError = .true.
     return
-   endif  ! if there is a water balance error
+    endif  ! if there is a water balance error
   endif  ! if hydrology states exist in the soil domain
 
- endif  ! if checking the mass balance
+  endif  ! if checking the mass balance
 
- ! -----
- ! * remove untapped melt energy...
- ! --------------------------------
+  ! -----
+  ! * remove untapped melt energy...
+  ! --------------------------------
 
- ! only work with energy state variables
- if(size(ixNrgOnly)>0)then  ! energy state variables exist
+  ! only work with energy state variables
+  if(size(ixNrgOnly)>0)then  ! energy state variables exist
 
   ! loop through energy state variables
   do iState=1,size(ixNrgOnly)
 
-   ! get index of the control volume within the domain
-   ixSubset       = ixNrgOnly(iState)             ! index within the state subset
-   ixFullVector   = ixMapSubset2Full(ixSubset)    ! index within full state vector
-   ixControlIndex = ixControlVolume(ixFullVector) ! index within a given domain
+    ! get index of the control volume within the domain
+    ixSubset       = ixNrgOnly(iState)             ! index within the state subset
+    ixFullVector   = ixMapSubset2Full(ixSubset)    ! index within full state vector
+    ixControlIndex = ixControlVolume(ixFullVector) ! index within a given domain
 
-   ! compute volumetric melt (kg m-3)
-   volMelt = dt*untappedMelt(ixSubset)/LH_fus  ! (kg m-3)
+    ! compute volumetric melt (kg m-3)
+    volMelt = dt*untappedMelt(ixSubset)/LH_fus  ! (kg m-3)
 
-   ! update ice content
-   select case( ixDomainType(ixFullVector) )
+    ! update ice content
+    select case( ixDomainType(ixFullVector) )
     case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
     case(iname_veg);  scalarCanopyIceTrial                        = scalarCanopyIceTrial                        - volMelt*canopyDepth  ! (kg m-2)
     case(iname_snow); mLayerVolFracIceTrial(ixControlIndex)       = mLayerVolFracIceTrial(ixControlIndex)       - volMelt/iden_ice     ! (-)
     case(iname_soil); mLayerVolFracIceTrial(ixControlIndex+nSnow) = mLayerVolFracIceTrial(ixControlIndex+nSnow) - volMelt/iden_water   ! (-)
     case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
-   end select
+    end select
 
-   ! update liquid water content
-   select case( ixDomainType(ixFullVector) )
+    ! update liquid water content
+    select case( ixDomainType(ixFullVector) )
     case(iname_cas);  cycle ! do nothing, since there is no snow stored in the canopy air space
     case(iname_veg);  scalarCanopyLiqTrial                        = scalarCanopyLiqTrial                        + volMelt*canopyDepth  ! (kg m-2)
     case(iname_snow); mLayerVolFracLiqTrial(ixControlIndex)       = mLayerVolFracLiqTrial(ixControlIndex)       + volMelt/iden_water   ! (-)
     case(iname_soil); mLayerVolFracLiqTrial(ixControlIndex+nSnow) = mLayerVolFracLiqTrial(ixControlIndex+nSnow) + volMelt/iden_water   ! (-)
     case default; err=20; message=trim(message)//'unable to identify domain type [remove untapped melt energy]'; return
-   end select
+    end select
 
   end do  ! looping through energy variables
 
@@ -881,52 +875,52 @@ subroutine varSubstep(&
   ! *** ice
 
   ! --> check if we removed too much water
-  if(scalarCanopyIceTrial < 0._dp  .or. any(mLayerVolFracIceTrial < 0._dp) )then
+  if(scalarCanopyIceTrial < 0._rkind  .or. any(mLayerVolFracIceTrial < 0._rkind) )then
 
-   ! **
-   ! canopy within numerical precision
-   if(scalarCanopyIceTrial < 0._dp)then
+    ! **
+    ! canopy within numerical precision
+    if(scalarCanopyIceTrial < 0._rkind)then
 
     if(scalarCanopyIceTrial > -verySmall)then
-     scalarCanopyLiqTrial = scalarCanopyLiqTrial - scalarCanopyIceTrial
-     scalarCanopyIceTrial = 0._dp
+      scalarCanopyLiqTrial = scalarCanopyLiqTrial - scalarCanopyIceTrial
+      scalarCanopyIceTrial = 0._rkind
 
     ! encountered an inconsistency: spit the dummy
     else
-     print*, 'dt = ', dt
-     print*, 'untappedMelt          = ', untappedMelt
-     print*, 'untappedMelt*dt       = ', untappedMelt*dt
-     print*, 'scalarCanopyiceTrial  = ', scalarCanopyIceTrial
-     message=trim(message)//'melted more than the available water'
-     err=20; return
+      print*, 'dt = ', dt
+      print*, 'untappedMelt          = ', untappedMelt
+      print*, 'untappedMelt*dt       = ', untappedMelt*dt
+      print*, 'scalarCanopyiceTrial  = ', scalarCanopyIceTrial
+      message=trim(message)//'melted more than the available water'
+      err=20; return
     endif  ! (inconsistency)
 
-   endif  ! if checking the canopy
+    endif  ! if checking the canopy
 
-   ! **
-   ! snow+soil within numerical precision
-   do iState=1,size(mLayerVolFracIceTrial)
+    ! **
+    ! snow+soil within numerical precision
+    do iState=1,size(mLayerVolFracIceTrial)
 
     ! snow layer within numerical precision
-    if(mLayerVolFracIceTrial(iState) < 0._dp)then
+    if(mLayerVolFracIceTrial(iState) < 0._rkind)then
 
-     if(mLayerVolFracIceTrial(iState) > -verySmall)then
+      if(mLayerVolFracIceTrial(iState) > -verySmall)then
       mLayerVolFracLiqTrial(iState) = mLayerVolFracLiqTrial(iState) - mLayerVolFracIceTrial(iState)
-      mLayerVolFracIceTrial(iState) = 0._dp
+      mLayerVolFracIceTrial(iState) = 0._rkind
 
-     ! encountered an inconsistency: spit the dummy
-     else
+      ! encountered an inconsistency: spit the dummy
+      else
       print*, 'dt = ', dt
       print*, 'untappedMelt          = ', untappedMelt
       print*, 'untappedMelt*dt       = ', untappedMelt*dt
       print*, 'mLayerVolFracIceTrial = ', mLayerVolFracIceTrial
       message=trim(message)//'melted more than the available water'
       err=20; return
-     endif  ! (inconsistency)
+      endif  ! (inconsistency)
 
     endif  ! if checking a snow layer
 
-   end do ! (looping through state variables)
+    end do ! (looping through state variables)
 
   endif  ! (if we removed too much water)
 
@@ -935,82 +929,83 @@ subroutine varSubstep(&
   ! *** liquid water
 
   ! --> check if we removed too much water
-  if(scalarCanopyLiqTrial < 0._dp  .or. any(mLayerVolFracLiqTrial < 0._dp) )then
+  if(scalarCanopyLiqTrial < 0._rkind  .or. any(mLayerVolFracLiqTrial < 0._rkind) )then
 
-   ! **
-   ! canopy within numerical precision
-   if(scalarCanopyLiqTrial < 0._dp)then
+    ! **
+    ! canopy within numerical precision
+    if(scalarCanopyLiqTrial < 0._rkind)then
 
     if(scalarCanopyLiqTrial > -verySmall)then
-     scalarCanopyIceTrial = scalarCanopyIceTrial - scalarCanopyLiqTrial
-     scalarCanopyLiqTrial = 0._dp
+      scalarCanopyIceTrial = scalarCanopyIceTrial - scalarCanopyLiqTrial
+      scalarCanopyLiqTrial = 0._rkind
 
     ! encountered an inconsistency: spit the dummy
     else
-     print*, 'dt = ', dt
-     print*, 'untappedMelt          = ', untappedMelt
-     print*, 'untappedMelt*dt       = ', untappedMelt*dt
-     print*, 'scalarCanopyLiqTrial  = ', scalarCanopyLiqTrial
-     message=trim(message)//'frozen more than the available water'
-     err=20; return
+      print*, 'dt = ', dt
+      print*, 'untappedMelt          = ', untappedMelt
+      print*, 'untappedMelt*dt       = ', untappedMelt*dt
+      print*, 'scalarCanopyLiqTrial  = ', scalarCanopyLiqTrial
+      message=trim(message)//'frozen more than the available water'
+      err=20; return
     endif  ! (inconsistency)
 
-   endif  ! checking the canopy
+    endif  ! checking the canopy
 
-   ! **
-   ! snow+soil within numerical precision
-   do iState=1,size(mLayerVolFracLiqTrial)
+    ! **
+    ! snow+soil within numerical precision
+    do iState=1,size(mLayerVolFracLiqTrial)
 
     ! snow layer within numerical precision
-    if(mLayerVolFracLiqTrial(iState) < 0._dp)then
+    if(mLayerVolFracLiqTrial(iState) < 0._rkind)then
 
-     if(mLayerVolFracLiqTrial(iState) > -verySmall)then
+      if(mLayerVolFracLiqTrial(iState) > -verySmall)then
       mLayerVolFracIceTrial(iState) = mLayerVolFracIceTrial(iState) - mLayerVolFracLiqTrial(iState)
-      mLayerVolFracLiqTrial(iState) = 0._dp
+      mLayerVolFracLiqTrial(iState) = 0._rkind
 
-     ! encountered an inconsistency: spit the dummy
-     else
+      ! encountered an inconsistency: spit the dummy
+      else
       print*, 'dt = ', dt
       print*, 'untappedMelt          = ', untappedMelt
       print*, 'untappedMelt*dt       = ', untappedMelt*dt
       print*, 'mLayerVolFracLiqTrial = ', mLayerVolFracLiqTrial
       message=trim(message)//'frozen more than the available water'
       err=20; return
-     endif  ! (inconsistency)
+      endif  ! (inconsistency)
 
     endif  ! checking a snow layer
 
-   end do ! (looping through state variables)
+    end do ! (looping through state variables)
 
   endif  ! (if we removed too much water)
 
- endif  ! (if energy state variables exist)
+  endif  ! (if energy state variables exist)
 
- ! -----
- ! * update prognostic variables...
- ! --------------------------------
+  ! -----
+  ! * update prognostic variables...
+  ! --------------------------------
 
- ! update state variables for the vegetation canopy
- scalarCanairTemp    = scalarCanairTempTrial    ! trial value of canopy air temperature (K)
- scalarCanopyTemp    = scalarCanopyTempTrial    ! trial value of canopy temperature (K)
- scalarCanopyWat     = scalarCanopyWatTrial     ! trial value of canopy total water (kg m-2)
- scalarCanopyLiq     = scalarCanopyLiqTrial     ! trial value of canopy liquid water (kg m-2)
- scalarCanopyIce     = scalarCanopyIceTrial     ! trial value of canopy ice content (kg m-2)
+  ! update state variables for the vegetation canopy
+  scalarCanairTemp    = scalarCanairTempTrial    ! trial value of canopy air temperature (K)
+  scalarCanopyTemp    = scalarCanopyTempTrial    ! trial value of canopy temperature (K)
+  scalarCanopyWat     = scalarCanopyWatTrial     ! trial value of canopy total water (kg m-2)
+  scalarCanopyLiq     = scalarCanopyLiqTrial     ! trial value of canopy liquid water (kg m-2)
+  scalarCanopyIce     = scalarCanopyIceTrial     ! trial value of canopy ice content (kg m-2)
 
- ! update state variables for the snow+soil domain
- mLayerTemp          = mLayerTempTrial          ! trial vector of layer temperature (K)
- mLayerVolFracWat    = mLayerVolFracWatTrial    ! trial vector of volumetric total water content (-)
- mLayerVolFracLiq    = mLayerVolFracLiqTrial    ! trial vector of volumetric liquid water content (-)
- mLayerVolFracIce    = mLayerVolFracIceTrial    ! trial vector of volumetric ice water content (-)
- mLayerMatricHead    = mLayerMatricHeadTrial    ! trial vector of matric head (m)
- mLayerMatricHeadLiq = mLayerMatricHeadLiqTrial ! trial vector of matric head (m)
+  ! update state variables for the snow+soil domain
+  mLayerTemp          = mLayerTempTrial          ! trial vector of layer temperature (K)
+  mLayerVolFracWat    = mLayerVolFracWatTrial    ! trial vector of volumetric total water content (-)
+  mLayerVolFracLiq    = mLayerVolFracLiqTrial    ! trial vector of volumetric liquid water content (-)
+  mLayerVolFracIce    = mLayerVolFracIceTrial    ! trial vector of volumetric ice water content (-)
+  mLayerMatricHead    = mLayerMatricHeadTrial    ! trial vector of matric head (m)
+  mLayerMatricHeadLiq = mLayerMatricHeadLiqTrial ! trial vector of matric head (m)
 
- ! update state variables for the aquifer
- scalarAquiferStorage = scalarAquiferStorageTrial
+  ! update state variables for the aquifer
+  scalarAquiferStorage = scalarAquiferStorageTrial
 
- ! end associations to info in the data structures
- end associate
+  ! end associations to info in the data structures
+  end associate
 
- end subroutine updateProg
+  end subroutine updateProg
 
 end module varSubstep_module
+  
\ No newline at end of file
diff --git a/utils/laugh_tests/BE/colbeck1976/run_test_summa_actors.sh b/utils/laugh_tests/BE/colbeck1976/run_test_summa_actors.sh
index 42b7a5c..27be92c 100755
--- a/utils/laugh_tests/BE/colbeck1976/run_test_summa_actors.sh
+++ b/utils/laugh_tests/BE/colbeck1976/run_test_summa_actors.sh
@@ -1,5 +1,5 @@
 #! /bin/bash
 
-# /Summa-Actors/bin/summaMain -g 1 -n 1 -c /Summa-Actors/utils/laugh_tests/colbeck1976/config/exp1
+/Summa-Actors/bin/summaMain -g 1 -n 1 -c /Summa-Actors/utils/laugh_tests/colbeck1976/config/exp1
 /Summa-Actors/bin/summaMain -g 1 -n 1 -c /Summa-Actors/utils/laugh_tests/colbeck1976/config/exp2
-# /Summa-Actors/bin/summaMain -g 1 -n 1 -c /Summa-Actors/utils/laugh_tests/colbeck1976/config/exp3
+/Summa-Actors/bin/summaMain -g 1 -n 1 -c /Summa-Actors/utils/laugh_tests/colbeck1976/config/exp3
-- 
GitLab